【AWS】【Terraform】OIDCを作成してGitHubActionsからAWSへアクセスできるようにする
GitHub Actions で AWS へアクセスする際に認証をどう突破するかが重要です。
GitHub の Actions secrets and variables から AWS の認証情報を読み込む方法もありますが、
機密情報を持たせておくのはセキュリティ的にはよろしくない。
そこで、AWS で OIDC を作成し、使用することを考えます。
今回は「terraform_test」という名前の Git リポジトリを使用し、 OIDC は Terraform を使用して作成します。
便宜上 GitHub Actions を使用したいリポジトリ内に Terraform のファイルを作成していますが、その必要はない点にご注意ください
OIDC(OpenID Connect)を作成
こちらを参考に main.tf および iam.tf を作成します
// ディレクトリ
terraform_test
├── .gitignore
├── README.md
├── **iam.tf** // 作成
└── **main.tf** // 作成
(main.tf)
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "ap-northeast-1"
}
(iam.tf)
#============================================================================
# Github Actions 用ロール
#============================================================================
# -----------------------------------------------------------------------------
# GitHub Actions プロバイダー設定
# -----------------------------------------------------------------------------
resource "aws_iam_openid_connect_provider" "terraform_cicd" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
# このコードは固定値
# OIDC ID プロバイダーのサムプリント
thumbprint_list = ["6938fd4d98bab03faadb97b34396831e3780aea1"]
}
# -----------------------------------------------------------------------------
# GitHub Actions 用ロール作成
# -----------------------------------------------------------------------------
resource "aws_iam_role" "terraform_cicd_oidc_role" {
name = "TerraCICDDemoOIDCRole"
path = "/"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = "sts:AssumeRoleWithWebIdentity"
Principal = {
Federated = aws_iam_openid_connect_provider.terraform_cicd.arn
}
Condition = {
StringLike = {
"token.actions.githubusercontent.com:sub" = [
# リポジトリ制限
# 複数定義可能
# xxxxx:GitHubのアカウント名
# terraform_testの部分はGitHubActionsを使用したいリポジトリ名
"repo:xxxxx/terraform_test:*",
]
}
}
}]
})
}
# -----------------------------------------------------------------------------
# ポリシーのアタッチ(AdministratorAccess_attachment)
# -----------------------------------------------------------------------------
resource "aws_iam_role_policy_attachment" "AdministratorAccess_attachment" {
role = aws_iam_role.terraform_cicd_oidc_role.name
# Admin権限を指定
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
上記を terraform apply してID プロバイダを作成します
terraform_test$ terraform plan
aws_s3_bucket.terraform_state: Refreshing state... [id=terraform-state-hisui]
aws_s3_bucket_versioning.terraform_state: Refreshing state... [id=terraform-state-hisui]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_iam_openid_connect_provider.terraform_cicd will be created
+ resource "aws_iam_openid_connect_provider" "terraform_cicd" {
+ arn = (known after apply)
+ client_id_list = [
+ "sts.amazonaws.com",
]
+ id = (known after apply)
+ tags_all = (known after apply)
+ thumbprint_list = [
+ "6938fd4d98bab03faadb97b34396831e3780aea1",
]
+ url = "https://token.actions.githubusercontent.com"
}
# aws_iam_role.terraform_cicd_oidc_role will be created
+ resource "aws_iam_role" "terraform_cicd_oidc_role" {
+ arn = (known after apply)
+ assume_role_policy = (known after apply)
+ create_date = (known after apply)
+ force_detach_policies = false
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "TerraCICDOIDCRole"
+ name_prefix = (known after apply)
+ path = "/"
+ role_last_used = (known after apply)
+ tags_all = (known after apply)
+ unique_id = (known after apply)
}
# aws_iam_role_policy_attachment.AdministratorAccess_attachment will be created
+ resource "aws_iam_role_policy_attachment" "AdministratorAccess_attachment" {
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
+ role = "TerraCICDOIDCRole"
}
Plan: 3 to add, 0 to change, 0 to destroy.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
terraform_test$ terraform apply -auto-approve
aws_s3_bucket.terraform_state: Refreshing state... [id=terraform-state-hisui]
aws_s3_bucket_versioning.terraform_state: Refreshing state... [id=terraform-state-hisui]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_iam_openid_connect_provider.terraform_cicd will be created
+ resource "aws_iam_openid_connect_provider" "terraform_cicd" {
+ arn = (known after apply)
+ client_id_list = [
+ "sts.amazonaws.com",
]
+ id = (known after apply)
+ tags_all = (known after apply)
+ thumbprint_list = [
+ "6938fd4d98bab03faadb97b34396831e3780aea1",
]
+ url = "https://token.actions.githubusercontent.com"
}
# aws_iam_role.terraform_cicd_oidc_role will be created
+ resource "aws_iam_role" "terraform_cicd_oidc_role" {
+ arn = (known after apply)
+ assume_role_policy = (known after apply)
+ create_date = (known after apply)
+ force_detach_policies = false
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ max_session_duration = 3600
+ name = "TerraCICDOIDCRole"
+ name_prefix = (known after apply)
+ path = "/"
+ role_last_used = (known after apply)
+ tags_all = (known after apply)
+ unique_id = (known after apply)
}
# aws_iam_role_policy_attachment.AdministratorAccess_attachment will be created
+ resource "aws_iam_role_policy_attachment" "AdministratorAccess_attachment" {
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
+ role = "TerraCICDOIDCRole"
}
Plan: 3 to add, 0 to change, 0 to destroy.
aws_iam_openid_connect_provider.terraform_cicd: Creating...
aws_iam_openid_connect_provider.terraform_cicd: Creation complete after 1s [id=arn:aws:iam::××××××××××××:oidc-provider/token.actions.githubusercontent.com]
aws_iam_role.terraform_cicd_oidc_role: Creating...
aws_iam_role.terraform_cicd_oidc_role: Creation complete after 1s [id=TerraCICDOIDCRole]
aws_iam_role_policy_attachment.AdministratorAccess_attachment: Creating...
aws_iam_role_policy_attachment.AdministratorAccess_attachment: Creation complete after 1s [id=TerraCICDOIDCRole-××××××××××××]
AWS コンソールでも作成が確認できました
いったんここまでの内容を main ブランチに commit、push しておきます
$ git add .
$ git commit -m "create_OIDC"
$ git push
GitHub Actions で AWS にアクセスできるかテスト
terraform_test リポジトリから AWS にアクセスできるかテストしてみます!
main ブランチからテスト用の test ブランチをきります
terraform_test$ git branch
* main
terraform_test$ git checkout -b test
Switched to a new branch 'test'
terraform_test$ git branch
main
* test
GitHub Actions のワークフローを定義するため、 .github/workflows/aws_access_test.ymlを作成します
.github/workflows/ 配下の YAML ファイルに ワークフローを定義することで GitHub Actions を使用できます
(ディレクトリ)
terraform_test
├── .github
│ └── workflows
│ └── aws_access_test.yml // 作成
├── .gitignore
├── README.md
├── iam.tf
└── main.tf
こちらを参考に aws_access_test.yml に記述していきます
name: AWS Deploy
on:
push:
branches:
# 作業ブランチ
- test
env:
# ×××××××××:AWSアカウントID
AWS_ROLE_ARN: arn:aws:iam::×××××××××:role/TerraCICDOIDCRole
permissions:
id-token: write
contents: read
jobs:
aws-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: ${{ env.AWS_ROLE_ARN }}
aws-region: ap-northeast-1
- run: aws sts get-caller-identity
test ブランチに push した際に
aws sts get-caller-identity
が実行されるワークフローが定義できました!
このワークフローでGitHub Actions から AWS にアクセスできるか push して確認します
terraform_test$ git add .
terraform_test$ git commit -m "commit aws_access_test.yml"
terraform_test$ git push origin test
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 16 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 743 bytes | 743.00 KiB/s, done.
Total 5 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
remote:
remote: Create a pull request for 'test' on GitHub by visiting:
remote: https://github.com/×××××××××/terraform_test/pull/new/test
remote:
To https://github.com/×××××××××/terraform_test.git
* [new branch] test -> test
GitHub > リポジトリ > Actions から結果を確認できます
無事成功していますね!
参考
Discussion