使用 IAM 角色将您的本地 Kubernetes 集群连接到亚马逊云科技API

作者: 瓦伦·夏尔马, Nishant Mainro, Roshini Jagarapu |

许多客户希望将其本地 Kubernetes 工作负载与亚马逊云科技服务无缝集成、实施混合工作负载或迁移到亚马逊云科技。以前,一种常见的方法是创建长期访问密钥,这会带来安全风险,因此不再推荐使用。尽管存在诸如Kubernetes机密库和第三方选项之类的解决方案,但它们无法有效解决潜在问题。

将您的本地 Kubernetes 工作负载连接到亚马逊云科技API 的一种选择是使用服务账户发放者发现功能。这允许 Kubernetes API 服务器充当 OpenID Connect (OIDC) 身份提供商,并与 Amazon Identity and Access Management (IAM) 联合。但是,这种方法需要公共互联网访问Kubernetes API服务器,这对于某些客户来说可能并不理想。

为了帮助消除对长期访问密钥的需求或将Kubernetes API服务器暴露给公共互联网,亚马逊云科技在任何地方引入了Amazon IAM角色。此功能支持将本地 Kubernetes 工作负载与亚马逊云科技服务安全无缝集成,从而促进稳健的安全实践,并最大限度地降低与长期凭证或公开风险相关的潜在风险。

IAM Roles Anywhere 通过将 X.509 绑定身份交换为临时亚马逊云科技证书,使亚马逊云科技以外的工作负载能够访问亚马逊云科技资源。借助 IAM 角色随处可见,您可以使用与亚马逊云科技工作负载相同的 IAM 角色和策略来访问亚马逊云科技资源,从而提高一致性。

任何地方的 IAM 角色都可以与标准公钥基础设施解决方案相结合。在这篇博文中,我们使用了亚马逊云科技私有证书颁发机构 (Private Certificate Authority),与使用自签名证书颁发机构 (CA) 相比,它有几个优点。首先,它减少了运营和管理开销,因为亚马逊云科技会为您管理 CA。其次,加密密钥材料可以存储在硬件安全模块中,也可以至少存储在保险库中,这可以帮助您保护您的私有CA免受密钥泄露的影响。此外,证书的有效期可能很短,这与动态 Kubernetes 环境一致,在这些环境中,pod 的生命周期通常比传统服务器短。

我们还演示了如何在不修改现有工作负载 Docker 文件的情况下随时随地集成 IAM 角色,以及如何在短期证书模式下使用证书管理器和亚马逊云科技私有 CA 后端自动执行 X.509 证书生命周期。通过使用这些功能,您可以将本地 Kubernetes 工作负载与亚马逊云科技服务无缝集成,推广稳健的安全实践,最大限度地降低与长期证书相关的风险,并帮助确保简化、一致的访问管理体验。

这篇文章适用于在不使用亚马逊 EKS Anywhere 的情况下在亚马逊云科技之外运行自己的 Kubernetes 集群的客户。如果你使用的是亚马逊 Elastic Kubernetes Service(亚马逊 EKS),请改为使用服务账户的 IAM 角色或亚马逊 EKS Pod Identity。

背景

“为什么我应该更喜欢 X.509 证书而不是 IAM 访问密钥?”访问密钥是长期证书,必须定期轮换,以最大限度地降低未经授权访问的风险。它们需要安全地部署到托管使用它们的应用程序的服务器上,这需要执行安全传输和删除临时副本的程序。随着应用程序和访问密钥数量的增加,跟踪和管理它们在操作上变得非常困难。

相比之下,X.509 证书使用公钥基础架构 (PKI)。私钥直接在应用服务器上生成,不会离开。只有不包含机密的证书签名请求会发送到 CA 进行签名并返回证书。这减轻了对安全传输密钥的需求。

但是,你可以争辩说,X.509 证书也是长期的证书。这种担忧是有道理的,但不一定是正确的。正如 Let's Encrypt 等项目所证明的那样,通过实现证书续订自动化,可以将证书的有效期从几年缩短到几个月。在这样的机制到位后,证书的有效期可以进一步限制为几天甚至几小时。

在这篇文章中,我们介绍了相互验证的传输层安全性 (mTL),它使用证书进行高保障的双向身份验证。证书用于在客户端和服务器之间建立信任,确保双方都经过身份验证并获得安全通信的授权。通过实施 mTLS,您可以提高通信渠道的安全性和信任度,降低与未经授权的访问或中间人攻击相关的潜在风险。在这里,我们实现了与 pod 生命周期相关的临时证书。当 pod 启动时,会自动创建证书,证书将在短时间后过期,除非 pod 正在积极使用该证书,在这种情况下,证书管理器会自动续订。这种方法可以验证证书仅在 pod 的生命周期内有效,从而最大限度地降低了与长期证书相关的潜在风险。此外,IAM Roles Anywhere 支持证书吊销列表 (CRL) 检查,允许您在需要时明确撤销证书。此功能提供了额外的安全层,使您能够在凭据泄露或其他安全问题时立即撤消访问权限。

在本文中,我们假设您对任何地方的 IAM 角色都有基本的了解。有关更多信息,您可以查看这篇博客文章。此外,我们假设你熟悉 Kubernetes、kubectl Helm 和 cert-manager。

