AWS SAM の Pipeline コマンドで OIDC プロバイダーが指定出来るようになりました

2022.10.17

いわさです。

AWS SAM では SAM CLI を使って CI/CD パイプラインを自動で作成するsam pipelineという機能があります。

こちら大変便利な機能なのですが AWS へリソースをデプロイする際に従来は IAM ユーザーを指定する必要がありましたが、今回の SAM CLI のアップデートで OIDC プロバイダーを構成するオプションが追加されたため、デプロイ用の IAM ユーザーを用意しなくても良くなりました。

いくつか OIDC プロバイダーが選択出来るのですが、今回は GitHub Actions を使ってこちらを試してみました。
なお GitHub Actions で OIDC プロバイダーを使う方法は以下が参考になります。

こちらの記事では手動でパイプラインを構築しておりその際に IAM 側のリソースを用意したり Assume Role させるように設定していますが、今回の機能ではこのあたりを全て自動化してくれます。便利すぎる。

AWS SAM CLI v1.60.0 から利用可能

前提条件として AWS SAM CLI の v1.60.0 から利用が可能です。
事前にバージョンアップしておきましょう。

SAM CLI のリリースノートは以下です。

更新方法は以下をご参照ください。

% sam --version
SAM CLI, version 1.60.0

使ってみる

流れとしては SAM アプリケーションを新規作成するところから行いたいと思います。
今回の SAM パイプライン機能では GitHub Actions 用の pipeline.yaml を自動作成してくれるので、流れとしては以下を行ってみます。

  • sam initで新規アプリケーション(Python 3.9)を作成し GitHub リポジトリへプッシュ
  • sam pipelineでパイプライン部分を作成
  • 再度プッシュし、パイプラインが実行される

新規アプリケーションを作成

アプリケーション作成はsam initで適当なテンプレートを今回は選択しています。

% sam init

You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.

Which template source would you like to use?
    1 - AWS Quick Start Templates
    2 - Custom Template Location
Choice: 1

Choose an AWS Quick Start application template
    1 - Hello World Example
    2 - Multi-step workflow
    3 - Serverless API
    4 - Scheduled task
    5 - Standalone function
    6 - Data processing
    7 - Infrastructure event management
    8 - Serverless Connector Hello World Example
    9 - Multi-step workflow with Connectors
    10 - Lambda EFS example
    11 - Machine Learning
Template: 1

:

こちらを GitHub リポジトリにプッシュしておきます。

パイプラインを作成

同じリポジトリにパイプライン用のファイルを生成したいので、同一リポジトリ内でそのままsam pipelimeを実行します。
前提としてパイプライン用ではないのですがsam pipelineを実行するための IAM ユーザーは必要です。このユーザーを使って IAM ID Provider など必要な AWS リソースを自動作成します。あくまでもパイプライン上から IAM ユーザーを削除出来ますよということです。

% ls -l
total 32
-rw-r--r--  1 iwasa.takahito  staff  8393 Oct 17 08:27 README.md
-rw-r--r--  1 iwasa.takahito  staff     0 Oct 17 08:27 __init__.py
drwxr-xr-x  3 iwasa.takahito  staff    96 Oct 17 08:27 events
drwxr-xr-x  5 iwasa.takahito  staff   160 Oct 17 08:27 hello_world
-rw-r--r--  1 iwasa.takahito  staff  1669 Oct 17 08:27 template.yaml
drwxr-xr-x  6 iwasa.takahito  staff   192 Oct 17 08:27 tests

:

% sam pipeline init --bootstrap

sam pipeline init generates a pipeline configuration file that your CI/CD system
can use to deploy serverless applications using AWS SAM.
We will guide you through the process to bootstrap resources for each stage,
then walk through the details necessary for creating the pipeline config file.

Please ensure you are in the root folder of your SAM application before you begin.

Select a pipeline template to get started:
    1 - AWS Quick Start Pipeline Templates
    2 - Custom Pipeline Template Location
Choice: 1

Cloning from https://github.com/aws/aws-sam-cli-pipeline-init-templates.git (process may take a moment)
Select CI/CD system
    1 - Jenkins
    2 - GitLab CI/CD
    3 - GitHub Actions
    4 - Bitbucket Pipelines
    5 - AWS CodePipeline
Choice: 3
You are using the 2-stage pipeline template.
 _________    _________ 
|         |  |         |
| Stage 1 |->| Stage 2 |
|_________|  |_________|

Checking for existing stages...

[!] None detected in this account.

Do you want to go through stage setup process now? If you choose no, you can still reference other bootstrapped resources. [Y/n]:            

For each stage, we will ask for [1] stage definition, [2] account details, and [3]
reference application build resources in order to bootstrap these pipeline
resources.

We recommend using an individual AWS account profiles for each stage in your
pipeline. You can set these profiles up using aws configure or ~/.aws/credentials. See
[https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-set-up-credentials.html].

ここまでは従来と同じ構成ですが、ステージの作成時に OIDC プロバイダーを選択出来るようになっています。
続きを見ていきましょう。

:

Stage 1 Setup

[1] Stage definition
Enter a configuration name for this stage. This will be referenced later when you use the sam pipeline init command:
Stage configuration name: hoge-stage1

[2] Account details
The following AWS credential sources are available to use.
To know more about configuration AWS credentials, visit the link below:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html                
    1 - Environment variables (not available)
    2 - default (named profile)
:
    q - Quit and configure AWS credentials
Select a credential source to associate with this stage: 5
Associated account 123456789012 with configuration hoge-stage1.

Enter the region in which you want these resources to be created [ap-northeast-1]: 
Select a user permissions provider:
    1 - IAM (default)
    2 - OpenID Connect (OIDC)
Choice (1, 2): 2
Enter the URL of the OIDC provider [https://token.actions.githubusercontent.com]: 
Enter the OIDC client ID (sometimes called audience) [sts.amazonaws.com]: 
Enter the GitHub organization that the code repository belongs to. If there is no organization enter your username instead: Tak1wa
Enter GitHub repository name: hoge1017sam
Enter the name of the branch that deployments will occur from [main]: 

[3] Reference application build resources
Enter the pipeline execution role ARN if you have previously created one, or we will create one for you []: 
Enter the CloudFormation execution role ARN if you have previously created one, or we will create one for you []: 
Please enter the artifact bucket ARN for your Lambda function. If you do not have a bucket, we will create one for you []: 
Does your application contain any IMAGE type Lambda functions? [y/N]: 

[4] Summary
Below is the summary of the answers:
    1 - Account: 123456789012
    2 - Stage configuration name: hoge-stage1
    3 - Region: ap-northeast-1
    4 - OIDC identity provider URL: https://token.actions.githubusercontent.com
    5 - OIDC client ID: sts.amazonaws.com
    6 - GitHub organization: Tak1wa
    7 - GitHub repository: hoge1017sam
    8 - Deployment branch:  main
    9 - Pipeline execution role: [to be created]
    10 - CloudFormation execution role: [to be created]
    11 - Artifacts bucket: [to be created]
    12 - ECR image repository: [skipped]
Press enter to confirm the values above, or select an item to edit the value: 

This will create the following required resources for the 'hoge-stage1' configuration: 
    - IAM OIDC Identity Provider
    - Pipeline execution role
    - CloudFormation execution role
    - Artifact bucket
Should we proceed with the creation? [y/N]: y
    Updating the required resources...

:

Successfully created the pipeline configuration file(s):
    - .github/workflows/pipeline.yaml

上記ハイライト部分で IAM か OIDC を選択出来るようになっていますね。
OIDC プロバイダーごとにデフォルト値が定義されているので GitHub Actions の場合であればそのままデフォルト値でいけました。

途中、「Should we proceed with the creation」の部分で AWS 上に ID プロバイダーリソースなどが作成されています。

パイプラインを実行してみる

pipeline.yaml が作成されています。
確認してみると以下のように Assume Role が使われており、アクセスキーやシークレットの埋め込みは見当たりませんね。

pipeline.yaml

name: Pipeline

on:
  push:
    branches:
      - 'main'
      - 'feature**'
  delete:
    branches:
      - 'feature**'

:

  deploy-prod:
    if: github.ref == 'refs/heads/main'
    needs: [integration-test]
    runs-on: ubuntu-latest
    # Configure GitHub Action Environment to have a manual approval step before deployment to production
    # https://docs.github.com/en/actions/reference/environments
    # environment: <configured-environment>
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-python@v2
      - uses: aws-actions/setup-sam@v1
      - uses: actions/download-artifact@v2
        with:
          name: packaged-prod.yaml

      - name: Assume the prod pipeline user role
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: ${{ env.PROD_REGION }}
          role-to-assume: ${{ env.PROD_PIPELINE_EXECUTION_ROLE }}
          role-session-name: prod-deployment
          role-duration-seconds: 3600
          role-skip-session-tagging: true

      - name: Deploy to production account
        run: |
          sam deploy --stack-name ${PROD_STACK_NAME} \
            --template packaged-prod.yaml \
            --capabilities CAPABILITY_IAM \
            --region ${PROD_REGION} \
            --s3-bucket ${PROD_ARTIFACTS_BUCKET} \
            --no-fail-on-empty-changeset \
            --role-arn ${PROD_CLOUDFORMATION_EXECUTION_ROLE}

当然ながら環境変数としてもシークレットは埋め込まれていません。

ではこのファイルをプッシュしてワークフローを実行してもらいましょう。

問題なくデプロイ出来ました。

% curl https://yb4mfuj46m.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world"}%

なお、実行ロールの信頼関係とポリシーは以下のように指定されていました。

Trust relationships

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "ForAllValues:StringLike": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
                    "token.actions.githubusercontent.com:sub": "repo:Tak1wa/hoge1017sam:ref:refs/heads/main"
                }
            }
        }
    ]
}

Permissions

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "iam:PassRole",
            "Resource": "arn:aws:iam::123456789012:role/aws-sam-cli-managed-hoge-CloudFormationExecutionR-L6ENO5FENT4R",
            "Effect": "Allow"
        },
        {
            "Action": [
                "cloudformation:CreateChangeSet",
                "cloudformation:DescribeChangeSet",
                "cloudformation:ExecuteChangeSet",
                "cloudformation:DeleteStack",
                "cloudformation:DescribeStackEvents",
                "cloudformation:DescribeStacks",
                "cloudformation:GetTemplate",
                "cloudformation:GetTemplateSummary",
                "cloudformation:DescribeStackResource"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:DeleteObject",
                "s3:GetObject*",
                "s3:PutObject*",
                "s3:GetBucket*",
                "s3:List*"
            ],
            "Resource": [
                "arn:aws:s3:::aws-sam-cli-managed-hoge-stage2-p-artifactsbucket-m4iqdqi8p6xk/*",
                "arn:aws:s3:::aws-sam-cli-managed-hoge-stage2-p-artifactsbucket-m4iqdqi8p6xk"
            ],
            "Effect": "Allow"
        }
    ]
}

良いですね!

さいごに

本日は AWS SAM の Pipeline コマンドで OIDC プロバイダーが指定出来るようになったので試してみました。

SAM パイプラインでもデプロイ用の IAM ユーザ のアクセスキーとシークレットを用意・管理しなくて良くなるので使いやすくなりますね。
既に SAM パイプラインを使われていて手動での OIDC 対応をまだされていない方は今回の新機能を試してみてください。