

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 保护基础架构（主机）
<a name="protecting-the-infrastructure"></a>

由于保护您的容器镜像非常重要，因此保护运行这些镜像的基础架构也同样重要。本节探讨降低直接针对主机的攻击所带来的风险的不同方法。这些指南应与 “[运行时安全](runtime-security.md)” 部分中概述的指南结合使用。

## 建议
<a name="_recommendations"></a>

### 使用专为运行容器而优化的操作系统
<a name="_use_an_os_optimized_for_running_containers"></a>

考虑使用 Flatcar Linux、Project Atomic、RancherOS 和 [Bottlerocket](https://github.com/bottlerocket-os/bottlerocket/)，后者是 AWS 专为运行 Linux 容器而设计的特殊用途操作系统。它包括减少攻击面、启动时经过验证的磁盘映像以及使用 SELinux 强制执行的权限边界。

或者，也可以为您的 Kubernetes 工作节点使用 EK [S 优化的 AMI](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-amis.html)。EKS 优化的 AMI 定期发布，其中包含运行容器化工作负载所需的最少一组操作系统包和二进制文件。

请参阅 [Amazon EKS AMI RHEL 构建规范](https://github.com/aws-samples/amazon-eks-ami-rhel)，了解示例配置脚本，该脚本可用于使用 Hashicorp Packer 构建在红帽企业 Linux 上运行的自定义 Amazon EKS AMI。可以进一步利用此脚本来构建符合 STIG 标准的 EKS 自定义 AMI。

### 让你的工作节点操作系统保持最新状态
<a name="_keep_your_worker_node_os_updated"></a>

无论您使用的是容器优化的主机操作系统（如 Bottlerocket）还是更大但仍然极简主义的 Amazon Machine Image（如 EKS 优化的 AMI），最佳做法是使用最新的安全补丁使这些主机操作系统映像保持最新状态。

对于 EKS 优化的 AMI，请定期查看 C [HANGELOG and/or ](https://github.com/awslabs/amazon-eks-ami/blob/master/CHANGELOG.md) [发行说明频道](https://github.com/awslabs/amazon-eks-ami/releases)，并自动将更新的工作节点映像部署到您的集群中。

### 将您的基础架构视为不可变的，并自动更换工作节点
<a name="_treat_your_infrastructure_as_immutable_and_automate_the_replacement_of_your_worker_nodes"></a>

与其执行就地升级，不如在有新的补丁或更新可用时更换工作人员。有几种方法可以解决这个问题。您可以使用最新的 AMI 向现有自动扩缩组添加实例，因为您可以按顺序封锁和清空节点，直到该组中的所有节点都被最新的 AMI 替换。或者，您可以向新节点组添加实例，同时按顺序封锁和清空旧节点组中的节点，直到所有节点都被替换。EKS [托管节点组](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)使用第一种方法，当新 AMI 可用时，将在控制台中显示一条消息以升级您的工作程序。 `eksctl`还有一种机制，用于使用最新 AMI 创建节点组，并在实例终止之前优雅地封锁和排出节点组中的 Pod。如果您决定使用其他方法来替换工作节点，强烈建议您自动执行该过程以最大限度地减少人为监督，因为随着新 updates/patches 工作节点的发布和控制平面升级，您可能需要定期更换工作节点。

借助 EKS Fargate，AWS 将在更新可用时自动更新底层基础设施。通常，这可以无缝完成，但有时更新可能会导致你的 pod 被重新安排。因此，我们建议您在作为 Fargate pod 运行应用程序时，创建包含多个副本的部署。

### 定期运行 kube-bench 以验证是否符合 Kubernetes 的 CI [S](https://www.cisecurity.org/benchmark/kubernetes/) 基准
<a name="_periodically_run_kube_bench_to_verify_compliance_with_cis_benchmarks_for_kubernetes"></a>

kube-bench 是 Aqua 推出的一个开源项目，它根据 Kubernetes 的 CIS 基准测试来评估你的集群。该基准测试描述了保护非托管 Kubernetes 集群的最佳实践。CIS Kubernetes 基准测试包括控制平面和数据平面。由于 Amazon EKS 提供了完全托管的控制平面，因此并非所有来自 CIS Kubernetes 基准测试的建议都适用。为了确保该范围反映亚马逊 EKS 的实施方式，AWS 创建了 *CIS 亚马逊 EKS 基准测试*。EKS 基准测试继承自 CIS Kubernetes 基准测试，社区提供了其他意见，其中包括 EKS 集群的具体配置注意事项。

对 EKS 集群运行 [kube-bench](https://github.com/aquasecurity/kube-bench) 时，请按照 Aqua Security [中的这些说明进行操作](https://github.com/aquasecurity/kube-bench/blob/main/docs/running.md#running-cis-benchmark-in-an-eks-cluster)。欲了解更多信息，请参阅 [CIS Amazon EKS 基准测试简介](https://aws.amazon.com/blogs/containers/introducing-cis-amazon-eks-benchmark/)。

### 尽量减少对工作节点的访问
<a name="_minimize_access_to_worker_nodes"></a>

当您需要远程访问主机时，请使用 [SSM 会话管理器](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html)，而不是启用 SSM 会话管理器。与可能丢失、复制或共享的 SSH 密钥不同，会话管理器允许您使用 IAM 控制对 EC2 实例的访问权限。此外，它还提供在实例上运行的命令的审计跟踪和日志。

自 2020 年 8 月 19 日起，托管节点组支持自定义 AMI 和 EC2 启动模板。这允许您将 SSM 代理嵌入 AMI 或在工作节点被引导时安装它。如果您不想修改优化的 AMI 或 ASG 的启动模板，则可以 DaemonSet 按照[本](https://github.com/aws-samples/ssm-agent-daemonset-installer)示例中的方式安装 SSM 代理。

#### 基于 SSM 的 SSH 访问的最低 IAM 策略
<a name="_minimal_iam_policy_for_ssm_based_ssh_access"></a>

`AmazonSSMManagedInstanceCore`AWS 托管策略包含许多权限， RunCommand 如果您只是想避开 SSH 访问，SSM 会话管理器/SSM 就不需要这些权限。特别值得关注的是允许角色访问参数存储中的所有参数（包括 SecureStrings 配置了 AWS 托管 KMS 密钥的情况下）的`*`权限。`ssm:GetParameter(s)`

以下 IAM 策略包含允许通过 SSM Systems Manager 访问节点的最低权限集。

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "EnableAccessViaSSMSessionManager",
      "Effect": "Allow",
      "Action": [
        "ssmmessages:OpenDataChannel",
        "ssmmessages:OpenControlChannel",
        "ssmmessages:CreateDataChannel",
        "ssmmessages:CreateControlChannel",
        "ssm:UpdateInstanceInformation"
      ],
      "Resource": "*"
    },
    {
      "Sid": "EnableSSMRunCommand",
      "Effect": "Allow",
      "Action": [
        "ssm:UpdateInstanceInformation",
        "ec2messages:SendReply",
        "ec2messages:GetMessages",
        "ec2messages:GetEndpoint",
        "ec2messages:FailMessage",
        "ec2messages:DeleteMessage",
        "ec2messages:AcknowledgeMessage"
      ],
      "Resource": "*"
    }
  ]
}
```

有了这个策略并安装了[会话管理器插件](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)，你就可以运行了

```
aws ssm start-session --target [INSTANCE_ID_OF_EKS_NODE]
```

访问该节点。

**注意**  
您可能还需要考虑添加权限以[启用会话管理器日志记录](https://docs.aws.amazon.com/systems-manager/latest/userguide/getting-started-create-iam-instance-profile.html#create-iam-instance-profile-ssn-logging)。

### 将工作人员部署到私有子网
<a name="_deploy_workers_onto_private_subnets"></a>

通过将工作人员部署到私有子网，可以最大限度地减少他们接触经常发起攻击的 Internet 的机会。从 2020 年 4 月 22 日起，托管节点组中节点的公有 IP 地址的分配将由其部署到的子网控制。在此之前，托管节点组中的节点会被自动分配一个公有 IP。如果您选择将工作节点部署到公有子网，请实施限制性的 AWS 安全组规则以限制其风险。

### 运行 Amazon Inspector 来评估主机是否存在漏洞、漏洞以及与最佳实践的偏差
<a name="_run_amazon_inspector_to_assess_hosts_for_exposure_vulnerabilities_and_deviations_from_best_practices"></a>

您可以使用 [Amazon Inspec](https://docs.aws.amazon.com/inspector/latest/user/what-is-inspector.html) tor 检查您的节点是否存在意外网络访问以及底层 Amazon EC2 实例上是否存在漏洞。

只有安装并启用了亚马逊 EC2 Systems Manager (SSM) 代理，Amazon Inspector 才能为您的亚马逊 EC2 实例提供常见漏洞和风险敞口 (CVE) 数据。该代理已预安装在多个[亚马逊系统映像 (AMI) 上，包括 EKS 优](https://docs.aws.amazon.com/systems-manager/latest/userguide/ami-preinstalled-agent.html)[化的亚马逊 Linux](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami.html) AMI。不管 SSM 代理状态如何，都会对您的所有 Amazon EC2 实例进行网络可访问性问题扫描。有关为 Amazon EC2 配置扫描的更多信息，请参阅扫[描 Amazon EC2 实例](https://docs.aws.amazon.com/inspector/latest/user/enable-disable-scanning-ec2.html)。

**重要**  
Inspector 无法在用于运行 Fargate 容器的基础设施上运行。

## 替代方案
<a name="_alternatives"></a>

### 运行 SELinux
<a name="iam-se-linux"></a>

**注意**  
可在红帽企业 Linux (RHEL)、CentOS、Bottlerocket 和亚马逊 Linux 2023 上线

SELinux 提供了额外的安全层，使容器彼此隔离，并与主机隔离。SELinux 允许管理员对每个用户、应用程序、进程和文件实施强制访问控制 (MAC)。可以将其视为一种支持，它根据一组标签将可以针对特定资源执行的操作限制在特定资源上。在 EKS 上，SELinux 可用于防止容器访问彼此的资源。

容器 SELinux 策略是在容器 selinux 软件[包](https://github.com/containers/container-selinux)中定义的。Docker CE 需要此软件包（及其依赖项），这样 Docker（或其他容器运行时）创建的进程和文件才能在有限的系统访问权限下运行。容器利用作为别名的`container_t`标签`svirt_lxc_net_t`。这些策略可以有效地防止容器访问主机的某些功能。

当你为 Docker 配置 SELinux 时，Docker 会自动将工作负载标记`container_t`为一种类型，并为每个容器提供唯一的 MCS 级别。这将使容器相互隔离。如果您需要更宽松的限制，可以在 SELinux 中创建自己的配置文件，为容器授予文件系统特定区域的权限。这与 PSP 类似，因为您可以为不同的配置文件创建不同的配置文件。 containers/pods例如，您可以为具有一组限制性控制的常规工作负载设置一个配置文件，为需要特权访问权限的内容设置另一个配置文件。

适用于容器的 SELinux 有一组选项，可以将其配置为修改默认限制。您可以根据需要启用或禁用以下 SELinux 布尔值：


| 布尔值 | 默认值 | 说明 | 
| --- | --- | --- | 
|  `container_connect_any`  |  `off`  | 允许容器访问主机上的特权端口。例如，如果您有一个容器需要将端口映射到主机上的 443 或 80。 | 
|  `container_manage_cgroup`  |  `off`  | 允许容器管理 cgroup 配置。例如，运行 systemd 的容器需要将其启用。 | 
|  `container_use_cephfs`  |  `off`  | 允许容器使用 ceph 文件系统。 | 

默认情况下，允许 read/execute 容器从中读取大部分内容`/etc`。`/usr`文件位于`/var/lib/docker`并`/var/lib/containers`带有标签`container_var_lib_t`。要查看默认标签的完整列表，请参阅 con [tainer.fc 文件。](https://github.com/containers/container-selinux/blob/master/container.fc)

```
docker container run -it \
  -v /var/lib/docker/image/overlay2/repositories.json:/host/repositories.json \
  centos:7 cat /host/repositories.json
# cat: /host/repositories.json: Permission denied

docker container run -it \
  -v /etc/passwd:/host/etc/passwd \
  centos:7 cat /host/etc/passwd
# cat: /host/etc/passwd: Permission denied
```

标有标签的文件`container_file_t`是唯一可由容器写入的文件。如果要使卷装入可写入，则需要`:Z`在末尾指定`:z`或。
+  `:z`将重新标记文件以便容器可以 read/write
+  `:Z`将重新标记文件以便**只有**容器可以 read/write

```
ls -Z /var/lib/misc
# -rw-r--r--. root root system_u:object_r:var_lib_t:s0   postfix.aliasesdb-stamp

docker container run -it \
  -v /var/lib/misc:/host/var/lib/misc:z \
  centos:7 echo "Relabeled!"

ls -Z /var/lib/misc
#-rw-r--r--. root root system_u:object_r:container_file_t:s0 postfix.aliasesdb-stamp
```

```
docker container run -it \
  -v /var/log:/host/var/log:Z \
  fluentbit:latest
```

在 Kubernetes 中，重新标记略有不同。您可以指定自定义 MCS 标签来运行 pod，而不是让 Docker 自动重新标记文件。支持重新标记的卷将自动重新标记，以便可以访问。带有匹配的 MCS 标签的 Pod 将能够访问该卷。如果您需要严格隔离，请为每个 pod 设置不同的 MCS 标签。

```
securityContext:
  seLinuxOptions:
    # Provide a unique MCS label per container
    # You can specify user, role, and type also
    # enforcement based on type and level (svert)
    level: s0:c144:c154
```

在此示例中，`s0:c144:c154`对应于分配给允许容器访问的文件的 MCS 标签。

在 EKS 上，您可以创建允许特权容器运行的策略，例如 FluentD，并创建 SELinux 策略以允许它在无需重新标记主机目录的情况下从主机上的 var/log /中读取。具有相同标签的 Pod 将能够访问相同的主机卷。

我们已经[为亚马逊 EKS 实施了示例 AMI，这些示例](https://github.com/aws-samples/amazon-eks-custom-amis)在 CentOS 7 和 RHEL 7 上配置了 SELinux。开发这些 AMI 是为了演示符合高度监管客户要求的示例实施。

**警告**  
SELinux 将忽略类型不受限制的容器。

## 工具和资源
<a name="_tools_and_resources"></a>
+  [SELinux Kubernetes RBAC 和应用程序发布安全政策 On-prem ](https://platform9.com/blog/selinux-kubernetes-rbac-and-shipping-security-policies-for-on-prem-applications/) 
+  [Kubernetes 的迭代强化](https://jayunit100.blogspot.com/2019/07/iterative-hardening-of-kubernetes-and.html) 
+  [审计 2 允许](https://linux.die.net/man/1/audit2allow) 
+  [SeAlert](https://linux.die.net/man/8/sealert) 
+  [使用 Udica 为容器生成 SELinux 策略](https://www.redhat.com/en/blog/generate-selinux-policies-containers-with-udica)描述了一种工具，该工具可以查看 Linux 功能、端口和挂载点的容器规范文件，并生成一组允许容器正常运行的 SELinux 规则
+  [AMI 强化](https://github.com/aws-samples/amazon-eks-custom-amis#hardening)操作手册，用于强化操作系统以满足不同的监管要求
+  [Keiko Upgrade Manager](https://github.com/keikoproj/upgrade-manager) 是一个来自 Intuit 的开源项目，用于协调工作节点的轮换。
+  [Sysdig 安全](https://sysdig.com/products/kubernetes-security/) 
+  [eksctl](https://eksctl.io/) 