解决方案概述

该解决方案假设你有一个在亚马逊云科技之外运行的现有 Kubernetes 集群。

图 1 显示了我们解决方案的高级架构。本地 Kubernetes 集群使用 IAM 角色随时随地访问亚马逊云科技API,使用亚马逊云科技私有 CA 颁发的 X.509 证书,采用短期证书模式。

图 1:访问 AWS API 的本地 Kubernetes 的高级架构

图 1:访问亚马逊云科技API 的本地 Kubernetes 的高级架构

该解决方案的工作原理如下,如图 1 所示:

  1. 处于短期证书模式的亚马逊云科技私有 CA 会为您的 pod 颁发 X.509 证书。
  2. 当您将亚马逊云科技私有 CA 设置为可信来源并建立特定配置文件时,IAM Roles Anywhere 将验证并接受使用您的亚马逊云科技私有 CA 颁发的证书的身份验证请求。
  3. 证书管理器部署到您的 Kubernetes 集群中,负责协调向授权的 pod 颁发亚马逊云科技私有 CA 证书的过程。
  4. 每个 pod 都使用 IAM 角色随时随地使用其私钥和从证书管理器获得的 X.509 证书创建亚马逊云科技会话。

让我们更详细地探索架构的不同部分。

亚马逊云科技私有 CA 短期证书

亚马逊云科技Private CA 提供短期证书,其有效期限制为 7 天或更短。您可以查看此亚马逊云科技博客,了解如何使用亚马逊云科技私有 CA 短期证书。这种新模式可用于为您的 Kubernetes pod 颁发证书,并受益于更低的运营成本。通过将证书生命周期与 Pod 的生命周期同步,您可以最大限度地减少此解决方案的运营开销。为了帮助满足可审计性和透明度要求,您可以使用审计报告功能以机器可读的格式列出已颁发的证书。

任何地方的 IAM 角色

图 2 详细概述了使用 IAM 角色进行身份验证所涉及的组件。

图 2:随处可见的 IAM 角色的组件

图 2:随处可见的 IAM 角色的组件

IAM Roles Anywhere 允许您为在亚马逊云科技之外运行的工作负载获取临时安全证书。您的工作负载必须使用可信的 PKI CA 颁发的证书通过 IAM 角色进行身份验证。通过创建指向 CA 根的信任锚点,您可以在 IAM Roles Anywhere 和您的 CA 之间建立信任。

证书经理

图 3 详细概述了本文中使用的证书管理器设置,包括用于集成亚马逊云科技私有 CA 的aws-privateca-issuer插件。

图 3:证书管理器设置的详细概述

图 3:证书管理器设置的详细概述

cert-manager 是在 Kubernetes 中管理 X.509 证书的工具。如图 3 所示,cert-manager 将确保证书有效且是最新的,并尝试在证书到期之前续订。通过使用插件,您可以配置不同的后端来颁发 X.509 证书。在这篇文章中,我们将探讨如何使用该插件将证书管理器与亚马逊云科技私有 CA 集成。aws-privateca-issueraws-privateca-issuer插件定义了两个自定义资源AWSPCAIssuerAWSPCAClusterIssuer,用于配置指向亚马逊云科技私有 CA 的链接。它们与证书管理器附带的IssuerClusterIssuer资源类似,但特定于。aws-privateca-issuer

AWSPCAIssuerAWSPCAClusterIssuer可用后,使用从 IAM Rol aws-privateca-issuer es Anywhere 获得的临时安全证书向亚马逊云科技API 进行身份验证。证书管理器监视证书资源,证书资源引用,而证书资源又引用亚马逊云科技私有 CA。AWSPCAIssueraws-privatca-issuer向亚马逊云科技私有 CA 申请证书。自动生成的私钥和签名证书存储在 Kubernetes 机密中。

使用证书和机密

证书管理器支持通过多种方式集成到您的 Kubernetes 工作负载中。您可以使用证书资源,这些资源代表了证书签名请求 (CSR) 的人类可读定义,并包含有关证书有效期和续订时间的信息。使用证书时,自动生成的私钥和签名证书存储在 Kubernetes 机密中。

使用此选项,可以手动颁发 X.509 证书并将其另存为密钥。将 PKI 配置为颁发者后,将创建证书资源以自动续订证书。使用证书资源,证书的生命周期与使用证书的 Pod 的生命周期分离。这样,即使在部署可信 PKI 之前,您也可以启动 X.509 证书。

使用 CSI 驱动程序

集成证书管理器的另一种方法是使用 CSI 驱动程序。在这种情况下,证书生命周期绑定到 Pod 的生命周期。X.509 证书和私钥安装在预定义的文件夹中,您的工作负载可以在其中读取它们。创建 pod 时,cert-manager 会自动创建私钥并为配置的可信 PKI 请求证书。删除 pod 后,私钥和证书也会被删除并失效,因为它们没有被证书管理器续订。

在这篇文章中,我们使用适用于工作负载的 CSI 驱动程序方法,为 IAM 角色随时随地创建临时证书。

工作负载配置

