in source/services/tasks/tasks.ts [1020:1110]
async generateCloudFormationTemplate(task: object): Promise<string | ErrorReturn> {
let actionName = task['actionName'];
try {
// Gets CloudFormation template from S3
LOGGER.info('Getting CloudFormation template from S3...');
const getParams: AWS.S3.GetObjectAclRequest = {
Bucket: this.cloudFormationBucket,
Key: `${actionName}/cloudformation.template`
};
let data = await this.s3.getObject(getParams).promise();
let yaml = data.Body.toString().replace('%%TASK_ID%%', task['taskId']);
// Adds event related resources to the CloudFormation template
if (task['triggerType'] === TriggerType.Event) {
// Removes event pattern to prevent JSON parsing problem to make CloudWatch Events event rule
let eventPattern = task['eventPattern'];
delete task['eventPattern'];
task['resources'] = '<resources>';
let eventTemplate = fs.readFileSync('tasks/event-handler.template').toString()
.replace(/%%TASK_ID%%/g, task['taskId'])
.replace('%%TASK_DESCRIPTION%%', task['description'])
.replace('%%EVENT_PATTERN%%', eventPattern.replace(/\n/g, ''))
.replace('%%TASK%%', JSON.stringify(task)
.replace(/\\n/g, '')
.replace(/\\/g, '')
.replace(/"/g, '\\"'))
.replace(/%%MASTER_SNS_ARN%%/g, this.masterSnsArn)
.replace('%%MASTER_KMS_ARN%%', this.masterKmsArn)
.replace('%%MASTER_REGION%%', this.region);
yaml = yaml.concat(eventTemplate);
delete task['resources'];
// Adds event pattern again to the task
task['eventPattern'] = eventPattern;
await this.editSnsPolicy(task['taskId'], task['accounts']);
await this.editKmsPolicy(task['taskId'], task['accounts']);
}
LOGGER.info('Putting CloudFormation template from S3...');
// Uploads the CloudFormation template to S3
let putParams: AWS.S3.PutObjectRequest = {
Bucket: this.cloudFormationBucket,
Body: yaml,
Key: `${actionName}/${task['taskId']}.template`,
ContentType: 'binary/octet-stream'
};
await this.s3.putObject(putParams).promise();
LOGGER.info('Modifying S3 bucket policy...');
// Gets bucket policy
let bucketPolicy = await this.s3.getBucketPolicy({ Bucket: this.cloudFormationBucket }).promise();
let policy = JSON.parse(bucketPolicy.Policy);
// Deletes bucket policy
await this.s3.deleteBucketPolicy({ Bucket: this.cloudFormationBucket }).promise();
// Puts new bucket policy
let statement = (policy['Statement'] as object[]).filter((statement) => statement['Sid'] !== task['taskId']);
statement.push({
Sid: task['taskId'],
Effect: 'Allow',
Principal: {
AWS: [
...
(task['accounts'] as string[]).map((account) => {
return `arn:aws:iam::${account}:root`
})
]
},
Action: 's3:GetObject',
Resource: `arn:aws:s3:::${this.cloudFormationBucket}/*`
});
policy['Statement'] = statement;
await this.s3.putBucketPolicy({
Bucket: this.cloudFormationBucket,
Policy: JSON.stringify(policy)
}).promise();
return Promise.resolve(
`https://${this.cloudFormationBucket}.s3.${this.region}.amazonaws.com/${actionName}/${task['taskId']}.template`
);
} catch (error) {
LOGGER.error(`generateCloudFormationTemplate Error: ${JSON.stringify(error)}`);
return Promise.reject(
COMMON_UTIL.getErrorObject('GenerateCloudFormationTemplateFailure', 500, 'Error occurred while generating CloudFormation template.', error)
);
}
}