mirror of
https://github.com/Sea-Haven-Industries/seahaven-org-baseline.git
synced 2026-10-07 12:38:55 +00:00
fix(baseline): remove the management account web acl from the baseline (#173)
The live template already retains the WebACL. Dropping the construct forgets that missing ACL and deletes the management SSM parameter. Prod keeps seahaven-app-web-acl.
This commit is contained in:
parent
cd37817e1f
commit
86666b8d0b
4 changed files with 10 additions and 55 deletions
|
|
@ -222,10 +222,9 @@ new DeploySubstrateStack(app, "deploy-substrate-dev", {
|
||||||
// PLAT-145). External-dev stays: SHOC IAM is not moving (PLAT-148).
|
// PLAT-145). External-dev stays: SHOC IAM is not moving (PLAT-148).
|
||||||
// deploy-substrate stays for remaining SAM (PLAT-150).
|
// deploy-substrate stays for remaining SAM (PLAT-150).
|
||||||
|
|
||||||
// Shared CloudFront WAF for seahaven-prod (PLAT-92). Same AppWebAcl construct
|
// Shared CloudFront WAF for seahaven-prod (PLAT-92). The management account
|
||||||
// as mgmt account-baseline; thin stack so prod does not inherit the full
|
// no longer publishes /seahaven/waf/app-web-acl-arn. This stack publishes that
|
||||||
// mgmt baseline. Publishes /seahaven/waf/app-web-acl-arn for in-account
|
// parameter for in-account CloudFront associations (same-account only).
|
||||||
// CloudFront associations (same-account only).
|
|
||||||
new AppWebAclStack(app, "app-web-acl-prod", {
|
new AppWebAclStack(app, "app-web-acl-prod", {
|
||||||
stackName: "seahaven-app-web-acl",
|
stackName: "seahaven-app-web-acl",
|
||||||
env: { account: PROD_ACCOUNT, region: "us-east-1" },
|
env: { account: PROD_ACCOUNT, region: "us-east-1" },
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import { BedrockLogging } from "./bedrock-logging";
|
||||||
import { CisMonitoring } from "./cis-monitoring";
|
import { CisMonitoring } from "./cis-monitoring";
|
||||||
import { FlowLogs } from "./flow-logs";
|
import { FlowLogs } from "./flow-logs";
|
||||||
import { SesMonitoring } from "./ses-monitoring";
|
import { SesMonitoring } from "./ses-monitoring";
|
||||||
import { AppWebAcl } from "./web-acl";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account-level security baseline for Sea Haven (account 328440206208).
|
* Account-level security baseline for Sea Haven (account 328440206208).
|
||||||
|
|
@ -252,19 +251,6 @@ export class AccountBaselineStack extends cdk.Stack {
|
||||||
vpcIds: props.flowLogVpcIds,
|
vpcIds: props.flowLogVpcIds,
|
||||||
});
|
});
|
||||||
new SesMonitoring(this, "SesMonitoring");
|
new SesMonitoring(this, "SesMonitoring");
|
||||||
// Shared CloudFront WAF WebACL (M-17); ARN published to SSM for app stacks.
|
|
||||||
// RETAIN on the WebACL only. The physical ACL is already gone
|
|
||||||
// (WAFNonexistentItemException) while this stack still owns it. The
|
|
||||||
// deletion policy has to be in the live template before the construct is
|
|
||||||
// removed, or CloudFormation Deletes, fails, and rollback tries to
|
|
||||||
// recreate it. The SSM parameter stays on Delete.
|
|
||||||
// existingWebAclId keeps the parameter and output off WebACL.Arn. GetAtt
|
|
||||||
// calls GetWebACL, which fails because the ACL is gone. The id is the
|
|
||||||
// physical id CloudFormation already recorded for AppWebAclFE38F02F.
|
|
||||||
new AppWebAcl(this, "AppWebAcl", {
|
|
||||||
webAclRemovalPolicy: cdk.RemovalPolicy.RETAIN,
|
|
||||||
existingWebAclId: "cd668fe8-5cff-4d6a-9432-5c32145a7db4",
|
|
||||||
});
|
|
||||||
|
|
||||||
// ── Day 5 AI governance ──
|
// ── Day 5 AI governance ──
|
||||||
// Bedrock model invocation logging destinations + delivery role (H-20).
|
// Bedrock model invocation logging destinations + delivery role (H-20).
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,10 @@ import { AppWebAcl } from "./web-acl";
|
||||||
* Thin per-account stack that owns the shared CloudFront WAFv2 WebACL (M-17)
|
* Thin per-account stack that owns the shared CloudFront WAFv2 WebACL (M-17)
|
||||||
* and publishes its ARN to SSM `/seahaven/waf/app-web-acl-arn`.
|
* and publishes its ARN to SSM `/seahaven/waf/app-web-acl-arn`.
|
||||||
*
|
*
|
||||||
* Mgmt already has this ACL inside `AccountBaselineStack`. Workload accounts
|
* Prod owns this stack (PLAT-92). The management account's copy lived inside
|
||||||
* (starting with seahaven-prod / PLAT-92) get a dedicated stack so we do not
|
* `AccountBaselineStack` and was removed after its deletion policy was Retain,
|
||||||
* pull the full mgmt baseline (trail, budgets, flow logs, …) into prod just
|
* because the physical ACL was already gone. App stacks associate by reading
|
||||||
* to share a CloudFront WAF. App stacks associate by reading the SSM param
|
* the SSM param in-account. WAFv2 CloudFront associations are same-account only.
|
||||||
* in-account — WAFv2 CloudFront associations are same-account only.
|
|
||||||
*/
|
*/
|
||||||
export class AppWebAclStack extends cdk.Stack {
|
export class AppWebAclStack extends cdk.Stack {
|
||||||
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
|
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
|
||||||
|
|
|
||||||
|
|
@ -13,25 +13,8 @@ import { Construct } from "constructs";
|
||||||
* The ARN is published to SSM (`/seahaven/waf/app-web-acl-arn`) so app stacks in
|
* The ARN is published to SSM (`/seahaven/waf/app-web-acl-arn`) so app stacks in
|
||||||
* other repos can consume it via `{{resolve:ssm:...}}` without a hard CFN export.
|
* other repos can consume it via `{{resolve:ssm:...}}` without a hard CFN export.
|
||||||
*/
|
*/
|
||||||
export interface AppWebAclProps {
|
|
||||||
/**
|
|
||||||
* Deletion policy for the WebACL only. The SSM parameter keeps the default
|
|
||||||
* Delete policy so a later stack update can remove the parameter. Prod does
|
|
||||||
* not set this. Management sets RETAIN first because the live WebACL is
|
|
||||||
* already gone and a Delete call would fail and roll back into a recreate.
|
|
||||||
*/
|
|
||||||
readonly webAclRemovalPolicy?: cdk.RemovalPolicy;
|
|
||||||
/**
|
|
||||||
* Physical id of a WebACL CloudFormation already tracks. When set, the SSM
|
|
||||||
* parameter and output publish `global/webacl/seahaven-app-waf/<id>` with
|
|
||||||
* account and region tokens, and do not reference WebACL.Arn. GetAtt on a
|
|
||||||
* missing ACL calls GetWebACL and fails the stack update.
|
|
||||||
*/
|
|
||||||
readonly existingWebAclId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class AppWebAcl extends Construct {
|
export class AppWebAcl extends Construct {
|
||||||
constructor(scope: Construct, id: string, props?: AppWebAclProps) {
|
constructor(scope: Construct, id: string) {
|
||||||
super(scope, id);
|
super(scope, id);
|
||||||
|
|
||||||
const vis = (metric: string): wafv2.CfnWebACL.VisibilityConfigProperty => ({
|
const vis = (metric: string): wafv2.CfnWebACL.VisibilityConfigProperty => ({
|
||||||
|
|
@ -81,25 +64,13 @@ export class AppWebAcl extends Construct {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
if (props?.webAclRemovalPolicy) {
|
|
||||||
webAcl.applyRemovalPolicy(props.webAclRemovalPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
const publishedArn = props?.existingWebAclId
|
|
||||||
? cdk.Stack.of(this).formatArn({
|
|
||||||
service: "wafv2",
|
|
||||||
resource: "global/webacl",
|
|
||||||
resourceName: `seahaven-app-waf/${props.existingWebAclId}`,
|
|
||||||
arnFormat: cdk.ArnFormat.SLASH_RESOURCE_NAME,
|
|
||||||
})
|
|
||||||
: webAcl.attrArn;
|
|
||||||
|
|
||||||
new ssm.StringParameter(this, "AppWebAclArnParam", {
|
new ssm.StringParameter(this, "AppWebAclArnParam", {
|
||||||
parameterName: "/seahaven/waf/app-web-acl-arn",
|
parameterName: "/seahaven/waf/app-web-acl-arn",
|
||||||
stringValue: publishedArn,
|
stringValue: webAcl.attrArn,
|
||||||
description: "ARN of the shared CloudFront WAF WebACL (audit M-17)",
|
description: "ARN of the shared CloudFront WAF WebACL (audit M-17)",
|
||||||
});
|
});
|
||||||
|
|
||||||
new cdk.CfnOutput(this, "AppWebAclArn", { value: publishedArn });
|
new cdk.CfnOutput(this, "AppWebAclArn", { value: webAcl.attrArn });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue