GitHub Actions上でTerraformを実行する際にAWS ProviderでProfileを使う方法

GitHub Actions上でTerraformを実行する際にAWS ProviderでProfileを使う方法

2026.02.15

Terraform AWS Providerでは以下のようにAWSプロファイルを指定することができます。

例えば以下のように設定して、main.tfを使ってterraform planを行うとAWSプロファイルdev-1に対してterraform planが行われます。

main.tf
provider "aws" {
  region  = "us-east-1" # Replace with your desired AWS region
  profile = "dev-1"
}
~/.aws/config
[profile dev-1]
region = ap-northeast-1
output = text
[profile dev-2]
region = ap-northeast-1
output = text

Docs overview | hashicorp/aws | Terraform | Terraform Registry

今回はProvider定義でprofileを指定しつつ、GitHub Actions上でTerraformを実行してみました。

GitHub Actionsから各AWSアカウントのIAMロール引き受け

architecture-diagram.png

GitHub ActionsでJumpアカウントのIAMロールを使って、dev-1とdev-2のIAMロールを引き受ける形にしています。

この方法の他にGitHub ActionsのOIDC用IAMロールをdev-1とdev-2にそれぞれデプロイして直接GitHub Actionsからdev-1とdev-2のIAMロールを使うことも1つの方法です。

Jumpアカウントを経由した理由は、プロファイルの切り替えをGitHub Actionsではなく、設定ファイル(./aws/config)で行いたかったからです。

1ワークフローファイルで複数のAWSアカウント認証情報を扱う場合、AWS認証情報のログイン処理(aws-actions/configure-aws-credentials)を複数回実行する必要があります。

AWSアカウントの数が増えてくるとGitHub Actionsワークフローファイルが煩雑になっていきます。

各AWSアカウントの認証情報を./aws/configで管理することでGitHub Actionsワークフローファイルをシンプルにしました。

ちなみにaws-actions/configure-aws-credentialsは執筆時点(2026/2時点)でAWSプロファイルに対応していません。

https://github.com/aws-actions/configure-aws-credentials/issues/1586

ディレクトリ構成

検証用サンプルコードのディレクトリ構成は以下です。

.
├── .github
│   └── workflows
│       └── terraform.yml
├── environments
│   ├── dev-1
│   │   └── main.tf
│   └── dev-2
│       └── main.tf
├── README.md
└── setup
    ├── oidc-role
    │   └── main.tf
    └── target-account-resources
        ├── env
        │   ├── dev1.tfbackend
        │   └── dev2.tfbackend
        ├── main.tf
        └── terraform.tfvars.example

GitHub Actions OIDC用IAM Roleを作成(Jumpアカウント)

JumpアカウントににGitHub Actions OIDC用IAM Roleを作成します。

以下のコードを準備します。

setup/oidc-role/main.tf
# GitHub Actions OIDC用のIAMロール
# terraform-aws-modules/github-oidc-provider/awsモジュールを使用

module "github_oidc_provider" {
  source = "terraform-aws-modules/github-oidc-provider/aws"

  create_oidc_provider = true
  create_oidc_role     = true

  repositories              = ["msato0731/gha-terraform-aws-profile"]
  oidc_role_attach_policies = []

  tags = {
    Purpose = "GitHub Actions OIDC"
  }
}

# 他のAWSアカウントのデプロイ用ロールをAssumeするためのポリシー
resource "aws_iam_role_policy" "assume_deploy_roles" {
  name = "AssumeDeployRoles"
  role = module.github_oidc_provider.oidc_role_name

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = "sts:AssumeRole"
        Resource = [
          "arn:aws:iam::*:role/terraform-deploy"
        ]
      }
    ]
  })
}

output "role_arn" {
  description = "GitHub Actions用IAMロールのARN"
  value       = module.github_oidc_provider.oidc_role_arn
}

Terraformを実行してリソースを作成します。role_arnが出力されるためこれを控えておきます。

terraform init
terraform plan
terraform apply

各AWSアカウントにTerraformデプロイ用のロール・バックエンド用のS3バケットを作成(Dev-1/Dev-2アカウント)

