Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CDK Nag pattern implementation #178

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ module.exports = {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-unused-vars": [1, {"argsIgnorePattern": "^_"}],
"@typescript-eslint/no-unused-vars": [1, { "argsIgnorePattern": "^_" }],
indent: ['error', 4],
"prefer-const": "off",
"semi": ['error',"always"],
"semi": ['error', "always"],
},
};
10 changes: 10 additions & 0 deletions bin/cdk-nag.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as cdk from 'aws-cdk-lib';
import { AwsSolutionsChecks } from 'cdk-nag';
import { configureApp } from '../lib/common/construct-utils';
import CdkNagConstruct from '../lib/cdk-nag-construct';


const app = configureApp();
cdk.Aspects.of(app).add(new AwsSolutionsChecks()); // run CDK-nag

new CdkNagConstruct(app, "cdk-nag-validation", app.account!);
4 changes: 2 additions & 2 deletions cdk.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"app": "npx ts-node dist/lib/common/default-main.js",
"app": "npx ts-node dist/lib/common/default-main.js"
"context": {
"conformitron.amp.endpoint": "https://aps-workspaces.us-east-1.amazonaws.com/workspaces/ws-77b8828d-0985-49e0-9268-2e0e8f3ba758/",
"conformitron.amp.arn":"arn:aws:aps:us-east-1:975050283200:workspace/ws-77b8828d-0985-49e0-9268-2e0e8f3ba758",
Expand Down Expand Up @@ -29,4 +29,4 @@
]
}
}
}
}
10 changes: 5 additions & 5 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
roots: ['<rootDir>/test'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest'
}
roots: ['<rootDir>/test'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest'
}
};
14 changes: 7 additions & 7 deletions lib/amp-monitoring/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ import * as team from '../teams/multi-account-monitoring';
* Demonstrates how to leverage more than one node group along with Fargate profiles.
*/
export default class AmpMonitoringConstruct {
build(scope: Construct, id: string, account?: string, region?: string ) {
build(scope: Construct, id: string, account?: string, region?: string) {
// Setup platform team
const accountID = account ?? process.env.CDK_DEFAULT_ACCOUNT! ;
const awsRegion = region ?? process.env.CDK_DEFAULT_REGION! ;
const accountID = account ?? process.env.CDK_DEFAULT_ACCOUNT!;
const awsRegion = region ?? process.env.CDK_DEFAULT_REGION!;

const stackID = `${id}-blueprint`;
this.create(scope, accountID, awsRegion)
.build(scope, stackID);
}

create(scope: Construct, account?: string, region?: string ) {
create(scope: Construct, account?: string, region?: string) {
// Setup platform team
const accountID = account ?? process.env.CDK_DEFAULT_ACCOUNT! ;
const awsRegion = region ?? process.env.CDK_DEFAULT_REGION! ;
const accountID = account ?? process.env.CDK_DEFAULT_ACCOUNT!;
const awsRegion = region ?? process.env.CDK_DEFAULT_REGION!;
const ampWorkspaceName = "multi-account-monitoring";
const ampPrometheusEndpoint = (blueprints.getNamedResource(ampWorkspaceName) as unknown as amp.CfnWorkspace).attrPrometheusEndpoint;

Expand Down
6 changes: 3 additions & 3 deletions lib/aws-batch-on-eks-construct/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { PolicyStatement, Effect } from 'aws-cdk-lib/aws-iam';

export default class BatchOnEKSConstruct {
build(scope: Construct, id: string, teams: BatchEksTeam[]) {

const batchIamPolicy = new PolicyStatement({
effect: Effect.ALLOW,
actions: [
Expand All @@ -25,9 +25,9 @@ export default class BatchOnEKSConstruct {
.account(process.env.CDK_DEFAULT_ACCOUNT!)
.region(process.env.CDK_DEFAULT_REGION!)
.addOns(
new blueprints.AwsBatchAddOn(),
new blueprints.AwsBatchAddOn(),
new blueprints.AwsForFluentBitAddOn({
iamPolicies:[batchIamPolicy],
iamPolicies: [batchIamPolicy],
values: {
cloudWatch: {
enabled: true,
Expand Down
4 changes: 2 additions & 2 deletions lib/backstage-construct/backstage-secret-addon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,14 @@ export class BackstageSecretAddOn implements blueprints.ClusterAddOn {
secretKey: "POSTGRES_PASSWORD",
remoteRef: {
key: databaseInstanceCredentialsSecretName,
property: "password"
property: "password"
}
},
{
secretKey: "POSTGRES_USER",
remoteRef: {
key: databaseInstanceCredentialsSecretName,
property: "username"
property: "username"
}
},
],
Expand Down
2 changes: 1 addition & 1 deletion lib/backstage-construct/database-credentials.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Secret,ISecret } from 'aws-cdk-lib/aws-secretsmanager';
import { Secret, ISecret } from 'aws-cdk-lib/aws-secretsmanager';
import { ResourceContext, ResourceProvider } from '@aws-quickstart/eks-blueprints';

export interface DatabaseInstanceCredentialsProviderProps {
Expand Down
6 changes: 3 additions & 3 deletions lib/backstage-construct/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export class BackstageConstruct extends Construct {
databaseSecretTargetName: blueprints.utils.valueFromContext(scope, "backstage.database.secret.target.name", "backstage-database-secret"),
};

const subdomain = props.backstageLabel+"."+props.parentDomain;
const subdomain = props.backstageLabel + "." + props.parentDomain;

const databaseInstanceCredentialsProviderProps = {
username: props.username
} as DatabaseInstanceCredentialsProviderProps;
Expand Down Expand Up @@ -82,6 +82,6 @@ export class BackstageConstruct extends Construct {
.addOns(...addOns)
.version('auto')
.teams()
.build(scope, props.backstageLabel+"-blueprint");
.build(scope, props.backstageLabel + "-blueprint");
}
}
8 changes: 4 additions & 4 deletions lib/backstage-construct/rds-database-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ export class DatabaseInstanceProvider implements ResourceProvider<rds.IDatabaseI
throw new Error("VPC not found in context");
}

const dbSecurityGroup = new SecurityGroup(context.scope, id+"-security-group", {
const dbSecurityGroup = new SecurityGroup(context.scope, id + "-security-group", {
vpc: vpc
});

dbSecurityGroup.addIngressRule(Peer.ipv4(vpc.vpcCidrBlock), Port.tcp(this.props.databaseInstancePort), "Connect from within VPC");

const rdsConfig: rds.DatabaseInstanceProps = {
Expand All @@ -55,7 +55,7 @@ export class DatabaseInstanceProvider implements ResourceProvider<rds.IDatabaseI
securityGroups: [dbSecurityGroup],
credentials: rds.Credentials.fromSecret(databaseCredentialsSecret),
};
return new rds.DatabaseInstance(context.scope, id+"-database-instance", rdsConfig);

return new rds.DatabaseInstance(context.scope, id + "-database-instance", rdsConfig);
}
}
8 changes: 4 additions & 4 deletions lib/bottlerocket-construct/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import * as team from '../teams';
* and leverage container-optimized Bottlerocket OS: https://aws.amazon.com/bottlerocket/
*/
export default class BottlerocketConstruct {

build(scope: Construct, id: string) {

const stackID = `${id}-blueprint`;
const accountID = process.env.CDK_DEFAULT_ACCOUNT!;
const platformTeam = new team.TeamPlatform(accountID);

const clusterProvider = new blueprints.MngClusterProvider({
version: eks.KubernetesVersion.V1_25,
amiType: eks.NodegroupAmiType.BOTTLEROCKET_X86_64
});

blueprints.EksBlueprint.builder()
.account(accountID)
.region('us-east-1')
Expand Down
69 changes: 69 additions & 0 deletions lib/cdk-nag-construct/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Construct } from 'constructs';
import * as blueprints from '@aws-quickstart/eks-blueprints';
import { ArnPrincipal } from 'aws-cdk-lib/aws-iam';
import { NagSuppressionsConfig } from './nag-rules';
import { KubernetesVersion } from 'aws-cdk-lib/aws-eks';


export default class CdkNagConstruct {

constructor(scope: Construct, id: string, account: string) {
const stackId = `${id}-blueprint`;

const addOns: Array<blueprints.ClusterAddOn> = [
new blueprints.addons.SSMAgentAddOn(),
new blueprints.addons.CoreDnsAddOn('auto'),
new blueprints.addons.KubeProxyAddOn("v1.29.1-eksbuild.2"),
new blueprints.addons.EbsCsiDriverAddOn(),
];

const applicationTeams: Array<EKSaaPApplicationTeam> = [
new EKSaaPApplicationTeam("one", [
new ArnPrincipal(`arn:aws:iam::${account}:role/its-user`)
]),
new EKSaaPApplicationTeam("two", [
new ArnPrincipal(`arn:aws:iam::${account}:role/its-user`)
])
];

const platformTeam = new EKSaaPPlatformTeam([
new ArnPrincipal(`arn:aws:iam::${account}:role/its-admin`)
]);

const promise = blueprints.EksBlueprint.builder()
.addOns(...addOns)
.version(KubernetesVersion.V1_29)
.teams(platformTeam, ...applicationTeams)
.useDefaultSecretEncryption(true)
.compatibilityMode(true)
.buildAsync(scope, stackId);

promise.then(stack => new NagSuppressionsConfig(stack));
}
}

export class EKSaaPPlatformTeam extends blueprints.PlatformTeam {
constructor(
allowedArnPrincipals: Array<ArnPrincipal>,
name?: string
) {
super({
name: name ?? "infrastructure",
users: allowedArnPrincipals
});
}
}

export class EKSaaPApplicationTeam extends blueprints.ApplicationTeam {
constructor(
name: string,
allowedArnPrincipals: Array<ArnPrincipal>,
namespace?: string
) {
super({
name,
namespace,
users: allowedArnPrincipals
});
}
}
Loading
Loading