🌟

【AWS】【Terraform】OIDCを作成してGitHubActionsからAWSへアクセスできるようにする

2025/01/03に公開

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 から結果を確認できます

無事成功していますね!

参考

https://zenn.dev/rinchsan/articles/de981e561eb36ebfab70

https://go-journey.club/archives/17053

https://rurukblog.com/post/GitHub-Actions-Terraform/

Discussion