图 4 详细介绍了如何使用提供模仿亚马逊弹性计算云 (Amazon EC2) 实例元数据终端节点行为的 IMDSv2 终端节点,将容器配置为在任何地方使用 IAM 角色而无需更改底层 Docker 镜像。

图 4:使用 sidecar 配置 Pod

图 4:使用 sidecar 配置 Pod

如图 4 所示,使用证书资源时,自动生成的私钥和签名证书存储在 Kubernetes 机密中并安装到 pod 中。使用 CSI 驱动程序时,将在本地(为 pod)生成私钥,根据给定属性向 cert-manager 请求证书并由颁发AWSPCAIssuer,证书直接挂载到 pod 中,不创建中间密钥。

IAM Roles Anywhere 使用 CreateSession API 使用私钥及其关联的 X.509 证书通过 Sigv4a 签名对请求进行身份验证。该交易所提供 IAM 角色会话凭证,就好像您担任了 IAM 角色一样。提供了 aws_signing_helper 二进制文件,用于从命令行调用 CreateSession API。在这篇文章中,使用了一个为工作负载容器提供 IMDSv2 端点的 sidecar 容器。该容器使用aws_signing_helper二进制文件并使用其服务命令。

这样,使用亚马逊云科技开发工具包的应用程序可以使用AWS_EC2_METADATA_SERVICE_ENDPOINT环境变量将实例元数据终端节点设置为本地主机接口上的正确端口。X.509 证书和私钥以文件形式提供给 sidecar 容器。

解决方案部署

在本节中,我们展示了在您的亚马逊云科技账户中部署解决方案所需的步骤。

先决条件

要部署本文中的解决方案,请确保您具备以下条件:

  • 亚马逊云科技命令行接口 (亚马逊云科技CLI) v2
  • 亚马逊云科技账户和 IAM、IAM 角色任意位置和亚马逊云科技私有 CA 的 IAM 权限
  • 最新的稳定版 Kubernetes
  • kubectl(匹配你的 Kubernetes 版本)
  • 头盔 3
  • jq

注意:除了使用亚马逊云科技CLI 之外,您还可以使用适用于亚马逊云科技私有 CA 的亚马逊云科技控制器 (ACK) 服务控制器来创建和管理 CertificateAuthorityCertificate,以及直接在 Kubernetes 集群中创建和管理CertificateAuthorityActivation资源。使用 ACK 控制器建立 CA 层次结构后,您可以按照本文所述继续执行涉及 IAM 角色aws-privateca-issuer、Anywhere 集成和证书管理器的后续步骤。

第 1 步 —亚马逊云科技私有 CA

  1. 在亚马逊云科技私有 CA 中设置根 CA,这将为你的 pod 颁发短期证书。在此示例中,您仅使用一个 CA;对于生产环境,应检查设计 CA 层次结构的注意事项。首先使用亚马逊云科技CLI 创建配置。
    cat <<EOF > ca-config.json
    {
       "KeyAlgorithm":"RSA_2048",
       "SigningAlgorithm":"SHA256WITHRSA",
       "Subject":{
          "Country":"DE",
          "Organization":"Example Corp",
          "OrganizationalUnit":"SREs",
          "State":"HE",
          "Locality":"FRANKFURT",
          "CommonName":"Blogpost CA"
       }
    }
    EOF
    Plain text
  2. 使用短期证书模式在亚马逊云科技私有 CA 中创建 CA。
    aws acm-pca create-certificate-authority \
      --certificate-authority-configuration file://ca-config.json \
      --certificate-authority-type "ROOT" \
      --usage-mode SHORT_LIVED_CERTIFICATE
    Plain text
  3. 该命令将返回 aCertificateAuthorityArn,您需要使用它来执行其他命令,因此将其导出以备后用。替换<region>为您的亚马逊云科技区域。
    export PCA_ARN=arn:aws:acm-pca:<region>:012345678912:certificate-authority/8213159d-cad0-481c-bf14-a0ced4d6d479
    Plain text
  4. 创建根 CA 后,该 CA 处于待处理状态。你需要创建 CSR。
    aws acm-pca get-certificate-authority-csr \
         --certificate-authority-arn ${PCA_ARN} \
         --output text > ca.csr
    Plain text
  5. 现在,CSR 需要由根 CA 签署。
    aws acm-pca issue-certificate \
         --certificate-authority-arn ${PCA_ARN} \
         --csr fileb://ca.csr \
         --signing-algorithm SHA256WITHRSA \
         --template-arn arn:aws:acm-pca:::template/RootCACertificate/V1 \
         --validity Value=365,Type=DAYS
    Plain text
  6. 此命令返回稍后需要CertificateArn的。将其导出。
    export ROOT_CA_CERTIFICATE_ARN=arn:aws:acm-pca:<region>:012345678912:certificate-authority/8213159d-cad0-481c-bf14-a0ced4d6d479/certificate/5830e475088eee553bd409b7f4964613
    Plain text
  7. 下载根 CA 证书并将其上传到您的亚马逊云科技私有 CA。
    aws acm-pca get-certificate \
        --certificate-authority-arn ${PCA_ARN} \
        --certificate-arn ${ROOT_CA_CERTIFICATE_ARN} \
        --output text > cert.pem
    
    aws acm-pca import-certificate-authority-certificate \
         --certificate-authority-arn ${PCA_ARN} \
         --certificate fileb://cert.pem
    Plain text
  8. 验证 PCA 的状态,应该是。ACTIVE
    aws acm-pca describe-certificate-authority \
        --certificate-authority-arn ${PCA_ARN} \
        --output json
    Plain text

