如何在不使用密钥的情况下将 GitHub 操作与 AWS 部署连接起来?

AlB*_*lue 8 amazon-web-services terraform terraform-provider-aws github-actions

我希望能够使用 GitHub Actions 来通过 AWS 部署资源,但无需使用硬编码用户。

我知道可以创建一个具有固定凭证的 IAM 用户,并且可以将其导出到 GitHub Secrets,但这意味着如果密钥泄露,我就会遇到很大的问题,而且如果忘记了,轮换此类密钥将非常困难。

有什么方法可以启用无密码身份验证流程以将代码部署到 AWS?

AlB*_*lue 20

是的,现在 GitHub 已经发布了与 GitHub Actions 一起使用的 Open ID Connector。您可以将 Open ID 连接器配置为 AWS 中的身份提供商,然后将其用作您希望启用的任何角色的访问点。然后,您可以将操作配置为使用在作业期间获取的凭据,并且当作业完成时,凭据将自动撤销。

要在 AWS 中进行设置,您需要使用AWS 上的说明或使用类似于以下内容的 Terraform 文件创建 Open Identity Connect 提供商:

resource "aws_iam_openid_connect_provider" "github" {
  url = "https://token.actions.githubusercontent.com"
  client_id_list = [
    // original value "sigstore",
    "sts.amazonaws.com", // Used by aws-actions/configure-aws-credentials
  ]
  thumbprint_list = [
    // original value "a031c46782e6e6c662c2c87c76da9aa62ccabd8e",
    "6938fd4d98bab03faadb97b34396831e3780aea1",
  ]
}
Run Code Online (Sandbox Code Playgroud)

客户端 ID 列表是用于访问此内容的“受众”——您可以更改它,只要您在所有正确的位置进行更改即可。指纹是 Open ID 连接器的哈希/证书,并且6938...aea1是 GitHub Actions 当前使用的指纹 - 您可以按照AWS 的说明计算/验证该值。最多thumbprint_list可以容纳 5 个值,因此可以在提前提供新版本时附加新版本,同时继续使用旧版本。

如果您对这个神奇值的来源感兴趣,可以参阅如何计算 OpenID Connect 服务器的指纹?

启用身份提供程序后,您可以使用它来创建一个或多个自定义角色(替换为:

data "aws_caller_identity" "current" {}
resource "aws_iam_role" "github_alblue" {
  name = "GitHubAlBlue"
  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [{
      Action = "sts:AssumeRoleWithWebIdentity"
      Effect = "Allow"
      Principal = {
        Federated = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/token.actions.githubusercontent.com"
      }
      Condition = {
        StringLike = {
          "token.actions.githubusercontent.com:aud" :  ["sts.amazonaws.com" ],
          "token.actions.githubusercontent.com:sub" : "repo:alblue/*"
        }
      }
    }]
  })
}
Run Code Online (Sandbox Code Playgroud)

您可以根据需要创建任意数量的不同角色,甚至可以按受众(例如“制作”、“开发”)将它们分开。如果 OpenID 连接器的受众受到帐户的信任,那么您就可以开始了。(您可以使用它来确保开发帐户中的 OpenID 连接器不信任生产帐户中的角色,反之亦然。)例如,您可以拥有一个用于执行的只读角色,然后拥有另一个用于执行的terraform validate角色。 terraform apply

该主题是从 GitHub 传递的,但看起来像:

repo:<organization>/<repository>:ref:refs/heads/<branch>
Run Code Online (Sandbox Code Playgroud)

稍后可能会出现不同的格式。:ref:refs/pulls/*如果您使用例如,您可以有一个专门针对 PR 的操作/角色,并且有另一个角色用于:ref:refs/heads/production/*.

最后一步是将 GitHub Actions 配置为使用从 AWS/OpenID Connect 返回的令牌:

标准方式

jobs:
  terraform-validate:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Configure AWS credentials from Test account
        uses: aws-actions/configure-aws-credentials@master
        with:
          role-to-assume: arn:aws:iam::<accountid>:role/GitHubAlBlue
          aws-region: us-east-1
      - name: Display Identity
        run: aws sts get-caller-identity
Run Code Online (Sandbox Code Playgroud)

手动方式

幕后实际发生的事情是这样的:

jobs:
  terraform-validate:
    runs-on: ubuntu-latest
    env:
      AWS_WEB_IDENTITY_TOKEN_FILE: .git/aws.web.identity.token.file
      AWS_DEFAULT_REGION: eu-west-2
      AWS_ROLE_ARN: arn:aws:iam::<accountid>:role/GitHubAlBlue
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Configure AWS
        run: |
          sleep 3 # Need to have a delay to acquire this
          curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
            "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sts.amazonaws.com" \
            | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE
          aws sts get-caller-identity
Run Code Online (Sandbox Code Playgroud)

您需要确保您的AWS_ROLE_ARN帐户与您的 AWS 账户中定义的帐户相同,并且受众与 OpenID Connect 接受的受众以及角色名称相同。

本质上,作业开始和令牌有效性之间存在竞争条件,直到 GitHub 确认作业已开始后才会出现;如果 的大小AWS_WEB_IDENITY_TOKEN_FILE小于 10 个字符,则可能是一个错误,睡眠/旋转将在之后为您提供值。

名称AWS_WEB_IDENTITY_TOKEN_FILE并不重要,只要保持一致即可。如果您使用的是 docker 容器,那么将其存储在 例如/tmp将意味着它在任何正在运行的容器中不可用。如果您将其放在.git工作区中,那么 git 不仅会忽略它(如果您正在进行任何哈希计算),而且它还会出现在您稍后执行的任何其他 docker run 操作中。

您可能想要配置您的角色,以便限制所用期限的有效性;获得 Web 令牌后,它在作业结束之前一直有效,但请求的令牌的生命周期为 15 分钟,因此运行时间较长的作业可能会暴露该令牌。

GitHub 很可能会在不久的将来发布一篇关于如何配置/使用它的博客文章。上述信息的灵感来自https://awsteele.com/blog/2021/09/15/aws-federation-comes-to-github-actions.html,如果您喜欢的话,他在 CloudFormation 模板中提供了一些示例。

更新GitHub(意外地)更改了他们的指纹并且示例已更新。请参阅 获取更多信息。新的指纹是6938fd4d98bab03faadb97b34396831e3780aea1,但 IAM OpenID 连接器中可以有多个指纹。