in cdk-stacks/lib/api/recordingAPI-stack.ts [30:200]
constructor(scope: cdk.Construct, id: string, props: RecordingAPIStackProps) {
super(scope, id, props);
//create startRecording Lambda
const startRecordingLambda = new nodeLambda.NodejsFunction(this, 'StartRecordingLambda', {
functionName: `${props.cdkAppName}-StartRecordingLambda`,
runtime: lambda.Runtime.NODEJS_12_X,
entry: 'lambdas/handlers/RecordingAPI/startRecording.js',
timeout: cdk.Duration.seconds(20),
environment: {
DDB_TABLE: props.appTable.tableName,
ECS_CLUSTER_ARN: props.recordingECSClusterARN,
ECS_CONTAINER_NAME: props.recordingContainerName,
ECS_TASK_DEFINITION_ARN: props.recordingTaskDefinitionARN,
RECORDING_BUCKET_NAME: props.recordingBucketName,
RECORDING_SCREEN_WIDTH: "1920",
RECORDING_SCREEN_HEIGHT: "1080",
RECORDING_ATTENDEE_NAME: props.SSMParams.recordingAttendeeName,
ConnectInstanceId: props.SSMParams.connectInstanceARN.split('/')[1]
}
});
props.appTable.grantReadWriteData(startRecordingLambda);
startRecordingLambda.role?.attachInlinePolicy(new iam.Policy(this, 'ChimeCreateAttendeeAccess', {
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['chime:CreateAttendee'],
resources: ['*']
})
]
}));
startRecordingLambda.role?.attachInlinePolicy(new iam.Policy(this, 'ECSRunTaskAccess', {
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['ecs:RunTask'],
resources: [props.recordingTaskDefinitionARN]
})
]
}));
startRecordingLambda.role?.attachInlinePolicy(new iam.Policy(this, 'IAMPassRoleAccess', {
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['iam:PassRole'],
resources: [props.recordingTaskDefinitionExecutionRoleARN]
})
]
}));
startRecordingLambda.role?.attachInlinePolicy(new iam.Policy(this, 'ConnectUpdateContactAttributesAccess', {
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['connect:UpdateContactAttributes'],
resources: [`${props.SSMParams.connectInstanceARN}/contact/*`]
})
]
}));
//create stopRecording Lambda
const stopRecordingLambda = new nodeLambda.NodejsFunction(this, 'StopRecordingLambda', {
functionName: `${props.cdkAppName}-StopRecordingLambda`,
runtime: lambda.Runtime.NODEJS_12_X,
entry: 'lambdas/handlers/RecordingAPI/stopRecording.js',
timeout: cdk.Duration.seconds(20),
environment: {
DDB_TABLE: props.appTable.tableName,
ECS_CLUSTER_ARN: props.recordingECSClusterARN,
}
});
props.appTable.grantReadWriteData(stopRecordingLambda);
stopRecordingLambda.role?.attachInlinePolicy(new iam.Policy(this, 'ECSStopTaskAccess', {
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['ecs:StopTask'],
resources: [`arn:aws:ecs:${this.region}:${this.account}:task/${props.recordingECSClusterName}/*`]
})
]
}));
stopRecordingLambda.role?.attachInlinePolicy(new iam.Policy(this, 'ChimeDeleteAttendeeAccess', {
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['chime:DeleteAttendee'],
resources: ['*']
})
]
}));
//create getRecordingSummary Lambda
const getRecordingSummaryLambda = new nodeLambda.NodejsFunction(this, 'GetRecordingSummaryLambda', {
functionName: `${props.cdkAppName}-GetRecordingSummaryLambda`,
runtime: lambda.Runtime.NODEJS_12_X,
entry: 'lambdas/handlers/RecordingAPI/getRecordingSummary.js',
timeout: cdk.Duration.seconds(20),
environment: {
DDB_TABLE: props.appTable.tableName,
recordingPlaybackSecurityProfileId: props.SSMParams.recordingPlaybackSecurityProfileId,
recordingPresignedURLExpiresMinutes: props.SSMParams.recordingPresignedURLExpiresMinutes
}
});
props.appTable.grantReadData(getRecordingSummaryLambda);
getRecordingSummaryLambda.role?.attachInlinePolicy(new iam.Policy(this, 'S3PreSignedAccess', {
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['S3:GetObject'],
resources: [`arn:aws:s3:::${props.recordingBucketName}/RECORDINGS/*`]
})
]
}))
const recordingAPI = new apigw2.HttpApi(this, 'RecordingAPI', {
apiName: `${props.cdkAppName}-RecordingAPI`,
corsPreflight: {
allowOrigins: props.SSMParams.agentAPIAllowedOrigins.split(',').map((item: string) => item.trim()),
allowMethods: [apigw2.CorsHttpMethod.GET, apigw2.CorsHttpMethod.POST, apigw2.CorsHttpMethod.DELETE],
allowHeaders: apigw.Cors.DEFAULT_HEADERS.concat(['cognitoIdToken'])
}
});
const startRecording_Route = new apigw2.HttpRoute(this, 'StartRecording_Route', {
httpApi: recordingAPI,
integration: new apigw2i.HttpLambdaIntegration('startRecordingLambda', startRecordingLambda),
routeKey: apigw2.HttpRouteKey.with('/recording', apigw2.HttpMethod.POST)
});
const startRecording_RouteCfn = startRecording_Route.node.defaultChild as apigw2.CfnRoute;
startRecording_RouteCfn.authorizationType = 'AWS_IAM';
const stopRecording_Route = new apigw2.HttpRoute(this, 'StopRecording_Route', {
httpApi: recordingAPI,
integration: new apigw2i.HttpLambdaIntegration('stopRecordingLambda', stopRecordingLambda),
routeKey: apigw2.HttpRouteKey.with('/recording', apigw2.HttpMethod.DELETE)
});
const stopRecording_RouteCfn = stopRecording_Route.node.defaultChild as apigw2.CfnRoute;
stopRecording_RouteCfn.authorizationType = 'AWS_IAM';
const getRecordingSummary_Route = new apigw2.HttpRoute(this, 'GetRecordingSummary_Route', {
httpApi: recordingAPI,
integration: new apigw2i.HttpLambdaIntegration('getRecordingSummaryLambda', getRecordingSummaryLambda),
routeKey: apigw2.HttpRouteKey.with('/recording-summary', apigw2.HttpMethod.GET)
});
const getRecordingSummary_RouteCfn = getRecordingSummary_Route.node.defaultChild as apigw2.CfnRoute;
getRecordingSummary_RouteCfn.authorizationType = 'AWS_IAM';
//Allow Identity Pool to invoke RecordingAPI resource
props.cognitoAuthenticatedRole.attachInlinePolicy(new iam.Policy(this, 'RecordingAPI_StartRecordingResource', {
statements: [new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["execute-api:Invoke"],
resources: [
`arn:aws:execute-api:${this.region}:${this.account}:${recordingAPI.httpApiId}/$default/${startRecording_RouteCfn.routeKey.replace(/\s+/g, '')}`,
`arn:aws:execute-api:${this.region}:${this.account}:${recordingAPI.httpApiId}/$default/${stopRecording_RouteCfn.routeKey.replace(/\s+/g, '')}`,
`arn:aws:execute-api:${this.region}:${this.account}:${recordingAPI.httpApiId}/$default/${getRecordingSummary_RouteCfn.routeKey.replace(/\s+/g, '')}`
]
})]
}));
this.recordingAPI = recordingAPI
}