feat(iam): allow frontend HCP apply to own release pointer and invalidation (PLAT-188)

Plan and apply roles can read .release/current; apply can PutObject that key and CreateInvalidation on the exact distribution.
This commit is contained in:
Adam Moussa 2026-09-11 12:54:07 -04:00
parent 0c6f307b61
commit 97b00ad0f4
No known key found for this signature in database
2 changed files with 24 additions and 2 deletions

View file

@ -439,7 +439,9 @@ job:
existing site resources only after a no-replacement plan. Apply-role writes
are limited to ordinary tags, `PutRolePolicy` on the exact deploy role,
`PutBucketPolicy` on the exact bucket, `UpdateDistribution` on the exact
distribution, `UpdateFunction` and `PublishFunction` on the exact CloudFront
distribution, `CreateInvalidation`/`GetInvalidation` on the exact
distribution, `GetObject`/`PutObject` on `.release/current`,
`UpdateFunction` and `PublishFunction` on the exact CloudFront
function, and A/AAAA changes for the exact site name with
CREATE/DELETE/UPSERT conditions.
5. For a future tf-poc, first provision and inventory the site outside these
@ -456,7 +458,9 @@ The apply roles explicitly deny role lifecycle/trust/boundary/managed-policy
changes, `PassRole`, secret and parameter reads, CloudFront/S3 create and
delete (including OAC mutation), and deletion of inline role or bucket
policies. `UpdateDistribution` is allowed on the exact pinned distribution ARN.
`UpdateFunction` and `PublishFunction` are allowed on the exact pinned function
`CreateInvalidation` and `GetInvalidation` are allowed on that same ARN so the
Terraform invalidation action can run. `GetObject`/`PutObject` on
`.release/current` lets Terraform own the release pointer. `UpdateFunction` and `PublishFunction` are allowed on the exact pinned function
ARN so Phase 2 ownership tags can apply; create, delete, and OAC updates stay
denied. IAM does not expose a condition key for an inline policy name, so
`PutRolePolicy` is constrained to the exact target-role ARN and requires the

View file

@ -113,6 +113,12 @@ const frontendReadPolicy = (
],
Resource: siteBucketArn,
},
{
Sid: "ReadReleasePointerObject",
Effect: "Allow",
Action: ["s3:GetObject", "s3:GetObjectVersion"],
Resource: `${siteBucketArn}/.release/current`,
},
{
Sid: "ReadExactCloudFrontResources",
Effect: "Allow",
@ -343,6 +349,18 @@ const frontendApplyPolicy = (
Action: ["cloudfront:UpdateFunction", "cloudfront:PublishFunction"],
Resource: functionArn(environment.functionName),
},
{
Sid: "InvalidateExactDistribution",
Effect: "Allow",
Action: ["cloudfront:CreateInvalidation", "cloudfront:GetInvalidation"],
Resource: distributionArn(environment.distributionId),
},
{
Sid: "WriteReleasePointerObject",
Effect: "Allow",
Action: ["s3:GetObject", "s3:GetObjectVersion", "s3:PutObject"],
Resource: `${bucketArn(environment.bucketName)}/.release/current`,
},
{
Sid: "ReplaceExactDeployInlinePolicy",
Effect: "Allow",