<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>OIDC on AI2CORE - AI技術ブログ</title>
    <link>https://www.ai2core.com/tags/oidc/</link>
    <description>Recent content in OIDC on AI2CORE - AI技術ブログ</description>
    <generator>Hugo -- 0.146.4</generator>
    <language>ja</language>
    <lastBuildDate>Thu, 05 Mar 2026 09:08:00 +0900</lastBuildDate>
    <atom:link href="https://www.ai2core.com/tags/oidc/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>GitHub Actions OIDCで実現する鍵レス本番デプロイ：漏えい事故を減らす実装プレイブック</title>
      <link>https://www.ai2core.com/posts/2026-03-05-github-actions-oidc-secure-deploy-playbook/</link>
      <pubDate>Thu, 05 Mar 2026 09:08:00 +0900</pubDate>
      <guid>https://www.ai2core.com/posts/2026-03-05-github-actions-oidc-secure-deploy-playbook/</guid>
      <description>長期シークレットを廃止し、GitHub Actions OIDCでAWSへ安全にデプロイするための設計・実装・監査手順を具体的に解説。</description>
      <content:encoded><![CDATA[<h1 id="github-actions-oidcで実現する鍵レス本番デプロイ漏えい事故を減らす実装プレイブック">GitHub Actions OIDCで実現する鍵レス本番デプロイ：漏えい事故を減らす実装プレイブック</h1>
<p>CI/CD の事故は、ビルドが失敗することより「漏えいしても気づけない鍵」が残り続けることのほうが深刻です。特に <code>AWS_ACCESS_KEY_ID</code> のような長期シークレットを GitHub Secrets に保存し続ける運用は、便利ですがリスクが高いです。</p>
<p>本記事では、GitHub Actions の <strong>OIDC（OpenID Connect）連携</strong>を使って、長期鍵を使わずに AWS へデプロイする実践手順をまとめます。単なる設定紹介ではなく、<strong>最小権限・ブランチ制限・監査ログ設計</strong>まで含めて、明日から本番投入できる形で説明します。</p>
<h2 id="1-まず何が危険なのか長期シークレット運用の限界">1. まず何が危険なのか：長期シークレット運用の限界</h2>
<p>従来構成では、次のような問題が起きます。</p>
<ul>
<li>Secret が漏れても検知が遅い（CIログ、誤コミット、権限の広いメンバー）</li>
<li>ローテーションが後回しになる</li>
<li>1つの鍵で複数環境へアクセスできてしまう</li>
<li>「誰のどの workflow 実行が何をしたか」が追いにくい</li>
</ul>
<p>OIDC 連携では、GitHub が発行する短命トークンを信頼し、AWS 側で一時認証情報を払い出します。つまり、<strong>保管する鍵そのものを減らす</strong>のが最大の価値です。</p>
<h2 id="2-全体アーキテクチャ">2. 全体アーキテクチャ</h2>
<p>基本フローは以下です。</p>
<ol>
<li>GitHub Actions ジョブが OIDC トークンを取得</li>
<li>AWS IAM の OIDC プロバイダとロール信頼ポリシーで検証</li>
<li>条件に一致したジョブだけ <code>AssumeRoleWithWebIdentity</code></li>
<li>一時クレデンシャルで S3/CloudFront/ECR/ECS へデプロイ</li>
</ol>
<p>ポイントは「GitHub 側の workflow 制御」だけでなく、<strong>AWS 側で repo・branch・workflow を強制する</strong>ことです。</p>
<h2 id="3-aws-側の初期設定oidc-provider--iam-role">3. AWS 側の初期設定（OIDC Provider + IAM Role）</h2>
<h3 id="31-oidc-provider-を作成">3.1 OIDC Provider を作成</h3>
<p>CLI 例（すでに存在する場合はスキップ）:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>aws iam create-open-id-connect-provider <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --url https://token.actions.githubusercontent.com <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --client-id-list sts.amazonaws.com <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>  --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="32-信頼ポリシーを厳密化する">3.2 信頼ポリシーを厳密化する</h3>
<p>以下のように <code>sub</code> と <code>aud</code> を必ず絞ります。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Version&#34;</span>: <span style="color:#e6db74">&#34;2012-10-17&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;Statement&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Effect&#34;</span>: <span style="color:#e6db74">&#34;Allow&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Principal&#34;</span>: {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;Federated&#34;</span>: <span style="color:#e6db74">&#34;arn:aws:iam::&lt;ACCOUNT_ID&gt;:oidc-provider/token.actions.githubusercontent.com&#34;</span>
</span></span><span style="display:flex;"><span>      },
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Action&#34;</span>: <span style="color:#e6db74">&#34;sts:AssumeRoleWithWebIdentity&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;Condition&#34;</span>: {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;StringEquals&#34;</span>: {
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;token.actions.githubusercontent.com:aud&#34;</span>: <span style="color:#e6db74">&#34;sts.amazonaws.com&#34;</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;StringLike&#34;</span>: {
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;token.actions.githubusercontent.com:sub&#34;</span>: <span style="color:#e6db74">&#34;repo:your-org/your-repo:ref:refs/heads/main&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>sub</code> を <code>repo:org/repo:*</code> のように広く取りすぎると、意図しない workflow からも引き受ける可能性があり危険です。</p>
<h3 id="33-デプロイ権限ポリシーを分離する">3.3 デプロイ権限ポリシーを分離する</h3>
<p>「ロール1個に全部盛り」は避けます。</p>
<ul>
<li><code>deploy-web-prod-role</code>: S3同期 + CloudFront invalidation</li>
<li><code>deploy-api-prod-role</code>: ECR push + ECS update</li>
<li><code>read-only-audit-role</code>: CloudWatch Logs / Describe 系のみ</li>
</ul>
<p>環境別（dev/stg/prod）にロールを分離すると、誤デプロイ時の被害半径が大きく減ります。</p>
<h2 id="4-github-actions-workflow-実装">4. GitHub Actions workflow 実装</h2>
<p>最小サンプル:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">name</span>: <span style="color:#ae81ff">deploy-web</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">on</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">push</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">branches</span>: [<span style="color:#e6db74">&#34;main&#34;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">permissions</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">id-token</span>: <span style="color:#ae81ff">write</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">contents</span>: <span style="color:#ae81ff">read</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">jobs</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">deploy</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">runs-on</span>: <span style="color:#ae81ff">ubuntu-latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>: <span style="color:#ae81ff">production</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">steps</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">actions/checkout@v4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Configure AWS credentials via OIDC</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">aws-actions/configure-aws-credentials@v4</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">with</span>:
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">role-to-assume</span>: <span style="color:#ae81ff">arn:aws:iam::&lt;ACCOUNT_ID&gt;:role/deploy-web-prod-role</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">aws-region</span>: <span style="color:#ae81ff">ap-northeast-1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Build</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">run</span>: |<span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          npm ci
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          npm run build</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Upload to S3</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">run</span>: <span style="color:#ae81ff">aws s3 sync ./dist s3://example-prod-web --delete</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Invalidate CloudFront</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">run</span>: <span style="color:#ae81ff">aws cloudfront create-invalidation --distribution-id E123456 --paths &#34;/*&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>重要なのは <code>permissions.id-token: write</code> を明示する点です。これがないと OIDC トークンを取得できません。</p>
<h2 id="5-事故を防ぐための実務ルール">5. 事故を防ぐための実務ルール</h2>
<h3 id="51-branch-protection-と-environment-protection-を組み合わせる">5.1 branch protection と environment protection を組み合わせる</h3>
<ul>
<li><code>main</code> 直push禁止</li>
<li>必ず PR + 1 approval</li>
<li>production environment には Required reviewers を設定</li>
<li>夜間デプロイを禁止したい場合は手動承認ステップを入れる</li>
</ul>
<h3 id="52-workflow-ファイル改変の監査">5.2 workflow ファイル改変の監査</h3>
<p><code>.github/workflows/*.yml</code> の変更は CODEOWNERS で必ずレビュアー固定にします。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-txt" data-lang="txt"><span style="display:flex;"><span>.github/workflows/*  @platform-team
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="53-self-hosted-runner-の扱い">5.3 self-hosted runner の扱い</h3>
<p>OIDC を導入しても、runner 自体が侵害されると意味が薄れます。</p>
<ul>
<li>runner をプロジェクト共有にしない（専用化）</li>
<li>ジョブ後にワークディレクトリをクリーン</li>
<li>egress 制限をかける</li>
<li>runner グループを環境ごとに分離</li>
</ul>
<h2 id="6-トラブルシューティング">6. トラブルシューティング</h2>
<h3 id="症状1-not-authorized-to-perform-stsassumerolewithwebidentity">症状1: <code>Not authorized to perform sts:AssumeRoleWithWebIdentity</code></h3>
<p>確認ポイント:</p>
<ol>
<li><code>aud</code> が <code>sts.amazonaws.com</code> になっているか</li>
<li><code>sub</code> が実際の実行 ref と一致しているか（タグ実行でハマりやすい）</li>
<li><code>permissions.id-token: write</code> が設定されているか</li>
<li>Role ARN の typo がないか</li>
</ol>
<h3 id="症状2-main-以外で偶発的にデプロイされた">症状2: main 以外で偶発的にデプロイされた</h3>
<ul>
<li>workflow の <code>on.push.branches</code> 見直し</li>
<li>IAM 信頼ポリシー <code>sub</code> を main 固定へ</li>
<li>環境保護ルール（Required reviewers）追加</li>
</ul>
<h3 id="症状3-デプロイは通るが操作が一部失敗">症状3: デプロイは通るが操作が一部失敗</h3>
<p>これは IAM 権限不足の可能性が高いです。CloudTrail の <code>eventName</code> と <code>errorCode</code> を見て、必要最小限のアクションだけ追加します。闇雲に <code>*</code> を付けないこと。</p>
<h2 id="7-段階的な移行計画既存運用からの切替">7. 段階的な移行計画（既存運用からの切替）</h2>
<p>実務では一気に切り替えず、以下の順が安全です。</p>
<ol>
<li>OIDC ロールを作成（既存シークレットは残す）</li>
<li>staging workflow だけ OIDC に切替</li>
<li>1週間監視（失敗率・デプロイ時間・CloudTrail）</li>
<li>production を OIDC 化</li>
<li>最後に長期シークレットを削除</li>
</ol>
<p>削除前に「どの workflow がどの secret を参照しているか」を grep で確認しておくと事故が減ります。</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git grep -n <span style="color:#e6db74">&#34;AWS_ACCESS_KEY_ID\|AWS_SECRET_ACCESS_KEY&#34;</span> .github/workflows
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="8-監査ログ設計何を見れば安全性が上がるか">8. 監査ログ設計：何を見れば安全性が上がるか</h2>
<p>最低限、次をダッシュボード化すると運用しやすいです。</p>
<ul>
<li><code>AssumeRoleWithWebIdentity</code> 実行回数（日次）</li>
<li>失敗イベント数（権限エラー/条件不一致）</li>
<li>production deploy 実行者（workflow + sha + actor）</li>
<li>1回のデプロイで変更された主要リソース数</li>
</ul>
<p>CloudTrail + CloudWatch Logs Insights での簡易クエリ例:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span>fields <span style="color:#f92672">@</span><span style="color:#66d9ef">timestamp</span>, userIdentity.sessionContext.sessionIssuer.userName, eventName, errorCode
</span></span><span style="display:flex;"><span><span style="color:#f92672">|</span> filter eventSource <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;sts.amazonaws.com&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">|</span> filter eventName <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;AssumeRoleWithWebIdentity&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">|</span> sort <span style="color:#f92672">@</span><span style="color:#66d9ef">timestamp</span> <span style="color:#66d9ef">desc</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">|</span> <span style="color:#66d9ef">limit</span> <span style="color:#ae81ff">50</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="まとめ">まとめ</h2>
<p>OIDC は「設定が新しいから導入する」ものではなく、<strong>長期鍵を削減して事故確率を下げるための運用設計</strong>です。導入時にやるべきことはシンプルで、次の3つに集約できます。</p>
<ol>
<li>IAM 信頼ポリシーを repo/branch 単位で厳密化する</li>
<li>workflow 側で id-token 権限と環境保護を設定する</li>
<li>CloudTrail で AssumeRole の監査を継続する</li>
</ol>
<p>ここまで実施すれば、CI/CD のセキュリティは「頑張って守る」状態から、「漏えいしにくい仕組みで守る」状態へ進化します。まずは staging 1本から置き換えるのがおすすめです。</p>
]]></content:encoded>
      <category>Tech</category>
      <category>GitHub Actions</category>
      <category>OIDC</category>
      <category>Security</category>
      <category>AWS</category>
      <category>CI/CD</category>
    </item>
  </channel>
</rss>
