Esempio n. 1
0
def add_contact_api(stack: CDKMasterStack, project_name: str, domain: str,
                    forwarding_email: str):

    module_path = os.path.dirname(__file__)
    lambda_path = os.path.join(module_path, "lambda")
    api_path = "contact"

    base_lambda = aws_lambda.Function(
        stack,
        'ContactFormLambda',
        handler='lambda_handler.handler',
        runtime=aws_lambda.Runtime.PYTHON_3_7,
        environment={
            "TARGET_EMAIL":
            forwarding_email,
            "SENDER_EMAIL":
            f"contact@{domain}",
            "SENDER_NAME":
            f"{project_name.capitalize()}",
            "SENDER":
            f"{project_name.capitalize()} Contact Form <contact@{domain}>"
        },
        code=aws_lambda.Code.asset(lambda_path),
    )

    base_lambda.add_to_role_policy(
        aws_iam.PolicyStatement(effect=aws_iam.Effect.ALLOW,
                                resources=["*"],
                                actions=["ses:SendEmail", "ses:SendRawEmail"]))

    verify_domain_create_call = AwsSdkCall(
        service="SES",
        action="verifyDomainIdentity",
        parameters={"Domain": domain},
        physical_resource_id=PhysicalResourceId.from_response(
            "VerificationToken"))

    policy_statement = PolicyStatement(actions=["ses:VerifyDomainIdentity"],
                                       resources=["*"])
    verify_domain_identity = AwsCustomResource(
        stack,
        "VerifyDomainIdentity",
        on_create=verify_domain_create_call,
        policy=AwsCustomResourcePolicy.from_statements(
            statements=[policy_statement]))

    aws_route53.TxtRecord(
        stack,
        "SESVerificationRecord",
        zone=stack.zone,
        record_name=f"_amazonses.{domain}",
        values=[
            verify_domain_identity.get_response_field("VerificationToken")
        ])

    stack.add_api_method(api_path, "POST", base_lambda)
Esempio n. 2
0
    def __init__(self, scope: Construct, id: str, bucket_name):
        super().__init__(scope, id)

        res = AwsCustomResource(
            scope=self,
            id='AWSCustomResource',
            policy=AwsCustomResourcePolicy.from_sdk_calls(resources=[f'arn:aws:s3:::{bucket_name}/*']),
            log_retention=logs.RetentionDays.INFINITE,
            on_create=self.create(bucket_name),
            on_delete=self.delete(bucket_name),
            resource_type='Custom::MyCustomResource'
        )
Esempio n. 3
0
    def create_function(self, other_stack: Stack, id, *, code: AssetCode,
                        handler: str, runtime: Runtime) -> IVersion:
        func = Function(
            self,
            id,
            code=code,
            handler=handler,
            runtime=runtime,
            role=self._role,
        )

        # If code/runtime changes, CDK doesn't re-evaluate the version. In
        # result, we store an old version, and things don't work. But we also
        # don't want to generate a new version every run. The compromise: use
        # the sha256 hash of the index file.
        with open(f"{code.path}/index.js", "rb") as f:
            sha256 = hashlib.sha256(f.read()).hexdigest()
        version = func.add_version(f"Version-{sha256}")

        # Create an entry in the parameter-store that tells the arn of this lambda
        parameter_name = parameter_store.get_parameter_name(
            f"/LambdaEdge/{id}")
        StringParameter(
            self,
            parameter_name,
            string_value=Fn.join(
                ":",
                [
                    func.function_arn,
                    version.version,
                ],
            ),
            parameter_name=parameter_name,
        )

        other_stack.add_dependency(self)

        # Create a custom resource that fetches the arn of the lambda
        cross_region_func = LambdaEdgeFunction(
            other_stack,
            f"LambdaEdgeFunction-{sha256}",
            parameter_name=parameter_name,
            policy=AwsCustomResourcePolicy.from_sdk_calls(
                resources=AwsCustomResourcePolicy.ANY_RESOURCE),
        )
        # Create the lambda function based on this arn
        return Version.from_version_arn(other_stack, id,
                                        cross_region_func.get_arn())
    def __init__(
        self,
        scope: core.Construct,
        id_: str,
        role_alias: str,
        role_arn: str,
        credential_duration_seconds: int,
        log_retention=None,
        timeout=None,
    ) -> None:
        super().__init__(scope, id_)

        on_create = self.get_on_create(
            role_alias=role_alias,
            role_arn=role_arn,
            credential_duration_seconds=credential_duration_seconds)
        on_update = self.get_on_update(
            role_alias=role_alias,
            role_arn=role_arn,
            credential_duration_seconds=credential_duration_seconds)
        on_delete = self.get_on_delete(role_alias=role_alias)

        account_id = Stack.of(self).account
        region = Stack.of(self).region

        policy = AwsCustomResourcePolicy.from_sdk_calls(resources=[
            f'arn:aws:iot:{region}:{account_id}:rolealias/{role_alias}'
        ])
        lambda_role_singleton = CustomResourcesLambdaRole(scope)
        lambda_role_singleton.add_to_policy(actions=["iam:PassRole"],
                                            resources=[role_arn])

        # lambda_role = self.get_provisioning_lambda_role(role_arn)

        AwsCustomResource(scope=self,
                          id=f'CustomResource',
                          policy=policy,
                          log_retention=log_retention,
                          on_create=on_create,
                          on_update=on_update,
                          on_delete=on_delete,
                          resource_type='Custom::AWS-IoT-Role-Alias',
                          role=lambda_role_singleton.role,
                          timeout=timeout)
Esempio n. 5
0
    def __init__(self,
                 scope: core.Construct,
                 id: str,
                 project_name: str,
                 log_retention=None) -> None:
        super().__init__(scope, id)
        self.project_name = project_name
        policy = AwsCustomResourcePolicy.from_sdk_calls(
            resources=AwsCustomResourcePolicy.ANY_RESOURCE)

        self.custom_resource = AwsCustomResource(
            scope=self,
            id=f'{id}-CustomResource',
            policy=policy,
            log_retention=log_retention,
            on_create=self.create_project(project_name),
            on_update=self.update_project(project_name),
            on_delete=self.delete_project(project_name),
            resource_type='Custom::AWS-DeviceFarm-Project')
        self.project_arn = self.custom_resource.get_response_field_reference(
            'project.arn')
        self.project_id = core.Fn.select(
            6, core.Fn.split(":", core.Token.as_string(self.project_arn)))
Esempio n. 6
0
    def __init__(
        self,
        scope: core.Construct,
        id_: str,
        bucket_name: str,
        object_key: str,
        object_content: Any,
        log_retention=None,
        timeout=Duration.seconds(amount=DEFAULT_S3_READ_TIMEOUT_SEC)
    ) -> None:
        super().__init__(scope, id_)

        tenant_config_bucket = s3.Bucket.from_bucket_name(
            scope=scope, id="TenantConfigBucket", bucket_name=bucket_name)

        on_create = self.get_on_create(bucket_name=bucket_name,
                                       object_key=object_key,
                                       object_content=object_content)
        on_update = on_create  # Updating an S3 object is actually creating a new version
        on_delete = self.get_on_delete(bucket_name, object_key)

        policy = AwsCustomResourcePolicy.from_sdk_calls(
            resources=[f'{tenant_config_bucket.bucket_arn}/{object_key}'])

        lambda_role = self.get_provisioning_lambda_role()
        # lambda_role = None

        AwsCustomResource(scope=scope,
                          id='AwsCustomResourceTenantMetadataS3Object',
                          policy=policy,
                          log_retention=log_retention,
                          on_create=on_create,
                          on_update=on_update,
                          on_delete=on_delete,
                          resource_type='Custom::AWS-S3-Object',
                          role=lambda_role,
                          timeout=timeout)
Esempio n. 7
0
    def __init__(self, scope: core.Construct, id: str, es_domain: CfnDomain, kda_role: iam.Role,
                 source_bucket: s3.Bucket, dest_bucket: s3.Bucket, **kwargs):
        super().__init__(scope, id, **kwargs)

        stack = Stack.of(self)

        kda_role.add_to_policy(PolicyStatement(actions=['cloudwatch:PutMetricData'],
                                               resources=['*']))

        artifacts_bucket_arn = 'arn:aws:s3:::' + _config.ARA_BUCKET.replace("s3://", "")
        kda_role.add_to_policy(PolicyStatement(actions=['s3:GetObject', 's3:GetObjectVersion'],
                                               resources=[artifacts_bucket_arn, artifacts_bucket_arn + '/binaries/*']))
        log_group = logs.LogGroup(scope=self,
                                  id='KdaLogGroup',
                                  retention=logs.RetentionDays.ONE_WEEK,
                                  removal_policy=RemovalPolicy.DESTROY)

        log_stream = logs.LogStream(scope=self,
                                    id='KdaLogStream',
                                    log_group=log_group,
                                    removal_policy=RemovalPolicy.DESTROY)

        log_stream_arn = stack.format_arn(service='logs',
                                          resource='log-group',
                                          resource_name=log_group.log_group_name + ':log-stream:' +
                                                        log_stream.log_stream_name,
                                          sep=':')

        # TODO: restrict
        kda_role.add_to_policy(PolicyStatement(actions=['logs:*'],
                                               resources=[stack.format_arn(service='logs', resource='*')]))

        kda_role.add_to_policy(PolicyStatement(actions=['logs:DescribeLogStreams', 'logs:DescribeLogGroups'],
                                               resources=[log_group.log_group_arn,
                                                          stack.format_arn(service='logs', resource='log-group',
                                                                           resource_name='*')]))

        kda_role.add_to_policy(PolicyStatement(actions=['logs:PutLogEvents'],
                                               resources=[log_stream_arn]))

        kda_role.add_to_policy(PolicyStatement(actions=['es:ESHttp*'],
                                               resources=[stack.format_arn(service='es', resource='domain',
                                                                           resource_name=es_domain.domain_name + '/*')]))

        # TODO: restrict
        kda_role.add_to_policy(PolicyStatement(actions=['s3:*'],
                                               resources=['arn:aws:s3::::*']))

        # Define delivery stream
        # delivery_stream_name = 'clean_delivery_stream'
        #
        # s3_configuration = {
        #     'bucketArn': '',
        #     'compressionFormat': 'Snappy',
        #     'dataFormatConversionConfiguration': {
        #         'enabled': True,
        #         'inputFormatConfiguration': {'deserializer': },
        #         'outputFormatConfiguration': {'serializer': {'parquetSerDe': }},
        #         'schemaConfiguration': {}
        #     },
        #     'prefix': 'streaming'
        # }
        #
        # delivery_stream = CfnDeliveryStream(scope=self,
        #                                     id='Firehose Delivery Stream',
        #                                     delivery_stream_name=delivery_stream_name,
        #                                     delivery_stream_type='DirectPut',
        #                                     extended_s3_destination_configuration=s3_configuration
        #                                     )

        # Define KDA application
        application_configuration = {
            'environmentProperties': {
                'propertyGroups': [
                    {
                        'propertyGroupId': 'ConsumerConfigProperties',
                        'propertyMap': {
                            'CustomerStream': scope.customer_stream.stream_name,
                            'AddressStream': scope.address_stream.stream_name,
                            'SaleStream': scope.sale_stream.stream_name,
                            'PromoDataPath': source_bucket.s3_url_for_object('promo'),
                            'ItemDataPath': source_bucket.s3_url_for_object('item'),
                            'aws.region': scope.region
                        }
                    },
                    {
                        'propertyGroupId': 'ProducerConfigProperties',
                        'propertyMap': {
                            'ElasticsearchHost': 'https://' + es_domain.attr_domain_endpoint + ':443',
                            'Region': scope.region,
                            'DenormalizedSalesS3Path': dest_bucket.s3_url_for_object() + '/',
                            'IndexName': 'ara-write'
                        }
                    }
                ]
            },
            'applicationCodeConfiguration': {
                'codeContent': {
                    's3ContentLocation': {
                        'bucketArn': artifacts_bucket_arn,
                        'fileKey': 'binaries/stream-processing-1.1.jar'
                    }
                },
                'codeContentType': 'ZIPFILE'
            },
            'flinkApplicationConfiguration': {
                'parallelismConfiguration': {
                    'configurationType': 'DEFAULT'
                },
                'checkpointConfiguration': {
                    'configurationType': 'DEFAULT'
                },
                'monitoringConfiguration': {
                    'logLevel': 'DEBUG',
                    'metricsLevel': 'TASK',
                    'configurationType': 'CUSTOM'
                }
            },
            'applicationSnapshotConfiguration': {
                'snapshotsEnabled': False
            }
        }

        self.__app = CfnApplicationV2(scope=self,
                                      id='KDA application',
                                      runtime_environment='FLINK-1_11',
                                      application_name='KDA-application',
                                      service_execution_role=kda_role.role_arn,
                                      application_configuration=application_configuration)

        logging = CfnApplicationCloudWatchLoggingOptionV2(scope=self, id='KDA application logging',
                                                          application_name=self.__app.ref,
                                                          cloud_watch_logging_option={'logStreamArn': log_stream_arn})

        logging.apply_removal_policy(policy=RemovalPolicy.RETAIN, apply_to_update_replace_policy=True,
                                     default=RemovalPolicy.RETAIN)

        # Use a custom resource to start the application
        create_params = {
            'ApplicationName': self.__app.ref,
            'RunConfiguration': {
                'ApplicationRestoreConfiguration': {
                    'ApplicationRestoreType': 'SKIP_RESTORE_FROM_SNAPSHOT'
                },
                'FlinkRunConfiguration': {
                    'AllowNonRestoredState': True
                }
            }
        }

        # See https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/ for service name, actions and parameters
        create_action = AwsSdkCall(service='KinesisAnalyticsV2',
                                   action='startApplication',
                                   parameters=create_params,
                                   physical_resource_id=PhysicalResourceId.of(self.__app.ref + '-start'))

        delete_action = AwsSdkCall(service='KinesisAnalyticsV2',
                                   action='stopApplication',
                                   parameters={'ApplicationName': self.__app.ref, 'Force': True})

        custom_resource = AwsCustomResource(scope=self,
                                            id='KdaStartAndStop',
                                            on_create=create_action,
                                            on_delete=delete_action,
                                            policy=AwsCustomResourcePolicy.from_statements([PolicyStatement(
                                                actions=['kinesisanalytics:StartApplication',
                                                         'kinesisanalytics:StopApplication',
                                                         'kinesisanalytics:DescribeApplication',
                                                         'kinesisanalytics:UpdateApplication'], resources=[
                                                    stack.format_arn(service='kinesisanalytics', resource='application',
                                                                     resource_name=self.app.application_name)])]))

        custom_resource.node.add_dependency(self.app)
    def __init__(
        self, scope: core.Construct, id: str, central_account, **kwargs
    ) -> None:
        super().__init__(scope, id, **kwargs)
        self.current_dir = os.path.dirname(__file__)

        # Change to your central account
        self.central_account_id = central_account

        self.quicksight_migration_target_assume_role = iam.Role(
            self,
            "quicksight-migration-target-assume-role",
            description="Role for the Quicksight dashboard migration Lambda function to assume",
            role_name="quicksight-migration-target-assume-role",
            max_session_duration=core.Duration.seconds(3600),
            assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"),
            inline_policies={
                "AllowAccess": iam.PolicyDocument(
                    statements=[
                        iam.PolicyStatement(
                            effect=iam.Effect.ALLOW,
                            actions=[
                                "quicksight:*",
                            ],
                            resources=["*"],
                        ),
                        iam.PolicyStatement(
                            effect=iam.Effect.ALLOW,
                            actions=[
                                "ssm:GetParameter",
                            ],
                            resources=[
                                f"arn:aws:ssm:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:parameter/infra/config"
                            ],
                        ),
                        iam.PolicyStatement(
                            effect=iam.Effect.ALLOW,
                            actions=["secretsmanager:GetSecretValue"],
                            resources=[
                                f"arn:aws:secretsmanager:{core.Aws.REGION}:{core.Aws.ACCOUNT_ID}:secret:*"
                            ],
                        ),
                    ]
                )
            },
        )

        self.quicksight_migration_target_assume_role.assume_role_policy.add_statements(
            iam.PolicyStatement(
                effect=iam.Effect.ALLOW,
                actions=["sts:AssumeRole"],
                principals=[iam.AccountPrincipal(self.central_account_id)],
            )
        )

        ssm.StringParameter(
            self,
            "InfraConfigParam",
            parameter_name="/infra/config",
            string_value=json.dumps(self.to_dict()),
        )

        self.quicksight_managed_resources_policy = iam.ManagedPolicy(
            self,
            "iam_policy",
            managed_policy_name="QuickSightMigrationPolicy",
            statements=[
                iam.PolicyStatement(
                    sid="AWSResourceAccess",
                    effect=iam.Effect.ALLOW,
                    actions=[
                        "iam:List*",
                        "redshift:Describe*",
                        "rds:Describe*",
                        "athena:Get*",
                        "athena:List*",
                        "athena:BatchGetQueryExecution",
                        "athena:StartQueryExecution",
                        "athena:StopQueryExecution",
                        "s3:GetBucketLocation",
                        "s3:GetObject",
                        "s3:ListBucket",
                        "s3:ListBucketMultipartUploads",
                        "s3:ListMultipartUploadParts",
                        "s3:AbortMultipartUpload",
                        "s3:CreateBucket",
                        "s3:PutObject",
                        "s3:PutBucketPublicAccessBlock",
                    ],
                    resources=["*"],
                ),
            ],
        )
        # create a custom resource that will create a quicksight user using the IAM target role
        self.qs_user = AwsCustomResource(
            self,
            "AWSCustomResourceQSUser",
            role=self.quicksight_migration_target_assume_role,
            policy=AwsCustomResourcePolicy.from_sdk_calls(
                resources=AwsCustomResourcePolicy.ANY_RESOURCE
            ),
            on_create=self.create_qsuser(),
            on_delete=self.delete_qsuser(),
            resource_type="Custom::QuickSightMigrationUser",
        )
        self.qs_user.node.add_dependency(self.quicksight_managed_resources_policy)

        # create a custom resource that will create a quicksight policy assignment
        self.qs_policy_assignment = AwsCustomResource(
            self,
            "AWSCustomResourceQSPolicyAssignment",
            role=self.quicksight_migration_target_assume_role,
            policy=AwsCustomResourcePolicy.from_sdk_calls(
                resources=AwsCustomResourcePolicy.ANY_RESOURCE
            ),
            on_create=self.create_policy_assignment(),
            on_delete=self.delete_policy_assignment(),
            resource_type="Custom::QuickSightPolicyAssignment",
        )
        self.qs_policy_assignment.node.add_dependency(self.qs_user)
    def create_package(self):
        """
        First step: 
        - Define lambda role to ger ResourceToken
        - Define policy. In this step policy might be overpermissive, but we don't know the ARN resource \
        So we will use ANY_RESOURCE tricl
        """
        lambda_role_mediapackage = self.get_provisioning_lambda_role(
            role_name=f'stack-the-media-live')
        custom_policy = AwsCustomResourcePolicy.from_sdk_calls(
            resources=AwsCustomResourcePolicy.ANY_RESOURCE)
        """
        Second step:
        - Define create/update/delete method for both: MediaPackageChannel and MediaPackageOriginEndpoint
        """
        on_create_mediapackage = self.on_create_mediapackage()
        on_update_mediapackage = self.on_update_mediapackage()
        on_delete_mediapackage = self.on_delete_mediapackage()

        on_create_mediapackage_endpoint = self.on_create_mediapackage_endpoint(
        )
        on_update_mediapackage_endpoint = self.on_update_mediapackage_endpoint(
        )
        on_delete_mediapackage_endpoint = self.on_delete_mediapackage_endpoint(
        )
        """
        Third step:
        - Create MediaPackageChannel
        """
        channel = AwsCustomResource(
            scope=self.scope,
            id=f'{self.id_channel}-MediaPackage-AWSCustomResource',
            policy=custom_policy,
            log_retention=None,  # We don't need log at this moment
            on_create=on_create_mediapackage,
            on_update=on_update_mediapackage,
            on_delete=on_delete_mediapackage,
            resource_type='Custom::MediaPackageChannel',
            role=lambda_role_mediapackage,
            timeout=None
        )  # Timeout of the Lambda implementing this custom resource. Default: Duration.minutes(2)
        """
        Fourth step:
        - Create MediaPackageOriginEndpoint
        By default HLS endpoint is the most common endpoint used, so we will create it
        You can choose your own endpoint here: 
        https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/MediaPackage.html#createOriginEndpoint-property
        """
        hls_endpoint = AwsCustomResource(
            scope=self.scope,
            id=f'{self.id_channel}-MediaPackageEndpoint-AWSCustomResource',
            policy=custom_policy,
            log_retention=None,  # We don't need log at this moment
            on_create=on_create_mediapackage_endpoint,
            on_update=on_update_mediapackage_endpoint,
            on_delete=on_delete_mediapackage_endpoint,
            resource_type='Custom::MediaPackageHlsEndpoint',
            role=lambda_role_mediapackage,
            timeout=None
        )  # Timeout of the Lambda implementing this custom resource. Default: Duration.minutes(2)
        """ Must fix the dependency among custom resources """
        mediadep = core.ConcreteDependable()
        mediadep.add(channel)
        hls_endpoint.node.add_dependency(mediadep)

        core.CfnOutput(scope=self,
                       id="media-package-url-strem",
                       value=hls_endpoint.get_response_field("Url"))

        return hls_endpoint.get_response_field("Url")