mirror of
https://github.com/Sea-Haven-Industries/seahaven-org-baseline.git
synced 2026-10-03 04:33:13 +00:00
feat(iam): add view-only access across all five accounts (PLAT-237) (#176)
Give the view group ViewOnlyAccess in every account without a data-plane read or an assume-role path, and include the stack on the management deploy job.
This commit is contained in:
parent
031e1d1a3b
commit
5589c6d34c
4 changed files with 110 additions and 1 deletions
2
.github/workflows/deploy.yaml
vendored
2
.github/workflows/deploy.yaml
vendored
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
uses: Sea-Haven-Industries/.github/.github/workflows/cd-cdk.yaml@e5691d8a7f96ac4d5a841a82975ff0a4354d53ac # v1.0.7
|
||||
with:
|
||||
node-version: "24"
|
||||
stacks: "account-baseline dynamodb-cmk regional-baseline-us-west-2 regional-baseline-us-east-2 backup-offsite backup org-governance platform-access engineering-access"
|
||||
stacks: "account-baseline dynamodb-cmk regional-baseline-us-west-2 regional-baseline-us-east-2 backup-offsite backup org-governance platform-access engineering-access view-access"
|
||||
secrets:
|
||||
deploy-role-arn: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ are noted):
|
|||
| `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-engineering-access` | 328440206208 | us-east-1 | Identity Center group `engineering`. `EngineeringProd` reads payments-dashboard configuration and seahaven-site in 011934824531. `EngineeringDev` has no allow (PLAT-235, PLAT-236). |
|
||||
| `seahaven-view-access` | 328440206208 | us-east-1 | Identity Center group `view`. Permission set `View` is `ViewOnlyAccess` on all five accounts. No data-plane reads and no assume-role. Membership is outside this stack. |
|
||||
| `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-terraform-substrate` | 011934824531, 710827005802 | us-east-1 | Removed from the CDK app and from CD (PLAT-147). Live stacks remain until `scripts/delete-terraform-substrate-prod-dev.sh`. The six imported prod pairs are already forgotten. |
|
||||
| `seahaven-hcptf` | 011934824531, 710827005802 | us-east-1 | payments-dashboard HCP apply and plan roles, scoped policies, and the Lambda boundary in prod and dev. Prod also owns the imported `hcptf-seahaven-site` apply and plan roles (PLAT-225), with policies at `/tf-managed/`. Trust is pinned per workspace. On the dev and prod deploy jobs. Do not create the roles. |
|
||||
|
|
@ -67,6 +68,7 @@ the TypeScript source — no separate compile step needed for `cdk synth` /
|
|||
| `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` |
|
||||
| `engineering-access` | `seahaven-engineering-access` | 328440206208 | us-east-1 | `lib/engineering-access-stack.ts` |
|
||||
| `view-access` | `seahaven-view-access` | 328440206208 | us-east-1 | `lib/view-access-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` |
|
||||
| `dev-baseline` | `seahaven-dev-baseline` | 710827005802 | us-east-1 | `lib/member-baseline-stack.ts` (orgManagedDetection) |
|
||||
|
|
|
|||
11
bin/app.ts
11
bin/app.ts
|
|
@ -15,6 +15,7 @@ import { MemberBaselineStack } from "../lib/member-baseline-stack";
|
|||
import { OrgGovernanceStack } from "../lib/org-governance-stack";
|
||||
import { PlatformAccessStack } from "../lib/platform-access-stack";
|
||||
import { EngineeringAccessStack } from "../lib/engineering-access-stack";
|
||||
import { ViewAccessStack } from "../lib/view-access-stack";
|
||||
|
||||
const ACCOUNT = "328440206208";
|
||||
const EXTERNAL_DEV_ACCOUNT = "396287094661";
|
||||
|
|
@ -95,6 +96,16 @@ new EngineeringAccessStack(app, "engineering-access", {
|
|||
prodAccountId: PROD_ACCOUNT,
|
||||
});
|
||||
|
||||
new ViewAccessStack(app, "view-access", {
|
||||
stackName: "seahaven-view-access",
|
||||
env: { account: ACCOUNT, region: "us-east-1" }, // pragma: allowlist secret
|
||||
managementAccountId: ACCOUNT,
|
||||
securityAccountId: SECURITY_ACCOUNT,
|
||||
externalDevAccountId: EXTERNAL_DEV_ACCOUNT,
|
||||
devAccountId: DEV_ACCOUNT,
|
||||
prodAccountId: PROD_ACCOUNT,
|
||||
});
|
||||
|
||||
new MemberBaselineStack(app, "external-dev-baseline", {
|
||||
stackName: "seahaven-external-dev-baseline",
|
||||
env: { account: EXTERNAL_DEV_ACCOUNT, region: "us-east-1" },
|
||||
|
|
|
|||
96
lib/view-access-stack.ts
Normal file
96
lib/view-access-stack.ts
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
import * as cdk from "aws-cdk-lib";
|
||||
import * as identitystore from "aws-cdk-lib/aws-identitystore";
|
||||
import * as sso from "aws-cdk-lib/aws-sso";
|
||||
import { Construct } from "constructs";
|
||||
|
||||
const IDENTITY_CENTER_INSTANCE_ARN =
|
||||
"arn:aws:sso:::instance/ssoins-722321f42ca610e4";
|
||||
const IDENTITY_STORE_ID = "d-9067ec8e26";
|
||||
const VIEW_ONLY_POLICY = "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess";
|
||||
|
||||
export interface ViewAccessStackProps extends cdk.StackProps {
|
||||
managementAccountId: string;
|
||||
securityAccountId: string;
|
||||
externalDevAccountId: string;
|
||||
devAccountId: string;
|
||||
prodAccountId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identity Center group and permission set for view-only access across
|
||||
* every organization account.
|
||||
*
|
||||
* ViewOnlyAccess lists and describes resources. It does not read S3
|
||||
* objects, secret values, DynamoDB items, or log contents. There is no
|
||||
* inline policy and no sts:AssumeRole on OrganizationAccountAccessRole.
|
||||
*
|
||||
* Group membership is outside this stack.
|
||||
*/
|
||||
export class ViewAccessStack extends cdk.Stack {
|
||||
constructor(scope: Construct, id: string, props: ViewAccessStackProps) {
|
||||
super(scope, id, props);
|
||||
|
||||
const group = new identitystore.CfnGroup(this, "ViewGroup", {
|
||||
identityStoreId: IDENTITY_STORE_ID,
|
||||
displayName: "view",
|
||||
description:
|
||||
"View-only across all organization accounts. No data-plane reads.",
|
||||
});
|
||||
|
||||
const permissionSet = new sso.CfnPermissionSet(this, "ViewPermissionSet", {
|
||||
instanceArn: IDENTITY_CENTER_INSTANCE_ARN,
|
||||
name: "View",
|
||||
description:
|
||||
"ViewOnlyAccess in every organization account. No assume-role.",
|
||||
sessionDuration: "PT8H",
|
||||
managedPolicies: [VIEW_ONLY_POLICY],
|
||||
});
|
||||
|
||||
this.assignment(
|
||||
"ViewManagementAssignment",
|
||||
permissionSet,
|
||||
group,
|
||||
props.managementAccountId,
|
||||
);
|
||||
this.assignment(
|
||||
"ViewSecurityAssignment",
|
||||
permissionSet,
|
||||
group,
|
||||
props.securityAccountId,
|
||||
);
|
||||
this.assignment(
|
||||
"ViewExternalDevAssignment",
|
||||
permissionSet,
|
||||
group,
|
||||
props.externalDevAccountId,
|
||||
);
|
||||
this.assignment(
|
||||
"ViewDevAssignment",
|
||||
permissionSet,
|
||||
group,
|
||||
props.devAccountId,
|
||||
);
|
||||
this.assignment(
|
||||
"ViewProdAssignment",
|
||||
permissionSet,
|
||||
group,
|
||||
props.prodAccountId,
|
||||
);
|
||||
}
|
||||
|
||||
private assignment(
|
||||
id: string,
|
||||
permissionSet: sso.CfnPermissionSet,
|
||||
group: identitystore.CfnGroup,
|
||||
targetId: string,
|
||||
): void {
|
||||
new sso.CfnAssignment(this, id, {
|
||||
instanceArn: IDENTITY_CENTER_INSTANCE_ARN,
|
||||
permissionSetArn: permissionSet.attrPermissionSetArn,
|
||||
principalId: group.attrGroupId,
|
||||
principalType: "GROUP",
|
||||
targetId,
|
||||
targetType: "AWS_ACCOUNT",
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue