认证和授权
Red Hat OpenShift Service on AWS 集群的安全。
摘要
第 1 章 假设服务帐户的 AWS IAM 角色
使用 AWS 安全令牌服务 (STS) 的 Red Hat OpenShift Service on AWS 集群包括一个 pod 身份 Webhook,用于在用户定义的项目中运行的 pod。
您可以使用 pod 身份 Webhook 启用服务帐户,以便在您自己的 pod 中自动假设 AWS Identity and Access Management (IAM) 角色。如果假定的 IAM 角色具有所需的 AWS 权限,pod 可以使用临时 STS 凭证运行 AWS SDK 操作。
1.1. 了解用户定义的项目中的 pod 身份 Webhook 工作流
当使用 AWS 安全令牌服务 (STS) 在 AWS 集群上安装 Red Hat OpenShift Service 时,默认包括 Pod 身份 Webhook 资源。
您可以使用 pod 身份 Webhook 在用户定义的项目中启用服务帐户,来假定同一项目中的 pod 中的 AWS Identity and Access Management (IAM) 角色。当假定 IAM 角色时,会为 pod 中的服务帐户提供临时 STS 凭证。如果假定角色具有所需的 AWS 权限,则服务帐户可以在 pod 中运行 AWS SDK 操作。
要为 pod 启用 pod 身份 Webhook,您必须在项目中使用 eks.amazonaws.com/role-arn 注解创建一个服务帐户。该注解必须引用您要假定服务帐户的 AWS IAM 角色的 Amazon Resource Name (ARN)。您还必须在 Pod 规格中引用服务帐户,并将 pod 部署到与服务帐户相同的项目中。
用户定义的项目中的 Pod 身份 Webhook 工作流
下图演示了用户定义的项目中的 pod 身份 Webhook 工作流:
图 1.1. 用户定义的项目中的 Pod 身份 Webhook 工作流

