閲覧いただきありがとうございます。
現在、サーバーサイドエンジニアとしてAPIの運用保守業務を担当しています。
AWS Lambdaへのデプロイ自動化について学ぶため、GitHub ActionsとOIDCを利用したCI/CDパイプラインを構築しました。
mainブランチへのpushをトリガーとして、pytestによるテスト、OIDCを利用したAWS認証、Lambdaへのデプロイを自動実行する方法を紹介します。
内容に誤りや改善点などがありましたら、ご指摘いただけますと幸いです。
1.今回実施すること
処理の流れ
・mainブランチへのpushをトリガーとし、pytestの実行、OIDCでのAWS認証、Lambdaへのデプロイ自動化を目指します。
構成
lambda/
├── lambda_function.py
├── requirements.txt
└── tests/
└── test_lambda.py
.github/workflows/
└── deploy-lambda.yml
lambda/配下がlambda関数にデプロイされるファイル群です。
.github/workflows配下のYAMLをプッシュ時にGitHub Actionsが読み込み、コマンドを実行する流れとなります。
基本情報
AWS Lambda
- サーバーを管理することなくコードを実行できるサーバーレスコンピューティングサービスです。本記事では、Pythonで作成した関数のデプロイ先として利用します。(参考)
GitHub Actions
- GitHub上のイベントをトリガーとして、テストやビルド、デプロイなどの処理を自動実行できる仕組みです。
deploy-lambda.ymlに、いつ、どの環境で、何を実行するのかを記述します
OIDC
- GitHub ActionsがOIDCトークンを使用してIAMロールを引き受け、一時的な認証情報を取得する仕組みです。長期間有効なAWSアクセスキーをGitHub上に保存する必要がありません
2.Lambda関数とテストコードの作成
デプロイする関数の作成
「hello,lambda」をレスポンスとして返すだけのシンプルな関数を用意します。
lambda_function.py
import json
def lambda_handler(event,context):
return{
"statusCode":200,
"body":json.dumps(
{
"message":"hello,lambda",
}
),
}
テストコードを用意します。
lambda/tests/test_lambda.py
from pathlib import Path
import sys
import json
# 1つ上の lambda フォルダをimport対象に追加
lambda_dir = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(lambda_dir))
from lambda_function import lambda_handler
def test_lambda_handler_returns_success():
# Lambdaへ渡される入力データ
event = {}
# 今回はcontextを使わないためNone
context = None
result = lambda_handler(event, context)
assert result["statusCode"] == 200
#pythonの辞書型に変換
body = json.loads(result["body"])
assert body["message"] == "hello,lambda"
3.AWS側の設定
以下を作成します。
- デプロイ先のLambda関数
- GitHub Actions用のIAMロール
Lambda関数の作成
・AWSコンソール→Lambda→関数の作成をクリックし、下記を入力します。
| 関数名 | ランタイム |
|---|---|
| hello_lambda | Python 3.12 |
IDプロバイダーの追加
OIDC認証利用のため、GitHub ActionsのOIDCプロバイダーをIAMに登録します。
詳細画面で下記を入力し、「プロバイダを追加」を押下(参考)
- プロバイダのタイプ:OpenID Connect
- URL:
https://token.actions.githubusercontent.com - 対象者:sts.amazonaws.com
GitHub Actions用のIAMロールを作成
GitHub ActionsがOIDC認証によって引き受けるIAMロールを作成します。
| アイデンティティプロバイダー | Audience | GitHub Organization | GitHub repository | GitHub branch |
|---|---|---|---|---|
| token.actions.githubusercontent.com | sts.amazonaws.com | ご自身のorganization | リポジトリ名 | プッシュ先ブランチ名 |
インラインポリシーを作成
下記のポリシーを作成し、先ほど作成したロールにアタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DeployExsitingLambda",
"Effect": "Allow",
"Action": [
"lambda:GetFunctionConfiguration",
"lambda:UpdateFunctionConfiguration",
"lambda:UpdateFunctionCode"
],
"Resource": [
"arn:aws:lambda:{リージョン名}:{AWSアカウントID}:function:{Lambda関数名}"
]
}
]
}
今回は既に作成したLambda関数を更新する構成のため、iam:PassRoleは使用していません。
GitHub Actionsから新しくLambda関数を作成する場合は、Lambda関数に実行ロールを指定する必要があるため、GitHub Actionsが引き受けるIAMロールに対して、対象のLambda実行ロールに対するiam:PassRole,関数作成のためのlambda:CreateFunctionを付与します。
ロールまとめメモ
現時点でロールは2つ存在している。
- GitHub Actions用のロール:OIDCでGitHub Actionsが引き受ける。Lambdaの設定取得・更新、コード変更を行う
- Lambda実行ロール:Lambda関数そのものが使う
GitHub Actions
↓ 引き受ける
① GitHub Actions用IAMロール
↓ Lambdaを更新
Lambda関数
↓ 実行時に使う
② Lambda実行ロール
# GitHub Actions用ロールは、Lambda実行ロールの割り当ては変更を行わない
GitHub ActionsからLambda関数を新規作成する場合、作成するLambda関数にLambda実行ロールを割り当てる必要がある。
そのため、GitHub Actions用IAMロールに、対象のLambda実行ロールをLambdaサービスに引き渡すための権限と、関数作成のための権限を付与する必要がある。
GitHub上での設定
GitHubリポジトリの「Settings」→「Secrets and variables」→「Actions」を開き、「Variables」に先ほど作成したIAMロールのARNを登録します。

