Kolla Security

非 Root 容器

在 Kolla 的容器内部,OpenStack 服务(少数例外)以非 root 用户身份运行。Kolla 使用 Docker 提供的 USER 标志为每个服务设置适当的用户。

SELinux

Kolla 中 SELinux 的状态仍在进行中。简短的回答是,在为 Docker 容器编写 selinux 策略之前,您必须禁用它。

为了理解为什么 Kolla 需要为某些服务设置特定的 selinux 策略,而这些服务可能并不需要它们(rabbitmq、mariadb、glance 等),我们必须退一步,谈谈 Docker。

Docker 最近才有了持久化容器数据的概念。这意味着当容器运行时,它创建的数据会在容器消失时被销毁,这显然不适用于升级的情况。

有人建议数据容器可以通过仅在未被重新创建时才保存数据来解决这个问题,从而导致一种可怕的状态,即如果执行了错误的命令,您可能会失去对数据的访问权限。这个问题的真正答案出现在 Docker 1.9 中,随着命名卷的引入。现在您可以直接通过名称来引用卷,从而完全消除了所谓的 数据容器 的需求。

另一种解决持久化数据问题的方法是使用主机绑定挂载,这涉及将主机目录(例如 var/lib/mysql)在容器内部可用(例如 var/lib/mysql)。这绝对解决了持久化数据的问题,但它引入了另一个安全问题,即权限。使用这种主机绑定挂载解决方案,var/lib/mysql 中的数据将由容器中的 mysql 用户拥有。不幸的是,容器中的 mysql 用户可以拥有任何 UID/GID,而这将是容器外部数据的所有者,从而引入潜在的安全风险。此外,这种方法会弄脏主机,并且需要对要绑定挂载的目录进行主机权限。

Kolla 选择的解决方案是命名卷。

这在 SELinux 的情况下有什么关系? Kolla 并不运行进程。在大多数情况下,它以 root 身份启动。因此,glance-api 以 glance 用户身份运行,mariadb 以 mysql 用户身份运行,依此类推。当将命名卷挂载到将存储持久化数据的位置时,它将由 root 用户和组拥有。现在 mysql 用户没有权限写入此文件夹。Kolla 允许作为 mysql 用户运行少数几个带有 sudo 的命令。这允许 mysql 用户 chown 一个特定的、明确的目录,并将数据存储在命名卷中,而无需主机绑定挂载的安全风险和其他缺点。缺点是 selinux 会阻止这些 sudo 命令,并且在制定明确的策略允许这些操作之前,它会这样做。

Kolla-ansible 用户

在 Queens 之前,当用户想要使用非 root 用户连接时,他们必须添加额外的选项 ansible_become=True,这既不方便又会增加安全风险。在 Queens 中,几乎所有服务都支持仅对必要任务进行升级。在 Rocky 中,所有服务都具有此功能,因此如果连接用户具有无密码 sudo 功能,则用户无需添加 ansible_become 选项。

在 Rocky 之前,ansible_user(Ansible 用于通过 SSH 连接的用户)是目标节点中的默认配置所有者和组。从 Rocky 版本开始,Kolla 支持使用具有无密码 sudo 功能的任何用户进行连接。为了设置自定义所有者用户和组,用户可以在 globals.yml 中设置 config_owner_userconfig_owner_group

FirewallD

在 Zed 之前,Kolla Ansible 会禁用任何系统防火墙,将配置留给最终用户。现在支持 Firewalld,并将为每个启用的 OpenStack 服务配置外部 api 端口。

应在 Kolla Ansible 的 globals.yml 中配置以下变量

  • external_api_firewalld_zone
    • 为外部 API 访问配置端口的默认区域

    • 字符串 - 默认值为 public 区域

  • enable_external_api_firewalld
    • 设置为 true 将启用外部 API 端口配置

    • 布尔值 - 设置为 true 或 false

  • disable_firewall
    • 设置为 false 将停止 Kolla Ansible 禁用系统防火墙

    • 布尔值 - 设置为 true 或 false

先决条件

Firewalld 需要预先安装。

Kayobe 可用于在运行 Kolla Ansible 之前自动安装和配置 firewalld。如果您不使用 Kayobe,则必须确保已正确安装和设置 firewalld。

您可以通过运行以下命令来检查当前活动区域。如果命令的输出为空,则未配置任何区域为活动状态。

sudo firewall-cmd --get-active-zones

您应该确保可以通过 SSH 访问系统,以避免锁定,要将 ssh 添加到特定区域,请运行以下命令。

sudo firewall-cmd --permanent --zone=<zone>  --add-service=ssh

您还应该通过运行以下命令将所需的接口设置为特定区域。这将把该区域标记为指定接口上的活动状态。

sudo firewall-cmd --permanent --zone=<zone> --change-interface=<interface>

如果特定区域需要多个接口,可以通过运行以下命令来实现

sudo firewall-cmd --permanent --zone=public --add-interface=<additional interface>

任何其他需要在系统上打开的端口都应事先完成。以下命令会将其他端口添加到区域

sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent

根据您的基础设施安全策略,您可能希望在 public 区域添加一个 drop 策略,可以通过运行以下命令来实现。

sudo firewall-cmd --permanent --set-target=DROP --zone=public

要将更改应用于系统防火墙,请运行

sudo firewalld-cmd --reload

有关更多信息和配置,请参阅:https://firewalld.org/documentation/man-pages/firewall-cmd.html