seahaven-org-baseline/lib/terraform-substrate-stack.ts

119 lines
5 KiB
TypeScript
Raw Normal View History

import * as cdk from "aws-cdk-lib";
import * as cfninc from "aws-cdk-lib/cloudformation-include";
import * as path from "path";
import { Construct } from "constructs";
import { ShocFrontendResources } from "./terraform-substrate/shoc-frontend-resources";
export interface TerraformSubstrateStackProps extends cdk.StackProps {
/**
* Create the app.terraform.io OIDC identity provider in this account.
* Defaults to true - Phase-0 checks (2026-07-30) confirmed neither prod nor
* dev has one. Set false for an account that already has the provider: an
* account holds exactly ONE provider per URL, so a duplicate create fails.
*
* This flag also makes a first-create rollback recoverable. The provider is
* Retain, so if any other resource in this stack fails on FIRST create the
* provider survives as an orphan while the stack lands in ROLLBACK_COMPLETE
* (which cannot be updated). Recovery is to delete the stack and either
* remove the orphaned provider or redeploy with this false.
*/
createOidcProvider?: boolean;
/**
* Enable the two SHOC backend tf-poc HCP roles. Defaults false so the
* external-dev base-stack create is role-free.
*/
enableShocBackendPocRoles?: boolean;
/**
* Enable the four existing SHOC backend dev/staging HCP roles. Defaults
* false because these names must enter the stack through CloudFormation
* resource import, never a normal create/update.
*/
enableShocBackendLiveRoles?: boolean;
/**
* Enable the SHOC frontend tf-poc HCP roles after its exact CloudFront
* identifiers and deploy-role guardrails have been reconciled.
*/
enableShocFrontendPocRoles?: boolean;
/**
* Enable the SHOC frontend dev/staging HCP roles after the existing GitHub
* deploy roles have their exact boundaries and manager tags.
*/
enableShocFrontendLiveRoles?: boolean;
/** Exact tf-poc site identifiers; empty values keep its roles disabled. */
shocFrontendPocDistributionId?: string;
shocFrontendPocOriginAccessControlId?: string;
shocFrontendPocFunctionName?: string;
shocFrontendPocHostedZoneId?: string;
shocFrontendPocCertificateArn?: string;
}
/**
* Per-account HCP Terraform deploy substrate: the conditional
* app.terraform.io OIDC provider, the prod/dev shared boundary-gated IAM
* manager, and reviewed per-workspace role pairs. External-dev conditions out
* the shared manager and uses exact inline policies for its SHOC import roles.
*
* Deliberately NOT here: per-workspace hcptf-<stack> / hcptf-<stack>-plan
* roles. Those are appended to the template at each stack's migration time
* (accumulator pattern, parallel to per-repo githubdeploy-* roles) so an
* account never accumulates trust for workspaces that do not deploy to it.
*
* The IAM guardrail statements DERIVE FROM seahaven-cfn-exec-iam-management in
* lib/deploy-substrate/deploy-substrate.template.yaml but are deliberately
* STRICTER (role writes and PassRole confined to the tf-managed path, wider
* DenySelfMutation) - the SAM copy's Resource "*" grants were confirmed a
* critical escalation primitive by the 2026-07-30 security review, and its
* justification for them does not transfer to Terraform. See the provenance
* header in lib/terraform-substrate/terraform-substrate.template.yaml for the
* full divergence list, and for the boundary-ARN coupling to the
* seahaven-deploy-substrate stack (bin/app.ts carries the explicit
* addStackDependency; the ARN reference alone creates no CFN edge).
*/
export class TerraformSubstrateStack extends cdk.Stack {
constructor(
scope: Construct,
id: string,
props?: TerraformSubstrateStackProps,
) {
super(scope, id, props);
const substrate = new cfninc.CfnInclude(this, "Substrate", {
templateFile: path.join(
__dirname,
"terraform-substrate",
"terraform-substrate.template.yaml",
),
parameters: {
CreateOIDCProvider: props?.createOidcProvider === false ? "false" : "true",
EnableShocBackendPocRoles:
props?.enableShocBackendPocRoles === true ? "true" : "false",
EnableShocBackendLiveRoles:
props?.enableShocBackendLiveRoles === true ? "true" : "false",
},
});
if (props?.env?.account === "396287094661") {
new ShocFrontendResources(this, "ShocFrontend", {
template: substrate,
enablePocRoles: props?.enableShocFrontendPocRoles === true,
enableLiveRoles: props?.enableShocFrontendLiveRoles === true,
pocDistributionId: props?.shocFrontendPocDistributionId ?? "",
pocOriginAccessControlId:
props?.shocFrontendPocOriginAccessControlId ?? "",
pocFunctionName: props?.shocFrontendPocFunctionName ?? "",
pocHostedZoneId: props?.shocFrontendPocHostedZoneId ?? "",
pocCertificateArn: props?.shocFrontendPocCertificateArn ?? "",
});
}
cdk.Tags.of(this).add("Project", "account-baseline");
cdk.Tags.of(this).add("Owner", "adam@seahavenind.com");
cdk.Tags.of(this).add("ManagedBy", "cdk");
}
}