feat(infra): デプロイ権限を CI ロールに集約し、push と rollout を分離する - #107
Merged
Conversation
人間の手動デプロイが admin で CI のガードレールを迂回していた。CI ロールの trust に permission set 経由の経路を足し、人間と CI が同じ権限定義を通るようにする。 principals に ARN のワイルドカードは書けないため、入口をアカウントにして aws:PrincipalArn の ArnLike で絞る。permission set のロール名は割り当てを 作り直すたびに接尾辞が変わるため完全一致では書けない。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
build は Dockerfile と依存パッケージのコードが実際に走る工程なので、そこに本番を 差し替える権限を持たせない。app-deploy を app-push (ECR のみ) と app-rollout (ECS のみ) に割り、後者の sub を environment 限定にする。承認されるまで job が 起動せず OIDC token が発行されないため、承認ゲートが経路の不在として成立する。 rollout job は cluster に service を問い合わせて対象を数える。workflow に段の 一覧を持つと locals.tf と 2 箇所になり、段の追加が黙って漏れるため。family の 最新 ACTIVE revision を土台に image tag だけ差し替えるので、Terraform 由来の env / secrets の変更もそこで取り込まれる。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
レビュー指摘の反映。 - role ARN を vars から secrets へ。with: の値はステップ開始時にログへ出るため、 run: 側の ::add-mask:: では間に合わない。mask-aws-account-id は action 自身の 出力に対する補助として併用する。 - 空ガードが到達不能だった。grep -vx は該当なしで exit 1 を返し、set -e が先に 効く。AWS 側の失敗を握り潰さないよう list-services を単独で実行し、|| true は grep だけに付ける。 - rollout を 2 パス化。全段の revision を登録してから入れ替えるので、途中失敗で 一部だけ新 revision になる窓が短くなる。 - IMMUTABLE tag の焼き直しで push が落ち、rollout に到達しない問題。既に在る tag は skip する。batch-get-image は image 不在でも exit 0 なので images 配列の 長さで判定する。 - waiter の上限は botocore 側の 15 秒 x 40 回 = 10 分で、job timeout より先に 効く。コメントを事実に直し、1 回だけ待ち直す。 - 二重 dispatch で rollout が並走しないよう concurrency を追加する。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
Fly / Neon 退役後、本番への反映経路は手動の
terraform applyとaws ecs update-serviceだけになっている。この経路はWorkloadAdministratorで実行されており、CI 用に定義済みの最小権限ロールとその Deny 群を丸ごと迂回していた。「デプロイで何ができるか」の定義は
oidc.tfに既にある。人間用に別ポリシーを書くとその定義が 2 箇所になるため、人間も同じロールを通す方向で解決する。あわせて、image を焼く工程と本番を入れ替える工程を分離する。1. 人間が CI ロールを assume できるようにする
CI ロールの trust policy に、IAM Identity Center の permission set 経由の経路を追加する。
data.aws_iam_policy_document.github_trustをci_role_trustにリネーム (GitHub Actions 以外も入るため)Sid = "DeployPermissionSet"を追加。permission set 名はdeploy_permission_set変数 (defaultVectorDeploy)principalsに ARN のワイルドカードは書けないため、入口をアカウントにしてaws:PrincipalArnのArnLikeで絞る。permission set のロール名は割り当てを作り直すたびに接尾辞が変わるため完全一致では書けない。両者は AND で評価されるので、実効的に通るのは deploy permission set のロールだけになる。2. push と rollout の role を分ける
app-deployを 2 つに割る。app-pushref:refs/heads/main(承認不要)app-rolloutPassRoleのみenvironment:production(承認必須)docker buildは Dockerfile と依存パッケージのコードが実際に走る工程で、外部から入るコードの実行点になる。ここに本番差し替えの権限を持たせると、依存 1 つの侵害が本番に直結する。分けると、build job が侵害されても ECR に image が置かれるだけで本番は動かない。1 つの role に両方の sub を許す案もあるが、それだと承認を経ない job からも rollout でき、ゲートが「回避しない約束」に退化する。sub を分けると、承認済み job の外では rollout 用の token がそもそも発行されない。
3. rollout job を足す
aws-app-images.ymlにenvironment: productionの rollout job を追加する。locals.tfと 2 箇所になり、段の追加が黙って漏れる。proxyだけ image も workflow も別系統なので除外するwait services-stableで 1 段でも安定しなければ失敗させる検証
terraform fmt/validate、workflow の YAML パースを確認済み。1 は apply 済み (
0 added, 3 changed, 0 destroyed) で、実機で確認した:DeployPermissionSetが入ったか2 と 3 は未 apply。plan は
4 to add, 0 to change, 2 to destroy。merge 前に必要な手動作業
terraform apply(bootstrap) —app-deployが消えてapp-push/app-rolloutができるAWS_PUSH_ROLE_ARN/AWS_ROLLOUT_ROLE_ARNを追加し、AWS_DEPLOY_ROLE_ARNを削除productionenvironment に required reviewer を設定 (現状は branch policy のみで、承認ゲートが存在しない)VectorDeploypermission set のインラインポリシーが参照する role ARN を新しい 2 つに更新Non-goals
ManagementAdministratorの break-glass 分離🤖 Generated with Claude Code