chore(iam): remove frontend tf-poc substrate after teardown (PLAT-194) (#146)
Some checks failed
Deploy / deploy-management (push) Has been cancelled
Deploy / deploy-external-dev (push) Has been cancelled
Deploy / deploy-security (push) Has been cancelled
Deploy / deploy-dev (push) Has been cancelled
Deploy / deploy-prod (push) Has been cancelled

This commit is contained in:
Adam Moussa 2026-09-11 22:17:00 +00:00 • committed by GitHub
parent 5d613c73bc
commit a492a45e07
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 40 additions and 114 deletions

View file

@ -406,19 +406,20 @@ external-dev IAM guardrail SCP is 5,095 compact characters against its
5,120-character Organizations limit; keep size assertions in every change. 5,120-character Organizations limit; keep size assertions in every change.
**External-dev SHOC frontend adoption uses separate gates and creates its **External-dev SHOC frontend adoption uses separate gates and creates its
boundaries first.** The three retained boundaries are boundaries first.** The two live retained boundaries are
`shoc-frontend-new-{tf-poc,dev,staging}-deploy-boundary`. Each permits only `shoc-frontend-new-{dev,staging}-deploy-boundary`. Each permits only
bucket location/list/version reads, object get/put/current and version delete, bucket location/list/version reads, object get/put/current and version delete,
`GetDistribution`/`GetDistributionConfig`, and invalidation create/read for `GetDistribution`/`GetDistributionConfig`, and invalidation create/read for
one exact distribution. Dev is pinned to `E2CWLM1AFB964P`; staging is pinned one exact distribution. Dev is pinned to `E2CWLM1AFB964P`; staging is pinned
to `E2JDVEZ6EGD49J`. The tf-poc distribution, OAC, function, hosted-zone, and to `E2JDVEZ6EGD49J`. The frontend tf-poc rehearsal is retired: its site,
certificate identifiers are intentionally empty in `cdk.json`. They must come HCP workspace, and GitHub deploy role are gone. `enableShocFrontendPocRoles`
from the frontend shared creator outputs; this substrate does not reuse the is false and the five `shocFrontendPoc*` identifiers are empty, so
backend tf-poc zone or certificate. Its site name is `ShouldManageShocFrontendPocRoles` stays false. After the stack update,
`frontend-tf-poc.seahaven.com`. While the identifier set is empty, its delete the retained orphans `hcptf-shoc-frontend-new-tf-poc`,
boundary omits distribution read and invalidation access and `hcptf-shoc-frontend-new-tf-poc-plan`, and
`ShouldManageShocFrontendPocRoles` remains false even if its role gate is `shoc-frontend-new-tf-poc-deploy-boundary` with
mistakenly enabled. `OrganizationAccountAccessRole`. A later rehearsal must
inventory new identifiers before that gate is turned on.
The frontend role transition is manual and is not part of the external-dev CD The frontend role transition is manual and is not part of the external-dev CD
job: job:
@ -457,14 +458,9 @@ job:
a false gate as rollback after CloudFormation owns a role. a false gate as rollback after CloudFormation owns a role.
The apply roles explicitly deny role lifecycle/trust/boundary/managed-policy The apply roles explicitly deny role lifecycle/trust/boundary/managed-policy
changes, `PassRole`, secret and parameter reads, CloudFront/S3 create, and changes, `PassRole`, secret and parameter reads, CloudFront/S3 create and
(for dev and staging) CloudFront/S3 delete including OAC mutation and bucket delete (including OAC mutation), and deletion of inline role or bucket
policy deletion. The tf-poc apply role is the exception: it keeps create policies. `UpdateDistribution` is allowed on the exact pinned distribution ARN.
denied and allows destroy of the exact rehearsal bucket (including object
versions), distribution `E73KH1SPNFL00`, OAC `E14MP8Z5YRWO93`, function
`us-east-1shocfrontendtfpocSpaRewrite4B1A4F5F`, and A/AAAA in
`Z10433621DH3UOWM8663D`. It still does not delete `githubdeploy-*`; SCP
`ProtectDeploymentPrincipalLifecycle` denies that for HCP principals. `UpdateDistribution` is allowed on the exact pinned distribution ARN.
`CreateInvalidation` and `GetInvalidation` are allowed on that same ARN so the `CreateInvalidation` and `GetInvalidation` are allowed on that same ARN so the
Terraform invalidation action can run. `GetObject`/`GetObjectTagging`/`PutObject`/`PutObjectTagging` on Terraform invalidation action can run. `GetObject`/`GetObjectTagging`/`PutObject`/`PutObjectTagging` on
`.release/current` lets Terraform own the release pointer, including the `.release/current` lets Terraform own the release pointer, including the

View file

@ -20,12 +20,12 @@
"@aws-cdk/core:target-partitions": ["aws"], "@aws-cdk/core:target-partitions": ["aws"],
"enableShocBackendPocRoles": true, "enableShocBackendPocRoles": true,
"enableShocBackendLiveRoles": true, "enableShocBackendLiveRoles": true,
"enableShocFrontendPocRoles": true, "enableShocFrontendPocRoles": false,
"enableShocFrontendLiveRoles": true, "enableShocFrontendLiveRoles": true,
"shocFrontendPocDistributionId": "E73KH1SPNFL00", "shocFrontendPocDistributionId": "",
"shocFrontendPocOriginAccessControlId": "E14MP8Z5YRWO93", "shocFrontendPocOriginAccessControlId": "",
"shocFrontendPocFunctionName": "us-east-1shocfrontendtfpocSpaRewrite4B1A4F5F", "shocFrontendPocFunctionName": "",
"shocFrontendPocHostedZoneId": "Z10433621DH3UOWM8663D", "shocFrontendPocHostedZoneId": "",
"shocFrontendPocCertificateArn": "arn:aws:acm:us-east-1:396287094661:certificate/3dbc8c23-3467-47db-9f6c-39236ca11682" "shocFrontendPocCertificateArn": ""
} }
} }

View file

@ -66,7 +66,7 @@
"Effect": "Deny", "Effect": "Deny",
"Action": ["iam:PutRolePolicy", "iam:TagRole", "iam:UntagRole"], "Action": ["iam:PutRolePolicy", "iam:TagRole", "iam:UntagRole"],
"Resource": "arn:aws:iam::396287094661:role/githubdeploy-*", "Resource": "arn:aws:iam::396287094661:role/githubdeploy-*",
"Condition": { "ArnNotLike": { "aws:PrincipalArn": ["arn:aws:iam::396287094661:role/OrganizationAccountAccessRole", "arn:aws:iam::396287094661:role/cdk-hnb659fds-*", "arn:aws:iam::396287094661:role/hcptf-shoc-backend-tf-poc", "arn:aws:iam::396287094661:role/hcptf-shoc-backend-dev", "arn:aws:iam::396287094661:role/hcptf-shoc-backend-staging", "arn:aws:iam::396287094661:role/hcptf-shoc-frontend-new-tf-poc", "arn:aws:iam::396287094661:role/hcptf-shoc-frontend-new-dev", "arn:aws:iam::396287094661:role/hcptf-shoc-frontend-new-staging"] } } "Condition": { "ArnNotLike": { "aws:PrincipalArn": ["arn:aws:iam::396287094661:role/OrganizationAccountAccessRole", "arn:aws:iam::396287094661:role/cdk-hnb659fds-*", "arn:aws:iam::396287094661:role/hcptf-shoc-backend-tf-poc", "arn:aws:iam::396287094661:role/hcptf-shoc-backend-dev", "arn:aws:iam::396287094661:role/hcptf-shoc-backend-staging", "arn:aws:iam::396287094661:role/hcptf-shoc-frontend-new-dev", "arn:aws:iam::396287094661:role/hcptf-shoc-frontend-new-staging"] } }
}, },
{ {
"Sid": "DenyUnmanagedGithubRole", "Sid": "DenyUnmanagedGithubRole",

View file

@ -230,93 +230,6 @@ const frontendReadPolicy = (
}; };
}; };
const infrastructureReplacementDenyActions = (
environment: FrontendEnvironment,
): string[] => {
const createOnly = [
"cloudfront:CreateDistribution",
"cloudfront:CreateFunction",
"cloudfront:CreateOriginAccessControl",
"s3:CreateBucket",
];
if (environment.key === "tf-poc") {
// Destroy needs Delete* and the Put/Delete calls Terraform uses to
// remove versioning, encryption, ownership, and public-access configs.
return createOnly;
}
return [
...createOnly,
"cloudfront:DeleteDistribution",
"cloudfront:DeleteFunction",
"cloudfront:DeleteOriginAccessControl",
"cloudfront:UpdateOriginAccessControl",
"s3:DeleteBucket",
"s3:DeleteBucketEncryption",
"s3:DeleteBucketOwnershipControls",
"s3:DeleteBucketPolicy",
"s3:DeleteBucketPublicAccessBlock",
"s3:PutBucketOwnershipControls",
"s3:PutBucketPublicAccessBlock",
"s3:PutBucketVersioning",
"s3:PutEncryptionConfiguration",
];
};
const frontendPocDestroyStatements = (
environment: FrontendEnvironment,
): Record<string, unknown>[] => {
if (environment.key !== "tf-poc") {
return [];
}
const siteBucketArn = bucketArn(environment.bucketName);
return [
{
Sid: "DestroyExactPocBucket",
Effect: "Allow",
Action: [
"s3:DeleteBucket",
"s3:DeleteBucketEncryption",
"s3:DeleteBucketOwnershipControls",
"s3:DeleteBucketPolicy",
"s3:DeleteBucketPublicAccessBlock",
"s3:GetBucketVersioning",
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:PutBucketOwnershipControls",
"s3:PutBucketPublicAccessBlock",
"s3:PutBucketVersioning",
"s3:PutEncryptionConfiguration",
],
Resource: siteBucketArn,
},
{
Sid: "DestroyExactPocBucketObjects",
Effect: "Allow",
Action: [
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetObject",
"s3:GetObjectVersion",
],
Resource: `${siteBucketArn}/*`,
},
{
Sid: "DestroyExactPocCloudFront",
Effect: "Allow",
Action: [
"cloudfront:DeleteDistribution",
"cloudfront:DeleteFunction",
"cloudfront:DeleteOriginAccessControl",
],
Resource: [
distributionArn(environment.distributionId),
functionArn(environment.functionName),
originAccessControlArn(environment.originAccessControlId),
],
},
];
};
const frontendApplyPolicy = ( const frontendApplyPolicy = (
environment: FrontendEnvironment, environment: FrontendEnvironment,
): Record<string, unknown> => ({ ): Record<string, unknown> => ({
@ -356,7 +269,25 @@ const frontendApplyPolicy = (
{ {
Sid: "DenyInfrastructureReplacement", Sid: "DenyInfrastructureReplacement",
Effect: "Deny", Effect: "Deny",
Action: infrastructureReplacementDenyActions(environment), Action: [
"cloudfront:CreateDistribution",
"cloudfront:CreateFunction",
"cloudfront:CreateOriginAccessControl",
"cloudfront:DeleteDistribution",
"cloudfront:DeleteFunction",
"cloudfront:DeleteOriginAccessControl",
"cloudfront:UpdateOriginAccessControl",
"s3:CreateBucket",
"s3:DeleteBucket",
"s3:DeleteBucketEncryption",
"s3:DeleteBucketOwnershipControls",
"s3:DeleteBucketPolicy",
"s3:DeleteBucketPublicAccessBlock",
"s3:PutBucketOwnershipControls",
"s3:PutBucketPublicAccessBlock",
"s3:PutBucketVersioning",
"s3:PutEncryptionConfiguration",
],
Resource: "*", Resource: "*",
}, },
{ {
@ -472,7 +403,6 @@ const frontendApplyPolicy = (
}, },
}, },
}, },
...frontendPocDestroyStatements(environment),
], ],
}); });