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



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

我知道可以创建一个具有固定凭据的IAM用户,并且可以导出到GitHub Secrets,但这意味着如果密钥泄漏,我会遇到很大的问题,如果忘记了,旋转这样的密钥将是一个挑战。

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

是的,现在GitHub已经发布了他们的开放ID连接器,用于GitHub操作。您可以将Open ID Connector配置为AWS中的身份提供程序,然后将其用于您希望启用的任何角色的访问点。然后,您可以将操作配置为使用在作业期间获取的凭据,当作业完成时,凭据将自动吊销。

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

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",
]
}

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

如果你对这个神奇的值的来源感兴趣,你可以在How can I calculate the thumbprint of a OpenID Connect server上找到答案?

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

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/*"
}
}
}]
})
}

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

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

repo:<organization>/<repository>:ref:refs/heads/<branch>

稍后可能会出现不同的格式。例如,如果使用:ref:refs/pulls/*,则可以为PR指定一个操作/角色,并为:ref:refs/heads/production/*指定另一个角色。

最后一步是将您的GitHub操作配置为使用从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

手动方式

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

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

您需要确保您的AWS_ROLE_ARN与AWS帐户中定义的内容相同,受众与OpenID Connect和角色名称所接受的内容相同。

从本质上讲,在作业开始和令牌的有效性之间存在竞争条件,直到GitHub确认作业已经开始后,令牌才会生效;如果AWS_WEB_IDENITY_TOKEN_FILE的大小小于10个字符,那么这可能是一个错误,睡眠/旋转之后会得到该值。

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

您可能需要配置您的角色,以便限制所用期间的有效性;一旦您有了web令牌,它就一直有效到作业结束,但请求的令牌的生存期为15分钟,因此运行时间较长的作业可能会公开它。

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

UpdateGitHub(意外)更改了他们的指纹,示例已经更新。有关详细信息,请参阅。新指纹是6938fd4d98bab03faadb97b34396831e3780aea1,但IAM OpenID连接器中可能有多个指纹。

Github最近更新了他们的证书链,重击已经从上面提到的a031c46782e6e6c662c2c87c76da9aa62ccabd8e变成了6938fd4d98bab03faadb97b34396831e3780aea1

Github问题:https://github.com/aws-actions/configure-aws-credentials/issues/357

出于某种原因,我一直用AlBlue:的答案来回答这个问题

"消息":"无法为访问群体"githubactions"颁发ID_TOKEN">

部署本文中提供的堆栈确实有效。

最新更新