GitHub ActionsでIAM Policy Autopilotを動かし、推奨ポリシーをコメントに投稿してみる

記事タイトルとURLをコピーする

こんにちは。
アプリケーションサービス部、DevOps担当の兼安です。

今回は2025年末に発表されたIAM Policy Autopilotの活用方法を考えてみました。
GitHub ActionsでIAM Policy Autopilotを動かし、推奨ポリシーをコメントに投稿させてみようと思います。

IAM Policy Autopilotとは

IAM Policy Autopilotは、2025年末に発表された比較的新しいサービスです。
コードからIAMポリシーを自動生成するコマンドラインツールでありMCPサーバーです。
詳細は同サービスを私が最初に触った時の記事があるのでこちらをご覧ください。

blog.serverworks.co.jp

IAM Policy Autopilotの活用方法

IAM Policy Autopilotの活用方法を考えた時、2つのやり方があると考えました。

  • IAMポリシーを最初からIAM Policy Autopilotで作成する
  • 開発プロセスのどこかにIAM Policy Autopilotを組み込む

今回は、後者を考えたいと思います。
コードレビューの場である、プルリクエストの中でIAM Policy Autopilotを動かし、推奨ポリシーを挙げてもらうことで、レビュアーが参考にできると考えました。
今回は推奨ポリシーを挙げるまでとしていますが、挙げてくれればAIに判断してもらったり編集してもらうことが可能になるのではと思います。

次項から、作成し動かしてみたGitHub Actionsのワークフローのコードなどを述べていきます。

GitHub ActionsのワークフローでIAM Policy Autopilotを動かすコード

今回、記事に使用したサンプルコードの構造は以下の通りです。
サンプルコードはAWS Lambdaを使っており、プログラムはPython 3.12、IaCにAWS SAMを使用しています。
Lambdaは、Amazon DynamoDB、Amazon S3への読み書きを伴う作りとしています。

.
├── .github/workflows/
│   └── iam-policy-autopilot.yml   # GitHub Actionsワークフロー
├── src/
│   └── handler.py                 # Lambda関数のコード
├── tests/
│   └── ...
└── template.yaml                  # SAMテンプレート

この中で、GitHub ActionsのワークフローのYAMLファイルは以下の通りです。

name: IAM Policy Autopilot

on:
  pull_request:
    types: [opened, synchronize]

permissions:
  contents: read
  pull-requests: write

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - name: リポジトリをチェックアウト
        uses: actions/checkout@v6

      - name: Python 3.12 をセットアップ
        uses: actions/setup-python@v6
        with:
          python-version: '3.12'

      - name: uv パッケージマネージャーをインストール
        uses: astral-sh/setup-uv@v7

      - name: PR差分からPythonファイルを検出
        id: detect-files
        uses: actions/github-script@v8
        with:
          script: |
            const files = await github.paginate(github.rest.pulls.listFiles, {
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.issue.number,
            });

            const pythonFiles = files
              .filter(f => f.filename.endsWith('.py'))
              .filter(f => f.status !== 'removed')
              .filter(f => f.filename.startsWith('src/'));

            const filePaths = pythonFiles.map(f => f.filename);
            core.info(`検出されたPythonファイル (${filePaths.length}件): ${JSON.stringify(filePaths, null, 2)}`);
            core.setOutput('python_files', JSON.stringify(filePaths));
            core.setOutput('has_python_files', filePaths.length > 0 ? 'true' : 'false');

      - name: ファイルごとにIAMポリシーを生成しPRコメントに投稿
        if: steps.detect-files.outputs.has_python_files == 'true'
        uses: actions/github-script@v8
        env:
          PYTHON_FILES: ${{ steps.detect-files.outputs.python_files }}
        with:
          script: |
            const { execSync } = require('child_process');
            const pythonFiles = JSON.parse(process.env.PYTHON_FILES);

            // 既存のPRコメントを取得し、投稿済みファイルを特定する
            const comments = await github.paginate(github.rest.issues.listComments, {
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
            });
            const commentedFiles = new Set(
              comments
                .filter(c => c.body.includes('IAM Policy Autopilot - 推奨IAMポリシー'))
                .map(c => {
                  const match = c.body.match(/対象ファイル: `([^`]+)`/);
                  return match ? match[1] : null;
                })
                .filter(Boolean)
            );

            for (const file of pythonFiles) {
              if (commentedFiles.has(file)) {
                core.info(`スキップ (投稿済み): ${file}`);
                continue;
              }
              try {
                const cmd = `uvx iam-policy-autopilot generate-policies -p ${file}`;
                core.info(`実行コマンド: ${cmd}`);
                const output = execSync(cmd, { encoding: 'utf-8' });
                core.info(`コマンド出力:\n${output}`);
                const body = `## 🔐 IAM Policy Autopilot - 推奨IAMポリシー\n\n対象ファイル: \`${file}\`\n\n以下はIAM Policy Autopilotによって自動生成されたIAMポリシーです。  \n\n\`\`\`json\n${output}\n\`\`\`\n\n> このコメントはGitHub Actionsによって自動生成されました。  `;
                await github.rest.issues.createComment({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  issue_number: context.issue.number,
                  body: body,
                });
              } catch (error) {
                const body = `## ⚠️ IAM Policy Autopilot - 実行エラー\n\n対象ファイル: \`${file}\`\n\nIAM Policy Autopilotの実行中にエラーが発生しました。  \n詳細はワークフローのログを確認してください。  \n\n> このコメントはGitHub Actionsによって自動生成されました。  `;
                await github.rest.issues.createComment({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  issue_number: context.issue.number,
                  body: body,
                });
              }
            }

      - name: PR差分取得またはIAM Policy Autopilotのエラー通知をPRコメントに投稿
        if: failure()
        uses: actions/github-script@v8
        with:
          script: |
            const output = `## ⚠️ IAM Policy Autopilot - エラー

            PR差分の取得またはIAM Policy Autopilotの実行中にエラーが発生しました。  
            詳細はワークフローのログを確認してください。  

            > このコメントはGitHub Actionsによって自動生成されました。  `;
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: output
            });

