0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【GitHub Actions】environment を付けると OIDC の sub が変わる──承認と AWS のロール引き受けを結び付けた話

0
Posted at

はじめに

GitHub Actions から Terraform で AWS を操作する CD を、長期キーを置かず OIDC で組みました。このとき1つやりたかったのが、

承認された“本番向けの実行”だけが、本番を変更できるロールを引き受けられる

という形です。これを、GitHub 側の承認と AWS 側のロール引き受け条件を、environment という共通の境界で連動させて実現できたので、その設計をまとめます。

先に結論:OIDC トークンの sub(subject)クレームは、ジョブに environment: を付けると形が変わります。その sub を AWS の IAM 信頼ポリシーで要求しておき、さらに environment 側に承認者を置くと、「承認を通った prod 実行だけが apply ロールを assume できる」という流れに寄せられます。

正直に書いておくと、私は最初から environment: prod を付けて運用しており、「外したら認証が拒否される」エラーを実際に踏んだわけではありません。以下は、公式仕様と実際の信頼ポリシーから導いた設計上の帰結として理解している内容です。

環境

  • GitHub Actions(OIDC / id-token: write)
  • Terraform(AWS プロバイダ)で apply を実行
  • AWS IAM OIDC プロバイダ + apply 用 IAM ロール
  • リージョン: ap-northeast-1(東京)

狙い:認証条件と承認ゲートを environment で結び付ける

CD で本番を触るロールは、できるだけ「誰でも・いつでも」引き受けられないようにしたい。そこで2つの制御を、environment という接点でつなぎました(別々の仕組みであることは意識しつつ)。

  • AWS 側(認証・認可境界):OIDC トークンと IAM 信頼ポリシーで「この実行を信用してよいか」を判定
  • GitHub 側(承認ゲート):Environment の Required reviewers で「ジョブを開始してよいか」を制御

この2つの“接点”になるのが environment: prod です。

仕組み①:sub は environment 指定で変わる

GitHub の OIDC トークンの sub は、ジョブの実行文脈で形が変わります(GitHub 公式の例より)。

ジョブの指定 sub の形
ブランチ実行 repo:<owner>/<repo>:ref:refs/heads/main
プルリクエスト repo:<owner>/<repo>:pull_request
environment: prod repo:<owner>/<repo>:environment:prod

つまり、ジョブに environment: prod を付けて初めて、sub が ...:environment:prod になります。

ワークフロー側はこうです(抜粋)。

jobs:
  provision-and-install:
    runs-on: ubuntu-latest
    environment: prod   # ★これで sub が ...:environment:prod になる
    permissions:
      id-token: write
      contents: read

補足:sub の形式は、組織やリポジトリで subject claim をカスタマイズしていると標準形と変わることがあります。カスタマイズしている場合は、実際の sub の値を確認して信頼ポリシーを合わせる必要があります。上の表はカスタマイズしていない、現行の標準形です。

仕組み②:信頼ポリシーでその sub だけを許す

AWS 側、apply ロールの信頼ポリシーは、sub が ...:environment:prod のときだけ assume を許すようにしてあります(抜粋)。

condition {
  test     = "StringEquals"
  variable = "token.actions.githubusercontent.com:aud"
  values   = ["sts.amazonaws.com"]
}
condition {
  test     = "StringEquals"
  variable = "token.actions.githubusercontent.com:sub"
  values   = ["repo:<owner>/<repo>:environment:prod"]
}

ここがポイントで、もしジョブから environment: prod を外すと、sub は ...:ref:refs/heads/main のような別の形になります。すると信頼ポリシーの StringEquals に一致しなくなるので、仕様上は sts:AssumeRoleWithWebIdentity が通りません。**「環境を通っていない実行は、本番ロールを引き受けられない」**が、AWS の信頼ポリシー側で機械的に担保される、という構図です。

(読み取り用の plan ロールは別に用意し、sub を pull_request と ref:refs/heads/main に限定して権限は ReadOnly にしています。「PR では読むだけ・本番変更は prod 環境から」という住み分けです。)

承認ゲートも environment に乗せる

environment: prod には、もう1つ乗せられるものがあります。GitHub の Environment には Required reviewers(承認者)を設定でき、設定した場合、ジョブはその承認が下りるまで開始されません。

  • Required reviewers の保護ルールを満たすまで、その Environment を参照するジョブは開始されない
  • そのため、通常の workflow 構成では OIDC トークン取得や AWS ロール引き受けの step も実行されない
  • 承認後に初めて、apply ロールを assume して terraform apply

ここは条件付きで、prod Environment に Required reviewers を設定している場合に承認ゲートが効きます(Environment は承認者なしでも使えて、その場合 sub は ...:environment:prod になりますが、人間の承認は挟まりません)。Required reviewers を設定した prod Environment を経由させることで、承認待ちのジョブと、apply ロールを取れるジョブを、実質的に同じ境界へ寄せられました。

補足:environment だけではブランチ制限にならない

注意点として、environment:prod の sub は標準形ではブランチ名を含みません。つまり信頼ポリシーで Environment を見ていても、それだけでは「main からの apply だけ」にはなりません。apply を main に限定したいなら、

  • GitHub Environment の deployment branch rules で main を許可対象にする
  • または workflow の on / ジョブの if で main を制限する

のどちらか(または両方)を別途明示します。ブランチ制御は Environment 側か workflow 側で行う、と切り分けて考えるのが安全でした。

学び

  • OIDC の sub は ジョブの実行文脈で形が変わる。environment: を付けると ...:environment:<name> になる(標準形・GitHub 公式の例で確認)。組織/リポジトリでカスタマイズしていると変わる。
  • AWS 側の信頼ポリシーで sub を ...:environment:prod に限定すると、その環境を参照した実行だけがそのロールを assume できる。
  • GitHub Environment に Required reviewers を設定すると、承認ゲートを同じ environment に乗せられる(設定した場合に限る)。
  • environment:prod だけではブランチ制限にならない。main 限定は deployment branch rules か workflow 側で別途。
  • 権限は用途で分ける:plan は ReadOnly(PR / main)、apply は変更可(environment:prod)。

おわりに

「鍵を置かない」だけでなく、「承認された実行しか本番を触れない」までを、environment という1つの境界に寄せられたのが、設計していて一番すっきりした部分でした😊 OIDC の sub が文脈で変わる、という小さな事実が効いています。同じく CD の権限設計で迷っている人の参考になれば嬉しいです🙌

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?