OIDC を使って GitHub Actions から AWS CDK を動かす
概要
OIDC(OpenID Connect)
GitHub Actions は OIDC(OpenID Connect)を使って動作させることができます。AWS でいうと、クレデンシャルを GitHub 上にシークレットとして埋め込まずに、IAM ロールの ARN をシークレットに埋め込んで利用できます。
クレデンシャルを ARN に変更できると、セキュリティリスクを大きく減らすことができます。また IAM ロールも CDK の bootstarp
で作られたものだけを使うので、最小権限で環境を作れます。
リポジトリ
下記リポジトリにて本記事の動作を確認できます。
構築
1. CDK 環境構築
① bootstrap
ローカルに CDK でデプロイできる環境を作ります。cdk bootstrap
で Assume Role 用の IAM ロールを作っておきます。
$ cdk init app --language typescript
$ npm run build
$ cdk bootstrap --profile XXX
② cdk deploy
ローカルからのデプロイを確認しておきます。デプロイするリソースはなんでもよいです。ここでは簡単なS3を作成しています。
💡コードは下記から拝借しつつ、若干変更を加えています。
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
export class GithubActionsOidcCdkServerlessStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const bucket = new s3.Bucket(this, 'CreateBucket', {
bucketName: "github-actions-oidc-cdk-20240831",
versioned: true,
removalPolicy: cdk.RemovalPolicy.DESTROY
});
}
}
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { GithubActionsOidcCdkServerlessStack } from '../lib/github-actions-oidc-cdk-stack';
const app = new cdk.App();
new GithubActionsOidcCdkServerlessStack(app, 'GithubActionsOidcCdkStack', {
});
- 差分の確認
$ cdk diff --profile XXX
- デプロイ
$ cdk deploy --profile XXX
2. IAM ロールの作成
この記事ではAWSコンソールで作成します。
① ID プロバイダの作成
IAM ロール → ID プロバイダ → プロバイダを追加
- プロバイダのタイプ:OpenID Connect
- プロバイダの URL:https://token.actions.githubusercontent.com
- 対象者:sts.amazonaws.com
② IAM ロールの作成
- カスタム信頼ポリシー
pull request
では、cdk diff
、merge
では、cdk deploy
という動作を想定して作ります。ブランチは簡易的なものとして、feature/XXX から master にpull request
、merge
されることを想定しています。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<アカウントID>:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:<GitHubユーザー名>/<GitHubリポジトリ名>:*"
}
}
}
]
}
💡 ブランチを絞りたい場合
Condition の部分を変更します。
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:<GitHubユーザー名>/<GitHubリポジトリ名>:ref:refs/heads/<ブランチ名>"
}
}
- IAM ポリシー
cdk bootstrap
で作成される IAM ロール名は共通です。アカウント ID だけかえましょう。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": [
"arn:aws:iam::<アカウントID>:role/cdk-hnb659fds-deploy-role-<アカウントID>-ap-northeast-1",
"arn:aws:iam::<アカウントID>:role/cdk-hnb659fds-file-publishing-role-<アカウントID>-ap-northeast-1",
"arn:aws:iam::<アカウントID>:role/cdk-hnb659fds-image-publishing-role-<アカウントID>-ap-northeast-1",
"arn:aws:iam::<アカウントID>:role/cdk-hnb659fds-lookup-role-<アカウントID>-ap-northeast-1"
]
}
]
}
3. GitHub Actions 設定
① IAM ロールの ARN シークレット登録
Settings → Security → Secrets and variables → Actions → New repository secret
コード上で使うシークレット名をいれて、実際の ARN は Secret に入力する
② GitHub Actions 設定ファイルの作成
name: cdk
on:
push:
branches:
- master
pull_request:
jobs:
aws_cdk:
runs-on: ubuntu-latest
env:
AWS_REGION: "ap-northeast-1"
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup dependencies
run: npm ci
- name: Assume Role
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: CDK Diff Check
if: contains(github.event_name, 'pull_request')
run: npm run cdk:diff
- name: CDK Deploy
if: contains(github.event_name, 'push')
run: npm run cdk:deploy
③ package.json の編集
scripts に cdk:diff と cdk:deploy を追記する。
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"test": "jest",
"cdk": "cdk",
"cdk:diff": "cdk diff",
"cdk:deploy": "cdk deploy --require-approval never"
},
動作確認
あとは master ブランチに対して pull request
すれば、 cdk diff
が動作、 merge
をすれば、 cdk deploy
が動作します。
-
cdk diff
-
cdk deloy
一度ローカルからデプロイしてるので、no changes になっています。実際にデプロイさせたい場合は CDK のコードを変更させてみましょう。
おわり☺️
参考
感謝です🙏
Discussion