第 2 步 — 随处可见的 IAM 角色

此时,您的根 CA 已设置完毕并可供使用。下一步是随时随地配置 IAM 角色。

  1. 首先定义一个信任锚点,该锚将引用您新创建的亚马逊云科技私有 CA,然后导出trustAnchorArn<value-of-trustAnchorArn>替换为您的 IAM Roles Anywhere 信任锚点的亚马逊资源名称 (ARN) 值。
    aws rolesanywhere create-trust-anchor \
    --name onprem-k8s-issuer \
    --enabled \
    --source sourceType=AWS_ACM_PCA,sourceData={acmPcaArn=${PCA_ARN}}
    
    export TRUST_ANCHOR_ARN=<value-of-trustAnchorArn>
    Plain text
  2. 创建一个 IAM 角色供aws-privateca-issuer证书管理器插件使用。该角色需要包括 IAMRA 要求的操作sts:AssumeRolests:SetSourceIdentitysts:TagSession<TA_ID>替换为你的信任锚。

    注意:您应该在 CN 中指定 principalTag。此外,应将其范围限定在IAMRA的服务主体范围内。这进一步限制了基于从 X.509 证书中提取的属性的授权,并通过帮助确保即使未经授权的一方获得了有效证书的访问权限,除非证书的 CN 与指定值相匹配,否则他们也无法担任该角色,从而提供了额外的安全层。

    cat <<EOF > trust-policy.json
    {
        "Version": "2012-10-17",
        "Statement": [{
            "Sid": "Statement1",
            "Effect": "Allow",
            "Principal": {
                "Service": "rolesanywhere.amazonaws.com"
            },
            "Action": [
                "sts:AssumeRole",
                "sts:SetSourceIdentity",
                "sts:TagSession"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:PrincipalTag/x509Subject/CN": "iamra-issuer"
                },
                "ArnEquals": {
                    "aws:SourceArn": [
                        "arn:aws:rolesanywhere:<region>:012345678912:trust-anchor/<TA_ID>"
                    ]
                }
    
            }
        }]
    }
    EOF
    Plain text
    • 使用以下命令创建iamra-issuer角色:
      aws iam create-role --role-name iamra-issuer \
        --assume-role-policy-document file://trust-policy.json
      Plain text
  3. 该命令将返回一个 JSON 文档,其中包含有关新创建的角色的信息。导出 ARN 以备后用。
    export IAMRA_ISSUER_ROLE=arn:aws:iam::012345678912:role/iamra-issuer
    Plain text
  4. 附加允许角色向您的 PCA 请求证书并检索证书的内联策略。请注意,有一个条件将亚马逊云科技私有 CA 模板限制为仅允许EndEntityCertificate
    cat <<EOF > inline-policy.json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "awspcaissuerread",
          "Action": [
            "acm-pca:DescribeCertificateAuthority",
            "acm-pca:GetCertificate"
          ],
          "Effect": "Allow",
          "Resource": "$PCA_ARN"
        },
        {
          "Sid": "awspcaissuerwrite",
          "Action": [
            "acm-pca:IssueCertificate"
          ],
          "Effect": "Allow",
          "Resource": "$PCA_ARN",
          "Condition":{
            "StringEquals":{
              "acm-pca:TemplateArn":"arn:aws:acm-pca:::template/EndEntityCertificate/V1"
            }
          }
        }
      ]
    }
    EOF
    Plain text
    • 使用以下命令将内联策略(在前面的步骤中创建)与iamra-issuer角色关联。
      aws iam put-role-policy --role-name iamra-issuer \
        --policy-name iamra-issuer \
        --policy-document file://inline-policy.json
      Plain text
  5. 最后,创建一个配置文件来定义可以代入哪些 IAM 角色,然后导出返回的 ARN。
    aws rolesanywhere create-profile --name iamra-issuer \
      --role-arns ${IAMRA_ISSUER_ROLE} \
      --enabled
    Plain text
    • 导出返回的 ARN:
      export IAMRA_PROFILE_ARN=arn:aws:rolesanywhere:<region>:012345678912:profile/<Profile_ID>
      Plain text

创建的角色iamra-issuer只能用于与亚马逊云科技私有 CA 集成。aws-privateca-issuer您应重复为工作负载创建 IAM 角色和 IAMRA 配置文件的过程。建议为每个工作负载创建单独的 IAM 角色,并在信任策略中使用条件语句限制其使用,检查工作负载身份和信任锚点(例如,匹配通用名称)。此外,将IAMRA添加到信任策略中并允许上述操作非常重要。IAM 角色的优秀做法是应用最低权限权限。

第 3 步 — 创建初始容器

