@vptech/aws-security-baseline
Version:
Auto-generate AWS security baselines, IAM policies, and security groups from TypeScript interfaces
255 lines (247 loc) • 9.89 kB
JavaScript
;
/**
* AWS CDK Integration for Security Baseline Generator
* Generates CDK constructs from security baselines
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.CDKSecurityIntegration = void 0;
class CDKSecurityIntegration {
/**
* Generate CDK constructs from security baseline
*/
generateCDKConstructs(baseline) {
const imports = this.generateImports();
const constructs = this.generateConstructs(baseline);
return `${imports}\n\n${constructs}`;
}
/**
* Create a complete security stack
*/
createSecurityStack(baseline, stackName) {
const imports = this.generateImports();
const stackClass = this.generateStackClass(baseline, stackName);
return `${imports}\n\n${stackClass}`;
}
/**
* Generate deployment script
*/
generateDeploymentScript(stackName) {
return `#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { ${stackName} } from './${stackName.toLowerCase()}';
const app = new cdk.App();
new ${stackName}(app, '${stackName}', {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
},
});`;
}
generateImports() {
return `import * as cdk from 'aws-cdk-lib';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as kms from 'aws-cdk-lib/aws-kms';
import * as logs from 'aws-cdk-lib/aws-logs';
import * as cloudtrail from 'aws-cdk-lib/aws-cloudtrail';
import * as config from 'aws-cdk-lib/aws-config';
import * as guardduty from 'aws-cdk-lib/aws-guardduty';
import * as securityhub from 'aws-cdk-lib/aws-securityhub';
import { Construct } from 'constructs';`;
}
generateConstructs(baseline) {
const constructs = [];
// Generate KMS keys
constructs.push(this.generateKMSKeyConstructs(baseline.kmsKeys));
// Generate IAM roles
constructs.push(this.generateIAMRoleConstructs(baseline.iamRoles));
// Generate Security Groups
constructs.push(this.generateSecurityGroupConstructs(baseline.securityGroups));
// Generate Audit Configuration
constructs.push(this.generateAuditConstructs(baseline.auditConfig));
return constructs.join('\n\n');
}
generateStackClass(baseline, stackName) {
const constructs = this.generateConstructs(baseline);
return `export class ${stackName} extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
${constructs.split('\n').map(line => ` ${line}`).join('\n')}
}
}`;
}
generateKMSKeyConstructs(keys) {
return keys.map(key => {
const keyPolicyDocument = this.generatePolicyDocument(key.keyPolicy);
return `// KMS Key: ${key.alias}
const ${this.toCamelCase(key.alias)} = new kms.Key(this, '${key.alias}', {
description: '${key.description}',
keyUsage: kms.KeyUsage.${key.keyUsage},
keySpec: kms.KeySpec.${key.keySpec},
enableKeyRotation: ${key.enableKeyRotation},
${key.deletionWindowInDays ? `removalPolicy: cdk.RemovalPolicy.RETAIN,\n pendingWindow: cdk.Duration.days(${key.deletionWindowInDays}),` : ''}
policy: ${keyPolicyDocument}
});
// Add alias for the key
new kms.Alias(this, '${key.alias}-alias', {
aliasName: '${key.alias}',
targetKey: ${this.toCamelCase(key.alias)}
});`;
}).join('\n\n');
}
generateIAMRoleConstructs(roles) {
return roles.map(role => {
const assumedByPrincipals = role.assumedBy.map(principal => `new iam.ServicePrincipal('${principal}')`).join(', ');
const managedPolicies = role.managedPolicies ?
role.managedPolicies.map(policy => `iam.ManagedPolicy.fromAwsManagedPolicyName('${policy.replace('arn:aws:iam::aws:policy/', '')}')`).join(',\n ') : '';
const inlinePolicies = role.inlinePolicies ?
Object.entries(role.inlinePolicies).map(([name, policy]) => {
const policyDoc = this.generatePolicyDocument(policy);
return ` '${name}': ${policyDoc}`;
}).join(',\n') : '';
return `// IAM Role: ${role.roleName}
const ${this.toCamelCase(role.roleName)} = new iam.Role(this, '${role.roleName}', {
roleName: '${role.roleName}',
description: '${role.description}',
assumedBy: new iam.CompositePrincipal(${assumedByPrincipals}),
${managedPolicies ? `managedPolicies: [\n ${managedPolicies}\n ],` : ''}
${inlinePolicies ? `inlinePolicies: {\n${inlinePolicies}\n },` : ''}
${role.maxSessionDuration ? `maxSessionDuration: cdk.Duration.seconds(${role.maxSessionDuration}),` : ''}
${role.path ? `path: '${role.path}',` : ''}
});
${this.generateRoleTags(role)}`;
}).join('\n\n');
}
generateSecurityGroupConstructs(securityGroups) {
return `// Note: Security Groups require a VPC context
// Assuming vpc is available in scope or passed as a prop
${securityGroups.map(sg => {
const rules = sg.rules.map(rule => {
const ruleConfig = this.generateSecurityGroupRule(rule);
return `${this.toCamelCase(sg.name)}.${ruleConfig}`;
}).join('\n');
return `// Security Group: ${sg.name}
const ${this.toCamelCase(sg.name)} = new ec2.SecurityGroup(this, '${sg.name}', {
vpc: vpc, // Assuming vpc is available
securityGroupName: '${sg.name}',
description: '${sg.description}',
allowAllOutbound: false
});
${rules}
${this.generateSecurityGroupTags(sg)}`;
}).join('\n\n')}`;
}
generateSecurityGroupRule(rule) {
const portRange = rule.fromPort === rule.toPort ?
`ec2.Port.tcp(${rule.fromPort})` :
`ec2.Port.tcpRange(${rule.fromPort}, ${rule.toPort})`;
if (rule.type === 'ingress') {
if (rule.cidrBlocks && rule.cidrBlocks.length > 0) {
return `addIngressRule(
ec2.Peer.ipv4('${rule.cidrBlocks[0]}'),
${portRange},
'${rule.description}'
);`;
}
if (rule.securityGroupIds && rule.securityGroupIds.length > 0) {
return `addIngressRule(
ec2.Peer.securityGroupId('${rule.securityGroupIds[0]}'),
${portRange},
'${rule.description}'
);`;
}
}
else {
if (rule.cidrBlocks && rule.cidrBlocks.length > 0) {
return `addEgressRule(
ec2.Peer.ipv4('${rule.cidrBlocks[0]}'),
${portRange},
'${rule.description}'
);`;
}
}
return `// Rule configuration needed for: ${rule.description}`;
}
generateAuditConstructs(auditConfig) {
const constructs = [];
if (auditConfig.enableCloudTrail) {
constructs.push(`// CloudTrail for audit logging
const auditTrail = new cloudtrail.Trail(this, 'AuditTrail', {
bucket: new s3.Bucket(this, 'AuditLogBucket', {
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
lifecycleRules: [{
id: 'AuditLogRetention',
expiration: cdk.Duration.days(${auditConfig.logRetentionDays})
}]
}),
includeGlobalServiceEvents: true,
isMultiRegionTrail: true,
enableFileValidation: true
});`);
}
if (auditConfig.enableConfigRules) {
constructs.push(`// AWS Config for compliance monitoring
const configRecorder = new config.ConfigurationRecorder(this, 'ConfigRecorder', {
role: new iam.Role(this, 'ConfigRole', {
assumedBy: new iam.ServicePrincipal('config.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/ConfigRole')
]
})
});
const configDeliveryChannel = new config.DeliveryChannel(this, 'ConfigDeliveryChannel', {
bucket: new s3.Bucket(this, 'ConfigLogBucket', {
encryption: s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL
})
});`);
}
return constructs.join('\n\n');
}
generatePolicyDocument(policy) {
const statements = policy.statement.map(stmt => {
const conditions = stmt.conditions ?
`,\n conditions: ${JSON.stringify(stmt.conditions, null, 8)}` : '';
const principals = stmt.principals ?
`,\n principals: [${stmt.principals.map(p => `new iam.ArnPrincipal('${p}')`).join(', ')}]` : '';
return ` new iam.PolicyStatement({
effect: iam.Effect.${stmt.effect.toUpperCase()},
actions: ${JSON.stringify(stmt.actions)},
resources: ${JSON.stringify(stmt.resources)}${conditions}${principals}
})`;
}).join(',\n');
return `new iam.PolicyDocument({
statements: [
${statements}
]
})`;
}
generateRoleTags(role) {
if (!role.tags || Object.keys(role.tags).length === 0) {
return '';
}
const tags = Object.entries(role.tags).map(([key, value]) => `cdk.Tags.of(${this.toCamelCase(role.roleName)}).add('${key}', '${value}');`).join('\n');
return `// Tags for ${role.roleName}
${tags}`;
}
generateSecurityGroupTags(sg) {
if (!sg.tags || Object.keys(sg.tags).length === 0) {
return '';
}
const tags = Object.entries(sg.tags).map(([key, value]) => `cdk.Tags.of(${this.toCamelCase(sg.name)}).add('${key}', '${value}');`).join('\n');
return `// Tags for ${sg.name}
${tags}`;
}
toCamelCase(str) {
return str
.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => {
return index === 0 ? word.toLowerCase() : word.toUpperCase();
})
.replace(/\s+/g, '')
.replace(/[-_]/g, '');
}
}
exports.CDKSecurityIntegration = CDKSecurityIntegration;
//# sourceMappingURL=cdk-integration.js.map