in source/use_cases/aws-serverless-image-handler/lib/index.ts [121:201]
constructor(scope: Construct, id: string, props: ServerlessImageHandlerProps) {
super(scope, id);
// If customProps is undefined, define it
this.customProps = (props.customProps === undefined) ? {} : props.customProps;
// Use case specific properties for the Lambda function
const useCaseFunctionProps: lambda.FunctionProps = {
code: lambda.Code.fromAsset(`${__dirname}/lambda/image-handler`),
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
environment: {
AUTO_WEBP: (props.autoWebP) ? 'Yes' : 'No',
CORS_ENABLED: (props.corsEnabled) ? 'Yes' : 'No',
CORS_ORIGIN: (props.corsOrigin) ? props.corsOrigin : ''
}
};
const functionProps = (this.customProps.lambdaFunctionProps) ?
defaults.overrideProps(useCaseFunctionProps, this.customProps.lambdaFunctionProps) : useCaseFunctionProps;
// Use case specific properties for the API Gateway
const useCaseApiProps: apiGateway.RestApiProps = {
binaryMediaTypes: [ "*/*" ]
};
const apiProps = (this.customProps.apiGatewayProps) ?
defaults.overrideProps(useCaseApiProps, this.customProps.apiGatewayProps) : useCaseApiProps;
// Build the CloudFrontToApiGatewayToLambda pattern
this.cloudFrontApiGatewayLambda = new CloudFrontToApiGatewayToLambda(this, 'CloudFrontApiGatewayLambda', {
cloudFrontDistributionProps: (this.customProps.cloudFrontDistributionProps) ? this.customProps.cloudFrontDistributionProps : undefined,
apiGatewayProps: apiProps,
lambdaFunctionProps: functionProps
});
const existingLambdaFn = this.cloudFrontApiGatewayLambda.lambdaFunction;
// Build the LambdaToS3 pattern
this.lambdaS3 = new LambdaToS3(this, 'ExistingLambdaS3', {
existingLambdaObj: existingLambdaFn,
bucketProps: this.customProps.bucketProps,
bucketPermissions: (this.customProps.bucketPermissions) ? this.customProps.bucketPermissions : undefined
});
// Add additional permissions for Lambda to source original images from any bucket in the account
const lambdaSourcingPolicyStmt = new iam.PolicyStatement({
effect: iam.Effect.ALLOW
});
lambdaSourcingPolicyStmt.addResources('arn:aws:s3:::*');
lambdaSourcingPolicyStmt.addActions('s3:GetObject*', 's3:GetBucket*', 's3:List*');
// Add additional permissions for Lambda to access Rekognition services
const lambdaRekognitionPolicyStmt = new iam.PolicyStatement({
effect: iam.Effect.ALLOW
});
lambdaRekognitionPolicyStmt.addResources('*');
lambdaRekognitionPolicyStmt.addActions('rekognition:DetectFaces');
// Append the additional permissions to an inline policy
const inlinePolicy = new iam.Policy(this, 'LambdaS3AccessPolicy', {
statements: [ lambdaSourcingPolicyStmt, lambdaRekognitionPolicyStmt ]
});
// Add cfn_nag suppression for Rekognition wildcard resource
const rawInlinePolicy: iam.CfnPolicy = inlinePolicy.node.findChild('Resource') as iam.CfnPolicy;
rawInlinePolicy.cfnOptions.metadata = {
cfn_nag: {
rules_to_suppress: [{
id: 'W12',
reason: `Specified Rekognition action needs wildcard resource.`
}]
}
};
// Attach the inline policy to the Lambda function role
existingLambdaFn.role?.attachInlinePolicy(inlinePolicy);
// Add the SOURCE_BUCKETS environment variable to the Lambda function
const bucketsArr = (props.sourceBuckets !== "") ? props.sourceBuckets.split(',') : [];
bucketsArr.push(this.lambdaS3.s3Bucket.bucketName);
const bucketsStr = bucketsArr.toString().replace(/\s+/g, '');
this.cloudFrontApiGatewayLambda.lambdaFunction.addEnvironment("SOURCE_BUCKETS", bucketsStr);
}