AWS SAM ApplicationをGitHub Actions + OIDCを利用してデプロイする

CodePipeline や CodeBuild を利用したパイプラインの作成記事はよく見ますが、GitHub Actions を利用した日本語記事はあまり見かけないので備忘録として残します。 特に難しいことはしていないのですが、Actions 用の Credential(IAM User)は作成せず、OpenID Connect(OIDC) を利用して AssumeRole(WithWebIdentity) してみました。以下はサンプルのレポジトリです。

github.com

1. SAM Application の作成

公式チュートリアルを参考に、sam initsam deploy を実行します。今回は Python 3.9 で作成しています。

docs.aws.amazon.com

2. Identity provider の作成

GitHub OIDC Provider から AWS に対して Credential を要求するために、AWS 側で OIDC Provider と IAM Role を作成する必要があります。 まずは IAM で OIDC Provider を CloudFormation(template.yaml) で作成します。AWS マネージメントコンソールと CloudFormation のドキュメント、GitHub のドキュメントを行き来しながら作成しました。

docs.aws.amazon.com

https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services

パラメータは以下を指定しました。これは 2022/06/27 時点での情報であり、今後変わる可能性もあるため作成の際は公式ドキュメントを確認するようにしてください。

Key Value
Provider URL https://token.actions.githubusercontent.com
Thumbprints 6938fd4d98bab03faadb97b34396831e3780aea1
Audience sts.amazonaws.com

CloudFormation template の記載方法は aws-actions/configure-aws-credentials の README を参考にしました。

github.com

3. IAM Role の作成

AWS 側の OIDC Provider で JWT を検証できたら、指定の IAM Role を利用し、一時 Credential を発行して Actions へ渡します。IAM Role には sam deploy に必要な IAM Policy をアタッチします。 IAM Role と IAM Policy も CloudFormation で作成します。IAM Role の Trust relationships も aws-actions/configure-aws-credentials の README を参考に記載しました。

IAM Role の Trust relationships(信頼関係)は以下のように指定しました。

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:enokawa/sam-cicd-sample:*"
                }
            }
        }
    ]
}

IAM Policy に必要な権限は、前述した通り sam deploy に必要なものを指定する必要があります。最小権限の原則に則った権限設定を行うことが望ましいですが、今回はおおざっぱな権限を付与しています。詳しくは以下の行を参照してください。プロダクションで利用する場合は、必要な権限やリソースを洗い出して設定するようにしましょう。

github.com

必要な権限やリソースの洗い出しにはかなりの労力が必要となりますが、以下のドキュメントが参考になるかもしれません。

aws.amazon.com

4. Secrets の登録

AWS アカウント ID やデプロイ先のリージョン、S3 バケット名など固有のリソース名は他者に知られたくないため、GitHub の Secrets に登録します。今回は Public レポジトリのため以下の設定としていますが、Private レポジトリでも利用した方がよいでしょう。

Key Value 用途
AWS_ACCOUNT_ID 12 桁の AWS アカウント ID aws-actions/configure-aws-credentials@v1 で IAM Role(role-to-assume) の ARN を指定する際に利用
AWS_REGION デプロイ先の AWS リージョン名 aws-actions/configure-aws-credentials@v1 で デプロイ先のリージョン(aws-region)を指定する際に利用
AWS_SAM_STACK_NAME デプロイする SAM の CloudFormation Stack 名 Integration test 時に Stack 名を指定する際に利用
S3_BUCKET_NAME Lambda のコードや CloudFormation template 保存先の S3 バケット sam deploy 時に S3 バケット名を指定する際に利用

5. Workflow の定義

ここまでできたら準備完了です。 .github ディレクトリ配下に Workflow や Job、Step を定義していきます。今回は、Build 用と Deploy 用で Workflow を分けてみました。YAML を修正しては GitHub に push して Actions がコケてまた YAML を修正して... を繰り返していました。試せていませんが、actionlint や act を使うことでもっとスムーズにデバッグできるかもしれません。

github.com

github.com

最終的に、以下のように無事 Actions が想定通りに動作することが確認できました。以降は、ローカルではデプロイせずに Actions からデプロイする運用を想定しています。ただ GitHub 側の障害もあり得るため、ローカルからデプロイができるように手順を準備しておいた方がよいかと思います。

まとめ

AWS SAM Application を GitHub Actions + OpenID Connect を利用してデプロイする方法を紹介しました。OIDC の利用は初めてだったのですが、IAM User を作成せずに一時 Credential を発行できるためセキュアに CI/CD パイプラインを構築できてよいですね。

参考記事

eh-career.com

zenn.dev

zenn.dev

gkzz.dev

https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect