我尝试创建使用GitHubActions OIDC进行Terraform工作流的方案
首先
2021年10月27日,官方宣布GitHub Actions现已支持OpenID Connect(OIDC)。
以前,為了從GitHubActions訪問各種雲端服務,需要將永久的認證信息保存在GitHub上,這帶來了洩漏的風險。引入OIDC的支援後,使得雲端供應商和GitHub之間能夠實現無縫認證。
我希望在本篇文章中总结关于通过GitHub Actions执行Terraform并访问AWS资源时的各种设置和验证结果。
※本文不涵盖OIDC的机制。如有兴趣了解的读者,以下的文章非常值得参考。
准备
-
- Terraform実行用のGitHubActionsワークフローの作成
Hashicorpが提供するサンプルがあるので、こちらをGitHubリポジトリに作成しておきます。このワークフローは、mainブランチへのpushイベントを契機として、リポジトリのルートディレクトリ配下でterraformの各種コマンドを実行します。
tfファイルの作成
検証用として、AWSのデフォルトVPCの情報を取得するmain.tfを用意しておきます。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "3.63.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
data "aws_vpc" "default" {
default = true
}
output "default_vpc_cidr_block" {
value = data.aws_vpc.default.cidr_block
}
设置步骤
我们将分别使用AWS和GitHub Actions依次执行以下设置。
AWS側の設定
Cloudformationテンプレートの作成
GitHubActions側の設定
id-tokenの許可設定を追加
アクセストークン取得処理追加
AWS的设置。
创建Cloudformation模板
将在AWS控制台上创建IAM提供程序和IAM角色。在configure-aws-credentials仓库中,提供了Cloudformation模板的示例,可以利用它来创建资源。由于我们只需要获取VPC的信息,因此将为IAM角色分配AmazonVPCReadOnlyAccess策略。
Parameters:
GitHubOrg:
Type: String
RepositoryName:
Type: String
OIDCProviderArn:
Description: Arn for the GitHub OIDC Provider.
Default: ""
Type: String
Conditions:
CreateOIDCProvider: !Equals
- !Ref OIDCProviderArn
- ""
Resources:
Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRoleWithWebIdentity
Principal:
Federated: !If
- CreateOIDCProvider
- !Ref GithubOidc
- !Ref OIDCProviderArn
Condition:
StringLike:
token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${RepositoryName}:*
# ロールに紐づけるIAMポリシーを設定
+ ManagedPolicyArns:
+ - arn:aws:iam::aws:policy/AmazonVPCReadOnlyAccess
GithubOidc:
Type: AWS::IAM::OIDCProvider
Condition: CreateOIDCProvider
Properties:
Url: https://token.actions.githubusercontent.com
ClientIdList:
- sts.amazonaws.com
ThumbprintList:
- a031c46782e6e6c662c2c87c76da9aa62ccabd8e
Outputs:
Role:
Value: !GetAtt Role.Arn
GitHub Actions的配置
为了在GitHub Actions中实现OIDC连接,需要授予获取OIDC令牌的权限,并在工作流中编写获取访问令牌的过程。
设定id-token的权限
通过指定”permissions”键,您可以更改GITHUB_TOKEN的默认权限。通过以下描述,您可以获取OIDC的ID令牌。
permissions:
id-token: write
新增获取访问令牌的处理方法。
通过使用aws-actions/configure-aws-credentials操作,从GitHub OIDC提供程序接收JWT并请求AWS访问令牌。在操作参数中指定以下两个参数。
role-to-assume: Cloudformationで作成されたIAMロールのARN
aws-region: AWSリージョン名
请查阅此处,以了解其他选项参数的具体操作方式。
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: arn:aws:iam::123456789012:role/OIDCTest-Role-XXXXXXXXXXXXX
aws-region: ap-northeast-1
随着2021年11月23日的v1.6.0发布,configure-aws-credentials已被附加上v1标签。GitHub的官方文档中明确指出可以使用分支指定(@master),但也可以使用标签指定(@v1)。由于分支指定可能会受到未预期的版本更新的影响,因此我认为最好使用标签指定。
修改Terraform示例工作流程的内容。
在创建GitHub Actions工作流程时,将上述两点添加到创建的工作流程中。修正后的工作流程如下所示。
# 这个工作流程安装最新版本的Terraform CLI,并配置Terraform CLI配置文件
# 使用一个API令牌来连接Terraform Cloud (app.terraform.io)。在拉取请求事件时,此工作流程将运行
# `terraform init`,`terraform fmt`,和`terraform plan`(通过Terraform Cloud进行规划)。在推送事件到主分支时
# 将会执行`terraform apply`。
#
# 有关`hashicorp/setup-terraform`的文档位于这里: https://github.com/hashicorp/setup-terraform
#
# 要使用此工作流程,您需要完成以下设置步骤。
#
# 1. 在该存储库的根目录下创建一个`main.tf`文件,其中包含`remote`后端和一个或多个资源定义。
# 示例 `main.tf`:
# # `remote`后端的配置。
# terraform {
# backend “remote” {
# # 您的Terraform Cloud组织的名称。
# organization = “example-organization”
#
# # 存储Terraform状态文件的Terraform Cloud工作区的名称。
# workspaces {
# name = “example-workspace”
# }
# }
# }
#
# # 一个没有任何操作的示例资源。
# resource “null_resource” “example” {
# triggers = {
# value = “一个没有任何操作的示例资源!”
# }
# }
#
#
# 2. 生成一个Terraform Cloud用户API令牌,并将其作为GitHub机密(例如TF_API_TOKEN)存储在该存储库上。
# 文档:
# – https://www.terraform.io/docs/cloud/users-teams-organizations/api-tokens.html
# – https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets
#
# 3. 在步骤中引用GitHub机密,使用`hashicorp/setup-terraform` GitHub Action。
# 示例:
# – name: 配置Terraform
# uses: hashicorp/setup-terraform@v1
# with:
# cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
name: ‘Terraform’
on:
push:
branches:
– main
jobs:
terraform:
name: ‘Terraform’
runs-on: ubuntu-latest
environment: production
# 添加id-token的写入权限
+ permissions:
+ id-token: write
# 不论GitHub Actions runner是ubuntu-latest,macos-latest还是windows-latest,都使用Bash shell
defaults:
run:
shell: bash
steps:
# 检出存储库到GitHub Actions runner
– name: 检出
uses: actions/checkout@v2
# 安装最新版本的Terraform CLI,并使用Terraform Cloud用户API令牌配置Terraform CLI配置文件
– name: 配置Terraform
uses: hashicorp/setup-terraform@v1
with:
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
# 添加获取访问令牌的步骤
+ – name: 配置AWS凭证
+ uses: aws-actions/configure-aws-credentials@v1
+ with:
+ role-to-assume: arn:aws:iam::123456789012:role/OIDCTest-Role-XXXXXXXXXXXXX
+ aws-region: ap-northeast-1
# 初始化Terraform工作目录(新建或现有):创建初始文件,加载任何远程状态,下载模块等。
– name: Terraform初始化
run: terraform init
# 检查所有Terraform配置文件是否符合规范格式
– name: Terraform格式化
run: terraform fmt -check
# 为Terraform生成执行计划
– name: Terraform计划
run: terraform plan
# 在推送到主分支时,根据Terraform配置文件构建或更改基础架构
# 注意:建议在存储库中设置所需的”strict”状态检查,用于”Terraform Cloud”。有关更多信息,请参阅关于”strict”所需状态检查的文档:https://help.github.com/en/github/administering-a-repository/types-of-required-status-checks
– name: Terraform应用
if: github.ref == ‘refs/heads/main’ && github.event_name == ‘push’
run: terraform apply -auto-approve
执行Terraform
将准备好的main.tf推送到GitHub仓库的main分支。这将触发已创建的GitHub Actions工作流程执行。
执行结果
只提取了Terraform Apply步骤,但我们可以看到环境变量中已经设置了AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY和AWS_SESSION_TOKEN,并且成功获取了默认VPC的CIDR块信息并进行了正确的输出。
总结
我创建了一个使用GitHub Actions工作流的Terraform执行流程,其中包含了OIDC集成处理。希望对考虑使用Terraform创建AWS资源环境的人有所帮助。