Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,22 @@ See detailed architecture and workflows in:
- `templates/service-catalog/template.yaml`


## Implemented platform product guardrails

The CDK app now applies two productized guardrails from the platform review recommendations:

- **Typed environment configuration** via `lib/platform-config.ts` with explicit `dev|stage|prod` validation and fail-fast errors for missing or invalid values.
- **Mandatory governance tags** standardized at stack level and validated in tests for key resources: `environment`, `project`, `owner`, `cost-center`, and `data-classification`.

Set the environment explicitly with either CDK context or environment variable:

```bash
npm run synth # defaults to dev when PLATFORM_ENV is unset
PLATFORM_ENV=stage npm run synth
# or, direct CDK command
npm run cdk -- synth -c platformEnv=prod
```

## Code review resolution

Review feedback and implemented fixes are tracked in:
Expand Down
13 changes: 7 additions & 6 deletions bin/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { CdkAppStack } from '../lib/cdk-app-stack';

// initialize the CDK app
import { loadPlatformConfig } from '../lib/platform-config';

const app = new cdk.App();
const platformEnv = app.node.tryGetContext('platformEnv') ?? process.env.PLATFORM_ENV;
const platformConfig = loadPlatformConfig(platformEnv);

// deploy the clouformation stack to the default account and region
new CdkAppStack(app, 'CdkAppStack', {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
},
platformConfig,
});
14 changes: 11 additions & 3 deletions lib/cdk-app-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ import * as logs from 'aws-cdk-lib/aws-logs';
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
import * as cwActions from 'aws-cdk-lib/aws-cloudwatch-actions';
import * as sns from 'aws-cdk-lib/aws-sns';
import { PlatformConfig } from './platform-config';

export interface CdkAppStackProps extends cdk.StackProps {
readonly platformConfig: PlatformConfig;
}

export class CdkAppStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
constructor(scope: Construct, id: string, props: CdkAppStackProps) {
super(scope, id, props);

const encryptionKey = new kms.Key(this, 'PlatformDataKey', {
Expand Down Expand Up @@ -274,7 +279,10 @@ export class CdkAppStack extends cdk.Stack {
});

// Optional: Add Tags to Resources
cdk.Tags.of(this).add('Environment', 'Development');
cdk.Tags.of(this).add('Project', 'DemoAPI');
cdk.Tags.of(this).add('environment', props.platformConfig.environment);
cdk.Tags.of(this).add('project', props.platformConfig.project);
cdk.Tags.of(this).add('owner', props.platformConfig.owner);
cdk.Tags.of(this).add('cost-center', props.platformConfig.costCenter);
cdk.Tags.of(this).add('data-classification', props.platformConfig.dataClassification);
}
}
57 changes: 57 additions & 0 deletions lib/platform-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
export type PlatformEnvironment = 'dev' | 'stage' | 'prod';

export interface PlatformConfig {
readonly environment: PlatformEnvironment;
readonly owner: string;
readonly costCenter: string;
readonly dataClassification: 'public' | 'internal' | 'confidential' | 'restricted';
readonly project: string;
}

const CONFIG_BY_ENV: Record<PlatformEnvironment, Omit<PlatformConfig, 'environment'>> = {
dev: {
owner: 'platform-engineering',
costCenter: 'ENG-PLATFORM',
dataClassification: 'internal',
project: 'DemoAPI',
},
stage: {
owner: 'platform-engineering',
costCenter: 'ENG-PLATFORM',
dataClassification: 'confidential',
project: 'DemoAPI',
},
prod: {
owner: 'platform-engineering',
costCenter: 'ENG-PLATFORM',
dataClassification: 'confidential',
project: 'DemoAPI',
},
};

export const resolvePlatformEnvironment = (value?: string): PlatformEnvironment => {
const normalized = value?.trim().toLowerCase();

if (!normalized) {
throw new Error(
'Platform environment must be explicitly specified via platformEnv context or PLATFORM_ENV. Allowed values: dev, stage, prod.',
);
}
Comment on lines +35 to +39
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Logic Error: Silently defaulting to 'dev' when no environment is specified creates a critical risk where production deployments could accidentally use development configuration if PLATFORM_ENV or platformEnv context are not set. This violates the principle of failing safely and could lead to incorrect infrastructure provisioning. Throw an error instead to force explicit environment selection.

Suggested change
if (!normalized) {
return 'dev';
}
if (!normalized) {
throw new Error(
'Platform environment must be explicitly specified via platformEnv context or PLATFORM_ENV. Allowed values: dev, stage, prod.',
);
}


if (normalized === 'dev' || normalized === 'stage' || normalized === 'prod') {
return normalized;
}

throw new Error(
`Invalid platform environment \"${value}\". Allowed values: dev, stage, prod.`,
);
};

export const loadPlatformConfig = (environmentValue?: string): PlatformConfig => {
const environment = resolvePlatformEnvironment(environmentValue);

return {
environment,
...CONFIG_BY_ENV[environment],
};
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"cdk": "cdk",
"deploy": "cdk deploy",
"destroy": "cdk destroy",
"synth": "cdk synth"
"synth": "bash -lc \"cdk synth -c platformEnv=${PLATFORM_ENV:-dev}\""
},
"devDependencies": {
"@types/aws-lambda": "^8.10.122",
Expand Down
Loading
Loading