GitHub ActionsとAWSのOIDC連携で特定のRepositoryやBranchにのみAssumeRoleを許可させてみた

2022.04.25

この記事は公開されてから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 で試してみます。StringLikeOperator によりこのようなワイルドカード(*)の使用が可能となります。

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

  • Repositoryaws-cdk-v2-project(一致)
  • Branchfeature/hoge1に Commit を Push(一致)

Workflow の実行が成功しました。

パターン2

  • Repositoryaws-cdk-v2-project(一致)
  • feature/hoge1からdevelopに Branch を Merge(一致?)

AssumeRole がNot authorized to perform sts:AssumeRoleWithWebIdentityとなり Workflow の実行が失敗しました。Merge 時は Compare Branch ではなく、Base Branch が Condition で許可されている必要があるようです。

パターン3

  • Repositoryaws-cdk-v2-project(一致)
  • Branchaaaaaaaaaaに Commit を Push(不一致)

Branchaaaaaaaaaaに Commit を Push すると、AssumeRole がNot authorized to perform sts:AssumeRoleWithWebIdentityとなり Workflow の実行が失敗しました。

パターン4

  • Repositoryaws_cdk_app(不一致)
  • Branchfeature/hoge1に Commit を Push(一致)

AssumeRole がNot authorized to perform sts:AssumeRoleWithWebIdentityとなり Workflow の実行が失敗しました。

補足

StringEqualsで指定する場合

Condition でワイルドカードを使わずに、StringEqualsOperator で複数の値を指定することもできます。

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 連携をする際には要確認しておきたいですね。

以上