GitHub ActionsでOpenID Connect(OIDC)認証を使ってTerraformをデプロイする(AWS)
はじめに
GitHub Actionsを使ったAWSへのTerraformデプロイ方法について、OpenID Connect(OIDC)を使用したセキュアな認証方法を使用する方法で設定してみます。
この方法を使うことで、AWSのアクセスキーを直接GitHub Secretsに保存する必要がなくなり、よりセキュアなCI/CDパイプラインを構築することができます。
OIDCとは
OpenID Connect(OIDC)は、OAuth 2.0プロトコルの上に構築された認証レイヤーです。OIDCを使用することで、アプリケーション(この場合はGitHub Actions)は別のサービス(AWS)に対して安全に認証を行うことができます。
GitHub ActionsのOIDC認証フロー
GitHub ActionsでAWS IAMロールのOIDC認証フローは通常の下記のようになります。
以下に各ステップの詳細を説明します:
- GitHub Actionsワークフローが開始されると、GitHub OIDCプロバイダーにOIDCトークン(JWT) をリクエストします。
- GitHub OIDCプロバイダーは、ワークフローに対して一意のトークンを発行します。このトークンには、リポジトリ名、ブランチ名、ジョブ名などの情報が含まれます。
- GitHub Actionsは、このトークンを使用してAWS Security Token Service (STS) の AssumeRoleWithWebIdentity APIを呼び出します。
- AWS STSは、受け取ったトークンを使用してAWS IAMロールに対する認証を試みます。IAMロールには、GitHub OIDCプロバイダーを信頼するように設定されたトラストポリシーが定義されている必要があります。
- AWS IAMは、トークンの内容とトラストポリシーを照合し、ロールの引き受けを承認します。
- 承認が成功すると、AWS STSはGitHub Actionsに対して一時的なAWS認証情報を提供します。
- GitHub Actionsは、これらの一時的な認証情報を使用してAWSのサービス(S3、EC2、RDSなど)にアクセスし、必要なタスクを実行します。
- AWSサービスは、リクエストに応じてレスポンスを返します。
なぜOIDCを使用するのか
セキュリティの向上:長期的なAWSアクセスキーをGitHubに保存する必要がありません。
管理の簡素化:アクセスキーのローテーションが不要になります。
細かなアクセス制御:特定のリポジトリやブランチからのみAWSリソースにアクセスできるように制限できます。
設定手順
前提条件
- デプロイするためのAWSアカウントがあること
- Terraform実行する環境が準備できていること
環境構築手順は下記記事を参照ください
Terraformを使うための環境構築手順をまとめてみた(AWS編)~Windows - GitHubアカウントがあること
1.GitHubでOrganizationを設定する
-
GitHubのコンソールで「Organizations」→「New Organization」を選択します
GitHubプランの選択画面が出ます。今回はFreeプランで問題ないので、一番左のFreeプランの「Create a free organization」を選択します。
-
Organization Name、Contact emailを入力します。今回は個人用なので「My personal account」を選択します
-
作成したOrganizationにユーザーを追加する画面になります
作成したユーザーはすでに追加されていますので、そのまま「Complete setup」を選択します。
Confirm accessで、再度GitHubのアクセスキーなどを入力して、Organization作成完了です。
作成したOrganization名は、のちほど使用します。
-
GitHub Actionsを使用するリポジトリを作成します
Organizationで、「Repositories」→「New repository」を選択します。
-
下記のような設定でリポジトリを作成します
Repository name:適当に名前をつけます
Private:今回はプライベートとします
Add .gitignore:今回はTerraformのHCLを管理するつもりなのでTerraformを選択
DescriptionとREADMEはお好みで、Choose a licenseは必要に応じて
「Create repository」を選択してリポジトリを作成します。
2.AWSでOIDCプロバイダーを設定する
GitHubの公式手順はこちら
OIDCプロバイダーやIAMロールもTerraformで作成したほうが管理しやすいと思いますが、今回はマネージメントコンソールで作成していきます。
-
AWSマネージメントコンソールでIAMに移動し、「IDプロバイダー」→「プロバイダーを追加」を選択します
-
「プロバイダーの設定」で下記のように設定します
タイプ:OpenID Connect
プロバイダーURL:https://token.actions.githubusercontent.com
対象者(Audience):sts.amazonaws.com
タグはお好みで入力して「プロバイダーを追加」を押すと、プロバイダーが追加されました。
3.IAMロールを作成する
-
IAM コンソールで「ロール」→「ロールの作成」を選択します
-
「信頼されたエンティティを選択 」で下記のように設定して「次へ」を選択します
信頼されたエンティティタイプ:ウェブアイデンティティ
アイデンティティプロバイダー:2で作成したGitHub ActionsのOIDCプロバイダー(https://token.actions.githubusercontent.com
)
Audience:2で設定したAudience(sts.amazonaws.com
)
GitHub組織:1で設定したGitHub Organization名
GitHubリポジトリ-オプション:許可するGitHubリポジトリとして1で作成したリポジトリ名
GitHub ブランチ-オプション:許可するGitHubブランチ(今回はスキップ)
-
必要なAWSの権限を付与して「次へ」を選択します
GitHub Actionsをじっこうするにあたり必要な権限を持つポリシーを選択します。
今回はAdministratorAccessを選択しますが、本来は必要最低限なポリシーを付与することが望ましいです。
-
ロール名を入力して「ロールを作成」を選択します
4.GitHub ActionsのSecretを作成する
GitHub Actionsのワークフロー内で使用するシークレットを登録します。3で作成したロールのARNをシークレットとして登録しておきます。
GitHubコンソールで1で作成したリポジトリを選択し、「Setting」タブから左メニュー内「Secrets and variables」のactionsを選択します。
「New repository secret」を押します。
シークレット名はASSUME_ROLE_ARN
とし、Secretは3で作成したロールのARN(arn:aws:iam::123456789012:role/kiku_github_terraform
)を設定します。
「Add secret」でシークレットを登録します。
5.GitHub Actionsワークフローを作成する
GitHub Actionsでワークフローを作成していきます。
-
まず1で作成したリポジトリをローカルPCにCloneします
普通にcloneしようとすると下記のようなSign inウィンドウが出ると思うので、WebブラウザやTokenを使用してSign inします。
-
ローカルPCにCloneしたリポジトリのフォルダを開きます
おそらくなかには.gitignoreやREADMEなどがあると思います(リポジトリ作成時の設定によっては何もない場合があります)。
.github
というフォルダを作成してフォルダを開き、なかにworkflows
というフォルダを作成します。
私の場合は下記のようなフォルダ構成となります。
workflows
フォルダ内にGitHub Actionsの動作を定義するYAMLファイルを下記のように作成します。
name: Terraform Deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
on:
push:
branches:
- main
paths:
- "terraform/**"
jobs:
deploy:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{secrets.ASSUME_ROLE_ARN}}
aws-region: ap-northeast-1
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.9.1
- name: Terraform Init
run: terraform -chdir=./terraform init
- name: Terraform Plan
run: terraform -chdir=./terraform plan
- name: Terraform Apply
run: terraform -chdir=./terraform apply -auto-approve
env: GitHub Actionsワークフロージョブの認証用トークン${{ secrets.GITHUB_TOKEN }}
を設定します。
こちらはあらかじめ用意されているシークレットなので自分でシークレットを登録する必要はありません。
on:ワークフローのトリガを設定します。
今回はmainブランチのterraform下にpushされた場合の自動トリガと手動トリガの両方を設定しておきます。
runs-on: ジョブを実行するランナーの設定をします。
セルフホステッドランナーを使用する場合もここで設定します。
timeout-minutes: ジョブのタイムアウト設定です。
設定しない場合はタイムアウトはデフォルト360分となりますので、適切な値を設定しておいたほうがいいと思います。
permissions: ジョブの権限設定です。
steps: ここで実際の動作を記載していきます。
uses
は、あらかじめ用意されたアクションを設定します。
actions/checkout@v4
のactions/
はGitHub公式のアクションです。
hashicorp/
などはサードパーティのアクションとなります。
checkout@v4
のcheckout
がアクション名となり、@v4
がバージョンになります。
with
で変数を設定します。
run
は、任意のコマンドを実行します。
role-to-assumeのところには[4](#4.GitHub ActionsのSecretを作成する)で作成したロールのシークレット(ASSUME_ROLE_ARN
)を設定しています。
GitHub Actions実行結果をSlackなどに通知するジョブを記載しておくと、GitHubコンソールで結果を確認しなくてもよいので楽です(今回は省略します)。
GitHub Actionsワークフローの記載方法の詳細は下記
- 作成したYAMLをPushしておきます
git add .
git commit -m "Add GitHub workflow"
git push origin main
6.GitHub Actionsワークフロー実行
- リポジトリ直下にterraformフォルダを作成します
- terraformフォルダ直下でtfファイルを作成します
下記を参考に簡単なtfファイルを作成します。
Terraformを使うための環境構築手順をまとめてみた(AWS編)~Windows
下記のような感じで一旦VPCとサブネットをデプロイしてきます。
resource "aws_vpc" "main" {
cidr_block = "10.1.0.0/16"
instance_tenancy = "default"
tags = {
Name = "test-vpc"
}
}
resource "aws_subnet" "main" {
vpc_id = aws_vpc.main.id
cidr_block = "10.1.0.0/24"
tags = {
Name = "private"
}
}
- tfファイルをPushします。
git add main.tf provider.tf
git commit -m "Add terraform tf file"
git push origin main
これによりワークフローがトリガされて、TerraformでVPCとサブネットが作成されます。
-
GitHubコンソールで対象リポジトリのActionsタブを開くと、workflowが並んでいます。
実行中のワークフローは黄色マークがついており、失敗(エラー)が赤、成功は緑となっています。
(ちなみに最初のワークフローは私のミスによりエラーになりました...)
ワークフローをクリックすると、詳細情報を確認できます。
下記だとワークフローが30秒で完了していますが、初めて実行したワークフローの場合はもっと時間がかかると思います。
ワークフロー内の各stepの実行内容も確認することができます。
-
AWSマネージメントコンソールで確認すると、ちゃんとリソースが作成されています。
まとめ
GitHub ActionsをOIDC認証で使えるように設定し、実際にGitHub ActionsのワークフローでTerraformを実行してAWS環境にデプロイしてみました。
Discussion