Github Actionsを使ってLambdaの更新を自動化してみた

お疲れ様です!tkmiです。

LambdaとSlackの連携について何度かやってきましたが、今回はGithub ActionsとOIDC認証を使って、Lambdaの更新をスムーズに自動化する方法を紹介します。

Github Actionsとは?

Github Actionsは、GitHubが提供するCI/CDツールで、リポジトリ内のコードの変更に基づいて自動化されたワークフローを実行することができます。これにより、コードのビルド、テスト、デプロイなどのプロセスを簡単に自動化することができます。

Github Actionsの利点としては、GitHubリポジトリと直接統合されているため、設定が非常に簡単であること、豊富なコミュニティアクションを利用できること、そして柔軟性が高く、カスタマイズ可能なワークフローを構築できることが挙げられます。

OIDC認証の基本とその重要性

OIDC(OpenID Connect)認証は、OAuth 2.0を基盤としたシンプルなアイデンティティレイヤーで、ユーザーの認証と、アプリケーションに対する認可を行うために使用されます。これにより、安全かつスムーズな認証プロセスを実現することができます。

OIDC認証の重要性は、セキュリティの向上にあります。特に、第三者のアプリケーションがユーザーのリソースにアクセスする際に、ユーザーのパスワードを共有することなく安全に認証を行うことができます。

Github ActionsとOIDC認証を使ったAWS Lambdaの設定方法

まず、これまでのコードとディレクトリ構造を整理します。
この時点でGithubリポジトリの作成と最初のコミットは済んでいる前提です。

C:.
|   .gitignore
|   
+---.github
|   \---workflows
|           deploy.yml
|           
+---lambda
|       lambda_function.py
|       
+---layer  # git管理からは除外する
    \---python
        +---slack
        \---slack_sdk
名称 詳細
.gitignore Git管理から除外するファイルを記述します。
.github/workflows/deploy.yml Github Actionsのワークフローファイルです。
Lambdaを更新するためのステップを定義します。
lambda/lambda_function.py lambda関数の本体です。
layer/python/slack
layer/python/slack_sdk
slack_sdkの本体です。
git管理からは除外したかったため、lambda関数本体とは別にしました。

OIDCプロバイダーの登録とIAMロールの作成

  1. OIDCプロバイダーの登録
  2. IAMポリシー・IAMロールの作成
  3. インラインポリシーの作成

1. OIDCプロバイダーの登録

まず、AWSにおいてOIDCプロバイダーを設定し、GitHubのOIDCトークンを認証するIAMロールを作成します。

コンソール画面、IAM>IDプロバイダから「プロバイダを追加」をクリック

以下のように入力して「プロバイダを追加」をクリック

項目 内容
プロバイダのタイプ OpenID Connect
プロバイダのURL https://token.actions.githubusercontent.com
対象者 sts.amazonaws.com

登録できました。

2. IAMポリシー・IAMロールの作成

次に作成したIDプロバイダを選択して「ロールの割り当て」をクリック

「新しいロールを作成」を選択して次へ

認証を許可する対象を設定します。
「ウェブアイデンティティ」が選択されているので、そのまま必要情報を入力します。
アイデンティティプロバイダーについては先ほど作成したGithubが選択されていると思いますのでそのままにします。

項目 内容
Audience sts.amazonaws.com
IDプロバイダ登録で対象者に入力したもの
Github組織 (Githubのアカウント)
Githubリポジトリ(オプション) (リポジトリ名)
Githubブランチ(オプション) (ブランチ名)

「次へ」をクリックして許可するポリシーを追加します。が、許可の範囲をできるだけ狭めたいため後ほどカスタムします。
一旦何も選択せずに「次へ」をクリック。

ロール名を付けてロールを作成します。

3. インラインポリシーの作成

作成したロールを選択して、「インラインポリシーを作成」をクリック

