Skip to content

Commit 0eea53b

Browse files
committed
Implement platform-product config and governance tagging defaults
1 parent e56f5c3 commit 0eea53b

6 files changed

Lines changed: 467 additions & 83 deletions

File tree

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,21 @@ See detailed architecture and workflows in:
7272
- `templates/service-catalog/template.yaml`
7373

7474

75+
## Implemented platform product guardrails
76+
77+
The CDK app now applies two productized guardrails from the platform review recommendations:
78+
79+
- **Typed environment configuration** via `lib/platform-config.ts` with explicit `dev|stage|prod` validation and fail-fast errors for invalid values.
80+
- **Mandatory governance tags** standardized at stack level and validated in tests for key resources: `environment`, `project`, `owner`, `cost-center`, and `data-classification`.
81+
82+
Set the environment with either CDK context or environment variable:
83+
84+
```bash
85+
npm run synth -- -c platformEnv=stage
86+
# or
87+
PLATFORM_ENV=prod npm run synth
88+
```
89+
7590
## Code review resolution
7691

7792
Review feedback and implemented fixes are tracked in:

bin/app.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22
import 'source-map-support/register';
33
import * as cdk from 'aws-cdk-lib';
44
import { CdkAppStack } from '../lib/cdk-app-stack';
5-
6-
// initialize the CDK app
5+
import { loadPlatformConfig } from '../lib/platform-config';
76

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

10-
// deploy the clouformation stack to the default account and region
1111
new CdkAppStack(app, 'CdkAppStack', {
12-
env: {
13-
account: process.env.CDK_DEFAULT_ACCOUNT,
14-
region: process.env.CDK_DEFAULT_REGION
12+
env: {
13+
account: process.env.CDK_DEFAULT_ACCOUNT,
14+
region: process.env.CDK_DEFAULT_REGION,
1515
},
16+
platformConfig,
1617
});

lib/cdk-app-stack.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@ import * as logs from 'aws-cdk-lib/aws-logs';
1313
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
1414
import * as cwActions from 'aws-cdk-lib/aws-cloudwatch-actions';
1515
import * as sns from 'aws-cdk-lib/aws-sns';
16+
import { PlatformConfig } from './platform-config';
17+
18+
export interface CdkAppStackProps extends cdk.StackProps {
19+
readonly platformConfig: PlatformConfig;
20+
}
1621

1722
export class CdkAppStack extends cdk.Stack {
18-
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
23+
constructor(scope: Construct, id: string, props: CdkAppStackProps) {
1924
super(scope, id, props);
2025

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

276281
// Optional: Add Tags to Resources
277-
cdk.Tags.of(this).add('Environment', 'Development');
278-
cdk.Tags.of(this).add('Project', 'DemoAPI');
282+
cdk.Tags.of(this).add('environment', props.platformConfig.environment);
283+
cdk.Tags.of(this).add('project', props.platformConfig.project);
284+
cdk.Tags.of(this).add('owner', props.platformConfig.owner);
285+
cdk.Tags.of(this).add('cost-center', props.platformConfig.costCenter);
286+
cdk.Tags.of(this).add('data-classification', props.platformConfig.dataClassification);
279287
}
280288
}

lib/platform-config.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
export type PlatformEnvironment = 'dev' | 'stage' | 'prod';
2+
3+
export interface PlatformConfig {
4+
readonly environment: PlatformEnvironment;
5+
readonly owner: string;
6+
readonly costCenter: string;
7+
readonly dataClassification: 'public' | 'internal' | 'confidential' | 'restricted';
8+
readonly project: string;
9+
}
10+
11+
const CONFIG_BY_ENV: Record<PlatformEnvironment, Omit<PlatformConfig, 'environment'>> = {
12+
dev: {
13+
owner: 'platform-engineering',
14+
costCenter: 'ENG-PLATFORM',
15+
dataClassification: 'internal',
16+
project: 'DemoAPI',
17+
},
18+
stage: {
19+
owner: 'platform-engineering',
20+
costCenter: 'ENG-PLATFORM',
21+
dataClassification: 'confidential',
22+
project: 'DemoAPI',
23+
},
24+
prod: {
25+
owner: 'platform-engineering',
26+
costCenter: 'ENG-PLATFORM',
27+
dataClassification: 'confidential',
28+
project: 'DemoAPI',
29+
},
30+
};
31+
32+
export const resolvePlatformEnvironment = (value?: string): PlatformEnvironment => {
33+
const normalized = value?.trim().toLowerCase();
34+
35+
if (!normalized) {
36+
return 'dev';
37+
}
38+
39+
if (normalized === 'dev' || normalized === 'stage' || normalized === 'prod') {
40+
return normalized;
41+
}
42+
43+
throw new Error(
44+
`Invalid platform environment \"${value}\". Allowed values: dev, stage, prod.`,
45+
);
46+
};
47+
48+
export const loadPlatformConfig = (environmentValue?: string): PlatformConfig => {
49+
const environment = resolvePlatformEnvironment(environmentValue);
50+
51+
return {
52+
environment,
53+
...CONFIG_BY_ENV[environment],
54+
};
55+
};

0 commit comments

Comments
 (0)