要将 IAM 角色集成到您的 Kubernetes 环境中的任何地方,您需要通过将二进制文件作为边车运行来为应用程序容器提供 IMDSv2 终端节点。aws_signing_helper您还需要使用环境变量配置应用程序,以使用新的实例元数据终端节点。为此,请构建一个可用作边车的 Docker 镜像。

在此步骤中,创建满足上述要求的基本镜像。在您的环境中,您可能需要调整此示例,以使用自己的基础映像并实现映像强化过程。

复制以下脚本并将其另存为init.sh

#!/bin/sh

if [[ -z "$TRUST_ANCHOR_ARN" ]]; then
  echo "Must provide TRUST_ANCHOR_ARN environment variable." 1>&2
  exit 1
fi

if [[ -z "$PROFILE_ARN" ]]; then
  echo "Must provide PROFILE_ARN environment variable." 1>&2
  exit 1
fi

if [[ -z "$ROLE_ARN" ]]; then
  echo "Must provide ROLE_ARN environment variable." 1>&2
  exit 1
fi

echo "starting IMDSv2 endpoint with aws_signing_helper ..."
/aws_signing_helper serve \
  --certificate /iamra/tls.crt         \
  --private-key /iamra/tls.key         \
  --trust-anchor-arn $TRUST_ANCHOR_ARN \
  --profile-arn $PROFILE_ARN           \
  --role-arn $ROLE_ARN
Plain text

这个脚本是 sidecar 容器的入口点。它需要所需的环境变量TRUST_ANCHOR_ARNPROFILE_ARNROLE_ARN、和aws_signing_helper。它还期望在文件夹中有一个 X.509 证书及其私钥/iamra,这些证书将在 pod 初始化的后期阶段挂载。最后,它aws_signing_helper使用指令调用,该serve指令在默认情况下创建一个 IMDSv2 端点监听 9911。可以使用--port参数对其进行自定义。

现在让我们检查 Docker 文件。

注意:在撰写本文时,我们使用了 alpine3.17.0 图片。使用经过强化的基础映像,该映像旨在确保安全并符合您的环境要求。

FROM alpine:3.17.0

COPY init.sh .
RUN apk add --no-cache libc6-compat libgcc wget
RUN wget https://rolesanywhere.amazonaws.com/releases/1.3.0/X86_64/Linux/aws_signing_helper
RUN chmod +x /aws_signing_helper /init.sh 
RUN ln -s /lib/libc.musl-x86_64.so.1 /lib/libresolv.so.2
ENTRYPOINT ["/bin/sh", "-c", "/init.sh"]
Plain text

这个 Docker 文件复制init.sh并下载aws_signing_helper二进制文件。该init.sh脚本被定义为容器的入口点。所需的动态库aws_signing_helper是使用 Alpine Linux 包管理器 (Apk) 安装的。

现在构建 docker 镜像,登录并推送它以备后用。对于以下命令,请<my-docker-registry>替换为本地注册表的主机名或使用 ECR 存储库。

docker build . -t <my-docker-registry>/iamra-sidecar
docker login <my-docker-registry>
docker push <my-docker-registry>/iamra-sidecar
Plain text

第 4 步 — 安装证书管理器

在此步骤中,将 cert-manager 安装到您的集群中,并aws-privateca-issuer使用手动引导的证书进行配置。cert-manager-approver-policy用于控制工作负载可以请求哪些证书。然后,设置证书管理器 CSI 驱动程序,自动为您的工作负载容器配置 X.509 证书。

