UNPKG

@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
"use strict"; /** * 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