工作流有以下阶段:
-
在用户定义的项目中,用户会创建一个包括
eks.amazonaws.com/role-arn注解的服务帐户。该注解指向您希望服务帐户假定的 AWS IAM 角色的 ARN。 当使用引用被注解服务帐户的配置在同一项目中部署 pod 时,pod 身份 Webhook 会修改 pod。变异会将以下组件注入 pod,而无需在
Pod或Deployment资源配置中指定它们:-
$AWS_ARN_ROLE环境变量,其中包含 IAM 角色的 ARN,该角色具有运行 AWS SDK 操作所需的权限。 -
$AWS_WEB_IDENTITY_TOKEN_FILE环境变量,其中包含服务帐户的 OpenID Connect (OIDC)令牌的完整路径。完整路径为/var/run/secrets/eks.amazonaws.com/serviceaccount/token。 -
挂载到挂载点
/var/run/secrets/eks.amazonaws.com/serviceaccount上的aws-iam-token卷。名为token的 OIDC 令牌文件包含在卷中。
-
OIDC 令牌从 pod 传递给 OIDC 供应商。如果满足以下要求,供应商会验证服务帐户身份:
- 身份签名由私钥有效并签名。
sts.amazonaws.com受众列在 OIDC 令牌中,并与 OIDC 供应商中配置的受众匹配。注意默认情况下,pod 身份 Webhook 会将
sts.amazonaws.com受众应用到 OIDC 令牌。在带有 STS 的 AWS 上的 Red Hat OpenShift Service 中,OIDC 供应商会在安装过程中创建,并默认设置为服务帐户签发者。在 OIDC 供应商中默认设置
sts.amazonaws.com受众。- OIDC 令牌尚未过期。
- 令牌中的签发者值包含 OIDC 供应商的 URL。
- 如果项目和服务帐户位于被假定的 IAM 角色的信任策略范围内,则授权会成功。
- 成功身份验证和授权后,以会话令牌的形式将临时 AWS STS 凭证传递给 pod,供服务帐户使用。通过使用凭证,服务帐户被临时授予 IAM 角色中启用的 AWS 权限。
- 当您在 pod 中运行 AWS SDK 操作时,服务帐户为 AWS API 提供临时 STS 凭证来验证其身份。
1.2. 假设您自己的 pod 中的 AWS IAM 角色
按照本节中的步骤,启用服务帐户在用户定义的项目中部署的 pod 中假定 AWS Identity and Access Management (IAM)角色。
您可以创建所需资源,包括 AWS IAM 角色、服务帐户、包括 AWS SDK 的容器镜像,以及使用镜像部署的 pod。在示例中,使用了 Python 的 AWS Boto3 SDK。您还可以验证 pod 身份 Webhook 是否将 AWS 环境变量、卷挂载和令牌卷放入 pod。另外,您可以检查服务帐户是否在 pod 中假设 AWS IAM 角色,并可成功运行 AWS SDK 操作。
1.2.1. 为服务帐户设置 AWS IAM 角色
创建一个 AWS Identity and Access Management (IAM)角色,由 Red Hat OpenShift Service on AWS 集群中的服务帐户假定。附加您的服务帐户在 pod 中运行 AWS SDK 操作所需的权限。
先决条件
- 您有在 AWS 帐户中安装和配置 IAM 角色所需的权限。
- 您可以访问使用 AWS 安全令牌服务(STS)的 Red Hat OpenShift Service on AWS 集群。不需要 admin 级别用户权限。
您有 OpenID Connect (OIDC)供应商的 Amazon Resource Name (ARN),该供应商被配置为 Red Hat OpenShift Service on AWS 中的服务帐户签发者。
注意在带有 STS 的 AWS 上的 Red Hat OpenShift Service 中,OIDC 供应商会在安装过程中创建,并默认设置为服务帐户签发者。如果您不知道 OIDC 供应商 ARN,请联络您的集群管理员。
-
已安装 AWS CLI (
aws)。
流程
使用以下 JSON 配置创建一个名为
trust-policy.json的文件:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "<oidc_provider_arn>" 1 }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "<oidc_provider_name>:sub": "system:serviceaccount:<project_name>:<service_account_name>" 2 } } } ] }- 1
- 将
<oidc_provider_arn> 替换为 OIDC 供应商的 ARN,如arn:aws:iam::<aws_account_id>:oidc-provider/rh-oidc.s3.us-east-1.amazonaws.com/1v3r0n44npxu4g58so46aeohduomfres。 - 2
- 将角色限制为指定的项目和服务帐户。将
<oidc_provider_name> 替换为 OIDC 供应商的名称,如rh-oidc.s3.us-east-1.amazonaws.com/1v3r0n44npxu4g58so46aeohduomfres。将<project_name>:<service_account_name> 替换为您的项目名称和服务帐户名称,如my-project:test-service-account。注意另外,您可以使用 "<
oidc_provider_name>:sub": "system:serviceaccount:<project_name>:*",将角色限制为指定项目内的任何服务帐户。如果提供*通配符,则必须在上一行中将StringEquals替换为StringLike。
创建一个 AWS IAM 角色,它使用
trust-policy.json文件中定义的信任策略:$ aws iam create-role \ --role-name <aws_iam_role_name> \ 1 --assume-role-policy-document file://trust-policy.json 2输出示例:
ROLE arn:aws:iam::<aws_account_id>:role/<aws_iam_role_name> 2022-09-28T12:03:17+00:00 / AQWMS3TB4Z2N3SH7675JK <aws_iam_role_name> ASSUMEROLEPOLICYDOCUMENT 2012-10-17 STATEMENT sts:AssumeRoleWithWebIdentity Allow STRINGEQUALS system:serviceaccount:<project_name>:<service_account_name> PRINCIPAL <oidc_provider_arn>
在输出中为角色保留 ARN。角色 ARN 的格式为
arn:aws:iam::<aws_account_id>:role/<aws_iam_role_name>。附加服务帐户在 pod 中运行 AWS SDK 操作时所需的受管 AWS 权限:
$ aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess \ 1 --role-name <aws_iam_role_name> 2- 可选:在角色中添加自定义属性或权限边界。如需更多信息,请参阅 AWS 文档中的创建角色将权限委派给 AWS 服务。
1.2.2. 在项目中创建服务帐户
在用户定义的项目中添加服务帐户。在服务帐户配置中包含 eks.amazonaws.com/role-arn 注解,该注解引用 AWS Identity and Access Management (IAM)角色的 Amazon Resource Name (ARN)角色。
先决条件
- 您已为您的服务帐户创建 AWS IAM 角色。如需更多信息,请参阅为服务帐户设置 AWS IAM 角色。
- 您可以使用 AWS 安全令牌服务(STS)集群访问 Red Hat OpenShift Service on AWS。不需要 admin 级别用户权限。
-
已安装 OpenShift CLI(
oc)。
流程
在 Red Hat OpenShift Service on AWS 集群中,创建一个项目:
$ oc new-project <project_name> 1- 1
- 将
<project_name> 替换为项目的名称。名称必须与您在 AWS IAM 角色配置中指定的项目名称匹配。
注意在创建时,您将自动切换到项目。
使用以下服务帐户配置,创建名为
test-service-account.yaml的文件:apiVersion: v1 kind: ServiceAccount metadata: name: <service_account_name> 1 namespace: <project_name> 2 annotations: eks.amazonaws.com/role-arn: "<aws_iam_role_arn>" 3
在项目中创建服务帐户:
$ oc create -f test-service-account.yaml
输出示例:
serviceaccount/<service_account_name> created
查看服务帐户的详情:
$ oc describe serviceaccount <service_account_name> 1- 1
- 将
<service_account_name> 替换为服务帐户的名称。
输出示例:
Name: <service_account_name> 1 Namespace: <project_name> 2 Labels: <none> Annotations: eks.amazonaws.com/role-arn: <aws_iam_role_arn> 3 Image pull secrets: <service_account_name>-dockercfg-rnjkq Mountable secrets: <service_account_name>-dockercfg-rnjkq Tokens: <service_account_name>-token-4gbjp Events: <none>
1.2.3. 创建 AWS SDK 容器镜像示例
此流程中的步骤提供了创建包含 AWS SDK 的容器镜像的示例方法。
示例步骤使用 Podman 创建容器镜像和 Quay.io 来托管该镜像。有关 Quay.io 的更多信息,请参阅 Quay.io 入门。容器镜像可用于部署可运行 AWS SDK 操作的 pod。
在本例中,Python 的 AWS Boto3 SDK 安装到容器镜像中。有关安装和使用 AWS Boto3 SDK 的更多信息,请参阅 AWS Boto3 文档。有关其他 AWS SDK 的详情,请参阅 AWS 文档中的 AWS SDK 和工具参考指南。
先决条件
- 您已在安装主机上安装了 Podman。
- 您有一个 Quay.io 用户帐户。
流程
将以下配置添加到名为
Containerfile的文件中:FROM ubi9/ubi 1 RUN dnf makecache && dnf install -y python3-pip && dnf clean all && pip3 install boto3>=1.15.0 2
在包含文件的目录中,构建名为
awsboto3sdk的容器镜像:$ podman build -t awsboto3sdk .
登录到 Quay.io:
$ podman login quay.io
标记镜像以准备上传到 Quay.io:
$ podman tag localhost/awsboto3sdk quay.io/<quay_username>/awsboto3sdk:latest 1- 1
- 将
<quay_username> 替换为您的 Quay.io 用户名。
将标记的容器镜像推送到 Quay.io:
$ podman push quay.io/<quay_username>/awsboto3sdk:latest 1- 1
- 将
<quay_username> 替换为您的 Quay.io 用户名。
创建包含镜像 public 的 Quay.io 存储库。这会发布镜像,以便使用它来在 Red Hat OpenShift Service on AWS 集群中部署 pod:
- 在 https://quay.io/ 上,导航到包含该镜像的存储库的 Repository Settings 页面。
- 单击 Make Public,使存储库公开可用。
1.2.4. 部署包含 AWS SDK 的 pod
从包含 AWS SDK 的容器镜像,在用户定义的项目中部署 pod。在 pod 配置中,指定包含 eks.amazonaws.com/role-arn 注解的服务帐户。
随着服务帐户引用 pod,pod 身份 Webhook 会将 AWS 环境变量、卷挂载和令牌卷注入 pod。pod 变异可让服务帐户在 pod 中自动假设 AWS IAM 角色。
先决条件
- 您已为服务帐户创建了 AWS Identity and Access Management (IAM)角色。如需更多信息,请参阅为服务帐户设置 AWS IAM 角色。
- 您可以访问使用 AWS 安全令牌服务(STS)的 Red Hat OpenShift Service on AWS 集群。不需要 admin 级别用户权限。
-
已安装 OpenShift CLI(
oc)。 -
您已在项目中创建了一个服务帐户,其中包含一个
eks.amazonaws.com/role-arn注解,该注解引用您想要服务帐户的 IAM 角色的 Amazon Resource Name (ARN)。 您有一个包含 AWS SDK 的容器镜像,且镜像可供集群使用。具体步骤请参阅创建示例 AWS SDK 容器镜像。
注意在这个示例中使用 Python 的 AWS Boto3 SDK。有关安装和使用 AWS Boto3 SDK 的更多信息,请参阅 AWS Boto3 文档。有关其他 AWS SDK 的详情,请参阅 AWS 文档中的 AWS SDK 和工具参考指南。
流程
使用以下 pod 配置创建一个名为
awsboto3sdk-pod.yaml的文件:apiVersion: v1 kind: Pod metadata: namespace: <project_name> 1 name: awsboto3sdk 2 spec: serviceAccountName: <service_account_name> 3 containers: - name: awsboto3sdk image: quay.io/<quay_username>/awsboto3sdk:latest 4 command: - /bin/bash - "-c" - "sleep 100000" 5 terminationGracePeriodSeconds: 0 restartPolicy: Never
- 1
- 将
<project_name> 替换为项目的名称。名称必须与您在 AWS IAM 角色配置中指定的项目名称匹配。 - 2
- 指定 pod 的名称。
- 3
- 将 <
service_account_name> 替换为配置为假定 AWS IAM 角色的服务帐户的名称。名称必须与您在 AWS IAM 角色配置中指定的服务帐户名称匹配。 - 4
- 指定
awsboto3sdk容器镜像的位置。将<quay_username> 替换为您的 Quay.io 用户名。 - 5
- 在本例中,此行使 pod 保持运行 100000 秒,以便在 pod 中直接启用验证测试。如需详细的验证步骤,请参阅 pod 中验证假定的 IAM 角色。
部署
awsboto3sdkpod:$ oc create -f awsboto3sdk-pod.yaml
输出示例:
pod/awsboto3sdk created
1.2.5. 在 pod 中验证假定的 IAM 角色
在项目中部署 awsboto3sdk pod 后,验证 pod 身份 Webhook 是否已修改 pod。检查 pod 中是否存在所需的 AWS 环境变量、卷挂载和 OIDC 令牌卷。
您还可以在 pod 中运行 AWS SDK 操作时,验证服务帐户是否假定 AWS 帐户的 AWS Identity and Access Management (IAM)角色。
先决条件
- 您已为您的服务帐户创建 AWS IAM 角色。如需更多信息,请参阅为服务帐户设置 AWS IAM 角色。
- 您可以访问使用 AWS 安全令牌服务(STS)的 Red Hat OpenShift Service on AWS 集群。不需要 admin 级别用户权限。
-
已安装 OpenShift CLI(
oc)。 -
您已在项目中创建了一个服务帐户,其中包含一个
eks.amazonaws.com/role-arn注解,该注解引用您想要服务帐户的 IAM 角色的 Amazon Resource Name (ARN)。 您已在包含 AWS SDK 的用户定义的项目中部署了 pod。pod 引用了使用 pod 身份 Webhook 的服务帐户,以假设运行 AWS SDK 操作所需的 AWS IAM 角色。具体步骤请参阅部署包含 AWS SDK 的 pod。
注意在本例中,使用包括 Python 的 AWS Boto3 SDK 的 pod。有关安装和使用 AWS Boto3 SDK 的更多信息,请参阅 AWS Boto3 文档。有关其他 AWS SDK 的详情,请参阅 AWS 文档中的 AWS SDK 和工具参考指南。
流程
验证 AWS 环境变量、卷挂载和 OIDC 令牌卷是否在部署的
awsboto3sdkpod 的描述中列出:$ oc describe pod awsboto3sdk
输出示例:
Name: awsboto3sdk Namespace: <project_name> ... Containers: awsboto3sdk: ... Environment: AWS_ROLE_ARN: <aws_iam_role_arn> 1 AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token 2 Mounts: /var/run/secrets/eks.amazonaws.com/serviceaccount from aws-iam-token (ro) 3 ... Volumes: aws-iam-token: 4 Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 86400 ...- 1
- 列出由 pod 身份 webhook 注入 pod 的
AWS_ROLE_ARN环境变量。变量包含服务帐户假定的 AWS IAM 角色的 ARN。 - 2
- 列出由 pod 身份 Webhook 注入的
AWS_WEB_IDENTITY_TOKEN_FILE环境变量。变量包含用于验证服务帐户身份的 OIDC 令牌的完整路径。 - 3
- 列出 Pod 身份 Webhook 注入 pod 的卷挂载。
- 4
- 列出挂载到
/var/run/secrets/eks.amazonaws.com/serviceaccount挂载点的aws-iam-token卷。卷包含用于验证服务帐户的 OIDC 令牌,以假定 AWS IAM 角色。
在
awsboto3sdkpod 中启动一个交互式终端:$ oc exec -ti awsboto3sdk -- /bin/sh
在 pod 的交互式终端中,验证 pod 身份 webhook 是否将
$AWS_ROLE_ARN环境变量放入 pod 中:$ echo $AWS_ROLE_ARN
输出示例:
arn:aws:iam::<aws_account_id>:role/<aws_iam_role_name> 1- 1
- 输出必须指定 AWS IAM 角色的 ARN,该角色具有运行 AWS SDK 操作所需的权限。
在 pod 的交互式终端中,验证
$AWS_WEB_IDENTITY_TOKEN_FILE环境变量是否被 pod 身份 webhook 放入 pod 中:$ echo $AWS_WEB_IDENTITY_TOKEN_FILE
输出示例:
/var/run/secrets/eks.amazonaws.com/serviceaccount/token 1- 1
- 输出必须为服务帐户指定 pod 中到 OIDC 令牌的完整路径。
在 pod 的交互式终端中,验证包含 OIDC 令牌文件的
aws-iam-token卷挂载是否由 pod 身份 webhook 挂载:$ mount | grep -is 'eks.amazonaws.com'
输出示例:
tmpfs on /run/secrets/eks.amazonaws.com/serviceaccount type tmpfs (ro,relatime,seclabel,size=13376888k)
在 pod 的交互式终端中,验证
/var/run/secrets/eks.amazonaws.com/serviceaccount/挂载点中是否存在名为token的 OIDC 令牌文件:$ ls /var/run/secrets/eks.amazonaws.com/serviceaccount/token
输出示例:
/var/run/secrets/eks.amazonaws.com/serviceaccount/token 1- 1
aws-iam-token卷中的 OIDC 令牌文件,它由 pod 身份 Webhook 挂载到 pod 中。令牌用于验证 AWS 中服务帐户的身份。
在 pod 中,验证 AWS Boto3 SDK 操作是否已成功运行:
在 pod 的交互式终端中,启动一个 Python 3 shell:
$ python3
在 Python 3 shell 中导入
boto3模块:>>> import boto3
创建包含 Boto3
s3服务资源的变量:>>> s3 = boto3.resource('s3')打印 AWS 帐户中的所有 S3 存储桶的名称:
>>> for bucket in s3.buckets.all(): ... print(bucket.name) ...
输出示例:
<bucket_name> <bucket_name> <bucket_name> ...
如果服务帐户成功假定 AWS IAM 角色,则输出会列出 AWS 帐户中提供的所有 S3 存储桶。
1.3. 其他资源
- 有关在服务帐户中使用 AWS IAM 角色的更多信息,请参阅 AWS 文档中的 服务帐户的 IAM 角色。
- 有关 AWS IAM 角色委托的详情,请参阅 AWS 文档中的创建角色将权限委派给 AWS 服务。
- 有关 AWS SDK 的详情,请参阅 AWS 文档中的 AWS SDK 和工具参考指南。
- 有关为 Python 安装和使用 AWS Boto3 SDK 的更多信息,请参阅 AWS Boto3 文档。
- 如需有关 OpenShift webhook 准入插件的常规信息,请参阅 OpenShift Container Platform 文档中的 Webhook 准入插件。
第 2 章 管理安全性上下文约束
在 Red Hat OpenShift Service on AWS 中,您可以使用安全性上下文约束(SCC)来控制集群中 pod 的权限。
安装期间会创建默认 SCC,安装一些 Operator 或其他组件。作为集群管理员,您还可以使用 OpenShift CLI (oc)创建自己的 SCC。
不要修改默认 SCC。自定义默认 SCC 可能会导致在某些平台 Pod 部署或 ROSA 升级时出现问题。另外,默认 SCC 值会在一些集群升级过程中重置为默认值,这会丢弃对这些 SCC 的所有自定义。
根据需要创建并修改您自己的 SCC,而不是修改默认 SCC。有关详细步骤,请参阅 创建安全性上下文约束。
2.1. 关于安全性上下文约束
与 RBAC 资源控制用户访问的方式类似,管理员可以使用安全性上下文约束(SCC)来控制 Pod 的权限。这些权限决定了 Pod 可以执行的操作以及它们可以访问的资源。您可以使用 SCC 定义 Pod 运行必须满足的一组条件,以便其能被系统接受。
通过安全性上下文约束,管理员可以控制:
-
pod 是否可以使用
allowPrivilegedContainer标志运行特权容器 -
使用
allowPrivilegeEscalation标记限制 pod - 容器可以请求的功能
- 将主机目录用作卷
- 容器的 SELinux 上下文
- 容器用户 ID
- 使用主机命名空间和网络
-
拥有 pod 卷的
FSGroup的分配 - 允许的补充组的配置
- 容器是否需要对其 root 文件系统进行写访问权限
- 卷类型的使用
-
允许的
seccomp配置集的配置
不要在 Red Hat OpenShift Service on AWS 中的任何命名空间上设置 openshift.io/run-level 标签。此标签供内部 Red Hat OpenShift Service on AWS 组件用来管理主要 API 组的启动,如 Kubernetes API 服务器和 OpenShift API 服务器。如果设置了 openshift.io/run-level 标签,则不会将 SCC 应用到该命名空间中的 pod,从而导致该命名空间中运行的任何工作负载都具有高度特权。
2.1.1. 默认安全性上下文约束
集群包含多个默认安全性上下文约束 (SCC),如下表所述。将 Operator 或其他组件安装到 Red Hat OpenShift Service on AWS 时,可能会安装额外的 SCC。
不要修改默认 SCC。自定义默认 SCC 可能会导致在某些平台 Pod 部署或 ROSA 升级时出现问题。另外,默认 SCC 值会在一些集群升级过程中重置为默认值,这会丢弃对这些 SCC 的所有自定义。
根据需要创建并修改您自己的 SCC,而不是修改默认 SCC。有关详细步骤,请参阅 创建安全性上下文约束。
表 2.1. 默认安全性上下文约束
| 安全性上下文约束 | 描述 |
|---|---|
|
|
提供 |
|
| 允许访问所有主机命名空间,但仍要求使用分配至命名空间的 UID 和 SELinux 上下文运行容器集。 警告 此 SCC 允许主机访问命名空间、文件系统和 PID。它应当仅由受信任的容器集使用。请谨慎授予。 |
|
|
提供 警告 此 SCC 允许主机文件系统作为任何 UID 访问,包括 UID 0。请谨慎授予。 |
|
| 允许使用主机网络和主机端口,但仍要求使用分配至命名空间的 UID 和 SELinux 上下文运行容器集。 警告
如果在 control plane 主机上运行额外的工作负载,在提供 |
|
|
与
|
|
| 用于 Prometheus 节点导出器。 警告 此 SCC 允许主机文件系统作为任何 UID 访问,包括 UID 0。请谨慎授予。 |
|
|
提供 |
|
|
与
|
|
| 允许访问所有特权和主机功能,并且能够以任何用户、任何组、任何 FSGroup 以及任何 SELinux 上下文运行。 警告 这是最宽松的 SCC,应仅用于集群管理。请谨慎授予。
注意
在 Pod 规格中设置 |
|
| 拒绝访问所有主机功能,并且要求使用 UID 运行容器集,以及分配至命名空间的 SELinux 上下文。
在从 Red Hat OpenShift Service on AWS 4.10 或更早版本升级的集群中,任何经过验证的用户都可以使用这个 SCC。新 Red Hat OpenShift Service on AWS 4.11 或更高版本的安装用户不再提供 |
|
|
与
这是一个新安装可以提供的最严格的 SCC,经过身份验证的用户会默认使用它。 注意
|
2.1.2. 安全性上下文约束设置
安全性上下文约束 (SCC) 由控制 Pod 可访问的安全功能的设置和策略组成。这些设置分为三个类别:
| 类别 | 描述 |
|---|---|
| 由布尔值控制 |
此类型的字段默认为限制性最强的值。例如, |
| 由允许的集合控制 | 针对集合检查此类型的字段,以确保其值被允许。 |
| 由策略控制 | 具有生成某个值的策略的条目提供以下功能:
|
CRI-O 具有以下默认能力列表,允许用于 pod 的每个容器:
-
CHOWN -
DAC_OVERRIDE -
FSETID -
FOWNER -
SETGID -
SETUID -
SETPCAP -
NET_BIND_SERVICE -
KILL
容器使用此默认列表中的功能,但 Pod 清单作者可以通过请求额外功能或移除某些默认行为来修改列表。使用 allowedCapabilities、defaultAddCapabilities 和 requiredDropCapabilities 参数来控制来自容器集的此类请求。通过这些参数,您可以指定可以请求哪些功能,哪些必须添加到每一个容器,哪些必须被每个容器禁止或丢弃。
您可以通过将 requiredDropCapabilities 参数设置为 ALL 来丢弃容器的所有功能。这是 restricted-v2 SCC 的作用。
2.1.3. 安全性上下文约束策略
RunAsUser
MustRunAs- 需要配置runAsUser。使用配置的runAsUser作为默认值。针对配置的runAsUser进行验证。MustRunAs片断示例... runAsUser: type: MustRunAs uid: <id> ...
MustRunAsRange- 如果不使用预分配值,则需要定义最小值和最大值。使用最小值作为默认值。针对整个允许范围进行验证。MustRunAsRange代码片段示例... runAsUser: type: MustRunAsRange uidRangeMax: <maxvalue> uidRangeMin: <minvalue> ...
MustRunAsNonRoot- 需要 Pod 提交为具有非零runAsUser或具有镜像中定义的USER指令。不提供默认值。MustRunAsNonRoot片断示例... runAsUser: type: MustRunAsNonRoot ...
RunAsAny- 不提供默认值。允许指定任何runAsUser。RunAsAny代码片段示例... runAsUser: type: RunAsAny ...
SELinuxContext
-
MustRunAs- 如果不使用预分配的值,则需要配置seLinuxOptions。使用seLinuxOptions作为默认值。针对seLinuxOptions进行验证。 -
RunAsAny- 不提供默认值。允许指定任何seLinuxOptions。
SupplementalGroups
-
MustRunAs- 如果不使用预分配值,则需要至少指定一个范围。使用第一个范围内的最小值作为默认值。针对所有范围进行验证。 -
RunAsAny- 不提供默认值。允许指定任何supplementalGroups。
FSGroup
-
MustRunAs- 如果不使用预分配值,则需要至少指定一个范围。使用第一个范围内的最小值作为默认值。针对第一个范围内的第一个 ID 进行验证。 -
RunAsAny- 不提供默认值。允许指定任何fsGroupID。
2.1.4. 控制卷
通过设置 SCC 的 volumes 字段,控制特定卷类型的使用。
此字段的允许值与创建卷时定义的卷来源对应:
-
awsElasticBlockStore -
azureDisk -
azureFile -
cephFS -
cinder -
configMap -
csi -
downwardAPI -
emptyDir -
fc -
flexVolume -
flocker -
gcePersistentDisk -
gitRepo -
glusterfs -
hostPath -
iscsi -
nfs -
persistentVolumeClaim -
photonPersistentDisk -
portworxVolume -
projected -
quobyte -
rbd -
scaleIO -
secret -
storageos -
vsphereVolume - *(允许使用所有卷类型的一个特殊值)
-
none(禁止使用所有卷类型的一个特殊值。仅为向后兼容而存在。)
为新 SCC 推荐的允许卷最小集合是 configMap、downAPI、emptyDir、persistentVolumeClaim、secret 和 projected。
允许卷类型列表并不完整,因为每次发布新版 Red Hat OpenShift Service on AWS 时都会添加新的类型。
为向后兼容,使用 allowHostDirVolumePlugin 将覆盖 volumes 字段中的设置。例如,如果 allowHostDirVolumePlugin 设为 false,但在 volumes 字段中是允许,则将移除 volumes 中的 hostPath 值。
2.1.5. 准入控制
利用 SCC 的准入控制可以根据授予用户的能力来控制资源的创建。
就 SCC 而言,这意味着准入控制器可以检查上下文中提供的用户信息以检索一组合适的 SCC。这样做可确保 Pod 具有相应的授权,能够提出与其操作环境相关的请求或生成一组要应用到 Pod 的约束。
准入用于授权 Pod 的 SCC 集合由用户身份和用户所属的组来决定。另外,如果 Pod 指定了服务帐户,则允许的 SCC 集合包括服务帐户可访问的所有约束。
准入使用以下方法来创建 Pod 的最终安全性上下文:
- 检索所有可用的 SCC。
- 为请求上未指定的安全性上下文设置生成字段值。
- 针对可用约束来验证最终设置。
如果找到了匹配的约束集合,则接受 Pod。如果请求不能与 SCC 匹配,则拒绝 Pod。
Pod 必须针对 SCC 验证每一个字段。以下示例中只有其中两个字段必须验证:
这些示例是在使用预分配值的策略上下文中。
FSGroup SCC 策略为 MustRunAs
如果 Pod 定义了 fsGroup ID,该 ID 必须等于默认的 fsGroup ID。否则,Pod 不会由该 SCC 验证,而会评估下一个 SCC。
如果 SecurityContextConstraints.fsGroup 字段的值为 RunAsAny,并且 Pod 规格省略了 Pod.spec.securityContext.fsGroup,则此字段被视为有效。注意在验证过程中,其他 SCC 设置可能会拒绝其他 Pod 字段,从而导致 Pod 失败。
SupplementalGroups SCC 策略为 MustRunAs
如果 Pod 规格定义了一个或多个 supplementalGroups ID,则 Pod 的 ID 必须等于命名空间的 openshift.io/sa.scc.supplemental-groups 注解中的某一个 ID。否则,Pod 不会由该 SCC 验证,而会评估下一个 SCC。
如果 SecurityContextConstraints.supplementalGroups 字段的值为 RunAsAny,并且 Pod 规格省略了 Pod.spec.securityContext.supplementalGroups,则此字段被视为有效。注意在验证过程中,其他 SCC 设置可能会拒绝其他 Pod 字段,从而导致 Pod 失败。
2.1.6. 安全性上下文约束优先级
安全性上下文约束 (SCC) 具有一个优先级字段,它会影响准入控制器尝试验证请求时的排序。
优先级值为 0 是最低优先级。nil 优先级被视为 0 或最低优先级。在排序时,优先级更高的 SCC 会被移到集合的前面。
确定了一组可用 SCC 后,SCC 会按照以下方式排序:
- 最高优先级 SCC 首先排序。
- 如果优先级相等,则 SCC 按照限制性最强到最强的限制进行排序。
- 如果优先级和限制都相等,则 SCC 按照名称排序。
默认情况下,授权给集群管理员的 anyuid SCC 在 SCC 集合中具有优先权。这允许集群管理员通过在 Pod 的 SecurityContext 中指定 RunAsUser,以任何用户身份运行 Pod。
2.2. 关于预分配安全性上下文约束值
准入控制器清楚安全性上下文约束 (SCC) 中的某些条件,这些条件会触发它从命名空间中查找预分配值并在处理 Pod 前填充 SCC。每个 SCC 策略都独立于其他策略进行评估,每个策略的预分配值(若为允许)与 Pod 规格值聚合,为运行中 Pod 中定义的不同 ID 生成最终值。
以下 SCC 导致准入控制器在 Pod 规格中没有定义范围时查找预分配值:
-
RunAsUser策略为MustRunAsRange且未设置最小或最大值。准入查找openshift.io/sa.scc.uid-range注解来填充范围字段。 -
SELinuxContext策略为MustRunAs且未设定级别。准入查找openshift.io/sa.scc.mcs注解来填充级别。 -
FSGroup策略为MustRunAs。准入查找openshift.io/sa.scc.supplemental-groups注解。 -
SupplementalGroups策略为MustRunAs。准入查找openshift.io/sa.scc.supplemental-groups注解。
在生成阶段,安全性上下文提供程序会对 Pod 中未具体设置的参数值使用默认值。默认值基于所选的策略:
-
RunAsAny和MustRunAsNonRoot策略不提供默认值。如果 Pod 需要参数值,如组 ID,您必须在 Pod 规格中定义这个值。 -
MustRunAs(单值)策略提供始终使用的默认值。例如,对于组 ID,即使 Pod 规格定义了自己的 ID 值,命名空间的默认参数值也会出现在 Pod 的组中。 -
MustRunAsRange和MustRunAs(基于范围)策略提供范围的最小值。与单值MustRunAs策略一样,命名空间的默认参数值出现在运行的 Pod 中。如果基于范围的策略可以配置多个范围,它会提供配置的第一个范围的最小值。
如果命名空间上不存在 openshift.io/sa.scc.supplemental-groups 注解,则 FSGroup 和 SupplementalGroups 策略回退到 openshift.io/sa.scc.uid-range 注解。如果两者都不存在,则不创建 SCC。
默认情况下,基于注解的 FSGroup 策略使用基于注解的最小值的单个范围来配置其自身。例如,如果您的注解显示为 1/3,则 FSGroup 策略使用最小值和最大值 1 配置其自身。如果要允许 FSGroup 字段接受多个组,可以配置不使用注解的自定义 SCC。
openshift.io/sa.scc.supplemental-groups 注解接受以逗号分隔的块列表,格式为 <start>/<length 或 <start>-<end>。openshift.io/sa.scc.uid-range 注解只接受一个块。
2.3. 安全性上下文约束示例
以下示例演示了安全性上下文约束 (SCC) 格式和注解:
注解 privileged SCC
allowHostDirVolumePlugin: true allowHostIPC: true allowHostNetwork: true allowHostPID: true allowHostPorts: true allowPrivilegedContainer: true allowedCapabilities: 1 - '*' apiVersion: security.openshift.io/v1 defaultAddCapabilities: [] 2 fsGroup: 3 type: RunAsAny groups: 4 - system:cluster-admins - system:nodes kind: SecurityContextConstraints metadata: annotations: kubernetes.io/description: 'privileged allows access to all privileged and host features and the ability to run as any user, any group, any fsGroup, and with any SELinux context. WARNING: this is the most relaxed SCC and should be used only for cluster administration. Grant with caution.' creationTimestamp: null name: privileged priority: null readOnlyRootFilesystem: false requiredDropCapabilities: 5 - KILL - MKNOD - SETUID - SETGID runAsUser: 6 type: RunAsAny seLinuxContext: 7 type: RunAsAny seccompProfiles: - '*' supplementalGroups: 8 type: RunAsAny users: 9 - system:serviceaccount:default:registry - system:serviceaccount:default:router - system:serviceaccount:openshift-infra:build-controller volumes: 10 - '*'
- 1
- Pod 可以请求的功能列表。空列表表示不允许请求任何功能,而特殊符号
*则允许任何功能。 - 2
- 添加至任何 Pod 的附加功能列表。
- 3
FSGroup策略,指明安全性上下文的允许值。- 4
- 可访问此 SCC 的组。
- 5
- 从 pod 丢弃的功能列表。或者,指定
ALL以丢弃所有功能。 - 6
runAsUser策略类型,指明安全上下文的允许值。- 7
seLinuxContext策略类型,指明安全上下文的允许值。- 8
supplementalGroups策略,指明安全上下文的允许补充组。- 9
- 可访问此 SCC 的用户。
- 10
- 安全上下文允许的卷类型。在这个示例中,
*允许使用所有卷类型。
SCC 中的 users 和 groups 字段控制能够访问该 SCC 的用户。默认情况下,集群管理员、节点和构建控制器被授予特权 SCC 的访问权限。所有经过身份验证的用户都授予了访问 restricted-v2 的权限。
无显式 runAsUser 设置
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext: 1
containers:
- name: sec-ctx-demo
image: gcr.io/google-samples/node-hello:1.0
- 1
- 当容器或 Pod 没有指定应运行它的用户 ID 时,则生效的 UID 由发出此 Pod 的 SCC 决定。由于在默认情况下,
restricted-v2SCC 会授权给所有经过身份验证的用户,所以它可供所有用户和服务帐户使用,并在大多数情形中使用。restricted-v2SCC 使用MustRunAsRange策略来约束并默认分配securityContext.runAsUser字段的可能值。准入插件会在当前项目上查找openshift.io/sa.scc.uid-range注解来填充范围字段,因为它不提供此范围。最后,容器的runAsUser值等于这一范围中的第一个值,而这难以预测,因为每个项目都有不同的范围。
带有显式 runAsUser 设置
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000 1
containers:
- name: sec-ctx-demo
image: gcr.io/google-samples/node-hello:1.0
- 1
- 只有服务帐户或用户被授予对允许某一用户 ID 的 SCC 访问权限时,Red Hat OpenShift Service on AWS 才会接受请求该用户 ID 的容器或 Pod。SCC 允许任意 ID、属于某一范围的 ID,或特定于请求的确切用户 ID。
此配置对 SELinux、fsGroup 和补充组有效。
2.4. 创建安全性上下文约束
您可以使用 OpenShift CLI(oc)创建安全性上下文约束(SCC)。
创建和修改您自己的 SCC 是可能导致集群不稳定的高级操作。如果您对使用自己的 SCC 有疑问,请联系红帽支持。有关联系红帽支持的详情,请参考 获取支持。
先决条件
-
安装 OpenShift CLI (
oc) 。 -
以具有
cluster-admin角色的用户身份登录集群。
流程
在名为
scc-admin.yaml的 YAML 文件中定义 SCC:kind: SecurityContextConstraints apiVersion: security.openshift.io/v1 metadata: name: scc-admin allowPrivilegedContainer: true runAsUser: type: RunAsAny seLinuxContext: type: RunAsAny fsGroup: type: RunAsAny supplementalGroups: type: RunAsAny users: - my-admin-user groups: - my-admin-group
另外,您可以通过将
requiredDropCapabilities字段设为所需的值来丢弃 SCC 的特定功能。所有指定的功能都会从容器中丢弃。要丢弃所有的能力,请指定ALL。例如,要创建一个丢弃KILL、MKNOD和SYS_CHROOT功能的 SCC,请将以下内容添加到 SCC 对象中:requiredDropCapabilities: - KILL - MKNOD - SYS_CHROOT
注意您不能列出
allowedCapabilities和requiredDropCapabilities中的功能。CRI-O 支持 Docker 文档中找到的相同功能值列表。
通过传递文件来创建 SCC:
$ oc create -f scc-admin.yaml
输出示例
securitycontextconstraints "scc-admin" created
验证
验证 SCC 已创建好:
$ oc get scc scc-admin
输出示例
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP PRIORITY READONLYROOTFS VOLUMES scc-admin true [] RunAsAny RunAsAny RunAsAny RunAsAny <none> false [awsElasticBlockStore azureDisk azureFile cephFS cinder configMap downwardAPI emptyDir fc flexVolume flocker gcePersistentDisk gitRepo glusterfs iscsi nfs persistentVolumeClaim photonPersistentDisk quobyte rbd secret vsphere]
2.5. 基于角色的对安全性上下文限制的访问
您可以将 SCC 指定为由 RBAC 处理的资源。这样,您可以将对 SCC 访问的范围限定为某一项目或整个集群。直接将用户、组或服务帐户分配给 SCC 可保留整个集群的范围。
您无法将 SCC 分配给在以下某一默认命名空间中创建的 Pod: default、kube-system、kube-public、openshift-node、openshift-infra、openshift。这些命名空间不应用于运行 pod 或服务。
要使您的角色包含对 SCC 的访问,请在创建角色时指定 scc 资源。
$ oc create role <role-name> --verb=use --resource=scc --resource-name=<scc-name> -n <namespace>
这会生成以下角色定义:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: ... name: role-name 1 namespace: namespace 2 ... rules: - apiGroups: - security.openshift.io 3 resourceNames: - scc-name 4 resources: - securitycontextconstraints 5 verbs: 6 - use
当本地或集群角色具有这样的规则时,通过 RoleBinding 或 ClusterRoleBinding 与其绑定的主体可以使用用户定义的 SCC scc-name。
由于 RBAC 旨在防止升级,因此即使项目管理员也无法授予 SCC 访问权限。默认情况下,不允许他们对 SCC 资源使用操作动词 use,包括 restricted-v2 SCC。
2.6. 安全性上下文约束命令参考
您可以使用 OpenShift CLI (oc) 将实例中的安全性上下文约束 (SCC) 作为常规 API 对象进行管理。
2.6.1. 列出安全性上下文约束
获取当前的 SCC 列表:
$ oc get scc
输出示例
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP PRIORITY READONLYROOTFS VOLUMES anyuid false <no value> MustRunAs RunAsAny RunAsAny RunAsAny 10 false ["configMap","downwardAPI","emptyDir","persistentVolumeClaim","projected","secret"] hostaccess false <no value> MustRunAs MustRunAsRange MustRunAs RunAsAny <no value> false ["configMap","downwardAPI","emptyDir","hostPath","persistentVolumeClaim","projected","secret"] hostmount-anyuid false <no value> MustRunAs RunAsAny RunAsAny RunAsAny <no value> false ["configMap","downwardAPI","emptyDir","hostPath","nfs","persistentVolumeClaim","projected","secret"] hostnetwork false <no value> MustRunAs MustRunAsRange MustRunAs MustRunAs <no value> false ["configMap","downwardAPI","emptyDir","persistentVolumeClaim","projected","secret"] hostnetwork-v2 false ["NET_BIND_SERVICE"] MustRunAs MustRunAsRange MustRunAs MustRunAs <no value> false ["configMap","downwardAPI","emptyDir","persistentVolumeClaim","projected","secret"] node-exporter true <no value> RunAsAny RunAsAny RunAsAny RunAsAny <no value> false ["*"] nonroot false <no value> MustRunAs MustRunAsNonRoot RunAsAny RunAsAny <no value> false ["configMap","downwardAPI","emptyDir","persistentVolumeClaim","projected","secret"] nonroot-v2 false ["NET_BIND_SERVICE"] MustRunAs MustRunAsNonRoot RunAsAny RunAsAny <no value> false ["configMap","downwardAPI","emptyDir","persistentVolumeClaim","projected","secret"] privileged true ["*"] RunAsAny RunAsAny RunAsAny RunAsAny <no value> false ["*"] restricted false <no value> MustRunAs MustRunAsRange MustRunAs RunAsAny <no value> false ["configMap","downwardAPI","emptyDir","persistentVolumeClaim","projected","secret"] restricted-v2 false ["NET_BIND_SERVICE"] MustRunAs MustRunAsRange MustRunAs RunAsAny <no value> false ["configMap","downwardAPI","emptyDir","persistentVolumeClaim","projected","secret"]
2.6.2. 检查安全性上下文约束
您可以查看特定 SCC 的信息,包括这个 SCC 应用到哪些用户、服务帐户和组。
例如,检查 restricted SCC:
$ oc describe scc restricted
输出示例
Name: restricted Priority: <none> Access: Users: <none> 1 Groups: <none> 2 Settings: Allow Privileged: false Allow Privilege Escalation: true Default Add Capabilities: <none> Required Drop Capabilities: KILL,MKNOD,SETUID,SETGID Allowed Capabilities: <none> Allowed Seccomp Profiles: <none> Allowed Volume Types: configMap,downwardAPI,emptyDir,persistentVolumeClaim,projected,secret Allowed Flexvolumes: <all> Allowed Unsafe Sysctls: <none> Forbidden Sysctls: <none> Allow Host Network: false Allow Host Ports: false Allow Host PID: false Allow Host IPC: false Read Only Root Filesystem: false Run As User Strategy: MustRunAsRange UID: <none> UID Range Min: <none> UID Range Max: <none> SELinux Context Strategy: MustRunAs User: <none> Role: <none> Type: <none> Level: <none> FSGroup Strategy: MustRunAs Ranges: <none> Supplemental Groups Strategy: RunAsAny Ranges: <none>