続いてDev-1/Dev-2アカウントに以下のリソースを作成します。

  • Terraform実行用IAMロール
  • バックエンド用S3バケット

Terraform実行用IAMロールはJumpアカウントにあるGitHub Actions OIDCロールからAssume Roleできるように設定しておきます。

今回は動作確認でSQSを各アカウントにデプロイします。

そのため、Terraform実行用IAMロールにはSQSへのアクセス権限を与えています。

setup/target-account-resource/main.tf
terraform {
  required_version = ">= 1.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.27"
    }
  }
  backend "local" {
    # pathは実行時に指定
  }
}

data "aws_caller_identity" "current" {}

# デプロイ用IAMロール
resource "aws_iam_role" "terraform_deploy" {
  name = "terraform-deploy"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          AWS = var.github_actions_role_arn
        }
        Action = "sts:AssumeRole"
      }
    ]
  })

  tags = {
    Purpose = "Terraform Deployment"
  }
}

# SQS操作用のポリシー
resource "aws_iam_role_policy" "sqs_policy" {
  name = "SQSPolicy"
  role = aws_iam_role.terraform_deploy.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "sqs:CreateQueue",
          "sqs:DeleteQueue",
          "sqs:GetQueueAttributes",
          "sqs:GetQueueUrl",
          "sqs:ListQueues",
          "sqs:ListQueueTags",
          "sqs:TagQueue",
          "sqs:UntagQueue"
        ]
        Resource = "*"
      }
    ]
  })
}

# S3バケット操作用のポリシー(Terraformバックエンド用)
resource "aws_iam_role_policy" "s3_backend_policy" {
  name = "S3BackendPolicy"
  role = aws_iam_role.terraform_deploy.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "s3:GetObject",
          "s3:PutObject",
          "s3:DeleteObject",
          "s3:ListBucket"
        ]
        Resource = [
          aws_s3_bucket.terraform_backend.arn,
          "${aws_s3_bucket.terraform_backend.arn}/*"
        ]
      }
    ]
  })
}

# Terraformバックエンド用S3バケット
resource "aws_s3_bucket" "terraform_backend" {
  bucket = "terraform-backend-${data.aws_caller_identity.current.account_id}-20260213"

  tags = {
    Purpose = "Terraform Backend"
  }
}