从证书管理器设置开始:

  1. 将证书管理器存储库添加到 Helm 并安装图表。

    注意:在撰写本文时,我们使用的是证书管理器版本 1.16.2。检查最新的稳定版本。

    helm repo add jetstack https://charts.jetstack.io
    helm repo update
    helm install \
      cert-manager jetstack/cert-manager \
      --namespace cert-manager \
      --create-namespace \
      --version v1.16.2 \
      --set installCRDs=true \
      --set extraArgs={--controllers='*\,-certificaterequests-approver'}
      
    helm install \
      cert-manager-approver-policy jetstack/cert-manager-approver-policy \
      --namespace cert-manager \
      --wait \
        --set app.approveSignerNames="{\
    issuers.cert-manager.io/*,clusterissuers.cert-manager.io/*,\
    awspcaclusterissuers.awspca.cert-manager.io/*,awspcaissuers.awspca.cert-manager.io/*\
    }"
    
    
    #make modifications in cert-manager-approver-policy and add below permissions
    
    kubectl edit  Clusterrole cert-manager-approver-policy -n cert-manager -o yaml
    
    - apiGroups:
      - awspca.cert-manager.io
      resources:
      - awspcaissuers
      - awspcaclusterissuers
      verbs:
      - get
      - list
      - watch
    - apiGroups:
      - cert-manager.io
      - awspca.cert-manager.io
      resources:
      - signers
      verbs:
      - approve
    Plain text

    现在,安装证书管理器插件aws-privateca-issuer。这种集成将证书管理器与亚马逊云科技私有 CA 连接起来,并允许您自动颁发短期证书。目前,aws-privateca-issuerHelm Chart 本身不支持 IAMRA。因此,你将使用与工作负载init-container舱相同的方法来设置 IAMRA。

    你需要手动为 aws-privateca-issuer IAMRA 颁发第一个 X.509 证书。稍后,证书管理器将自动续订。

  2. 创建引导证书。当要求输入通用名称时,输入iamra-issuer
    openssl req -out iamra.csr -new -newkey rsa:2048 \
    -nodes -keyout iamra.key
    
    Plain text

    前面的命令将创建一个名为的 RSA 私钥iamra.key和一个证书签名请求名称iamra.csr。现在,您需要致电亚马逊云科技私有 CA 来颁发引导证书。

  3. 将证书的有效期设置为 1 天,这样 cert-manager 将在设置后替换它。执行此操作的 IAM 角色必须拥有 Amazon Certificate Manager (ACM)、IAM 和 IAM 角色的权限才能完成设置。
    aws acm-pca issue-certificate \
          --certificate-authority-arn ${PCA_ARN} \
          --csr fileb://iamra.csr \
          --signing-algorithm "SHA256WITHRSA" \
          --validity Value=1,Type="DAYS"
    Plain text
  4. 该命令将CertificateArn为您的iamra-issuer证书返回。将其导出并将证书保存到文件中。
    export IAMRA_ISSUER_CERT_ARN=arn:aws:acm-pca:<region>:012345678912:certificate-authority/8213159d-cad0-481c-bf14-a0ced4d6d479/certificate/afc47911ed2ded9c2664fa597a33b9fb
    aws acm-pca get-certificate \
          --certificate-authority-arn ${PCA_ARN} \
          --certificate-arn ${IAMRA_ISSUER_CERT_ARN} | \
          jq -r .'Certificate' > iamra-cert.pem
    Plain text
  5. 创建包含证书和私钥的 Kubernetes 密钥。
    kubectl create secret tls -n cert-manager iamra-issuer \
      --cert=iamra-cert.pem \
      --key=iamra.key
    Plain text

    您已准备好安装aws-privateca-issuer.你需要修改 Helm 图表,因为它目前不支持 IAMRA。你将把 Helm 图表渲染成 YAML 清单,然后对这些清单进行调整,使其适合 IAMRA。

  6. 安装 Helm 存储库并将图表呈现到文件中。
    helm repo add awspca https://cert-manager.github.io/aws-privateca-issuer
     helm template --release-name iamra --include-crds awspca/aws-privateca-issuer \
       -n cert-manager > privateca-issuer.yaml
    Plain text
  7. 将您之前构建的映像添加为 sidecar,并将环境变量替换为导出的值。搜索部署定义并添加以下部分:
    # Source: aws-privateca-issuer/templates/deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: iamra-aws-privateca-issuer
      namespace: cert-manager
      labels:
        helm.sh/chart: aws-privateca-issuer-v1.4.0
        app.kubernetes.io/name: aws-privateca-issuer
        app.kubernetes.io/instance: iamra
        app.kubernetes.io/version: "v1.4.0"
        app.kubernetes.io/managed-by: Helm
    spec:
      replicas: 1
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          app.kubernetes.io/name: aws-privateca-issuer
          app.kubernetes.io/instance: iamra
      template:
        metadata:
          labels:
            app.kubernetes.io/name: aws-privateca-issuer
            app.kubernetes.io/instance: iamra
        spec:
          serviceAccountName: iamra-aws-privateca-issuer
          securityContext:
            runAsUser: 65532
          volumes:
            - name: "iamra-secret"
              projected:
                sources:
                  - secret:
                      name: iamra-issuer
          containers:
            - name: iamra-sidecar
              image: 012345678912.dkr.ecr.us-east-2.amazonaws.com/<replace-with-iamra-sidecar-repository>
              imagePullPolicy: Always
              env:
                - name: "TRUST_ANCHOR_ARN"
                  value: "arn:aws:rolesanywhere:us-east-2:012345678912:trust-anchor/05d183f8-a34e-4f0c-ad2a-de6f803"
                - name: "PROFILE_ARN"
                  value: "arn:aws:rolesanywhere:us-east-2:012345678912:profile/7b45f9a9-73fa-47f8-a20f-88aacbf57"
                - name: "ROLE_ARN"
                  value: "arn:aws:iam::012345678912:role/iamra-issuer"
              volumeMounts:
                - name: iamra-secret
                  mountPath: "/iamra"
                  readOnly: true
            - name: aws-privateca-issuer
              securityContext:
                allowPrivilegeEscalation: false
              image: "public.ecr.aws/k1n1h4h4/cert-manager-aws-privateca-issuer:latest"
              env:
               - name: "AWS_EC2_METADATA_SERVICE_ENDPOINT"
                 value: "http://localhost:9911/"
              imagePullPolicy: IfNotPresent
              command:
                - /manager
              args:
                - --leader-elect
              ports:
                - containerPort: 8080
                  name: http
              livenessProbe:
                httpGet:
                  path: /healthz
                  port: 8081
                initialDelaySeconds: 15
                periodSeconds: 20
              readinessProbe:
                httpGet:
                  path: /healthz
                  port: 8081
                initialDelaySeconds: 5
                periodSeconds: 10
          terminationGracePeriodSeconds: 10
    Plain text
  8. 应用修改后的清单来安装aws-privateca-issuer和验证您修改的部署。它应该显示一个 pod 已准备就绪且可用。
    kubectl apply -f privateca-issuer.yaml
    
    kubectl get deployment -n cert-manager -l app.kubernetes.io/name=aws-privateca-issuer
    
    NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
    iamra-aws-privateca-issuer   1/1     1            1           4d10h
    Plain text
  9. 定义一个AWSPCAIssuer,它将用于续订插件的手动引导证书。aws-privateca-issuer

    注意:在撰写本文时,我们使用了 awspca cert-manager API 版本 v1beta1。检查最新的稳定版本。

    export AWS_REGION=<region>
    cat <<EOF | kubectl apply -f -
    apiVersion: awspca.cert-manager.io/v1beta1
    kind: AWSPCAIssuer
    metadata:
      name: iamra-cm-issuer
      namespace: cert-manager
    spec:
      arn: ${PCA_ARN}
      region: ${AWS_REGION}
    EOF
    Plain text
  10. 在至少AWSPCAClusterIssuer有一个AWSPCAIssuer或可用之后,aws-privateca-issuer将通过调用sts.get-caller-identity和验证身份验证方法向亚马逊云科技API 进行身份验证。您可以使用其日志文件对此进行验证。它应该打印所扮演的角色。
    kubectl logs -n cert-manager -l app.kubernetes.io/name=aws-privateca-issuer -c aws-privateca-issuer | grep -i getcalleridentity
    
    Defaulted container "aws-privateca-issuer" out of: aws-privateca-issuer, iamra-init (init)
    {"level":"info","ts":1669240040.2704494,"logger":"controllers.GenericIssuer","msg":"sts.GetCallerIdentity","genericissuer":"cert-manager/iamra-cm-issuer","arn":"arn:aws:sts::012345678912:assumed-role/iamra-issuer/5bafffcfb691969f0616a9b1a68032ec","account":"012345678912","user_id":"AROA2EIPPI5BVJ6SKBYOY:5bafffcfb691969f0616a9b1a68032ec"}
    Plain text

    现在,您可以创建一个证书管理器Certificate资源,该资源代表应由引用的证书管理器颁发的所需证书。Issuer它将企业社会责任的信息与有效期和续订的详细信息相结合。

  11. 创建证书对象:
    cat <<EOF | kubectl apply -f - 
      apiVersion: cert-manager.io/v1
      kind: Certificate
      metadata:
        name: iamra-privateca-issuer-cert
        namespace: cert-manager
      spec:
        secretName: iamra-issuer
        duration: 168h # 7d
        renewBefore: 24h # 15d
        subject:
          organizations:
            - "Example Corp."
          organizationalUnits:
            - "Admin"
        commonName: "iamra-issuer"
        isCA: false
        usages:
          - "client auth"
          - "server auth"
        issuerRef:
          group: awspca.cert-manager.io
          kind: AWSPCAIssuer
          name: iamra-cm-issuer
      EOF
      helm upgrade -i -n cert-manager cert-manager-csi-driver jetstack/cert-manager-csi-driver --wait
      -- > install policies:
      policy + role + role binding to allow service account to accept certs.
      cat <<EOF | kubectl apply -f - 
      apiVersion: policy.cert-manager.io/v1alpha1
      kind: CertificateRequestPolicy
      metadata:
        name: iamra-issuer-policy
      spec:
        allowed:
          commonName:
            required: true
            value: "iamra-issuer"
          subject:
            organizations:
              values: ["Example Corp."]
              required: true
            organizationalUnits:
              values: ["Admin"]
              required: true
          usages:
          - "server auth"
          - "client auth"
        selector:
          issuerRef:
            group: awspca.cert-manager.io
            kind: AWSPCAIssuer
            name: iamra-cm-issuer
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: cert-manager-policy:iamra-issuer-policy
      rules:
        - apiGroups: ["policy.cert-manager.io"]
          resources: ["certificaterequestpolicies"]
          verbs: ["use"]
          resourceNames: ["iamra-issuer-policy"]
      ---
      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: cert-manager-policy:iamra-issuer-policy
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: cert-manager-policy:iamra-issuer-policy
      subjects:
      - kind: ServiceAccount
        name: cert-manager
        namespace: cert-manager
      EOF
    Plain text

