サイトアイコン

toLog

GitHub ActionsでOIDC経由でAWSリソースにアクセスしてみた

  • 更新日:
  • 投稿日:
サムネイル

この記事は最終更新日から2年以上が経過しています。

はじめに

何番煎じ案件ですが、社内にて OIDC 経由で GitHub Actions に AWS アクセスしようぜが話題に上がっていたため、自分の方でも素振りをしてみたので備忘録を残しておきます。 社内の強い人たちの足跡をほぼほぼ辿っただけでしたが、永続的な Credentials を Actions に残したくない気持ちは同じだったので本当に助かります 🙇‍♂️

内容

OIDC 自体の解説はコチラが参考になるかと思います。🙏

まず、AWS 側で GitHub 向けの OIDC と role を設定します。

CDK のサンプルソースが見当たらず、公式が提供する AWS 向けの OIDC カスタムアクション aws-actions/configure-aws-credentials に CFn テンプレートが記述されていたため、それを参考に CDK を起こしています。 CDK で私が記述した場合は以下になります 💦

1// bin/index.ts
2const { principal: githubOIDCPrincipal } = new GitHubOIDC(app, "github-oidc", {
3  env,
4  subject: "repo:sample-org/sample-rep:*",
5});
6
7new IamRole(app, "build-role", {
8  env,
9  roleProps: {
10    roleName: "build",
11    assumedBy: githubOIDCPrincipal,
12    // 操作するリソース向けの policy を設定する必要があります。
13    // 以下の policy では、当然 Lambda のデプロイ等はできません。
14    managedPolicies: [
15      iam.ManagedPolicy.fromAwsManagedPolicyName("AWSCloudFormationFullAccess"),
16      iam.ManagedPolicy.fromAwsManagedPolicyName("IAMFullAccess"),
17    ],
18  },
19});
1// lib/open-id-connect.ts
2import * as cdk from "@aws-cdk/core";
3import * as iam from "@aws-cdk/aws-iam";
4
5type GitHubOIDCProps = cdk.StackProps & {
6  subject: string;
7};
8
9export class GitHubOIDC extends cdk.Stack {
10  public readonly principal: iam.FederatedPrincipal;
11
12  constructor(scope: cdk.App, id: string, props: GitHubOIDCProps) {
13    super(scope, id, props);
14
15    const { subject } = props;
16
17    // https://github.com/aws-actions/configure-aws-credentials#sample-iam-role-cloudformation-template
18    const { openIdConnectProviderArn } = new iam.OpenIdConnectProvider(
19      this,
20      id,
21      {
22        url: "https://token.actions.githubusercontent.com",
23        clientIds: ["sts.amazonaws.com"],
24        thumbprints: ["a031c46782e6e6c662c2c87c76da9aa62ccabd8e"],
25      }
26    );
27
28    // https://docs.github.com/ja/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#configuring-the-role-and-trust-policy
29    this.principal = new iam.FederatedPrincipal(
30      openIdConnectProviderArn,
31      {
32        StringLike: {
33          "token.actions.githubusercontent.com:sub": subject,
34        },
35      },
36      "sts:AssumeRoleWithWebIdentity"
37    );
38  }
39}
1// lib/iam.ts
2
3import * as cdk from "@aws-cdk/core";
4import * as iam from "@aws-cdk/aws-iam";
5
6type IamRoleProps = cdk.StackProps & {
7  roleProps: iam.RoleProps;
8};
9
10export class IamRole extends cdk.Stack {
11  public readonly role: iam.Role;
12
13  constructor(scope: cdk.App, id: string, props: IamRoleProps) {
14    super(scope, id, props);
15
16    const { roleProps } = props;
17
18    this.role = new iam.Role(this, id, {
19      ...roleProps,
20    });
21  }
22}

次に Actions になります。 以下は、認証を済ませた後に、Container Image を build、push する CI のサンプルになります。 コチラを参考にしています。

1name: sample
2
3on:
4  pull_request:
5    paths-ignore:
6      - "**.md"
7
8jobs:
9  build:
10    runs-on: ubuntu-20.04
11    #
12    permissions:
13      id-token: write
14      contents: read
15    env:
16      AWS_ROLE_ARN: arn:aws:iam::${お使いのaws-account-id}:role/build
17      AWS_WEB_IDENTITY_TOKEN_FILE: /tmp/awscreds
18      AWS_DEFAULT_REGION: ap-northeast-1
19      AWS_REGION: ap-northeast-1 # cdk内部でsdkを利用する関係で AWS_REGION が必要
20      AUDIENCE: sts.amazonaws.com
21
22    steps:
23      - uses: actions/checkout@v2
24
25      # ここで認証する
26      - name: Configure AWS
27        run: |
28          curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=$AUDIENCE" | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE
29
30      - name: Login to Amazon ECR
31        id: login-ecr
32        uses: aws-actions/amazon-ecr-login@v1
33
34      - name: Build, tag, and push image to Amazon ECR
35        working-directory: packages/graphql
36        env:
37          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
38          ECR_REPOSITORY: sample
39          IMAGE_TAG: ${{ github.sha }}
40        run: |
41          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
42          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

おわりに

永続的な credentials を排除できたのですが、role の 細かい policy 管理が出てきたため面倒だなとも思っています 💦 と言いつつ、今までいい加減に管理していたフルフルな role を正すのに良い機会だとも思っています 🙇‍♂️


プロフィール画像

canji

とにかく私的にサービスを作りたい発作を起こしている。お腹はペコペコ。

  • toLog Tools icon
  • dots icon