Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
// Load config file
var config = yaml.safeLoad(fs.readFileSync('./config/config.yaml', 'utf8'));
if (config['s3_bucket_containing_logs'] == 'MYBUCKET') {
console.log("You must configure the CDK app by editing ./config/config.yaml");
process.exit(1);
}
// Create Lambda
const partitioner = new lambda.Function(this, "partitioner", {
runtime: lambda.Runtime.PYTHON_3_7,
code: lambda.Code.asset("resources/partitioner"),
handler: "main.handler",
description: "Partitions the Athena table for CloudTrail",
logRetention: logs.RetentionDays.TWO_WEEKS,
timeout: cdk.Duration.seconds(900),
memorySize: 128,
environment: {
"S3_BUCKET_CONTAINING_LOGS": config['s3_bucket_containing_logs'],
"CLOUDTRAIL_PREFIX": config["cloudtrail_prefix"],
"PARTITION_DAYS": "1", // This is run nightly so only need to run partition for one day
"OUTPUT_S3_BUCKET": config["output_s3_bucket"],
"DATABASE": config["database"],
"TABLE_PREFIX": config["table_prefix"]
}
});
if (config['output_s3_bucket'] == "default") {
// This is only used for the IAM policy, we leave this as *-* because there is not
// an easy way of figuring out the AWS account from within the CDK
config['output_s3_bucket'] = "aws-athena-query-results-*-*"
// Create SNS for alarms to be sent to
const sns_topic = new sns.Topic(this, 'cloudmapper_alarm', {
displayName: 'cloudmapper_alarm'
});
// Connect the alarm to the SNS
error_alarm.addAlarmAction(new cloudwatch_actions.SnsAction(sns_topic));
// Create Lambda to forward alarms
const alarm_forwarder = new lambda.Function(this, "alarm_forwarder", {
runtime: lambda.Runtime.PYTHON_3_7,
code: lambda.Code.asset("resources/alarm_forwarder"),
handler: "main.handler",
description: "Forwards alarms from the local SNS to another",
logRetention: logs.RetentionDays.TWO_WEEKS,
timeout: cdk.Duration.seconds(30),
memorySize: 128,
environment: {
"ALARM_SNS": config['alarm_sns_arn']
},
});
// Add priv to publish the events so the alarms can be forwarded
alarm_forwarder.addToRolePolicy(new iam.PolicyStatement({
resources: [config['alarm_sns_arn']],
actions: ['sns:Publish']
}));
// Connect the SNS to the Lambda
sns_topic.addSubscription(new sns_subscription.LambdaSubscription(alarm_forwarder));
}
// Create SNS for alarms to be sent to
const sns_topic = new sns.Topic(this, 'cloudtrail_partitioner_alarm', {
displayName: 'cloudtrail_partitioner_alarm'
});
// Connect the alarm to the SNS
error_alarm.addAlarmAction(new cloudwatch_actions.SnsAction(sns_topic));
// Create Lambda to forward alarms
const alarm_forwarder = new lambda.Function(this, "alarm_forwarder", {
runtime: lambda.Runtime.PYTHON_3_7,
code: lambda.Code.asset("resources/alarm_forwarder"),
handler: "main.handler",
description: "Forwards alarms from the local SNS to another",
logRetention: logs.RetentionDays.TWO_WEEKS,
timeout: cdk.Duration.seconds(30),
memorySize: 128,
environment: {
"ALARM_SNS": config['alarm_sns_arn']
},
});
// Add priv to publish the events so the alarms can be forwarded
alarm_forwarder.addToRolePolicy(new iam.PolicyStatement({
resources: [config['alarm_sns_arn']],
actions: ['sns:Publish']
}));
// Connect the SNS to the Lambda
sns_topic.addSubscription(new sns_subscription.LambdaSubscription(alarm_forwarder));
}
const nginx = taskDef.addContainer('nginx', {
image: ecs.ContainerImage.fromAsset(path.join(__dirname, '../../', 'dockerAssets.d/nginx')),
logging: ecs.AwsLogDriver.awsLogs({
logRetention: logs.RetentionDays.ONE_MONTH,
streamPrefix: 'nginx'
})
})
nginx.addPortMappings({
containerPort: 80
})
const express = taskDef.addContainer('express', {
image: ecs.ContainerImage.fromAsset(path.join(__dirname, '../../', 'dockerAssets.d/expressService')),
logging: ecs.AwsLogDriver.awsLogs({
logRetention: logs.RetentionDays.ONE_MONTH,
streamPrefix: 'express'
})
})
// express.addPortMappings({
// containerPort: 3000
// })
const svc = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Svc', {
taskDefinition: taskDef,
cluster,
listenerPort: 80
})
svc.targetGroup.setAttribute('deregistration_delay.timeout_seconds', '30')
// Define the ECS task
const cluster = new ecs.Cluster(this, 'Cluster', { vpc });
const taskDefinition = new ecs.FargateTaskDefinition(this, 'taskDefinition', {});
taskDefinition.addContainer('cloudmapper-container', {
image: ecs.ContainerImage.fromAsset('./resources'),
memoryLimitMiB: 512,
cpu: 256,
environment: {
S3_BUCKET: config['s3_bucket'],
MINIMUM_ALERT_SEVERITY: config['minimum_alert_severity']
},
logging: new ecs.AwsLogDriver({
streamPrefix: 'cloudmapper',
logRetention: logs.RetentionDays.TWO_WEEKS
})
});
// Grant the ability to assume the IAM role in any account
taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({
resources: ["arn:aws:iam::*:role/"+config['iam_role']],
actions: ['sts:AssumeRole']
}));
// Grant the ability to read and write the files from the S3 bucket
taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({
resources: ["arn:aws:s3:::"+config['s3_bucket']],
actions: ['s3:ListBucket']
}));
taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({
resources: ["arn:aws:s3:::"+config['s3_bucket']+"/*"],
this.s3bucket.addToResourcePolicy(new iam.PolicyStatement({
resources: [this.s3bucket.arnForObjects(`AWSLogs/${Stack.of(this).account}/*`)],
actions: ["s3:PutObject"],
principals: [cloudTrailPrincipal],
conditions: {
StringEquals: {'s3:x-amz-acl': "bucket-owner-full-control"}
}
}));
let logGroup: logs.CfnLogGroup | undefined;
let logsRole: iam.IRole | undefined;
if (props.sendToCloudWatchLogs) {
logGroup = new logs.CfnLogGroup(this, "LogGroup", {
retentionInDays: props.cloudWatchLogsRetention || logs.RetentionDays.ONE_YEAR
});
logsRole = new iam.Role(this, 'LogsRole', { assumedBy: cloudTrailPrincipal });
logsRole.addToPolicy(new iam.PolicyStatement({
actions: ["logs:PutLogEvents", "logs:CreateLogStream"],
resources: [logGroup.attrArn],
}));
}
if (props.managementEvents) {
const managementEvent = {
includeManagementEvents: true,
readWriteType: props.managementEvents
};
this.eventSelectors.push(managementEvent);
})
const cluster = new ecs.Cluster(this, 'Cluster', {
vpc
})
const taskDef = new ecs.TaskDefinition(this, 'Task', {
compatibility: ecs.Compatibility.FARGATE,
cpu: '4096',
memoryMiB: '8192',
})
const nginx = taskDef.addContainer('nginx', {
image: ecs.ContainerImage.fromAsset(path.join(__dirname, '../../', 'dockerAssets.d/nginx')),
logging: ecs.AwsLogDriver.awsLogs({
logRetention: logs.RetentionDays.ONE_MONTH,
streamPrefix: 'nginx'
})
})
nginx.addPortMappings({
containerPort: 80
})
const express = taskDef.addContainer('express', {
image: ecs.ContainerImage.fromAsset(path.join(__dirname, '../../', 'dockerAssets.d/expressService')),
logging: ecs.AwsLogDriver.awsLogs({
logRetention: logs.RetentionDays.ONE_MONTH,
streamPrefix: 'express'
})
})
public bind(scope: Construct, containerDefinition: ContainerDefinition): LogDriverConfig {
this.logGroup = this.props.logGroup || new logs.LogGroup(scope, 'LogGroup', {
retention: this.props.logRetention || Infinity,
});
this.logGroup.grantWrite(containerDefinition.taskDefinition.obtainExecutionRole());
return {
logDriver: 'awslogs',
options: removeEmpty({
'awslogs-group': this.logGroup.logGroupName,
'awslogs-stream-prefix': this.props.streamPrefix,
'awslogs-region': Stack.of(containerDefinition).region,
'awslogs-datetime-format': this.props.datetimeFormat,
'awslogs-multiline-pattern': this.props.multilinePattern,
}),
};
}
addLogGroup(logGroupName: string) {
const retentionDays = Infinity
const props = { logGroupName, retentionDays, retainLogGroup: false }
return new LogGroup(this, `${this.id}-${logGroupName}`, props)
}
}));
this.s3bucket.addToResourcePolicy(new iam.PolicyStatement({
resources: [this.s3bucket.arnForObjects(`AWSLogs/${Stack.of(this).account}/*`)],
actions: ["s3:PutObject"],
principals: [cloudTrailPrincipal],
conditions: {
StringEquals: {'s3:x-amz-acl': "bucket-owner-full-control"}
}
}));
let logGroup: logs.CfnLogGroup | undefined;
let logsRole: iam.IRole | undefined;
if (props.sendToCloudWatchLogs) {
logGroup = new logs.CfnLogGroup(this, "LogGroup", {
retentionInDays: props.cloudWatchLogsRetention || logs.RetentionDays.ONE_YEAR
});
logsRole = new iam.Role(this, 'LogsRole', { assumedBy: cloudTrailPrincipal });
logsRole.addToPolicy(new iam.PolicyStatement({
actions: ["logs:PutLogEvents", "logs:CreateLogStream"],
resources: [logGroup.attrArn],
}));
}
if (props.managementEvents) {
const managementEvent = {
includeManagementEvents: true,
readWriteType: props.managementEvents
};