in use_cases/custom-cloud9-ssm/lib/index.ts [106:205]
constructor(scope: cdk.Construct, id: string, props: CustomCloud9SsmProps) {
super(scope, id)
let cloud9Env: cloud9.Ec2Environment
// Create the Cloud9 environment using the default configuration
if (!props.cloud9Ec2Props) {
cloud9Env = new cloud9.Ec2Environment(this,'Cloud9Ec2Environment', {
vpc: new ec2.Vpc(this, id + '-VPC', {
maxAzs: 2
})
})
}
// Create the Cloud9 environment using the received props
else {
cloud9Env = new cloud9.Ec2Environment(this,'Cloud9Ec2Environment', props.cloud9Ec2Props)
}
// Create a Role for the EC2 instance and an instance profile with it
this.ec2Role = new iam.Role(this,'Ec2Role', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
roleName: id + '-CustomCloud9SsmEc2Role',
managedPolicies: [
iam.ManagedPolicy.fromManagedPolicyArn(
this,
id + '-SsmManagedPolicy',
'arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore'
)
]
})
const instanceProfile = new iam.CfnInstanceProfile(this,'Ec2InstanceProfile', {
roles: [this.ec2Role.roleName]
})
// Create the SSM Document using the default configuration
if (!props.ssmDocumentProps) {
let content: string = fs.readFileSync(CustomCloud9Ssm.DEFAULT_DOCUMENT_FILE_NAME, 'utf8')
const ssmDocumentProps = {
documentType: 'Command',
content: yaml.parse(content),
name: id + '-' + CustomCloud9Ssm.DEFAULT_DOCUMENT_NAME
}
this.document = new ssm.CfnDocument(this,'SsmDocument', ssmDocumentProps)
this.resizeEBSTo(CustomCloud9Ssm.DEFAULT_EBS_SIZE)
}
// Create the SSM Document using the received props
else {
if (!props.ssmDocumentProps.name) {
throw new Error("The document name must be specified.")
}
this.document = new ssm.CfnDocument(this,'SsmDocument', props.ssmDocumentProps)
}
// Create an SSM Association to apply the document configuration
new ssm.CfnAssociation(this,'SsmAssociation', {
name: this.document.name as string,
targets: [
{
key: 'tag:aws:cloud9:environment',
values: [cloud9Env.environmentId]
}
]
})
// Create the Lambda function that attaches the instance profile to the EC2 instance
let code: string = fs.readFileSync(CustomCloud9Ssm.ATTACH_PROFILE_FILE_NAME, 'utf8')
const lambdaFunction = new lambda.Function(this,'LambdaFunction', {
runtime: lambda.Runtime.PYTHON_3_6,
code: lambda.Code.fromInline(code),
handler: 'index.handler',
timeout: cdk.Duration.seconds(60)
})
// Give permissions to the function to execute some APIs
lambdaFunction.addToRolePolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
'ec2:DescribeInstances',
'ec2:AssociateIamInstanceProfile',
'ec2:ReplaceIamInstanceProfileAssociation',
'ec2:RebootInstances',
'iam:ListInstanceProfiles',
'iam:PassRole'
],
resources: ['*']
}))
// Create the Custom Resource that invokes the Lambda function
new cdk.CustomResource(this, 'CustomResource', {
serviceToken: lambdaFunction.functionArn,
properties: {
cloud9_env_id: cloud9Env.environmentId,
profile_arn: instanceProfile.attrArn
}
})
}