mcpField
A
aws-github-oidc-scoped-role

aws-github-oidc-scoped-role

github.com/mizchiクラウド・DevOps41641 回インストール1 週間前に更新
リポジトリ

aws-github-oidc-scoped-role について

GitHub Actions の OIDC 信頼設定と、範囲を絞った AWS IAM ロールを構成するための技術ガイドです。特権ロールを特定のワークフローに限定し、Bedrock や権限設定の注意点も説明します。

主な機能

  1. 01ワークフローファイル単位の信頼範囲
  2. 02OIDC 条件の設定
  3. 03AI エージェントロールのパターン
  4. 04IAM と Bedrock の注意点

活用シーン

  1. 01GitHub Actions から AWS ロールへのアクセス制限
  2. 02読み取り専用 AWS AI エージェントロールの設定
  3. 03Bedrock の AccessDenied エラー調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mizchi/skills --skill aws-github-oidc-scoped-role

インストール後、Claude Code で/aws-github-oidc-scoped-roleを入力して読み込まれたか確認します。

同梱ファイルREADME.md

詳細

AWS GitHub Actions OIDC — スコープを限定した IAM ロール

OIDC プロバイダーの設定

data "tls_certificate" "github_oidc" {
  url = "https://token.actions.githubusercontent.com"
}

resource "aws_iam_openid_connect_provider" "github" {
  url             = "https://token.actions.githubusercontent.com"
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = [data.tls_certificate.github_oidc.certificates[0].sha1_fingerprint]
}

AWS アカウントごとにプロバイダーは 1 つです。すでに存在する場合は、代わりに data ソースを使用してください。

スコープ:sub(リポジトリ+ブランチ)と job_workflow_ref(特定のワークフローファイル)

多くのチュートリアルでは、sub クレームを使って、OIDC の信頼をリポジトリ+ブランチにスコープします。

# Minimal scope — any workflow in the repo on main can assume this role
condition {
  test     = "StringLike"
  variable = "token.actions.githubusercontent.com:sub"
  values   = ["repo:ORG/REPO:ref:refs/heads/main"]
}

特権ロール(AI エージェントやデプロイロールなど)では、job_workflow_ref を使って特定のワークフローファイルにスコープします。これにより、リポジトリに新たなワークフローが追加されても、そのロールを引き受けられないようにできます。

# Tight scope — only the specific workflow file from main can assume this role
condition {
  test     = "StringLike"
  variable = "token.actions.githubusercontent.com:sub"
  values   = ["repo:ORG/REPO:*"]  # AWS requires sub to be non-empty; use wildcard here
}
condition {
  test     = "StringEquals"
  variable = "token.actions.githubusercontent.com:job_workflow_ref"
  values   = ["ORG/REPO/.github/workflows/my-workflow.yml@refs/heads/main"]
}

aud 条件は常に必須です。

condition {
  test     = "StringEquals"
  variable = "token.actions.githubusercontent.com:aud"
  values   = ["sts.amazonaws.com"]
}

AI エージェントロールのパターン(ReadOnlyAccess + Bedrock + Deny によるオーバーライド)

AWS リソースの読み取りと Bedrock モデルの呼び出しが可能な、AI トリアージ/分析ロールの場合:

resource "aws_iam_role" "ai_agent" {
  name               = "myapp-ai-agent"
  assume_role_policy = data.aws_iam_policy_document.ai_agent_assume.json
}

# Broad read access to inspect infrastructure
resource "aws_iam_role_policy_attachment" "ai_agent_readonly" {
  role       = aws_iam_role.ai_agent.name
  policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess"
}

# Bedrock model invocation
resource "aws_iam_role_policy" "ai_agent_bedrock" {
  name = "bedrock-invoke"
  role = aws_iam_role.ai_agent.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "bedrock:InvokeModel",
          "bedrock:InvokeModelWithResponseStream",
          "bedrock:Converse",
          "bedrock:ConverseStream",
        ]
        Resource = [
          # Direct foundation model ARNs
          "arn:aws:bedrock:*::foundation-model/anthropic.*",
          # Cross-region inference profiles (jp.anthropic.*, us.anthropic.*, global.anthropic.*, etc.)
          "arn:aws:bedrock:*:*:inference-profile/*anthropic.*",
        ]
      },
      # Anthropic models on Bedrock are AWS Marketplace SaaS products.
      # Even when already subscribed at the account level, the *assuming role*
      # must have Marketplace view/subscribe permissions or Bedrock returns
      # AccessDenied regardless of the subscription status.
      {
        Effect = "Allow"
        Action = [
          "aws-marketplace:ViewSubscriptions",
          "aws-marketplace:Subscribe",
        ]
        Resource = "*"
      },
    ]
  })
}

# ReadOnlyAccess includes secretsmanager:GetSecretValue and kms:Decrypt.
# Deny these explicitly so the agent cannot read secrets or tfstate.
resource "aws_iam_role_policy" "ai_agent_deny" {
  name = "deny-sensitive-reads"
  role = aws_iam_role.ai_agent.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect   = "Deny"
        Action   = ["secretsmanager:GetSecretValue", "kms:Decrypt"]
        Resource = "*"
      },
      {
        Effect   = "Deny"
        Action   = ["s3:GetObject"]
        Resource = [
          "arn:aws:s3:::${var.tfstate_bucket}",
          "arn:aws:s3:::${var.tfstate_bucket}/*",
        ]
      },
    ]
  })
}

GitHub Actions ワークフロー側

permissions:
  id-token: write   # required for OIDC token issuance
  contents: read

jobs:
  ai-triage:
    runs-on: ubuntu-latest
    steps:
      - uses: aws-actions/configure-aws-credentials@v6
        with:
          role-to-assume: ${{ secrets.AWS_AI_AGENT_ROLE_ARN }}
          aws-region: ap-northeast-1
          role-session-name: ai-triage-${{ github.run_id }}

よくある落とし穴

  • Bedrock での aws-marketplace 権限の不足:Bedrock のサブスクリプションがアカウントレベルで有効でも、引き受けたロールに aws-marketplace:ViewSubscriptions(場合によっては Subscribe)が必要です。そうでない場合、Bedrock API の呼び出しは AccessDenied を返します。ほとんどの Bedrock IAM ドキュメントでは、この点に触れていません。

  • リージョン間推論プロファイルの ARN:Bedrock のリージョン間推論では、リージョンプレフィックス付きのモデル ID(jp.anthropic.*、us.anthropic.*、global.anthropic.*)を持つ inference-profile リソースタイプを使用します。標準の foundation-model/anthropic.* ARN で対象となるのは、同一リージョン内の呼び出しのみです。両方の ARN が必要です。

  • sub 条件を空にしないこと:AWS の OIDC 検証では、job_workflow_ref を使う場合でも、少なくとも 1 つの sub 条件が必要です。フォールバックとしてワイルドカード(repo:ORG/REPO:*)を使用してください。実際のスコープは job_workflow_ref によって設定されます。

  • job_workflow_ref には完全な ref が含まれること:値は ORG/REPO/.github/workflows/FILE.yml@refs/heads/main です。ファイルパスだけではありません。@refs/heads/main のサフィックスを省略すると、どのブランチからでもロールの引き受けを実行できます。

  • ReadOnlyAccess には機密性の高い読み取りアクションも含まれること:secretsmanager:GetSecretValue、kms:Decrypt、s3:GetObject はすべて ReadOnlyAccess に含まれています。インフラの調査だけが必要なエージェントロールでは、認証情報の漏えいを防ぐため、明示的な Deny ステートメントを追加してください。

コメント