4. GitHub Actions設定
deploy-lambda.ymlを作成
deploy-lambda.yml
行っていることは下記の通りです ①pytestの実行 ②lambda/配下をdist/へまとめる ③OIDC認証 ④Lambda関数へのデプロイname: Deploy Lambda
on:
push:
branches:
- main
paths:
- "lambda/**"
- ".github/workflows/deploy-lambda.yml"
# GitHubの画面から手動実行するための設定
workflow_dispatch:
permissions:
id-token: write
contents: read
concurrency:
group: lambda-deploy-${{ github.ref }}
cancel-in-progress: true
env:
AWS_REGION: ap-northeast-1
FUNCTION_NAME: hello_lambda
PYTHON_VERSION: "3.12"
jobs:
test-and-deploy:
runs-on: ubuntu-latest
steps:
# GitHubリポジトリの中身を実行環境へ取得
- name: Checkout repository
uses: actions/checkout@v7.0.0
# Lambdaと同じPythonバージョンを用意
- name: Set up Python
uses: actions/setup-python@v6.3.0
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
cache-dependency-path: lambda/requirements.txt
# テスト用の依存関係をインストール
- name: Install test dependencies
run: |
python -m pip install --upgrade pip
if [ -f lambda/requirements.txt ]; then
pip install -r lambda/requirements.txt
fi
pip install pytest
# デプロイ前にテスト
- name: Run tests
run: |
pytest lambda/tests
# Lambdaへ送るファイルをdistディレクトリにまとめる
- name: Build Lambda package
run: |
rm -rf dist
mkdir -p dist
if [ -f lambda/requirements.txt ]; then
pip install \
--requirement lambda/requirements.txt \
--target dist
fi
rsync -av \
--exclude "requirements.txt" \
--exclude "tests" \
--exclude "__pycache__" \
lambda/ dist/
# OIDCを使ってAWSのIAMロールを一時的に借りる
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6.2.2
with:
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
role-session-name: github-${{ github.run_id }}
# distの中身をZIP化してLambdaへデプロイ
- name: Deploy Lambda
uses: aws-actions/aws-lambda-deploy@v1.1.2
with:
function-name: ${{ env.FUNCTION_NAME }}
code-artifacts-dir: dist
handler: lambda_function.lambda_handler
runtime: python3.12
publish: false
5.動作確認・まとめ
あらかじめGitHub上にリポジトリを作成し、ローカルリポジトリのoriginとして登録しておきます。
動作確認
・実際にプッシュして動作確認を実施します。
git add .
git commit -m "first commit"
git branch -M main
git push -u origin main
まとめ
GitHub ActionsとOIDCを利用し、mainブランチへのpushをトリガーとしてpytestの実行からAWS Lambdaへのデプロイを自動化できました。
他にも気になるAWS関連の技術についてキャッチアップを進めたいと思います。
参考記事








