こちらの記事はAWS Lambda 実践入門 Advent Calendar 2025 11日目の記事になります。
はじめに
AWS Lambda における CI/CD は、これまで AccessKey/SecretKey を環境変数に入れて実行する方式が主流でした。
しかしこの方式は、運用が続くほど次のリスクが顕在化します。
- 誤ってキーが漏洩すると即アウト(影響範囲が読めない)
- ローテーションが「いつかやる」で止まりがち
- 権限が広すぎる設定が温存されやすい
- 監査で「長期クレデンシャルの管理」を問われやすい
そこで AWS と CI/CD の最新トレンドは 「OIDC(OpenID Connect)で安全に AssumeRole する方式」 です。
この記事では、CircleCI × OIDC × SAM を組み合わせて “壊れないデプロイ(安全・再現性・監査性が揃う)” を実現する方法を紹介します。
また Day10 の「最新 Layer ARN を自動取得」と接続し、 “最新 Layer を参照しつつ、鍵レスでデプロイ” までを一気通貫で作ります。
OIDC(OpenID Connect) とは?(最短 30 秒で理解)
CI/CD が AWS に対して「短時間だけ有効な一時クレデンシャル」を発行してもらう仕組みです。
ポイントは次の 3 つです。
- CircleCI はジョブ実行時に OIDC トークン(ID Token)を発行する
(環境変数$CIRCLE_OIDC_TOKEN/$CIRCLE_OIDC_TOKEN_V2で参照できる) - AWS 側は「この発行元(CircleCI)を信頼する」設定を行う
- STS が
AssumeRoleWithWebIdentityで一時クレデンシャルを払い出す
何が “壊れない” のか
-
秘密情報(長期キー)を持たない
→ 漏洩事故のクラスを消す -
最小権限で実行できる
→ “できてしまう事故” を防ぐ -
誰が・いつ・どの経路でデプロイしたか追跡できる
→ 監査・調査が壊れない -
デプロイ手順が再現可能(環境差分が出にくい)
→ 人間の手作業・属人性で壊れない
OIDC は 1 と 3 を強力に満たします。2 と 4 は IAM 設計と CI 設計で補強して完成します。
手順1:AWS 側(OIDC Provider と IAM Role)を作る
1) IAM Identity Provider(OIDC Provider)を作成
CircleCI の AWS OIDC では、プロバイダ URL は次の形式です。
https://oidc.circleci.com/org/<organization_id>
Audience(aud)はデフォルトで Organization ID です。
(カスタム aud を使う場合は CircleCI 側でカスタムクレームを発行します)
※ Organization ID は CircleCI の Organization Settings から確認できます。
2) Assume 用 IAM Role を作る(Trust Policy が肝)
最初は「Organization だけ許可」でも動きますが、実務では Project / Branch まで絞るのが推奨です。
Project で絞る例(まずはここまでで十分)
sub クレームを StringLike で絞ります。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/oidc.circleci.com/org/<organization_id>"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"oidc.circleci.com/org/<organization_id>:sub": "org/<organization_id>/project/<project_id>/user/*"
}
}
}
]
}
Branch(main)で絞る例(より堅牢)
$CIRCLE_OIDC_TOKEN_V2 の sub 形式を前提に、main ブランチのみ許可します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/oidc.circleci.com/org/<organization_id>"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"oidc.circleci.com/org/<organization_id>:sub": "org/<organization_id>/project/*/user/*/vcs-origin/github.com/<your-org>/*/vcs-ref/refs/heads/main"
}
}
}
]
}
手順2:CircleCI 側(aws-cli orb で OIDC セットアップ)
CircleCI では circleci/aws-cli orb の aws-cli/setup を使うのが最短です。このコマンドが OIDC トークンを使った認証セットアップを自動で行います。
CircleCI の設定例(実用形式)
- aws-cli/setup:
role_arn: ${AWS_ROLE_ARN}
region: ${AWS_REGION}
profile_name: OIDC-PROFILE
role_session_name: deploy-session
session_duration: "900"
補足:
-
session_durationは短くするほど安全です(例:15分) - CircleCI の OIDC トークンは
expが発行から 1 時間のため、長時間ジョブは避ける設計が無難です
手順3:SAM デプロイに統合する(validate → build → deploy)
「壊れない」に寄せるなら、最低でも validate を先に入れます。
sam validate
sam build
sam deploy \
--region "${AWS_REGION}" \
--no-fail-on-empty-changeset \
--no-confirm-changeset
Day10 と合体:最新 Layer ARN を安全に注入する
Day10 で「最新 Layer ARN を取得してファイルに保存」している前提で、
それを workspace 経由で deploy に渡します。
例:get-layer → deploy の 2 ジョブ構成(workspace で受け渡し)
version: 2.1
orbs:
aws-cli: circleci/aws-cli@5
jobs:
get-layer-arn:
docker:
- image: cimg/aws:2025.01
steps:
- checkout
- run:
name: "Get latest Layer ARN (Day10)"
command: |
./scripts/get_layer_arn.sh
cat scripts/layer_arn.txt
- persist_to_workspace:
root: .
paths:
- scripts/layer_arn.txt
deploy:
docker:
- image: cimg/aws:2025.01
environment:
AWS_REGION: ap-northeast-1
steps:
- checkout
- attach_workspace:
at: .
- aws-cli/setup:
role_arn: ${AWS_ROLE_ARN}
region: ${AWS_REGION}
profile_name: OIDC-PROFILE
role_session_name: deploy-session
session_duration: "900"
- run:
name: "SAM Deploy"
command: |
LAYER_ARN="$(cat scripts/layer_arn.txt)"
echo "Using Layer ARN: ${LAYER_ARN}"
sam build
sam deploy \
--region "${AWS_REGION}" \
--no-fail-on-empty-changeset \
--no-confirm-changeset \
--parameter-overrides LayerArn="${LAYER_ARN}"
workflows:
deploy-workflow:
jobs:
- get-layer-arn
- deploy:
context: aws
requires:
- get-layer-arn
ポイント:
- Day10 の成果(Layer ARN 自動取得)を workspace で確実に引き継ぐ
- Day11 の成果(OIDC)で AWS 側に鍵を置かない
- “安全に最新へ追従” が CI/CD の標準形になります
よくあるハマりどころ(短く潰す)
- Trust Policy がゆるい:最初は動いても、後で事故る。Project / Branch で絞る
- Role の権限が強すぎる:最小権限に寄せる(少なくとも “デプロイに必要な範囲” だけ)
- トークンの有効期限:長いジョブは分割(build と deploy を分けると安定する)
-
Parameter 名の不一致:
LayerArnは template.yaml の Parameters 名に合わせる
まとめ
- OIDC + SAM は現代の Lambda デプロイ標準
- AccessKey/SecretKey を CI/CD から排除できる
- Trust Policy を Project / Branch で絞ると “壊れない” に近づく
- Day10(Layer ARN 自動取得)と組み合わせると「安全に最新へ追従」できる