第 5 步 — 部署工作负载

在步骤 4 的子步骤 9 中,您创建了一个AWSPCAIssuer名字iamra-cm-issuer。然后,您使用它AWSPCAIssuer来续订手动引导的证书。aws-privateca-issuer

在步骤 4 的子步骤 11 中,您创建了aws-privateca-issuer由使用的证书iamra-privateca-issuer-cert

在此步骤中,您将部署示例工作负载。部署示例工作负载时,请确保重复为证书请求创建 IAM 角色和 IAMRA 配置文件(从步骤 2 开始)、AWSPCAIssuer(步骤 4,子步骤 9)和CertificateRequestPolicy(步骤 4,子步骤 11)的过程。

有关证书申请政策的更多信息,请参阅有关批准政策的证书管理器文档。

使用以下代码部署工作负载。

cat <<EOF | kubectl apply -f -
  
apiVersion: v1
kind: Pod
metadata:
   creationTimestamp: null
   labels:
     run: acmpca-csi-test
   name: acmpca-csi-test
spec:
  containers:
      - name: iamra-sidecar
        image: 056930860237.dkr.ecr.us-east-2.amazonaws.com/aws_sighning:latest
        imagePullPolicy: Always
        env:
          - name: "TRUST_ANCHOR_ARN"
            value: "arn:aws:rolesanywhere:us-east-2:012345678912:trust-anchor/05d183f8-a34e-4f0c-ad2a-de6f803ac172"
          - name: "PROFILE_ARN"
            value: "arn:aws:rolesanywhere:us-east-2:012345678912:profile/7b45f9a9-73fa-47f8-a20f-88aacbf579d2"
          - name: "ROLE_ARN"
            value: "arn:aws:iam::012345678912:role/iam-roles-anywhere-s3-full-access"
        volumeMounts:
          - name: "iamra-csi"
            mountPath: "/iamra"
            readOnly: true
      - name: aws-cli
        image: amazon/aws-cli:latest
        env:
        - name: "AWS_EC2_METADATA_SERVICE_ENDPOINT"
          value: "http://127.0.0.1:9911/"
        command:
          - sleep
          - "3600"
  dnsPolicy: ClusterFirst
  restartPolicy: Never
  volumes:
    - name: "iamra-csi"
      csi:
        readOnly: true
        driver: csi.cert-manager.io
        volumeAttributes:
            csi.cert-manager.io/issuer-name: my-pca
            csi.cert-manager.io/issuer-group: awspca.cert-manager.io
            csi.cert-manager.io/issuer-kind: AWSPCAIssuer
            csi.cert-manager.io/common-name: "${SERVICE_ACCOUNT_NAME}.${POD_NAMESPACE}"
            csi.cert-manager.io/duration: 168h
            csi.cert-manager.io/renew-before: 24h
            csi.cert-manager.io/is-ca: "false"
            csi.cert-manager.io/key-usages: "client auth, server auth"
  EOF
