mirror of
https://github.com/Sea-Haven-Industries/seahaven-org-baseline.git
synced 2026-09-30 05:43:17 +00:00
seahaven-prod account baseline (Phase 5) (#50)
* Add seahaven-prod member baseline (Phase 5) Account 011934824531 is the target for all new production stacks; the management account is frozen for new workloads. First proven exercise of the automatic enrollment sweep (Enabled in 124s, no manual create-members) and of AutoEnableStandards=NONE (no pre-enabled standards, so CFN owns FSBP + CIS v3.0 cleanly). Default VPC deleted; budget starts at $100 and resizes as tenants land. * Apply Phase-5 review findings Fleet gap closed: EBS encryption-by-default + IAM password policy were management-account-only (the runbook's unscoped 'applied' claim hid it); now applied and verified in all three member accounts, runbook scoped per account. README stack inventory corrected (eleven stacks, org-governance rows restored). Sweep comments reconciled: the automatic enrollment sweep is proven (seahaven-prod, ~2min).
This commit is contained in:
parent
0a7c1bc450
commit
2303a54ebc
4 changed files with 54 additions and 8 deletions
9
.github/workflows/deploy.yaml
vendored
9
.github/workflows/deploy.yaml
vendored
|
|
@ -50,3 +50,12 @@ jobs:
|
||||||
stack-name: "seahaven-dev-baseline"
|
stack-name: "seahaven-dev-baseline"
|
||||||
secrets:
|
secrets:
|
||||||
deploy-role-arn: ${{ secrets.AWS_DEPLOY_ROLE_ARN_DEV }}
|
deploy-role-arn: ${{ secrets.AWS_DEPLOY_ROLE_ARN_DEV }}
|
||||||
|
|
||||||
|
deploy-prod:
|
||||||
|
uses: Sea-Haven-Industries/.github/.github/workflows/cd-cdk.yaml@3cde673b9d05c0e68aac4d997d582f2543853d20 # main
|
||||||
|
with:
|
||||||
|
node-version: "24"
|
||||||
|
stacks: "prod-baseline"
|
||||||
|
stack-name: "seahaven-prod-baseline"
|
||||||
|
secrets:
|
||||||
|
deploy-role-arn: ${{ secrets.AWS_DEPLOY_ROLE_ARN_PROD }}
|
||||||
|
|
|
||||||
15
README.md
15
README.md
|
|
@ -28,9 +28,11 @@ Stacks (deployed by the CD workflow — one job per target account):
|
||||||
| `seahaven-regional-baseline-us-east-2` | 328440206208 | us-east-2 | Bedrock invocation logging + AWS Config recorder + Security Hub (INFRA-91 / INFRA-16) |
|
| `seahaven-regional-baseline-us-east-2` | 328440206208 | us-east-2 | Bedrock invocation logging + AWS Config recorder + Security Hub (INFRA-91 / INFRA-16) |
|
||||||
| `seahaven-backup` | 328440206208 | us-east-1 | Primary AWS Backup vault + plan + role (C-7) |
|
| `seahaven-backup` | 328440206208 | us-east-1 | Primary AWS Backup vault + plan + role (C-7) |
|
||||||
| `seahaven-backup-offsite` | 328440206208 | us-west-2 | Governance-locked offsite copy vault (C-7) |
|
| `seahaven-backup-offsite` | 328440206208 | us-west-2 | Governance-locked offsite copy vault (C-7) |
|
||||||
|
| `seahaven-org-governance` | 328440206208 | us-east-1 | AWS Organizations OU tree + SCPs (incl. the cdk-imported external-dev guardrails) |
|
||||||
| `seahaven-external-dev-baseline` | 396287094661 | us-east-1 | Member-account baseline: Config, GuardDuty, Security Hub (FSBP + CIS v3.0), Access Analyzer, flow logs, budget |
|
| `seahaven-external-dev-baseline` | 396287094661 | us-east-1 | Member-account baseline: Config, GuardDuty, Security Hub (FSBP + CIS v3.0), Access Analyzer, flow logs, budget |
|
||||||
| `seahaven-security-baseline` | 001520130573 | us-east-1 | Member-account baseline for the delegated security-admin account (same construct set) |
|
| `seahaven-security-baseline` | 001520130573 | us-east-1 | Member-account baseline for the delegated security-admin account (same construct set) |
|
||||||
| `seahaven-dev-baseline` | 710827005802 | us-east-1 | Member-account baseline for internal dev/staging (org-managed detection — no local GuardDuty/SecurityHub) |
|
| `seahaven-dev-baseline` | 710827005802 | us-east-1 | Member-account baseline for internal dev/staging (org-managed detection — no local GuardDuty/SecurityHub) |
|
||||||
|
| `seahaven-prod-baseline` | 011934824531 | us-east-1 | Member-account baseline for production workloads (org-managed detection; mgmt account frozen for new workloads) |
|
||||||
|
|
||||||
## CDK app
|
## CDK app
|
||||||
|
|
||||||
|
|
@ -43,12 +45,12 @@ the TypeScript source — no separate compile step needed for `cdk synth` /
|
||||||
| Path | Role |
|
| Path | Role |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `cdk.json` | CDK config: `app` synth command, `watch` includes/excludes, `context` feature flags |
|
| `cdk.json` | CDK config: `app` synth command, `watch` includes/excludes, `context` feature flags |
|
||||||
| `bin/app.ts` | App entry point — instantiates every stack with an explicit kebab-case `stackName` and its target `env` (account `328440206208`, per-region) |
|
| `bin/app.ts` | App entry point — instantiates every stack with an explicit kebab-case `stackName` and its target `env` (five accounts, per-account/per-region) |
|
||||||
| `lib/*-stack.ts` | Stack definitions (one class per stack; larger stacks compose the constructs in `lib/*.ts`) |
|
| `lib/*-stack.ts` | Stack definitions (one class per stack; larger stacks compose the constructs in `lib/*.ts`) |
|
||||||
| `tsconfig.json` | TypeScript compiler options (`outDir: cdk.out`) |
|
| `tsconfig.json` | TypeScript compiler options (`outDir: cdk.out`) |
|
||||||
| `package.json` | Pinned `aws-cdk-lib`, CDK CLI, and the `build` / `synth` / `diff` / `deploy` npm scripts |
|
| `package.json` | Pinned `aws-cdk-lib`, CDK CLI, and the `build` / `synth` / `diff` / `deploy` npm scripts |
|
||||||
|
|
||||||
`bin/app.ts` synthesizes nine stacks across three regions and four accounts:
|
`bin/app.ts` synthesizes eleven stacks across three regions and five accounts:
|
||||||
|
|
||||||
| Construct id | Stack name | Account | Region | Source |
|
| Construct id | Stack name | Account | Region | Source |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
|
|
@ -58,9 +60,11 @@ the TypeScript source — no separate compile step needed for `cdk synth` /
|
||||||
| `regional-baseline-us-east-2` | `seahaven-regional-baseline-us-east-2` | 328440206208 | us-east-2 | `lib/regional-baseline-stack.ts` |
|
| `regional-baseline-us-east-2` | `seahaven-regional-baseline-us-east-2` | 328440206208 | us-east-2 | `lib/regional-baseline-stack.ts` |
|
||||||
| `backup-offsite` | `seahaven-backup-offsite` | 328440206208 | us-west-2 | `lib/backup-offsite-stack.ts` |
|
| `backup-offsite` | `seahaven-backup-offsite` | 328440206208 | us-west-2 | `lib/backup-offsite-stack.ts` |
|
||||||
| `backup` | `seahaven-backup` | 328440206208 | us-east-1 | `lib/backup-stack.ts` |
|
| `backup` | `seahaven-backup` | 328440206208 | us-east-1 | `lib/backup-stack.ts` |
|
||||||
|
| `org-governance` | `seahaven-org-governance` | 328440206208 | us-east-1 | `lib/org-governance-stack.ts` |
|
||||||
| `external-dev-baseline` | `seahaven-external-dev-baseline` | 396287094661 | us-east-1 | `lib/member-baseline-stack.ts` |
|
| `external-dev-baseline` | `seahaven-external-dev-baseline` | 396287094661 | us-east-1 | `lib/member-baseline-stack.ts` |
|
||||||
| `security-baseline` | `seahaven-security-baseline` | 001520130573 | us-east-1 | `lib/member-baseline-stack.ts` |
|
| `security-baseline` | `seahaven-security-baseline` | 001520130573 | us-east-1 | `lib/member-baseline-stack.ts` |
|
||||||
| `dev-baseline` | `seahaven-dev-baseline` | 710827005802 | us-east-1 | `lib/member-baseline-stack.ts` (orgManagedDetection) |
|
| `dev-baseline` | `seahaven-dev-baseline` | 710827005802 | us-east-1 | `lib/member-baseline-stack.ts` (orgManagedDetection) |
|
||||||
|
| `prod-baseline` | `seahaven-prod-baseline` | 011934824531 | us-east-1 | `lib/member-baseline-stack.ts` (orgManagedDetection) |
|
||||||
|
|
||||||
Member-account stacks deploy with per-account credentials — the CD workflow
|
Member-account stacks deploy with per-account credentials — the CD workflow
|
||||||
runs one job per account, each assuming that account's OIDC deploy role. Local
|
runs one job per account, each assuming that account's OIDC deploy role. Local
|
||||||
|
|
@ -71,6 +75,7 @@ deploys/diffs assume `OrganizationAccountAccessRole` in the target account.
|
||||||
| 396287094661 (external-dev) | `githubdeploy-seahaven-external-dev-baseline` | `AWS_DEPLOY_ROLE_ARN_EXTDEV` |
|
| 396287094661 (external-dev) | `githubdeploy-seahaven-external-dev-baseline` | `AWS_DEPLOY_ROLE_ARN_EXTDEV` |
|
||||||
| 001520130573 (security) | `githubdeploy-seahaven-org-baseline` | `AWS_DEPLOY_ROLE_ARN_SECURITY` |
|
| 001520130573 (security) | `githubdeploy-seahaven-org-baseline` | `AWS_DEPLOY_ROLE_ARN_SECURITY` |
|
||||||
| 710827005802 (dev) | `githubdeploy-seahaven-org-baseline` | `AWS_DEPLOY_ROLE_ARN_DEV` |
|
| 710827005802 (dev) | `githubdeploy-seahaven-org-baseline` | `AWS_DEPLOY_ROLE_ARN_DEV` |
|
||||||
|
| 011934824531 (prod) | `githubdeploy-seahaven-org-baseline` | `AWS_DEPLOY_ROLE_ARN_PROD` |
|
||||||
|
|
||||||
Shared constructs (`DetectiveControls`, `FlowLogs`, `GovernanceToggles`) are
|
Shared constructs (`DetectiveControls`, `FlowLogs`, `GovernanceToggles`) are
|
||||||
prefix-parameterized — construct ids and physical names must stay
|
prefix-parameterized — construct ids and physical names must stay
|
||||||
|
|
@ -236,7 +241,11 @@ recording is never interrupted.
|
||||||
### CLI-applied governance toggles (no CloudFormation resource)
|
### CLI-applied governance toggles (no CloudFormation resource)
|
||||||
|
|
||||||
These account toggles have no native CloudFormation resource, so they are applied
|
These account toggles have no native CloudFormation resource, so they are applied
|
||||||
via CLI and recorded here. Applied 2026-06-01.
|
via CLI and recorded here — **per account** (they are account-scoped; a new
|
||||||
|
member account has NONE of them until applied). Applied: 328440206208
|
||||||
|
(2026-06-01); 001520130573, 710827005802, 011934824531 (2026-07-14 — EBS
|
||||||
|
encryption-by-default + password policy, verified per account; Inspector2 via
|
||||||
|
delegated admin; cost-allocation tags are org-level).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# M-3 EBS encryption-by-default (new volumes; existing 5 plaintext volumes are H-19-adjacent)
|
# M-3 EBS encryption-by-default (new volumes; existing 5 plaintext volumes are H-19-adjacent)
|
||||||
|
|
|
||||||
31
bin/app.ts
31
bin/app.ts
|
|
@ -13,6 +13,7 @@ const ACCOUNT = "328440206208";
|
||||||
const EXTERNAL_DEV_ACCOUNT = "396287094661";
|
const EXTERNAL_DEV_ACCOUNT = "396287094661";
|
||||||
const SECURITY_ACCOUNT = "001520130573";
|
const SECURITY_ACCOUNT = "001520130573";
|
||||||
const DEV_ACCOUNT = "710827005802";
|
const DEV_ACCOUNT = "710827005802";
|
||||||
|
const PROD_ACCOUNT = "011934824531";
|
||||||
|
|
||||||
// All 5 VPCs in 328440206208 / us-east-1 (4 custom + default), audit Agent 7.
|
// All 5 VPCs in 328440206208 / us-east-1 (4 custom + default), audit Agent 7.
|
||||||
// Index-derived logical IDs — append only, never reorder.
|
// Index-derived logical IDs — append only, never reorder.
|
||||||
|
|
@ -105,8 +106,9 @@ new MemberBaselineStack(app, "security-baseline", {
|
||||||
// Internal dev/staging workloads (NOT the external-dev engagement account).
|
// Internal dev/staging workloads (NOT the external-dev engagement account).
|
||||||
// Created 2026-07-14 AFTER org delegation went live: GuardDuty detector +
|
// Created 2026-07-14 AFTER org delegation went live: GuardDuty detector +
|
||||||
// Security Hub hub are org-managed — enrolled via delegated-admin
|
// Security Hub hub are org-managed — enrolled via delegated-admin
|
||||||
// create-members and verified Enabled (the AUTOMATIC new-account sweep
|
// create-members and verified Enabled (the AUTOMATIC sweep was later proven
|
||||||
// remains unexercised; do not rely on it without verifying). Standards and
|
// on seahaven-prod, ~2min; still verify enrollment before any org-managed
|
||||||
|
// stack's first deploy). Standards and
|
||||||
// the account analyzer stay CFN-owned (SH-DEV-001/SH-DEVBASE-002). Same
|
// the account analyzer stay CFN-owned (SH-DEV-001/SH-DEVBASE-002). Same
|
||||||
// lifecycle rule as the other new accounts: root-harden at org ROOT, then
|
// lifecycle rule as the other new accounts: root-harden at org ROOT, then
|
||||||
// move-account into the nonprod OU (ou-nbuj-zpt5ka98) — NO WORKLOADS until
|
// move-account into the nonprod OU (ou-nbuj-zpt5ka98) — NO WORKLOADS until
|
||||||
|
|
@ -128,6 +130,31 @@ new MemberBaselineStack(app, "dev-baseline", {
|
||||||
orgManagedDetection: true,
|
orgManagedDetection: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── Member-account baseline: seahaven-prod (Phase 5) ────────────────────────
|
||||||
|
// Target for ALL new production stacks (mgmt 328440206208 is frozen for new
|
||||||
|
// workloads). First tenant: proposal-system redeploy. Detection is org-managed
|
||||||
|
// (AUTO-enrolled by the sweep in 124s — first proven exercise, 2026-07-14 —
|
||||||
|
// and verified Enabled before this stack's first deploy); standards + account
|
||||||
|
// analyzer are CFN-owned per the Phase-4 review. Default VPC DELETED (prod
|
||||||
|
// workloads use purpose-built VPCs). Same lifecycle rule: root-harden at org
|
||||||
|
// ROOT, then move-account into the prod OU (ou-nbuj-5lc2wp6h) — NO WORKLOADS
|
||||||
|
// until the account is inside the OU. Budget starts at $100 and is resized as
|
||||||
|
// tenants land; AWS Backup vaults are added with the first stateful tenant
|
||||||
|
// (cross-account restore test = definition of done for that change).
|
||||||
|
new MemberBaselineStack(app, "prod-baseline", {
|
||||||
|
stackName: "seahaven-prod-baseline",
|
||||||
|
env: { account: PROD_ACCOUNT, region: "us-east-1" },
|
||||||
|
namePrefix: "seahaven-prod",
|
||||||
|
monthlyBudgetUsd: 100,
|
||||||
|
budgetAlertEmail: "aws@seahaven.com",
|
||||||
|
ownerEmail: "adam@seahaven.com",
|
||||||
|
// Append-only, never reorder (index-derived logical IDs). Empty: no VPCs
|
||||||
|
// exist yet; append ids via PR as purpose-built VPCs land.
|
||||||
|
flowLogVpcIds: [],
|
||||||
|
managedByTag: "seahaven-org-baseline",
|
||||||
|
orgManagedDetection: true,
|
||||||
|
});
|
||||||
|
|
||||||
// ── Shared DynamoDB CMK (INFRA-95 / M-3) ─────────────────────────────────────
|
// ── Shared DynamoDB CMK (INFRA-95 / M-3) ─────────────────────────────────────
|
||||||
// Dedicated, standalone stack so the customer-managed key for sensitive
|
// Dedicated, standalone stack so the customer-managed key for sensitive
|
||||||
// finance/PII DynamoDB tables is an independent shared dependency for the owning
|
// finance/PII DynamoDB tables is an independent shared dependency for the owning
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,10 @@ export interface MemberBaselineStackProps extends cdk.StackProps {
|
||||||
/** Value for the ManagedBy tag on every resource in the stack. */
|
/** Value for the ManagedBy tag on every resource in the stack. */
|
||||||
readonly managedByTag: string;
|
readonly managedByTag: string;
|
||||||
/**
|
/**
|
||||||
* TRUE for accounts created after org delegation (2026-07-14): GuardDuty /
|
* TRUE for accounts created after org delegation (2026-07-14): the GuardDuty
|
||||||
* Security Hub / analyzer are org-managed (auto-enrolled), so the stack must
|
* detector and Security Hub hub are org-managed (auto-enrolled), so the
|
||||||
* not create local duplicates. Default FALSE (pre-delegation accounts).
|
* stack must not create local duplicates. Standards and the account analyzer
|
||||||
|
* remain CFN-owned either way. Default FALSE (pre-delegation accounts).
|
||||||
*/
|
*/
|
||||||
readonly orgManagedDetection?: boolean;
|
readonly orgManagedDetection?: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue