はじめに
本記事では、GitHub ActionsのOIDCを利用して、
アクセスキー不要でAWSに安全にアクセスする方法を解説します。
TerraformでIAMロールも管理し、
最小権限のCI/CD構成を実現します。
この記事で分かること
- OIDCの仕組み
- IAM信頼ポリシーの書き方
- GitHub Actionsからのロール引き受け方法
- 動作確認の方法
従来はアクセスキーをSecretsに登録して利用する方法が一般的でしたが、
以下のような課題がありました。
- アクセスキーの漏洩リスク
- 定期ローテーションの手間
- 権限管理が煩雑
そこで今回はOIDCを使い、これらの課題を解決します。
OIDCとは
OIDC(OpenID Connect)は、外部サービス(GitHubなど)を信頼し、
一時的な認証情報を発行する仕組みです。
GitHub Actionsの場合は以下の流れになります。
- GitHubがOIDCトークンを発行
- AWSがそのトークンを検証
- IAMロールを一時的に引き受ける(AssumeRole)
これにより、アクセスキーを使わずにAWSへアクセスできます。
全体構成
今回の構成は以下の通りです。
- GitHub Actions → AWSへアクセス
- OIDCで認証
- Terraformでインフラ構築
- IAMロールで最小権限制御
構成図
TerraformでOIDCプロバイダを作成
resource "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"
client_id_list = [
"sts.amazonaws.com"
]
thumbprint_list = [
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
]
}
thumbprint_listの現在の扱い
2023年以降、GitHub Actionsなど一部のOIDCプロバイダでは、
AWS側が信頼済みの証明書を使用するため、
thumbprintによる検証は実質的に不要になりました。
そのため、現在はダミー値(例: ffffffffff...)を指定する方法が一般的です。
ただし、AWS APIの仕様上、thumbprint_list自体は必須項目のため、
完全に空のリストは指定できない点に注意が必要です。
⚠️ 注意
この挙動はGitHub Actionsに特化したものです。
Oktaなど他のOIDCプロバイダでは、
引き続きthumbprintの設定が必要な場合があります。
信頼ポリシー
data "aws_iam_policy_document" "github_actions_assume_role" {
statement {
effect = "Allow"
actions = [
"sts:AssumeRoleWithWebIdentity"
]
principals {
type = "Federated"
identifiers = [aws_iam_openid_connect_provider.github.arn]
}
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = ["sts.amazonaws.com"]
}
condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = [
"repo:xxx/xxx:ref:refs/heads/main",
"repo:xxx/xxx:pull_request"
]
}
}
}
principalsとは
principalsは「誰がこのロールを使ってよいか」を定義します。
Federated を指定することで、
GitHubのような外部IDプロバイダ(OIDC)からのアクセスを許可できます。
audとsubの違い
OIDCではaudとsubの2つの条件が重要です。
aud(Audience)
variable = "token.actions.githubusercontent.com:aud"
👉トークンの宛先を確認
-
sts.amazonaws.comが指定されている - AWS用のトークンかどうかをチェック
sub(Subject)
variable = "token.actions.githubusercontent.com:sub"
👉 実行元を制御
例
repo:xxx/xxx:ref:refs/heads/main
repo:xxx/xxx:pull_request
- リポジトリ
- ブランチ
- イベント
を制御できる
StringLikeとStringEqualsの使い分け
audはStringEquals
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = ["sts.amazonaws.com"]
理由
- sts.amazonaws.comは固定値
- 厳密一致で問題ない
subはStringLike
condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = [
"repo:xxx/xxx:ref:refs/heads/main",
"repo:xxx/xxx:pull_request"
]
}
理由
- ブランチやPRなど複数パターンがある
- ワイルドカードが使えるため、柔軟に設定できる
押さえておくべきポイント
sub条件を適切に設定することで、
「どのブランチからデプロイ可能か」「PRのみ許可するか」など、
CI/CDの挙動をセキュリティレベルで制御できます。
GitHub Actionsの設定
on:
pull_request:
branches:
- main
permissions:
contents: read
id-token: write
pull-requests: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::xxxx:role/xxx
aws-region: ap-northeast-1
GitHub Actionsのトリガー
GitHub Actionsでは、トリガーを決めて、それが発生したときにワークフローが開始されます。
例では、pull_requestされた時をトリガーにしましたが、他に
- プッシュ
- スケジュール
- 手動トリガー
- 外部トリガー
などがあります。
GitHub Actionsのpermissions
GitHub Actions における権限の管理は、ワークフローとアクションが実行時にアクセスできるリソースを制御する重要な機能です。
例では、
- 読み取り
- OIDCトークンを発行する権限(
id-token: write) - プルリクエストに対する書き込み権限
を設定しています。
⚠️ 注意
id-token: write は、GitHub ActionsがOIDCトークンを発行するための権限です。
OIDCトークンは事前に存在するものではなく、
実行時に新しく生成されるため「write」が必要になります。
role-to-assume にTerraformのロールを渡す方法
Terraformで作成したIAMロールは、output でARNを取得できます。
output "github_actions_role_arn" {
value = aws_iam_role.github_actions_terraform.arn
}
このARNをGitHub Actionsで使用します。
実務でのポイント
TerraformのoutputをそのままGitHub Actionsに渡すことはできないため、
- 手動でSecretsに登録
- もしくは変数として管理
といった運用になります
動作確認の方法
OIDCの設定が正しく動いているかは、以下で確認できます。
- name: Check identity
run: aws sts get-caller-identity
出力例
{
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/xxx/xxxx",
"UserId": "xxxx"
}
確認ポイント
- assumed-role になっているか
- 期待したロール名か
👉 ここが一致していれば成功
まとめ
OIDCを使うことで、
安全かつシンプルにAWSへアクセスできるようになります。
今回の構成により、
- アクセスキー不要(Secrets管理が不要)
- ローテーション不要(長期認証情報を持たない)
- 最小権限をコードで管理(Terraformで再現性あり)
といったメリットを実現できます。
