constructor()

in source/cdk-infrastructure/lib/back-end/back-end-construct.ts [42:194]


    constructor(scope: Construct, id: string, props: BackEndProps) {
        super(scope, id);

        const sourceCodeBucket = Bucket.fromBucketName(this, 'sourceCodeBucket', props.sourceCodeBucketName);

        this.issueNotificationTopic = new Topic(this, 'IssueNotificationTopic', {
            displayName: 'Amazon Virtual Andon Notifications',
            masterKey: Alias.fromAliasName(this, 'AwsManagedSnsKey', 'alias/aws/sns')
        });
        (this.issueNotificationTopic.node.defaultChild as CfnResource).overrideLogicalId('IssueNotificationTopic');

        this.appsyncApi = new AppSyncApi(this, 'AppSyncApi', {
            userPool: props.userPool,
            solutionDisplayName: props.solutionDisplayName,
            solutionVersion: props.solutionVersion,
            sourceCodeBucketName: props.sourceCodeBucketName,
            sourceCodeKeyPrefix: props.sourceCodeKeyPrefix,
            loggingLevel: props.loggingLevel,
            issueNotificationTopicArn: this.issueNotificationTopic.topicArn
        });

        const handleIssuesFunctionRole = new Role(this, 'HandleIssuesFunctionRole', {
            assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
            path: '/',
            inlinePolicies: {
                'GraphQLPolicy': new PolicyDocument({
                    statements: [new PolicyStatement({
                        effect: Effect.ALLOW,
                        actions: ['appsync:GraphQL'],
                        resources: [
                            `${this.appsyncApi.graphqlApi.arn}/types/Mutation/fields/createIssue`,
                            `${this.appsyncApi.graphqlApi.arn}/types/Mutation/fields/updateIssue`
                        ]
                    })]
                }),
                'SnsPolicy': new PolicyDocument({
                    statements: [new PolicyStatement({
                        effect: Effect.ALLOW,
                        actions: ['sns:Publish'],
                        resources: [this.issueNotificationTopic.topicArn]
                    })]
                }),
                'DynamoDbPolicy': new PolicyDocument({
                    statements: [
                        new PolicyStatement({
                            effect: Effect.ALLOW,
                            actions: ['dynamodb:GetItem'],
                            resources: [this.appsyncApi.dataHierarchyTable.tableArn]
                        }),
                        new PolicyStatement({
                            effect: Effect.ALLOW,
                            actions: ['dynamodb:Query'],
                            resources: [`${this.appsyncApi.issuesTable.tableArn}/index/ByDeviceEvent-index`]
                        })
                    ]
                }),
                'CloudWatchLogsPolicy': new PolicyDocument({
                    statements: [new PolicyStatement({
                        effect: Effect.ALLOW,
                        actions: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
                        resources: [Stack.of(this).formatArn({ service: 'logs', resource: 'log-group', resourceName: '/aws/lambda/*', arnFormat: ArnFormat.COLON_RESOURCE_NAME })]
                    })]
                })
            }
        });

        this.iotToLambda = new IotToLambda(this, 'IotToLambda', {
            iotTopicRuleProps: {
                topicRulePayload: {
                    description: 'Issues from the AVA Client are submitted to this topic and sent to lambda for processing',
                    sql: `SELECT * FROM '${IotConstants.ISSUES_TOPIC}'`,
                    actions: []
                }
            },
            lambdaFunctionProps: {
                runtime: Runtime.NODEJS_14_X,
                handler: 'ava-issue-handler/index.handler',
                timeout: Duration.seconds(60),
                description: `${props.solutionDisplayName} (${props.solutionVersion}): Handles issues posted to the '${IotConstants.ISSUES_TOPIC}' IoT Topic`,
                code: Code.fromBucket(sourceCodeBucket, [props.sourceCodeKeyPrefix, 'ava-issue-handler.zip'].join('/')),
                role: handleIssuesFunctionRole,
                environment: {
                    API_ENDPOINT: this.appsyncApi.graphqlApi.graphqlUrl,
                    ACCOUNT_ID: Aws.ACCOUNT_ID,
                    ISSUES_TABLE: this.appsyncApi.issuesTable.tableName,
                    DATA_HIERARCHY_TABLE: this.appsyncApi.dataHierarchyTable.tableName,
                    ISSUE_NOTIFICATION_TOPIC_ARN: this.issueNotificationTopic.topicArn,
                    LOGGING_LEVEL: props.loggingLevel,
                    SOLUTION_ID: props.solutionId,
                    SOLUTION_VERSION: props.solutionVersion
                }
            }
        });

        this.iotResourcePolicy = new CfnResource(this, 'IoTResourcePolicy', {
            type: 'AWS::IoT::Policy',
            properties: {
                PolicyDocument: {
                    Version: '2012-10-17',
                    Statement: [
                        {
                            Effect: Effect.ALLOW,
                            Action: ['iot:Publish'],
                            Resource: [
                                Stack.of(this).formatArn({ service: 'iot', resource: 'topic', resourceName: IotConstants.ISSUES_TOPIC, arnFormat: ArnFormat.SLASH_RESOURCE_NAME }),
                                Stack.of(this).formatArn({ service: 'iot', resource: 'topic', resourceName: `${IotConstants.GROUPS_TOPIC}/*`, arnFormat: ArnFormat.SLASH_RESOURCE_NAME })
                            ]
                        },
                        {
                            Effect: Effect.ALLOW,
                            Action: ['iot:Subscribe'],
                            Resource: [Stack.of(this).formatArn({ service: 'iot', resource: 'topicfilter', resourceName: `${IotConstants.GROUPS_TOPIC}/*`, arnFormat: ArnFormat.SLASH_RESOURCE_NAME })]
                        },
                        {
                            Effect: Effect.ALLOW,
                            Action: ['iot:Receive'],
                            Resource: [Stack.of(this).formatArn({ service: 'iot', resource: 'topic', resourceName: `${IotConstants.GROUPS_TOPIC}/*`, arnFormat: ArnFormat.SLASH_RESOURCE_NAME })]
                        },
                        {
                            Effect: Effect.ALLOW,
                            Action: ['iot:Connect'],
                            Resource: [Stack.of(this).formatArn({ service: 'iot', resource: 'client', resourceName: '*', arnFormat: ArnFormat.SLASH_RESOURCE_NAME })]
                        }
                    ]
                }
            }
        });

        this.dataAnalysisConstruct = new DataAnalysis(this, 'DataAnalysis', {
            solutionDisplayName: props.solutionDisplayName,
            solutionId: props.solutionId,
            solutionVersion: props.solutionVersion,
            sourceCodeBucketName: props.sourceCodeBucketName,
            sourceCodeKeyPrefix: props.sourceCodeKeyPrefix,
            loggingLevel: props.loggingLevel,
            issuesTable: this.appsyncApi.issuesTable,
            dataHierarchyTable: this.appsyncApi.dataHierarchyTable,
            logsBucket: props.logsBucket
        });

        this.externalIntegrationsConstruct = new ExternalIntegrations(this, 'ExternalIntegrations', {
            solutionDisplayName: props.solutionDisplayName,
            solutionId: props.solutionId,
            solutionVersion: props.solutionVersion,
            sourceCodeBucketName: props.sourceCodeBucketName,
            sourceCodeKeyPrefix: props.sourceCodeKeyPrefix,
            loggingLevel: props.loggingLevel,
            dataHierarchyTable: this.appsyncApi.dataHierarchyTable,
            issuesTable: this.appsyncApi.issuesTable,
            solutionHelperLambda: props.solutionHelperLambda,
            iotEndpointAddress: props.iotEndpointAddress
        });
    }