constructor()

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);
    }