mirror of
https://github.com/Sea-Haven-Industries/seahaven-org-baseline.git
synced 2026-10-03 22:23:12 +00:00
feat(iam): scope engineering prod view to day-one projects (PLAT-236) (#170)
Limit EngineeringProd to payments-dashboard configuration and the public site, and drop account-wide view in dev where those projects do not run.
This commit is contained in:
parent
42781f743e
commit
54c81dedc9
2 changed files with 187 additions and 22 deletions
|
|
@ -30,7 +30,7 @@ are noted):
|
|||
| `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-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` plus view-only permission sets `EngineeringDev` (710827005802) and `EngineeringProd` (011934824531). No members (PLAT-235). |
|
||||
| `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-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-site-hcptf` | 011934824531 | us-east-1 | Imported `hcptf-seahaven-site` apply and plan roles (PLAT-225). On the prod deploy job. Do not create. |
|
||||
|
|
|
|||
|
|
@ -6,34 +6,195 @@ import { Construct } from "constructs";
|
|||
const IDENTITY_CENTER_INSTANCE_ARN =
|
||||
"arn:aws:sso:::instance/ssoins-722321f42ca610e4";
|
||||
const IDENTITY_STORE_ID = "d-9067ec8e26";
|
||||
const VIEW_ONLY_ACCESS_ARN =
|
||||
"arn:aws:iam::aws:policy/job-function/ViewOnlyAccess";
|
||||
const PROD_ACCOUNT_ID = "011934824531";
|
||||
const REGION = "us-east-1";
|
||||
|
||||
const SITE_BUCKET = "seahaven-site-prod";
|
||||
const SITE_DISTRIBUTION_ID = "E35OCA79OAJ03H";
|
||||
const PAYMENTS_API_ID = "srjhpctwb9";
|
||||
|
||||
const prodArn = (service: string, resource: string): string =>
|
||||
`arn:aws:${service}:${REGION}:${PROD_ACCOUNT_ID}:${resource}`;
|
||||
|
||||
const SITE_OBJECT_ARNS = [`arn:aws:s3:::${SITE_BUCKET}/*`];
|
||||
const DEPLOY_PARAMETER_ARNS = [
|
||||
`arn:aws:ssm:${REGION}:${PROD_ACCOUNT_ID}:parameter/seahaven-site/deploy/*`,
|
||||
`arn:aws:ssm:${REGION}:${PROD_ACCOUNT_ID}:parameter/payments-dashboard/deploy/*`,
|
||||
];
|
||||
|
||||
/**
|
||||
* Blocks secret, object, and item reads if a broader managed policy is
|
||||
* attached later. ViewOnlyAccess is the allow. ReadOnlyAccess is not used.
|
||||
* Backstop if a managed policy is attached later. Site objects and the two
|
||||
* projects' deploy parameters stay readable. Payment items, payment files,
|
||||
* and secret values do not.
|
||||
*/
|
||||
const DATA_PLANE_DENY = {
|
||||
Version: "2012-10-17",
|
||||
Statement: [
|
||||
{
|
||||
Sid: "DenyDataPlaneReads",
|
||||
Sid: "DenySecretAndPaymentReads",
|
||||
Effect: "Deny",
|
||||
Action: [
|
||||
"secretsmanager:GetSecretValue",
|
||||
"secretsmanager:BatchGetSecretValue",
|
||||
"ssm:GetParameter",
|
||||
"ssm:GetParameters",
|
||||
"ssm:GetParametersByPath",
|
||||
"kms:Decrypt",
|
||||
"s3:GetObject",
|
||||
"dynamodb:GetItem",
|
||||
"dynamodb:BatchGetItem",
|
||||
"dynamodb:Query",
|
||||
"dynamodb:Scan",
|
||||
"sqs:ReceiveMessage",
|
||||
"sqs:DeleteMessage",
|
||||
"cloudfront:CreateInvalidation",
|
||||
],
|
||||
Resource: "*",
|
||||
},
|
||||
{
|
||||
Sid: "DenyObjectReadsExceptSite",
|
||||
Effect: "Deny",
|
||||
Action: ["s3:GetObject", "s3:GetObjectVersion"],
|
||||
NotResource: SITE_OBJECT_ARNS,
|
||||
},
|
||||
{
|
||||
Sid: "DenyParameterReadsExceptDeploy",
|
||||
Effect: "Deny",
|
||||
Action: [
|
||||
"ssm:GetParameter",
|
||||
"ssm:GetParameters",
|
||||
"ssm:GetParametersByPath",
|
||||
],
|
||||
NotResource: DEPLOY_PARAMETER_ARNS,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const PROD_PROJECT_VIEW = {
|
||||
Version: "2012-10-17",
|
||||
Statement: [
|
||||
...DATA_PLANE_DENY.Statement,
|
||||
{
|
||||
Sid: "ListSiteAndPaymentsBuckets",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"s3:ListBucket",
|
||||
"s3:GetBucketLocation",
|
||||
"s3:GetBucketPolicy",
|
||||
"s3:GetEncryptionConfiguration",
|
||||
"s3:GetBucketTagging",
|
||||
"s3:GetBucketVersioning",
|
||||
"s3:GetLifecycleConfiguration",
|
||||
"s3:GetBucketPublicAccessBlock",
|
||||
],
|
||||
Resource: [
|
||||
`arn:aws:s3:::${SITE_BUCKET}`,
|
||||
"arn:aws:s3:::payments-dashboard-artifacts-011934824531",
|
||||
"arn:aws:s3:::seahaven-payments-csv-011934824531",
|
||||
"arn:aws:s3:::seahaven-payments-boa-raw-011934824531",
|
||||
],
|
||||
},
|
||||
{
|
||||
Sid: "ReadSiteObjects",
|
||||
Effect: "Allow",
|
||||
Action: ["s3:GetObject", "s3:GetObjectVersion"],
|
||||
Resource: SITE_OBJECT_ARNS,
|
||||
},
|
||||
{
|
||||
Sid: "ReadSiteDistribution",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"cloudfront:GetDistribution",
|
||||
"cloudfront:GetDistributionConfig",
|
||||
"cloudfront:ListTagsForResource",
|
||||
"cloudfront:GetFunction",
|
||||
"cloudfront:DescribeFunction",
|
||||
],
|
||||
Resource: [
|
||||
`arn:aws:cloudfront::${PROD_ACCOUNT_ID}:distribution/${SITE_DISTRIBUTION_ID}`,
|
||||
`arn:aws:cloudfront::${PROD_ACCOUNT_ID}:function/seahaven-site-prod-directory-index`,
|
||||
],
|
||||
},
|
||||
{
|
||||
Sid: "ReadPaymentsFunctions",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"lambda:GetFunction",
|
||||
"lambda:GetFunctionConfiguration",
|
||||
"lambda:GetPolicy",
|
||||
"lambda:ListTags",
|
||||
"lambda:ListVersionsByFunction",
|
||||
],
|
||||
Resource: prodArn("lambda", "function:payments-*"),
|
||||
},
|
||||
{
|
||||
Sid: "DescribePaymentsTable",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"dynamodb:DescribeTable",
|
||||
"dynamodb:DescribeTimeToLive",
|
||||
"dynamodb:DescribeContinuousBackups",
|
||||
"dynamodb:ListTagsOfResource",
|
||||
],
|
||||
Resource: prodArn("dynamodb", "table/PaymentsDashboard"),
|
||||
},
|
||||
{
|
||||
Sid: "ReadPaymentsRoles",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"iam:GetRole",
|
||||
"iam:GetRolePolicy",
|
||||
"iam:ListRolePolicies",
|
||||
"iam:ListAttachedRolePolicies",
|
||||
],
|
||||
Resource: [
|
||||
`arn:aws:iam::${PROD_ACCOUNT_ID}:role/payments-dashboard-*`,
|
||||
`arn:aws:iam::${PROD_ACCOUNT_ID}:role/githubdeploy-payments-dashboard`,
|
||||
`arn:aws:iam::${PROD_ACCOUNT_ID}:role/hcptf-payments-dashboard`,
|
||||
`arn:aws:iam::${PROD_ACCOUNT_ID}:role/hcptf-payments-dashboard-plan`,
|
||||
`arn:aws:iam::${PROD_ACCOUNT_ID}:role/platform/hcptf-payments-dashboard`,
|
||||
`arn:aws:iam::${PROD_ACCOUNT_ID}:role/platform/hcptf-payments-dashboard-plan`,
|
||||
],
|
||||
},
|
||||
{
|
||||
Sid: "ReadPaymentsApi",
|
||||
Effect: "Allow",
|
||||
Action: "apigateway:GET",
|
||||
Resource: [
|
||||
`arn:aws:apigateway:${REGION}::/apis/${PAYMENTS_API_ID}`,
|
||||
`arn:aws:apigateway:${REGION}::/apis/${PAYMENTS_API_ID}/*`,
|
||||
],
|
||||
},
|
||||
{
|
||||
Sid: "ReadPaymentsQueueRulesAndAlarms",
|
||||
Effect: "Allow",
|
||||
Action: [
|
||||
"sqs:GetQueueAttributes",
|
||||
"sqs:GetQueueUrl",
|
||||
"events:DescribeRule",
|
||||
"events:ListTargetsByRule",
|
||||
"cloudwatch:DescribeAlarms",
|
||||
],
|
||||
Resource: [
|
||||
prodArn("sqs", "payments-processPaymentCsv-async-dlq"),
|
||||
prodArn("events", "rule/payments-dashboard-daily"),
|
||||
prodArn("events", "rule/payments-dashboard-intraday"),
|
||||
prodArn("cloudwatch", "alarm:payments-*"),
|
||||
],
|
||||
},
|
||||
{
|
||||
Sid: "DescribeProjectLogGroups",
|
||||
Effect: "Allow",
|
||||
Action: ["logs:DescribeLogGroups", "logs:DescribeLogStreams"],
|
||||
Resource: [
|
||||
prodArn("logs", "log-group:/aws/lambda/payments-*"),
|
||||
prodArn("logs", "log-group:/aws/lambda/payments-*:*"),
|
||||
prodArn("logs", "log-group:/aws/apigateway/payments-dashboard"),
|
||||
prodArn("logs", "log-group:/aws/apigateway/payments-dashboard:*"),
|
||||
],
|
||||
},
|
||||
{
|
||||
Sid: "ReadDeployParameters",
|
||||
Effect: "Allow",
|
||||
Action: ["ssm:GetParameter", "ssm:GetParameters"],
|
||||
Resource: DEPLOY_PARAMETER_ARNS,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
|
@ -43,15 +204,16 @@ export interface EngineeringAccessStackProps extends cdk.StackProps {
|
|||
}
|
||||
|
||||
/**
|
||||
* Identity Center group and view-only permission sets for the engineering
|
||||
* team (PLAT-235).
|
||||
* Identity Center group and permission sets for the engineering team
|
||||
* (PLAT-235, scoped in PLAT-236).
|
||||
*
|
||||
* Assigned to seahaven-dev and seahaven-prod only. The group has no members.
|
||||
* People are added after the roster exists, outside this stack. This is not
|
||||
* an SCP exemption and cannot assume OrganizationAccountAccessRole.
|
||||
* EngineeringProd can read payments-dashboard configuration and the public
|
||||
* seahaven-site bucket and distribution. It cannot read payment records,
|
||||
* payment files, or secrets. EngineeringDev stays assigned. Neither day-1
|
||||
* project has resources in seahaven-dev, so that set has no allow.
|
||||
*
|
||||
* A later SCIM sync of engineering@seahaven.com must adopt this group. A
|
||||
* second group with display name engineering will collide.
|
||||
* Group membership is outside this stack. A later SCIM sync of
|
||||
* engineering@seahaven.com must adopt this group.
|
||||
*/
|
||||
export class EngineeringAccessStack extends cdk.Stack {
|
||||
constructor(scope: Construct, id: string, props: EngineeringAccessStackProps) {
|
||||
|
|
@ -61,18 +223,20 @@ export class EngineeringAccessStack extends cdk.Stack {
|
|||
identityStoreId: IDENTITY_STORE_ID,
|
||||
displayName: "engineering",
|
||||
description:
|
||||
"Engineering team. View-only in seahaven-dev and seahaven-prod. No members until the roster exists.",
|
||||
"Engineering team. Prod view of payments-dashboard and seahaven-site. No secret or payment-data reads.",
|
||||
});
|
||||
|
||||
const devPermissionSet = this.permissionSet(
|
||||
"EngineeringDevPermissionSet",
|
||||
"EngineeringDev",
|
||||
"View-only in seahaven-dev. No secret, object, or item reads.",
|
||||
"No day-1 project resources in seahaven-dev.",
|
||||
DATA_PLANE_DENY,
|
||||
);
|
||||
const prodPermissionSet = this.permissionSet(
|
||||
"EngineeringProdPermissionSet",
|
||||
"EngineeringProd",
|
||||
"View-only in seahaven-prod. No secret, object, or item reads.",
|
||||
"Read payments-dashboard configuration and the seahaven-site bucket and distribution.",
|
||||
PROD_PROJECT_VIEW,
|
||||
);
|
||||
|
||||
this.assignment(
|
||||
|
|
@ -93,14 +257,15 @@ export class EngineeringAccessStack extends cdk.Stack {
|
|||
id: string,
|
||||
name: string,
|
||||
description: string,
|
||||
inlinePolicy: { Version: string; Statement: object[] },
|
||||
): sso.CfnPermissionSet {
|
||||
return new sso.CfnPermissionSet(this, id, {
|
||||
instanceArn: IDENTITY_CENTER_INSTANCE_ARN,
|
||||
name,
|
||||
description,
|
||||
sessionDuration: "PT8H",
|
||||
managedPolicies: [VIEW_ONLY_ACCESS_ARN],
|
||||
inlinePolicy: DATA_PLANE_DENY,
|
||||
managedPolicies: [],
|
||||
inlinePolicy,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue