こんにちは、カバー株式会社エンジニアのAです。
この記事は カバー株式会社 Advent Calendar 2024 12日目の記事になります。
前回の記事は @pvicugna11 による DocusaurusでWebページを作成してGithub Pagesで公開してみる! でした。こちらもぜひご覧ください。
はじめに
この記事ではGitHub ActionsでPythonコードを実行してAWS上のリソースを操作するワークフローの実装についてご紹介します。
今回のワークフローを実装した経緯について、
- 任意のタイミングで一定の処理を手動実行したい
- 時間のかかる処理を行うのでLambdaのtimeout(15分)では足りない
- 少し複雑な処理を行うのでAWS CLIでは事足りない
という事情がありました。
GitHub Actionsは UIから手動実行可能(定期実行も可能)で、ログも残しやすく、新しく実行環境等を整備する必要も少ないため、これを利用しました。
できたもの
name: Sample Workflow
on:
workflow_dispatch: { }
jobs:
SampleJob:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.11.7'
architecture: 'x64'
- name: Install Dependencies
run: |
pip install pipenv
pipenv install --dev
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ secrets.TF_VAR_AWS_ACCOUNT_ID }}:role/example_iam_role_name
aws-region: ap-northeast-1
- name: Run Python Script
run: pipenv run python example.py
env:
AWS_ROLE_ARN: arn:aws:iam::${{ secrets.TF_VAR_AWS_ACCOUNT_ID }}:role/example_iam_role_name
解説・ポイントなど
OIDCによる認証
GitHubActionsワークフローのAWSに対する認証はOpenID Connect (OIDC)を利用しています。
これを使うことで、GitHub Actionsで認証情報を保持する必要がなくなり、短期間有効なトークンを動的に取得することでセキュリティと運用効率を向上できます。
ワークフローでの認証の実行は以下の公式のActionsを利用しています。
role-to-assume
にはGitHub Actionsに付与するロールを指定します。
以下は付与するロールのTerraformサンプルです。
# OIDCで認証するために必要なAssumeRoleポリシー
data "aws_iam_policy_document" "sample_policy_document" {
statement {
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]
principals {
type = "Federated"
identifiers = ["arn:aws:iam::${var.aws_account_id}:oidc-provider/token.actions.githubusercontent.com"]
}
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = ["sts.amazonaws.com"]
}
condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = ["repo:OrganizationName/RepositoryName:ref:refs/heads/main"]
}
}
}
resource "aws_iam_role" "sample_role" {
name = "${var.prefix}-sample_role-${var.stage}"
assume_role_policy = data.aws_iam_policy_document.sample_policy.json
}
# Pythonコードで扱うリソースへのアクセス許可ポリシー
resource "aws_iam_policy" "sample_policy" {
name = "${var.prefix}-sample_policy-${var.stage}"
policy = jsonencode({
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Action" : [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket",
...
],
"Resource" : [
"arn:aws:s3:::sample_arn",
]
}
]
})
}
resource "aws_iam_role_policy_attachment" "sample_role" {
role = aws_iam_role.sample_role.name
policy_arn = aws_iam_policy.sample_policy.arn
}
また、 OIDCでの認証を実行するには、ワークフローのpermission
でid-token: write
を設定する必要があります(参考)。
permissions:
id-token: write
Pythonコード(boto3)の実行
example.py
内で、boto3を使った処理をいろいろ書いています。Pythonのパッケージ管理にはpipenvを利用しています。
実行時の環境変数にAWS_ROLE_ARN: {使用するロールのARN}
を設定することで、boto3からAWSリソースにアクセスできます(参考)。
run: pipenv run python example.py
env:
AWS_ROLE_ARN: arn:aws:iam::${{ secrets.TF_VAR_AWS_ACCOUNT_ID }}:role/example_iam_role_name
Pythonコード側で何か設定をする必要はありません。
おわりに
今回の記事では、GitHub Actionsを活用してAWSリソースを操作するワークフローを構築する方法をご紹介しました。
手動実行やログ管理がしやすいGitHub Actionsは、小規模な運用から始めたいケースや既存の開発フローに簡単に組み込める点で有用です。今回はこれを利用することで、狭いケースに対して解決策を簡単に実装することができました。
何かのご参考になれば幸いです。