在使用 AWS 安全令牌服务 (STS) 的 Red Hat OpenShift Service on AWS 集群中,可以启用 OpenShift API 服务器来投射签名的服务帐户令牌,这些令牌可用于在 Pod 中承担 AWS 身份和访问管理 (IAM) 角色。如果承担的 IAM 角色具有所需的 AWS 权限,则 Pod 可以使用临时 STS 凭证对 AWS API 进行身份验证以执行 AWS 操作。
您可以使用 Pod 身份 Webhook 来投射服务帐户令牌以承担您自己工作负载的 AWS 身份和访问管理 (IAM) 角色。如果承担的 IAM 角色具有所需的 AWS 权限,则 Pod 可以使用临时 STS 凭证运行 AWS SDK 操作。
当您安装使用 AWS 安全令牌服务 (STS) 的 Red Hat OpenShift Service on AWS 集群时,会创建集群特定的 Operator AWS 身份和访问管理 (IAM) 角色。这些 IAM 角色允许 Red Hat OpenShift Service on AWS 集群 Operator 运行核心 OpenShift 功能。
集群 Operator 使用服务帐户来承担 IAM 角色。当服务帐户承担 IAM 角色时,会为服务帐户提供临时 STS 凭证,供其在集群 Operator 的 Pod 中使用。如果承担的角色具有必要的 AWS 权限,则服务帐户可以在 Pod 中运行 AWS SDK 操作。
下图说明了在 SRE 拥有的项目中承担 AWS IAM 角色的工作流程
此工作流程包含以下阶段
在集群 Operator 运行的每个项目中,Operator 的部署规范都具有用于投射的服务帐户令牌的卷挂载,以及包含 Pod 的 AWS 凭据配置的密钥。令牌是面向受众的且有时限的。每小时,Red Hat OpenShift Service on AWS 都会生成一个新令牌,AWS SDK 会读取包含 AWS 凭据配置的已挂载密钥。此配置具有指向已挂载令牌和 AWS IAM 角色 ARN 的路径。密钥的凭据配置包含以下内容:
一个$AWS_ARN_ROLE
变量,其中包含具有运行 AWS SDK 操作所需权限的 IAM 角色的 ARN。
一个$AWS_WEB_IDENTITY_TOKEN_FILE
变量,其中包含 Pod 中服务帐户的 OpenID Connect (OIDC) 令牌的完整路径。完整路径为/var/run/secrets/openshift/serviceaccount/token
。
当集群 Operator 需要承担 AWS IAM 角色以访问 AWS 服务(例如 EC2)时,在 Operator 上运行的 AWS SDK 客户端代码会调用AssumeRoleWithWebIdentity
API 调用。
OIDC 令牌从 Pod 传递到 OIDC 提供程序。如果满足以下要求,提供程序将验证服务帐户身份:
身份签名有效且由私钥签名。
sts.amazonaws.com
受众列在 OIDC 令牌中,并与 OIDC 提供程序中配置的受众匹配。
在使用 STS 集群的 Red Hat OpenShift Service on AWS 中,OIDC 提供程序在安装期间创建,并默认设置为服务帐户发行者。 |
OIDC 令牌未过期。
令牌中的发行者值具有 OIDC 提供程序的 URL。
如果项目和服务帐户在要承担的 IAM 角色的信任策略范围内,则授权成功。
身份验证和授权成功后,AWS 访问令牌、密钥和会话令牌形式的临时 AWS STS 凭证将传递到 Pod,供服务帐户使用。通过使用这些凭证,服务帐户将临时授予 IAM 角色中启用的 AWS 权限。
集群操作符运行时,pod中使用AWS SDK的操作符会使用包含投影服务账户路径和AWS IAM角色ARN的密钥,以便向OIDC提供商进行身份验证。OIDC提供商会返回临时STS凭证,用于向AWS API进行身份验证。
当您在使用AWS安全令牌服务(STS)的AWS集群上安装Red Hat OpenShift Service时,pod身份webhook资源会默认包含。
您可以使用pod身份webhook启用用户定义项目中的服务账户,以便在同一项目中的pod中承担AWS身份和访问管理(IAM)角色。承担IAM角色后,会提供临时STS凭证供pod中的服务账户使用。如果承担的角色具有必要的AWS权限,则服务账户可以在pod中运行AWS SDK操作。
要为pod启用pod身份webhook,您必须在项目中创建一个带有eks.amazonaws.com/role-arn
注解的服务账户。该注解必须引用您希望服务账户承担的AWS IAM角色的Amazon资源名称(ARN)。您还必须在您的Pod
规范中引用服务账户,并在与服务账户相同的项目中部署pod。
下图说明了用户定义项目中的pod身份webhook工作流程
此工作流程包含以下阶段
在用户定义的项目中,用户创建一个包含eks.amazonaws.com/role-arn
注解的服务账户。该注解指向您希望服务账户承担的AWS IAM角色的ARN。
当使用引用带注解的服务账户的配置在同一项目中部署pod时,pod身份webhook会修改pod。修改会在pod中注入以下组件,而无需在您的Pod
或Deployment
资源配置中指定它们:
一个包含IAM角色ARN的$AWS_ARN_ROLE
环境变量,该角色具有运行AWS SDK操作所需的权限。
一个包含服务账户OpenID Connect (OIDC)令牌在pod中的完整路径的$AWS_WEB_IDENTITY_TOKEN_FILE
环境变量。完整路径为/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 集群的 Red Hat OpenShift Service on AWS 中,OIDC 提供程序在安装期间创建,并默认设置为服务帐户发行者。 |
OIDC 令牌未过期。
令牌中的发行者值包含OIDC提供商的URL。
如果项目和服务帐户在要承担的 IAM 角色的信任策略范围内,则授权成功。
身份验证和授权成功后,将以会话令牌的形式将临时AWS STS凭证传递给pod,供服务账户使用。通过使用这些凭证,服务账户将临时授予IAM角色中启用的AWS权限。
在pod中运行AWS SDK操作时,服务账户会将临时STS凭证提供给AWS API以验证其身份。
请按照本节中的步骤启用服务账户,以便在用户定义项目中部署的pod中承担AWS身份和访问管理(IAM)角色。
您可以创建所需的资源,包括AWS IAM角色、服务账户、包含AWS SDK的容器镜像以及使用该镜像部署的pod。在本例中,使用了AWS Boto3 SDK for Python。您还可以验证pod身份webhook是否将AWS环境变量、卷挂载和令牌卷修改到您的pod中。此外,您可以检查服务账户是否在您的pod中承担了AWS IAM角色,并能否成功运行AWS SDK操作。
创建一个AWS身份和访问管理(IAM)角色,由您在AWS上的Red Hat OpenShift Service集群中的服务账户承担。附加服务账户在pod中运行AWS SDK操作所需的权限。
您拥有在您的AWS账户中安装和配置IAM角色所需的权限。
您可以访问使用AWS安全令牌服务(STS)的Red Hat OpenShift Service on AWS集群。不需要管理员级用户权限。
您拥有在您的使用STS的Red Hat OpenShift Service on AWS集群中配置为服务账户发行者的OpenID Connect (OIDC)提供商的Amazon资源名称(ARN)。
在使用STS的Red Hat OpenShift Service on AWS集群中,OIDC提供商在安装期间创建,并默认设置为服务账户发行者。如果您不知道OIDC提供商ARN,请联系您的集群管理员。 |
您已安装AWS CLI (aws
)。
创建一个名为trust-policy.json
的文件,其中包含以下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 。
|
创建一个使用trust-policy.json
文件中定义的信任策略的AWS IAM角色
$ aws iam create-role \
--role-name <aws_iam_role_name> \ (1)
--assume-role-policy-document file://trust-policy.json (2)
1 | 将<aws_iam_role_name> 替换为您的IAM角色的名称,例如pod-identity-test-role 。 |
2 | 引用您在上一步中创建的trust-policy.json 文件。 |
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)
1 | 此示例中的策略向IAM角色添加只读访问权限。 |
2 | 将<aws_iam_role_name> 替换为在上一步中创建的IAM角色的名称。 |
可选:向角色添加自定义属性或权限边界。有关更多信息,请参阅AWS文档中的创建角色以将权限委派给AWS服务。
在您的用户定义项目中添加一个服务账户。在服务账户配置中包含一个eks.amazonaws.com/role-arn
注解,该注解引用您希望服务账户承担的AWS身份和访问管理(IAM)角色的Amazon资源名称(ARN)。
您已为您的服务帐户创建了一个 AWS IAM 角色。有关更多信息,请参阅为服务帐户设置 AWS IAM 角色。
您可以访问在 AWS 上运行的 Red Hat OpenShift 服务,该服务具有 AWS 安全令牌服务 (STS) 集群。不需要管理员级用户权限。
您已安装 OpenShift CLI (oc
)。
在您在 AWS 上运行的 Red Hat OpenShift 服务集群中,创建一个项目。
$ 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)
1 | 将<service_account_name> 替换为您服务帐户的名称。此名称必须与您在 AWS IAM 角色配置中指定的帐户名称匹配。 |
2 | 将<project_name> 替换为您项目的名称。此名称必须与您在 AWS IAM 角色配置中指定的项目名称匹配。 |
3 | 指定服务帐户在 Pod 中使用的 AWS IAM 角色的 ARN。将<aws_iam_role_arn> 替换为您为服务帐户创建的 AWS IAM 角色的 ARN。角色 ARN 的格式为arn:aws:iam::<aws_account_id>:role/<aws_iam_role_name> 。 |
在您的项目中创建服务帐户。
$ 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 IAM 角色的 ARN 的注释。 |
此步骤中的步骤提供了一种创建包含 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)
1 | 指定 Red Hat 通用基础镜像版本 9。 |
2 | 使用pip 包管理系统安装 AWS Boto3 SDK。在此示例中,安装 AWS Boto3 SDK 版本 1.15.0 或更高版本。 |
从包含该文件的目录中,构建名为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 用户名。 |
将包含镜像的 Quay.io 仓库设为公开。这会发布镜像,以便可以将其用于在您在 AWS 上运行的 Red Hat OpenShift 服务集群中部署 Pod。
在https://quay.io/上,导航到包含镜像的仓库的**仓库设置**页面。
单击**设为公开**以公开仓库。
从包含 AWS SDK 的容器镜像中,在用户定义的项目中部署 Pod。在您的 Pod 配置中,指定包含eks.amazonaws.com/role-arn
注释的服务帐户。
为您的 Pod 设置服务帐户引用后,Pod 身份 Webhook 会将 AWS 环境变量、卷挂载和令牌卷注入到您的 Pod 中。Pod 变异使服务帐户能够自动在 Pod 中承担 AWS IAM 角色。
您已为您的服务帐户创建了一个 AWS 身份和访问管理 (IAM) 角色。有关更多信息,请参阅为服务帐户设置 AWS IAM 角色。
您可以访问使用AWS安全令牌服务(STS)的Red Hat OpenShift Service on AWS集群。不需要管理员级用户权限。
您已安装 OpenShift CLI (oc
)。
您已在您的项目中创建了一个服务帐户,其中包含一个eks.amazonaws.com/role-arn
注释,该注释引用您希望服务帐户承担的 IAM 角色的 Amazon 资源名称 (ARN)。
您拥有一个包含 AWS SDK 的容器镜像,并且该镜像可用于您的集群。有关详细步骤,请参阅创建示例 AWS SDK 容器镜像。
在此示例过程中,使用了 Python 的 AWS Boto3 SDK。有关安装和使用 AWS Boto3 SDK 的更多信息,请参阅AWS Boto3 文档。有关其他 AWS SDK 的详细信息,请参阅 AWS 文档中的AWS SDK 和工具参考指南。 |
创建一个名为awsboto3sdk-pod.yaml
的文件,其中包含以下 Pod 配置。
apiVersion: v1
kind: Pod
metadata:
namespace: <project_name> (1)
name: awsboto3sdk (2)
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
serviceAccountName: <service_account_name> (3)
containers:
- name: awsboto3sdk
image: quay.io/<quay_username>/awsboto3sdk:latest (4)
command:
- /bin/bash
- "-c"
- "sleep 100000" (5)
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
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 配置中,此行使 Pod 运行 100000 秒,以便可以直接在 Pod 中进行验证测试。有关详细的验证步骤,请参阅验证 Pod 中承担的 IAM 角色。 |
部署awsboto3sdk
Pod。
$ oc create -f awsboto3sdk-pod.yaml
pod/awsboto3sdk created
在您的项目中部署awsboto3sdk
Pod 后,验证 Pod 身份 Webhook 是否已变异 Pod。检查 Pod 中是否存在所需的 AWS 环境变量、卷挂载和 OIDC 令牌卷。
您还可以验证在 Pod 中运行 AWS SDK 操作时,服务帐户是否承担 AWS 身份和访问管理 (IAM) 角色。
您已为您的服务帐户创建了一个 AWS IAM 角色。有关更多信息,请参阅为服务帐户设置 AWS IAM 角色。
您可以访问使用AWS安全令牌服务(STS)的Red Hat OpenShift Service on AWS集群。不需要管理员级用户权限。
您已安装 OpenShift CLI (oc
)。
您已在您的项目中创建了一个服务帐户,其中包含一个eks.amazonaws.com/role-arn
注释,该注释引用您希望服务帐户承担的 IAM 角色的 Amazon 资源名称 (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 令牌卷是否已列在已部署的awsboto3sdk
Pod 的描述中。
$ 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 注入到 Pod 中的AWS_WEB_IDENTITY_TOKEN_FILE 环境变量。该变量包含用于验证服务帐户身份的 OIDC 令牌的完整路径。 |
3 | 列出 Pod 身份 Webhook 注入到 Pod 中的卷挂载。 |
4 | 列出挂载到/var/run/secrets/eks.amazonaws.com/serviceaccount 挂载点的aws-iam-token 卷。该卷包含用于对服务帐户进行身份验证以承担 AWS IAM 角色的 OIDC 令牌。 |
在awsboto3sdk
Pod 中启动一个交互式终端。
$ 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 SDK 操作所需权限的 AWS IAM 角色的 ARN。 |
在 Pod 的交互式终端中,验证 pod 身份 webhook 是否已将$AWS_WEB_IDENTITY_TOKEN_FILE
环境变量变异到 Pod 中。
$ echo $AWS_WEB_IDENTITY_TOKEN_FILE
/var/run/secrets/eks.amazonaws.com/serviceaccount/token (1)
1 | 输出必须指定 Pod 中服务帐户 OIDC 令牌的完整路径。 |
在 Pod 的交互式终端中,验证 pod 身份 webhook 是否已挂载包含 OIDC 令牌文件的aws-iam-token
卷挂载。
$ 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 | pod 身份 webhook 挂载到 Pod 中的aws-iam-token 卷中的 OIDC 令牌文件。该令牌用于验证服务帐户在 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 存储桶。
有关将 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 准入插件。