Plain text

第 6 步 — 测试您的部署

要测试部署,您可以使用kubectl exec访问iamra-sidecar容器。导航到该iamra目录并检查证书和密钥是否已安装。

命令:
kubectl exec -it acmpca-csi-test  – sh
ls | grep iamra

输出:iamra

命令:
cd iamra
/iamra# ls

输出:ca.crt   tls.crt  tls.key

您还可以exec进入aws-cli容器验证调用者身份,然后向亚马逊简单存储服务 (Amazon S3) 进行 API 调用:

命令:
kubectl exec -it acmpca-csi-test -c aws-cli  – sh
$aws sts get-caller-identity

输出:你应该iam-roles-anywhere-s3-full-access在中看到caller-identity

命令:
$aws s3 ls

输出:您应该能够根据与担任的角色相关的权限列出 S3 存储桶。

摘要

在这篇文章中,您了解了使用 IAM 角色随时随地安全地将本地 Kubernetes 工作负载连接到亚马逊云科技服务的解决方案。该方法减少了对长期访问密钥的需求或Kubernetes API服务器的公共互联网暴露。通过将此解决方案用于容器化和全栈应用程序,您可以受益于:

  • 增强的安全性:使用短期的 X.509 证书而不是长期证书。
  • 简化管理:使用证书管理器和亚马逊云科技私有 CA 实现证书生命周期自动化。
  • 无缝集成:无需修改现有工作负载 Docker 文件。
  • 一致的策略:在亚马逊云科技和本地使用相同的 IAM 角色和策略。


如果你对这篇文章有反馈,请在下面的评论部分提交评论。如果您对这篇文章有疑问,请联系 Amazon Support。

瓦伦·夏尔马 瓦伦·夏尔马·
瓦伦是一位资深的亚马逊云科技云安全工程师,他自豪地穿着自己的安全斗篷。瓦伦是亚马逊 Cognito 和 IAM 的首选主题专家。当他不忙于保护云端时,你会在安全渗透测试的世界中找到他。工作之余,瓦伦换档,通过相机的镜头捕捉大自然之美。
Nishant Mainro Nishant Mainro
Nishant 是亚马逊云科技专业服务团队的高级安全顾问,常驻佐治亚州亚特兰大。他是一位充满技术和激情的亚马逊人,拥有超过16年的专业经验,专攻安全、风险和合规性。他专门开发和启用大规模安全控制措施,使客户能够实现其工作负载所需的安全目标。
Roshini Jagarapu 罗希尼·贾加拉普·罗
尼是亚马逊 EKS 主题专家,也是一名驻印度的亚马逊云科技云支持工程师。她与亚马逊 EKS 和亚马逊 ECS 等服务公司合作,帮助客户大规模运营。她的日常工作包括解决与容器技术相关的问题。Roshini 举办学习课程来教育客户,并对云原生解决方案充满热情。

*前述特定亚马逊云科技生成式人工智能相关的服务仅在亚马逊云科技海外区域可用,亚马逊云科技中国仅为帮助您发展海外业务和/或了解行业前沿技术选择推荐该服务。