resource "aws_s3_bucket_versioning" "terraform_backend" {
  bucket = aws_s3_bucket.terraform_backend.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_backend" {
  bucket = aws_s3_bucket.terraform_backend.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

resource "aws_s3_bucket_public_access_block" "terraform_backend" {
  bucket = aws_s3_bucket.terraform_backend.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}


variable "github_actions_role_arn" {
  description = "GitHub Actions OIDC用IAMロールのARN"
  type        = string
}

output "role_arn" {
  description = "デプロイ用IAMロールのARN"
  value       = aws_iam_role.terraform_deploy.arn
}

output "role_name" {
  description = "デプロイ用IAMロール名"
  value       = aws_iam_role.terraform_deploy.name
}

output "s3_bucket_name" {
  description = "TerraformバックエンドS3バケット名"
  value       = aws_s3_bucket.terraform_backend.bucket
}

JumpアカウントのGitHub Actions OIDC用IAMロールのARNはterraform.tfvarsで渡します。

terraform.tfvars
# GitHub Actions OIDC用IAMロールのARNを指定
github_actions_role_arn = "arn:aws:iam::0123456789:role/github-actions-role"

バックエンドを切り替えて、dev-1とdev-2を同じTerraformコードで作成します。

以下のファイルを用意します。

env/dev-1.tfbackend
path = "dev-1.tfstate"
env/dev-2.tfbackend
path = "dev-2.tfstate"

それぞれ以下のコマンドを実行して、リソースを各AWSアカウントにデプロイします。

cd setup/target-account-resources
# dev-1にデプロイ
terraform init -reconfigure -backend-config=env/dev-1.tfbackend
terraform plan
terraform apply
# dev-2にデプロイ
terraform init -reconfigure -backend-config=env/dev-2.tfbackend
terraform plan
terraform apply

.aws/configをリポジトリに追加

GitHub Actions上でAWSプロファイルを使うために、.aws/configをリポジトリに追加します。

.aws/config
[profile dev-1]
credential_source=Environment
role_arn=arn:aws:iam::1234567890:role/terraform-deploy

[profile dev-2]
credential_source=Environment
role_arn=arn:aws:iam::2345678901:role/terraform-deploy

credential_source=Environmentを指定することで、環境変数からソース認証情報を取得します。

後述するGitHub Actions aws-actionsconfigure-aws-credentialsを使うと環境変数にAWSアクセスキー・シークレットアクセスキー等がセットされます。

これでJumpアカウントのAWS認証情報がGitHub Actionsの環境変数にセットされます。JumpアカウントのAWS認証情報を使って、dev-1 dev-2のIAMロールを引き受けます。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-role.html

GitHub Actions Workflowファイルの作成

GitHub Actions Workflowファイルを用意します。

.github/workflows/terraform.yml
name: Terraform Deploy

on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  terraform-deploy:
    name: Deploy to Multiple Environments
    runs-on: ubuntu-latest
    environment: dev
    env:
      AWS_CONFIG_FILE: ${{ github.workspace }}/.aws/config

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v6
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }} # JumpアカウントのGitHub Actions OIDCロール
          aws-region: ap-northeast-1

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: 1.14.5

      # Dev-1 Environment
      - name: Terraform Init (Dev-1)
        working-directory: ./environments/dev-1
        run: terraform init

      - name: Terraform Plan (Dev-1)
        working-directory: ./environments/dev-1
        run: terraform plan

      - name: Terraform Apply (Dev-1)
        working-directory: ./environments/dev-1
        run: terraform apply -auto-approve

      # Dev-2 Environment
      - name: Terraform Init (Dev-2)
        working-directory: ./environments/dev-2
        run: terraform init

      - name: Terraform Plan (Dev-2)
        working-directory: ./environments/dev-2
        run: terraform plan

      - name: Terraform Apply (Dev-2)
        working-directory: ./environments/dev-2
        run: terraform apply -auto-approve

今回はテスト用のためトリガーはシンプルにmainブランチへのPush時にしています。

AWS_CONFIG_FILE環境変数を使うことで、AWS CLIが設定プロファイルを保存するために使用するファイルの場所を指定できます。リポジトリの.aws/configにファイルを置いたので、そこを指定しています。

https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html

aws-actions/configure-aws-credentialsでJumpアカウントのGitHub Actions OIDC IAMロールを指定して認証情報を取得しています。

dev-1とdev-2のIAMロールはTerraform実行時にJumpアカウントのIAMロールから引き受けるため、aws-actions/configure-aws-credentialsで設定する必要はありません。

動作確認: GitHub Actions上でTerraformを実行

GitHubリポジトリにファイルをPushしました。

以下の通り、Actionsが成功しました。

fix_configure-aws-credentials_·_msato0731_gha-terraform-aws-profile_0319736.png

各AWSアカウントにもSQSがデプロイされていることを確認できました。

$ aws sqs list-queues --profile dev-1
{
    "QueueUrls": [
        "https://sqs.ap-northeast-1.amazonaws.com/1234567890/sample-queue-dev-1"
    ]
}

$ aws sqs list-queues --profile dev-2
{
    "QueueUrls": [
        "https://sqs.ap-northeast-1.amazonaws.com/2345678901/sample-queue-dev-2"
    ]
}

おわりに

GitHub Actions上でTerraform AWS Providerのprofile設定を活用する方法についてでした。

今回の方法により、GitHub Actionsワークフローファイルをシンプルに保ちながら、複数環境への自動デプロイが可能になります。AWSアカウントが増えてもワークフローファイル側の変更は最小限に抑えられるため、保守性の向上も期待できます。

一方で、Jumpアカウントの管理やIAMロールの設定など初期セットアップの手間はあります。小規模なプロジェクトであれば、環境ごとに個別のOIDCロールを作成する方がシンプルかもしれません。

プロジェクトの規模や運用方針に応じて、最適な方法を選択していただければと思います。

この記事をシェアする

FacebookHatena blogX

関連記事