GitHub Actions が OpenID Connect をサポートし、デプロイがよりセキュアに出来るようになりました!

記事タイトルとURLをコピーする

はじめに

アプリケーションサービス部の宮本です。 今回は先日一般公開となった GitHub Actions の OpenID Connect サポートについてご紹介します。GitHub Actions から AWS リソースの操作を行なっている方にとっては必見のアップデートです。

github.blog

2023-08-10 更新

AWS 側で自動的に証明書の検証をしてくれるようになりました。そのため、明示的に2つの中間証明書を指定する必要がなくなったためテンプレートをアップデートしました。

2023-06-28 更新

GitHub より以下アナウンスがあり、2つの中間証明書に対応する必要があるためテンプレートをアップデートしました。

github.blog

2022-09-09 更新

2022/01 に GitHub の OIDC プロバイダの証明書が更新された為、CloudFormation にハードコードしている thumbprint が一致しなくなりました。 その為、パラメータで thumbprint を指定できる形に更新しました。 (デフォルト値は 2022-09-09 時点の thumbprint です。)

github.com

尚、thumbprint の取得の方法については以下ページをご確認ください。

docs.aws.amazon.com

何が変わったのか

これまで、GitHub Actions から AWS リソースの作成などを行う場合、IAM ユーザーを作成し、認証情報(アクセスキー、シークレットキー)を生成、GitHub Actions の Secrets に設定する必要がありました。

この方法は気軽に利用できる一方、認証情報のローテーションなど漏洩に対するリスク管理が必要で、積極的に利用したい方法ではありませんでした。

今回、GitHub Actions が OpenID Connect をサポートしたことにより、永続的な認証情報を預けることなく、OpenID Connect の仕様に則った一時的なトークン発行のみで、AWS リソースの操作が出来る様になりました。

概要イメージ (公式ブログ より引用)

図内の Cloud Provider が AWS に相当します。予め OpenID プロバイダと信頼関係を設定した IAM ロールを用意することで、認証情報不要で当該ロールに AssumeRole することが出来ます。

やってみる

AWS 提供の Action にちょうど良いサンプル があったのでこれをベースに S3 バケットへのファイルアップロードを試します。(S3 バケット、GitHub リポジトリは作成済みの前提で進めます。)

1. IAM ロールの作成、OpenID プロバイダーの登録

IAMロールの作成、OpenID プロバイダーの登録 を以下 CFn テンプレートで行います。ほぼサンプルからの転用ですが、S3 へのファイルアップロードの為にマネージドポリシー AmazonS3FullAccess を追加しています。(実運用では最小のアクセス権限を付与するようにしてください。)

パラメータは以下の4つです。

パラメータ名 説明
GitHubOrg Action を実行する GitHub リポジトリが所属する GitHub Organization (ユーザー名)を指定します。
RepositoryName Action を実行する GitHub リポジトリ名を指定します。
OIDCProviderArn GitHub を OpenID プロバイダーとして既に登録済みの場合は、その ARN を指定します。指定しなければ新規作成されます。
GitHubOIDCThumbprintList GitHub OpenID プロバイダー の thumbprint リスト(GitHub にて自動で検証してくれるため、任意の40文字を指定すればOK)
# example-github-actions-oidc.yaml
Parameters:
  GitHubOrg:
    Type: String
  RepositoryName:
    Type: String
  OIDCProviderArn:
    Description: Arn for the GitHub OIDC Provider.
    Default: ""
    Type: String
  GitHubOIDCThumbprintList:
    Description: GitHub OIDC thumbprint. see also https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
    Default: "ffffffffffffffffffffffffffffffffffffffff"
    Type: CommaDelimitedList

Conditions:
  CreateOIDCProvider: !Equals 
    - !Ref OIDCProviderArn
    - ""

Resources:
  Role:
    Type: AWS::IAM::Role
    Properties:
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Action: sts:AssumeRoleWithWebIdentity
            Principal:
              Federated: !If 
                - CreateOIDCProvider
                - !Ref GithubOidc
                - !Ref OIDCProviderArn
            Condition:
              StringLike:
                token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${RepositoryName}:*

  GithubOidc:
    Type: AWS::IAM::OIDCProvider
    Condition: CreateOIDCProvider
    Properties:
      Url: https://token.actions.githubusercontent.com
      ClientIdList: 
        - sts.amazonaws.com
      ThumbprintList: !Ref GitHubOIDCThumbprintList

Outputs:
  Role:
    Value: !GetAtt Role.Arn

GithubOidc の各プロパティは環境に合わせて変更する必要はなく、上記例のままで問題ありません。スタック作成後、作成されたロールの ARN を控えておきましょう。

2. GitHub Actions のワークフロー作成、各種設定

こちらも公式ドキュメントのサンプルを転用し、リポジトリ直下の .github/workflows/ に任意の名前でワークフローファイルを作成します。リポジトリへの Push トリガーでワークフローが実行され、S3 バケットにファイルがアップロードされる仕組みです。

BUCKET_NAMEAWS_REGIONROLE_ARN (前述の手順で作成した IAM ロールの ARN) は予め GitHub の Secrets に設定しておく必要があります。

# .github/workflows/example.yaml

# Sample workflow to access AWS resources when workflow is tied to branch
# The workflow Creates static website using aws s3
name: AWS example workflow
on:
  workflow_dispatch
env:
  BUCKET_NAME : ${{secrets.BUCKET_NAME}}
  AWS_REGION : ${{secrets.AWS_REGION}}
# permission can be added at job level or workflow level    
permissions:
  id-token: write
  contents: read    # This is required for actions/checkout
jobs:
  S3PackageUpload:
    runs-on: ubuntu-latest
    steps:
      - name: Git clone the repository
        uses: actions/checkout@v3
      - name: configure aws credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          role-to-assume: ${{secrets.ROLE_ARN}}
          role-session-name: samplerolesession
          aws-region: ${{env.AWS_REGION}}
      # Upload a file to AWS s3
      - name:  Copy index.html to s3
        run: |
          aws s3 cp ./index.html s3://${{env.BUCKET_NAME}}/

3. 動作確認

これで準備は概ね完了です。S3 へアップロードする index.html を任意の内容で作成し、ファイル一式を Commit、GitHub へ Push しましょう。

実行の結果、ログは GitHub リポジトリの Actions タブから確認できます。

実行結果

index.html がアップロードされているかも確認します。バケット名はご自身の環境に書き換えてください。

$ aws s3 ls s3://<your-bucket-name>
2021-11-02 23:42:46          0 index.html

まとめ

認証情報(アクセスキー、シークレットキー)を発行せずに、GitHub Actions から AWS リソースの操作を行うことが出来ました。比較的簡単な手順で実現できますので積極的に導入していきましょう。

参考