この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX 事業本部 IoT 事業部の若槻です。
今回は、GitHub Actions と AWS の OIDC 連携で特定の Repository や Branch にのみ AssumeRole を許可させてみました。
設定箇所
GitHub と AWS の OIDC 連携をさせるためには、AWS には次の 2 つのリソースを作成する必要があります。
- ID Provider
- IAM Role(および Inline Policy)
そして OIDC 可能な GitHub の Repository や Branch を制限する場合は、IAM Role の Trusted entities のConditionを設定する必要があります。
Trusted entities
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<Account ID>:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:<Account>/<Repository>:ref:refs/heads/<Branch>"
}
}
}
]
}
IAM Role の Trusted entities は、マネジメントコンソールで上だと[Trust relationships]の[Trusted entities]で確認および設定できます。
AWS CDK で作成するならaws_iam.FederatedPrincipal
の第二引数が Condition に該当する部分です。(詳細は以前のエントリを参照)
lib/aws-cdk-v2-project-stack.ts
const oidcDeployRole = new aws_iam.Role(this, 'GitHubOidcRole', {
roleName: 'github-oidc-role',
assumedBy: new aws_iam.FederatedPrincipal(
gitHubIdProvider.openIdConnectProviderArn,
{
StringLike: {
'token.actions.githubusercontent.com:sub': props.principalFederatedSub,
},
},
'sts:AssumeRoleWithWebIdentity'
),
});
やってみた
次の Workflow で試してみます。Secret から取得した IAM Role の Arn をaws-actions/configure-aws-credentialsで使用して OIDC による AssumeRole を行っていまうす。
.github/workflows/cicd.yaml
on:
push:
paths-ignore:
- '**/*.md'
jobs:
assumerole:
runs-on: ubuntu-latest
env:
AWS_OIDC_ROLE_ARN: ${{ secrets.AWS_OIDC_ROLE_ARN }}
AWS_REGION: ap-northeast-1
permissions:
id-token: write
contents: read
steps:
- name: debug
run: |
echo AWS_OIDC_ROLE_ARN: ${AWS_OIDC_ROLE_ARN/::*:/::XXXXXXXXXXXX:}
- name: Assume Role
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: ${{ env.AWS_OIDC_ROLE_ARN }}
aws-region: ${{env.AWS_REGION}}
Repository 名がaws-cdk-
から始まり、Branch 名がfeature/
から始まるという Condition で試してみます。StringLike
Operator によりこのようなワイルドカード(*
)の使用が可能となります。
Trusted entities
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::XXXXXXXXXXXX:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:cm-rwakatsuki/aws-cdk-*:ref:refs/heads/feature/*"
}
}
}
]
}
使用できる Condition operator については下記をご参照ください。
パターン1
- Repository
aws-cdk-v2-project
(一致) - Branch
feature/hoge1
に Commit を Push(一致)
Workflow の実行が成功しました。
パターン2
- Repository
aws-cdk-v2-project
(一致) feature/hoge1
からdevelop
に Branch を Merge(一致?)
AssumeRole がNot authorized to perform sts:AssumeRoleWithWebIdentity
となり Workflow の実行が失敗しました。Merge 時は Compare Branch ではなく、Base Branch が Condition で許可されている必要があるようです。
パターン3
- Repository
aws-cdk-v2-project
(一致) - Branch
aaaaaaaaaa
に Commit を Push(不一致)
Branchaaaaaaaaaa
に Commit を Push すると、AssumeRole がNot authorized to perform sts:AssumeRoleWithWebIdentity
となり Workflow の実行が失敗しました。
パターン4
- Repository
aws_cdk_app
(不一致) - Branch
feature/hoge1
に Commit を Push(一致)
AssumeRole がNot authorized to perform sts:AssumeRoleWithWebIdentity
となり Workflow の実行が失敗しました。
補足
StringEqualsで指定する場合
Condition でワイルドカードを使わずに、StringEquals
Operator で複数の値を指定することもできます。
Trusted entities(抜粋)
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:sub": [
"repo:cm-rwakatsuki/aws-cdk-v2-project:ref:refs/heads/feature/hoge1",
"repo:cm-rwakatsuki/aws-cdk-v2-project:ref:refs/heads/develop",
]
}
}
おわりに
GitHub Actions と AWS の OIDC 連携で特定の Repository や Branch にのみ AssumeRole を許可させてみました。
IAM Role 側で今回のような制限を行うことにより、Role が不本意な Repository で使われてしまったり、不必要な AWS アカウントへの AssumeRole が可能となってしまったりするリスクを権限することができます。OIDC 連携をする際には要確認しておきたいですね。
以上