GitHub Actionsのワークフローの起動条件

今回はプルリクエストの流れでIAM Policy Autopilotを動かし投稿することが目的なので、ワークフローの起動条件はプルリクエストの作成時と、追加コミットして同期が走った時になります。
ワークフローにおける記述はこうですね。

on:
  pull_request:
    types: [opened, synchronize]

IAM Policy Autopilotはuvxで動かす

今回、IAM Policy Autopilotはuvxで動かしています。
uvxで動かす場合、事前にuvをインストールしておけば他のインストールなどは不要です。
単純に動かすだけならばこれが一番手っ取り早いと判断し、この方法を取りました。
uvはワークフローの中のこの部分でインストールしています。

- name: uv パッケージマネージャーをインストール
  uses: astral-sh/setup-uv@v7

プルリクエストに含まれる差分ファイル群から、IAM Policy Autopilotの対象とするファイルを抽出する

次に、プルリクエストに含まれる差分ファイル群から、IAM Policy Autopilotの対象とするファイルを抽出します。

      - name: PR差分からPythonファイルを検出
        id: detect-files
        uses: actions/github-script@v8
        with:
          script: |
            const files = await github.paginate(github.rest.pulls.listFiles, {
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.issue.number,
            });

            const pythonFiles = files
              .filter(f => f.filename.endsWith('.py'))
              .filter(f => f.status !== 'removed')
              .filter(f => f.filename.startsWith('src/'));
        以下省略

これには、GitHub Scriptを使用します。
GitHub ScriptはGitHub Actionsのワークフロー内でJavaScriptを使ってAPI操作を簡単に記述できる公式アクションです。

github.com

これを使い、差分ファイル群から以下の条件を指定して対象を抽出しています。

  • 拡張子が.pyである
  • 削除ファイルではない
  • srcディレクトリ配下のファイルである

最後の条件はテストコードや、パッケージ管理でインストールされたファイルをIAM Policy Autopilotの対象としないための措置です。
抽出したらそのリストをcore.setOutputを使って次に引き渡しています。

この後は、引き続きGitHub Scriptを使用してファイルリストに対して一つずつIAM Policy Autopilotを実行。
その結果をプルリクエストのコメントとして投稿していきます。

GitHub ActionsでIAM Policy Autopilotを動かした時の画面

GitHub ActionsのワークフローでIAM Policy Autopilotを動かし、その推奨ポリシーを投稿した場合の画面はこちらです。
ワークフローの起動条件に従い、プルリクエスト作成時(Open時)にワークフローが起動します。

プルリクエスト作成時にワークフローが起動

ワークフローが終了すると、IAM Policy Autopilotが生成した推奨ポリシーが投稿されます。

IAM Policy Autopilotが生成した推奨ポリシーが投稿される

コードレビュアーはこれを見てポリシー周りのレビューができるのではと思います。
また、GitHub Actionsのワークフローは「コメントが投稿された時」もトリガーにすることもできるので、これをトリガーに別の自動処理を起動することにも繋げられると思っています。

IAMポリシーを最初からIAM Policy Autopilotで作成するのは検討中です

今回、IAMポリシーを最初からIAM Policy Autopilotで作成する方に触れていないのは、IAM Policy Autopilotが生成するポリシーにも特徴があるからです。
例えばDynamoDBへのポリシーであれば、IAM Policy Autopilotはこのようなポリシーを生成します。

{
  "Effect": "Allow",
  "Action": [
    "dynamodb:GetItem",
    "dynamodb:PutItem",
    "dynamodb:ReadDataForReplication",
    "dynamodb:WriteDataForReplication"
  ],
  "Resource": [
    "arn:aws:dynamodb:*:*:table/*"
  ]
}

ここは、私が書くとしたらDynamoDBのテーブル名は部分一致ではなくて完全一致で書くと思います。
このように、IAM Policy Autopilotが生成するポリシーにも特徴があるので、最初からIAM Policy Autopilotで生成するルールとするのは早計というかチーム内での協議が必要かなと思います。
なので、今回はこのような記事構成とさせていただきました。

今回は以上です。

兼安 聡(執筆記事の一覧)

アプリケーションサービス部 DS3課所属
2025 Japan AWS Top Engineers (AI/ML Data Engineer)
2025 Japan AWS All Certifications Engineers
2025 AWS Community Builders
Certified ScrumMaster
PMP
広島在住です。今日も明日も修行中です。
X(旧Twitter)