Lambda関数のコードの更新だけ許可したいので、アクションに「update」を入力して、
アクション許可は「UpdateFunctionCode」を選択。
リソースは対象となるLambda関数のみを指定したいので、「ARNを追加」をクリック。

リージョンと更新したいLambdaのFunction名を入力したら、「リソースARN」に自動的に反映されるのでそのまま「ARNを追加」をクリック。

反映されたら、「次へ」

ポリシー名を入力して、許可内容を確認し「ポリシーを作成」をクリック

これにより、GitHub Actionsが安全にAWSリソースにアクセスできるようになります。

Github Actionsの設定

githubの画面で「Actions」のタブを選択。「set up a workflow yourself」をクリック

GitHub Actionsのワークフローファイルを作成します。
ワークフローファイルには、コードのビルド、テスト、そしてAWS Lambdaへのデプロイを行うステップを記述します。
今回は試しに連携してみたいので、トリガーを「masterブランチにpushされた時」に指定しています。
運用する場合には、masterではなくリリース用のブランチを別に用意したり、もう少し細かく設定する方が良いでしょう。

ファイル名は「deploy.yml」

「steps」の部分以降が具体的な処理になります。

  1. リポジトリをチェックアウト
  2. AWS接続用のactionを使って認証を行う
  3. pythonを使う用意
  4. aws-cliを使う用意
  5. lambdaのコードをzip圧縮
  6. デプロイ実行
name: Deploy to AWS Lambda

on:
  push:
    branches:
      - master

jobs:
  deploy:
    runs-on: ubuntu-latest  # ワークフローの実行環境
    permissions:
      id-token: write # AWS認証(OIDC)
      contents: read  # repositoryからコードの読み取り

    steps:
      # actions/xxx@v2 Github公式アクション/アクション名@vバージョン
      # プレフィックス「actions/」は公式
      # some-user/some-action@v1 開発者作成
      # ./github/actions/action-name リポジトリ内の自作Action(.github/actions/のアクション)
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-region: $
          role-to-assume: $ # 認証設定
          role-session-name: GitHubActions

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.12'  # AWS Lambda のバージョンに合わせる

      - name: Install AWS CLI
        run: pip install awscli

      - name: Package Lambda function
        run: |
          cd lambda
          zip -r function.zip ./*

      - name: Deploy to AWS Lambda
        run: |
          aws lambda update-function-code \
            --function-name slack-notification-test \
            --zip-file fileb://lambda/function.zip \
            --publish

認証を行うため、先ほど作成したIAMロールのARNと対象のリージョンをGithub Secretsに登録します。

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-region: $
          role-to-assume: $ # 認証設定
          role-session-name: GitHubActions

Settings > Secrets and variables > Actionsの「New Repository secrets」から登録できます。

slack_sdkをLambda Layerに登録

Lambda Layerは、Lambda関数のコードを共通化し、再利用可能なライブラリや依存関係を管理するための便利な機能です。これにより、複数のLambda関数で共通のコードを使用することができます。

Lambda Layerを使うことで、関数のデプロイサイズを小さくし、デプロイ時間を短縮することができます。また、依存関係のバージョン管理も容易になります。

Lambdaコンソールから
その他のリソース > レイヤーを選択し、「レイヤーを作成」をクリック

python以下をまとめてzipにかためて、以下のように入力して登録。
Lambda関数のランタイムと同じものを含めるようにしてください。

作成できたら、レイヤーを登録したいLambda関数の「レイヤー」から「レイヤーの追加」をクリック

コードタブの一番下

カスタムレイヤーを選択して、さきほど登録した「slack_sdk」を選択して「追加」
バージョンは登録したてなので「1」のみ。

slack_sdkをレイヤーにしました。

リポジトリを更新して確認

もろもろの設定が終わりましたので
いざ!更新!

できました!

ちなみにデプロイ状況はgithubで確認できます。

slackからもテストしてみましょう。

できた~~~~~~~~~

以上です!