GitHub Action (OIDC認証) を用いてAWS Lambdaに自動デプロイする方法

業務内でSlack Botを開発した際に利用した実装方法を取りまとめました。
特にAWSのOIDC周りのUIが新しくなっていたため、備忘録としてまとめましたので参考にしていただければ幸いです。

ベストプラクティス、改善点等ありましたらお気軽にコメントください。

今回実装したSlack Botは定期的にメッセージを投げる簡単なものですが~~気が向いた際に~~記事を作成します。

# 概要
:::note warn
※2024年2月作成の記事なので今後仕様が変わる可能性ありますので最新の情報をご確認ください。
:::

* 特定ブランチが更新されたらLambdaにソースをデプロイ
* AWSのアクセスキー&シークレットキーの管理はGithub→Settingsにある"Select and Variables"には持たせずOIDCを用いて認証
→**IAMロールのarnを指定するだけで認証ができ、キーの管理が不要なのでめちゃ楽**

# 実装

## AWS側
### IAM IDプロバイダ登録

* IAMページ内の左のメニュー"ID プロバイダ"→プロバイダを追加を選択
![id_provider.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/43ea9a54-1dee-33be-0055-52868c77f88e.png)

画像に記載の通り入力（以下そのままコピペでOK）

プロバイダのタイプ：OpenID Connect
プロバイダのURL：`https://token.actions.githubusercontent.com`
対象者：`sts.amazonaws.com`

:::note warn
* 入力後、プロバイダのURL項目の右にある"サムプリントを取得"を押下
* サムプリントを取得をしないとプロバイダの追加ができない
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/9ce8d1a9-db38-7cc6-07c6-2b5fa59a9987.png)

### ロール割り当て
作成したIDプロバイダを選択しロール割り当てを行う

![id_provider2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/1de8a2b9-f631-32e9-a37f-ea87d4f8aea9.png)

### エンティティ設定
認証を許可する対象を指定。
GithubのOrganization、repository、branchまで指定可能

私の[Github](https://github.com/02tYasui)で例えるとGithub組織だけ"02tYasui"で指定すると私が持っているレポジトリすべて許可することになる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/e8eb47f6-c503-912b-1d27-426ae11605f4.png)

ポリシー設定
最低限の許可しか与えたくないので一旦そのまま次へを押下（後ほどカスタム）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/9fa2b270-6edc-e5e6-067a-dce36fdda6c4.png)

ロール名はご自由に
![role.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/c4749abb-a19a-979d-9255-78f75ba1dc0e.png)

### 作成したロールにポリシーを設定
![inline.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/bc6debdd-10f1-c953-909d-ac63a3ad3452.png)

Lambdaの更新を許可
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:UpdateFunctionCode"
            ],
            "Resource": "更新したいLambda関数のARN"
        },
        {
        "Effect": "Allow",
        "Action": [
            "iam:PassRole"
        ],
        "Resource": [
            "更新したいLambda関数についているロールのARN"
        ]
    ]
}
```
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/2b00b34a-36c9-08af-8255-6f3576fa66d9.png)

適当なポリシー名を付けてポリシー作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/d35c693d-5aaa-6231-f61c-62d6e3a76501.png)

### エンティティの追加設定
信頼関係→信頼ポリシーを編集を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/6800a288-9e29-2909-2263-e9e057db4b47.png)

OIDC用に追加
```json
{
    "Effect": "Allow",
    "Principal": {
        "Service": "lambda.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
}
```
![git2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/227f3dc0-11b7-afd5-06f2-3b0fe11b24cc.png)

AWS側の設定はこれで完了

## Github側

### deploy.yml作成
見つけにくい`set up a workflow yourself`をクリック
![git.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/98b2445e-f854-d49d-2658-c70b326797b1.png)

deploy.yml
masterブランチが更新されたらデプロイ発火
```yml
name: Lambda Deploy 
on:
  push:
    branches:
      - main

env:
  REGION_NAME: ap-northeast-1　#region
  FUNCTION_NAME: lambda関数名
  LAMBDA_WORKING_DIRECTORY: function #アプリケーションであればapplicationを記載
  LAMBDA_EXECUTION_ROLE: 更新したいLambda関数についているロールのARN

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - name: checkout
        uses: actions/checkout@v4

        # OIDC
      - name: Configure aws credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ env.LAMBDA_EXECUTION_ROLE }}
          role-session-name: GithubAction
          aws-region: ${{ env.REGION_NAME }}
          
        # 認証
      - name: get-caller-identity is allowed to run on role.
        run: aws sts get-caller-identity

        # Python設定
      - name: setup python
        uses: actions/setup-python@v5
        with:
          python-version: '3.x'

        # Lambdaが存在するか一応確認する
      - name: Check Function if Exists
        id: check-function
        continue-on-error: true
        run: |
          aws lambda get-function --function-name ${{ env.FUNCTION_NAME }}
        
        # デプロイ
      - name: deploy to lambda
      - if: steps.check-function.outcome == 'success'
        run: |
          pip3 install awscli
          cd "リポジトリ内のデプロイ対象Path" && zip -r deploy.zip ./* 
          aws lambda update-function-code --function-name "デプロイ対象の関数名" --zip-file fileb://package.zip --publish
```

deploy.ymlを作成したら右上の緑ボタンからcommit
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461981/177c843f-eecc-ae35-6bda-b772e29e60b0.png)

設定はこれで以上

# まとめ
リポジトリが更新されるとデプロイが作動する。
OIDCで認証しているので鍵管理が不要になり、今までのGithubのsecretsに鍵を置いておく必要がなくなる。

# 参考
https://dev.classmethod.jp/articles/lambda-github-actions/

https://qiita.com/shun198/items/89b2e020fa554233aa4c