constructor()

in source/infrastructure/lib/connection-builder.ts [66:268]


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

    const sourceCodeBucket = props.solutionConfig.sourceCodeBucket;
    const sourceCodePrefix = props.solutionConfig.sourceCodePrefix;
    const iotSitewiseGatewayArn = `arn:${Aws.PARTITION}:iotsitewise:${Aws.REGION}:${Aws.ACCOUNT_ID}:gateway/${props.iotSitewiseGateway.ref}`;

    const greengrassLambdaRole = new Role(this, 'GreengrassLambdaRole', {
      assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
      path: '/'
    });
    greengrassLambdaRole.attachInlinePolicy(props.cloudWatchLogsPolicy);

    const lambdaToDynamoDb = new LambdaToDynamoDB(this, 'ConnectionBuilder', {
      lambdaFunctionProps: {
        code: Code.fromBucket(sourceCodeBucket, `${sourceCodePrefix}/connection-builder.zip`),
        description: 'Machine to Cloud Connectivity connection builder function',
        environment: {
          IOT_ENDPOINT: props.iotEndpointAddress,
          IOT_SITEWISE_GATEWAY_ID: props.iotSitewiseGateway.ref,
          KINESIS_STREAM: props.kinesisStreamName,
          LOGGING_LEVEL: props.solutionConfig.loggingLevel,
          LOGS_DYNAMODB_TABLE: props.logsTableName,
          PAGE_SIZE: '20',
          SEND_ANONYMOUS_METRIC: props.solutionConfig.sendAnonymousUsage,
          SOLUTION_ID: props.solutionConfig.solutionId,
          SOLUTION_VERSION: props.solutionConfig.solutionVersion,
          SOLUTION_UUID: props.uuid
        },
        handler: 'connection-builder/index.handler',
        runtime: Runtime.NODEJS_14_X,
        timeout: Duration.minutes(1)
      },
      dynamoTableProps: {
        partitionKey: {
          name: 'connectionName',
          type: AttributeType.STRING
        }
      },
      tableEnvironmentVariableName: 'CONNECTION_DYNAMODB_TABLE'
    });
    this.connectionBuilderLambdaFunction = lambdaToDynamoDb.lambdaFunction;

    const cfnDynamoTable = lambdaToDynamoDb.dynamoTable.node.defaultChild as CfnTable;
    cfnDynamoTable.cfnOptions.deletionPolicy = CfnDeletionPolicy.DELETE;
    this.connectionDynamodbTableName = lambdaToDynamoDb.dynamoTable.tableName;

    const greengrassDeployerRole = new Role(this, 'GreengrassDeployerRole', {
      assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
      path: '/',
      inlinePolicies: {
        'GreengrassIoTPolicy': new PolicyDocument({
          statements: [
            new PolicyStatement({
              effect: Effect.ALLOW,
              actions: [
                'greengrass:Create*DefinitionVersion',
                'greengrass:Create*Definition',
                'greengrass:CreateDeployment',
                'greengrass:CreateGroupVersion',
                'greengrass:Get*DefinitionVersion',
                'greengrass:GetDeploymentStatus',
                'greengrass:GetGroupVersion',
                'greengrass:GetGroup',
                'greengrass:List*Definitions'
              ],
              resources: ['*']
            }),
            new PolicyStatement({
              effect: Effect.ALLOW,
              actions: ['iot:Publish'],
              resources: [
                `arn:${Aws.PARTITION}:iot:${Aws.REGION}:${Aws.ACCOUNT_ID}:topic/m2c2/job/*`,
                `arn:${Aws.PARTITION}:iot:${Aws.REGION}:${Aws.ACCOUNT_ID}:topic/m2c2/info/*`,
                `arn:${Aws.PARTITION}:iot:${Aws.REGION}:${Aws.ACCOUNT_ID}:topic/m2c2/error/*`
              ]
            }),
            new PolicyStatement({
              effect: Effect.ALLOW,
              actions: [
                'iotsitewise:DescribeGatewayCapabilityConfiguration',
                'iotsitewise:UpdateGatewayCapabilityConfiguration'
              ],
              resources: [iotSitewiseGatewayArn]
            })
          ]
        }),
        'LambdaPolicy': new PolicyDocument({
          statements: [
            new PolicyStatement({
              effect: Effect.ALLOW,
              actions: [
                'lambda:CreateFunction',
                'lambda:DeleteFunction',
                'lambda:PublishVersion',
                'lambda:CreateAlias',
                'lambda:DeleteAlias'
              ],
              resources: [`arn:${Aws.PARTITION}:lambda:${Aws.REGION}:${Aws.ACCOUNT_ID}:function:m2c2-*`]
            }),
            new PolicyStatement({
              effect: Effect.ALLOW,
              actions: ['iam:PassRole'],
              resources: [greengrassLambdaRole.roleArn]
            })
          ]
        }),
        'DynamoDBPolicy': new PolicyDocument({
          statements: [
            new PolicyStatement({
              effect: Effect.ALLOW,
              actions: [
                'dynamodb:DeleteItem',
                'dynamodb:GetItem',
                'dynamodb:PutItem',
                'dynamodb:Scan',
                'dynamodb:UpdateItem',
                'dynamodb:Query',
              ],
              resources: [lambdaToDynamoDb.dynamoTable.tableArn]
            })
          ]
        }),
        'S3Policy': new PolicyDocument({
          statements: [
            new PolicyStatement({
              effect: Effect.ALLOW,
              actions: ['s3:GetObject'],
              resources: [`arn:${Aws.PARTITION}:s3:::${sourceCodeBucket.bucketName}/${sourceCodePrefix}/*`]
            })
          ]
        })
      }
    });
    greengrassDeployerRole.attachInlinePolicy(props.cloudWatchLogsPolicy);
    addCfnSuppressRules(greengrassDeployerRole, [{
      id: 'W11', reason: 'The * resource is needed to control Greengrass resources.'
    }]);

    const greengrassDeployer = new LambdaFunction(this, 'GreengrassDeployer', {
      code: Code.fromBucket(sourceCodeBucket, `${sourceCodePrefix}/greengrass-deployer.zip`),
      description: 'Machine to Cloud Connectivity Greengrass deployer function',
      environment: {
        LAMBDA_ROLE: greengrassLambdaRole.roleArn,
        GREENGRASS_GROUP_ID: props.greengrassGroupId,
        IOT_ENDPOINT: props.iotEndpointAddress,
        IOT_SITEWISE_GATEWAY_ID: props.iotSitewiseGateway.ref,
        CONNECTION_DYNAMODB_TABLE: this.connectionDynamodbTableName,
        KINESIS_STREAM: props.kinesisStreamName,
        LOGGING_LEVEL: props.solutionConfig.loggingLevel,
        SEND_ANONYMOUS_METRIC: props.solutionConfig.sendAnonymousUsage,
        SOLUTION_ID: props.solutionConfig.solutionId,
        SOLUTION_VERSION: props.solutionConfig.solutionVersion,
        SOLUTION_UUID: props.uuid,
        SOURCE_S3_BUCKET: sourceCodeBucket.bucketName,
        SOURCE_S3_PREFIX: sourceCodePrefix
      },
      handler: 'greengrass-deployer/index.handler',
      retryAttempts: 0,
      reservedConcurrentExecutions: 1,
      role: greengrassDeployerRole,
      runtime: Runtime.NODEJS_14_X,
      timeout: Duration.minutes(5)
    });
    this.connectionBuilderLambdaFunction.addEnvironment('GREENGRASS_DEPLOYER_LAMBDA_FUNCTION', greengrassDeployer.functionName);

    const connectionBuilderPolicy = new Policy(this, 'ConnectionBuilderPolicy', {
      statements: [
        new PolicyStatement({
          effect: Effect.ALLOW,
          actions: ['iot:Publish'],
          resources: [
            `arn:${Aws.PARTITION}:iot:${Aws.REGION}:${Aws.ACCOUNT_ID}:topic/m2c2/job/*`,
            `arn:${Aws.PARTITION}:iot:${Aws.REGION}:${Aws.ACCOUNT_ID}:topic/m2c2/info/*`
          ]
        }),
        new PolicyStatement({
          effect: Effect.ALLOW,
          actions: ['lambda:InvokeFunction'],
          resources: [greengrassDeployer.functionArn]
        }),
        new PolicyStatement({
          effect: Effect.ALLOW,
          actions: [
            'dynamodb:Scan',
            'dynamodb:Query'
          ],
          resources: [props.logsTableArn]
        }),
        new PolicyStatement({
          effect: Effect.ALLOW,
          actions: [
            'iotsitewise:DescribeGatewayCapabilityConfiguration',
            'iotsitewise:UpdateGatewayCapabilityConfiguration'
          ],
          resources: [iotSitewiseGatewayArn]
        })
      ]
    });

    const connectionBuilderRole = this.connectionBuilderLambdaFunction.role as Role;
    connectionBuilderRole.attachInlinePolicy(connectionBuilderPolicy);
  }