mirror of
https://github.com/Sea-Haven-Industries/seahaven-org-baseline.git
synced 2026-10-03 10:23:13 +00:00
Limit EngineeringProd to payments-dashboard configuration and the public site, and drop account-wide view in dev where those projects do not run.
287 lines
8.6 KiB
TypeScript
287 lines
8.6 KiB
TypeScript
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 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/*`,
|
|
];
|
|
|
|
/**
|
|
* 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: "DenySecretAndPaymentReads",
|
|
Effect: "Deny",
|
|
Action: [
|
|
"secretsmanager:GetSecretValue",
|
|
"secretsmanager:BatchGetSecretValue",
|
|
"kms:Decrypt",
|
|
"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,
|
|
},
|
|
],
|
|
};
|
|
|
|
export interface EngineeringAccessStackProps extends cdk.StackProps {
|
|
devAccountId: string;
|
|
prodAccountId: string;
|
|
}
|
|
|
|
/**
|
|
* Identity Center group and permission sets for the engineering team
|
|
* (PLAT-235, scoped in PLAT-236).
|
|
*
|
|
* 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.
|
|
*
|
|
* 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) {
|
|
super(scope, id, props);
|
|
|
|
const group = new identitystore.CfnGroup(this, "EngineeringGroup", {
|
|
identityStoreId: IDENTITY_STORE_ID,
|
|
displayName: "engineering",
|
|
description:
|
|
"Engineering team. Prod view of payments-dashboard and seahaven-site. No secret or payment-data reads.",
|
|
});
|
|
|
|
const devPermissionSet = this.permissionSet(
|
|
"EngineeringDevPermissionSet",
|
|
"EngineeringDev",
|
|
"No day-1 project resources in seahaven-dev.",
|
|
DATA_PLANE_DENY,
|
|
);
|
|
const prodPermissionSet = this.permissionSet(
|
|
"EngineeringProdPermissionSet",
|
|
"EngineeringProd",
|
|
"Read payments-dashboard configuration and the seahaven-site bucket and distribution.",
|
|
PROD_PROJECT_VIEW,
|
|
);
|
|
|
|
this.assignment(
|
|
"EngineeringDevAssignment",
|
|
devPermissionSet,
|
|
group,
|
|
props.devAccountId,
|
|
);
|
|
this.assignment(
|
|
"EngineeringProdAssignment",
|
|
prodPermissionSet,
|
|
group,
|
|
props.prodAccountId,
|
|
);
|
|
}
|
|
|
|
private permissionSet(
|
|
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: [],
|
|
inlinePolicy,
|
|
});
|
|
}
|
|
|
|
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",
|
|
});
|
|
}
|
|
}
|