🙂

GitHub Actions+AWS SAMでCI/CD構築

2023/07/05に公開

はじめに

GitHub Actions+AWS SAMでCI/CD構築してみました。
構築・設定手順の備忘です。

前提条件

  • AWS SAM テンプレート作成
  • GitHub環境(アカウント作成・リポジトリ作成など)

全体イメージ

GitHubの特定のリポジトリのmainブランチにpushされたらAWS SAMのテンプレートを使用してAWSリソースをデプロイします。

構築手順

IDプロバイダの追加

IDプロバイダを追加します。

  • タイプ:OpenID Connect
  • URL:https://token.actions.githubusercontent.com
  • 対象者:sts.amazonaws.com
    上記の通りに入力後、「サムプリントを取得」をクリックして、サムプリントが表示されたら、「プロバイダを追加」をクリックして、IDプロバイダを作成します。
    ※サーバー証明書のサムプリントは、OpenID Connectプロバイダがキーを利用できるようにするドメインで使用されるX.509証明書の16進でエンコードされたSHA-1ハッシュ値です。

IAMロールの作成

GitHub ActionsでかぶるIAMロールを作成します。
IAMロールには、以下の2つを設定します。

  • 許可ポリシー
     AWSリソースへのアクセス許可ポリシー
  • 信頼ポリシー
     このロールを引き受けることができるエンティティの条件を指定します。
    まず、許可ポリシーに設定するポリシーを作ります。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "iam:GetRole",
                "s3:*",
                "apigateway:*",
                "cloudformation:*",
                "dynamodb:*",
                "iam:CreateRole",
                "iam:DeleteRole",
                "iam:AttachRolePolicy",
                "iam:PutRolePolicy",
                "iam:PassRole",
                "iam:DetachRolePolicy",
                "iam:DeleteRolePolicy",
                "lambda:*",
                "cognito-idp:*",
                "iam:GetRolePolicy"
            ],
            "Resource": "*"
        }
    ]
}

今回、必要なサービス(Cognito User Pools、API Gateway、Lambda、DynamoDB、S3)の全リソースへの全アクションを許可しています。
※全許可で動くことを確認してから個々のアクション、リソースを指定します。
ポリシーエディタでもしっかりと怒られてます。

できました。これを、この後作成するロールにアタッチします。

GitHub ActionsでかぶるIAMロールを作成します。エンティティタイプは、ウェブアイデンティティですね。プロバイダーと、オーディエンスは先ほど作成済みのIDプロバイダーを指定します。

先ほど作成した許可ポリシーをアタッチします。

ここの「ステップ1:信頼されたエンティティを選択する」でこのロールを引き受けることができるエンティティの条件を指定します。

編集ボタンから編集します。

!!!???
と、思ったのですが、この選択画面に行ってしまい、編集できないですね。
ひとまず、ロール作成してしまいます。
その後、できたロールを選択して、「信頼ポリシーを編集」から編集します。

Principalは自動で入っているフェデレーテッドユーザーのままで良いです。
Conditionに以下を追加します。

"StringLike": {
    "token.actions.githubusercontent.com:sub": "repo:{GitHubユーザー名}/sample-git-repository:*"
}


「ポリシーを更新」をクリック

できました。

GitHub Actions Secrets設定

GitHub Actions Secretsを設定します。
IAM_ROLE_ARN:先ほど作成したGitHub ActionsがかぶるIAMロールのARN
AWS_REGION:AWSのリージョン 例:ap-northeast-1
これらのシークレットキーを次の手順のワークフローファイルで参照する設定を入れます。

GitHub Actionsのワークフローファイル作成

GitHub Actionsのワークフローファイルを作成します。
ワークフロー構文
リポジトリの .github/workflows/ 配下に YML 形式で保存します。
例では、.github/workflows/deploy.yamlです。

name: Deploy-AWS-todo-app
 
on:
  push:
    branches:
      - 'main'
  workflow_dispatch:
 
env: 
  TEMPLATE_FILE: template.yaml

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions: 
      id-token: write
      contents: read
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Setup python
        uses: actions/setup-python@v3
        with:
          python-version: '3.9'
      - name: Setup aws-sam
        uses: aws-actions/setup-sam@v2
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1-node16
        with:
          aws-region: ${{secrets.AWS_REGION}}
          role-to-assume: ${{secrets.IAM_ROLE_ARN}}

      - run: aws sts get-caller-identity

      - name: Build & Deploy Cloudformation stacks
        run: |
          sam build --template-file ${TEMPLATE_FILE}
          sam deploy --template-file ${TEMPLATE_FILE}

permission: ではジョブに対して、IDトークンの書き込み権限を割り当てています。
ワークフローがGitHub OIDCのトークンを要求するために必要になります。


このテンプレートファイルをmainブランチにプッシュします。
すると、すぐに、始まりました!

むむ!失敗したようです。

エラーの詳細を見ていくと、

デプロイ中の質問に答えられずに中止されてしまったようです。
以下のファイルを修正します。
samconfig.toml

[default.deploy.parameters]
confirm_changeset = false

テンプレートファイルに「echo 'y'」入れるなどの対策があるようです。今回はこちらの対応で行きます。
※confirm_changesetオプション(デフォルトfalse)は、デプロイ前に変更セットを作成してからデプロイするかどうかの設定です。予期しないリソース置換を防ぐ事ができるため、trueが推奨です。


そして、Action実行!

右上「Run workflow」から実行できます。workflow_dispatchも対象にしているため。


お、おぉぉぉぉ!成功しました。

この後、AWSマネジメントコンソールで確認しましたが、各リソースが正常にデプロイされていました。めでたしめでたし。

最後に

と、思ったのですが、デプロイ後のLambda関数の実行ログで以下のエラーが出てしまいアプリケーションが動作しませんでした(毎回)。現在まだ原因は特定できていません。

[ERROR] Runtime.ImportModuleError: Unable to import module 'app': No module named 'awsgi' Traceback (most recent call last):

ローカル環境からsam deployでデプロイすると、起きないエラーです。
requirement.txtにaws-wsgiを記載していますが、構築時に失敗してしまうのでしょうか。
あと、ローカルからsam deployでデプロイすると、

となるのですが、GitHub Actionsからデプロイすると、コードが見えるのですよね。上がるものが違う?
進捗あり次第、追記します。

参考

Discussion