<gh_stars>0
import os

from aws_cdk import (
    aws_route53 as r53,
    aws_route53_targets as r53Targets,
    core as cdk,
    aws_lambda as _lambda,
    aws_apigateway as apigw,
    aws_iam as iam,
    aws_dynamodb as dynamo,
    aws_certificatemanager as certmgr,
    aws_s3 as s3,
    aws_s3_deployment as s3deploy,
)

from .bundler import Bundler


class SmpServiceStack(cdk.Stack):
    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # retrieve context specific settings
        env = os.getenv("ENV_NAME", "dev")
        config = scope.node.try_get_context(env)
        clean_assets = scope.node.try_get_context("clean") or False
        network_domain = config["network_domain"]
        cert_arn = config["cert_arn"]
        api_key = scope.node.try_get_context("api_key") or config["api_key"]
        smp_api_subdomain_prefix = config["smp_api_subdomain_prefix"]
        smp_registrations_table = config["smp_registration_table"]

        # Lookup existing hosted zone
        smp_hosted_zone = r53.HostedZone.from_lookup(
            self, "NetworkHostedZone", domain_name=network_domain
        )

        # Create a Dynamodb table to save requests
        reg_table = dynamo.Table(
            self,
            "SMPRegTable",
            table_name=smp_registrations_table,
            billing_mode=dynamo.BillingMode.PROVISIONED,
            read_capacity=3,
            write_capacity=3,
            point_in_time_recovery=False,
            partition_key=dynamo.Attribute(
                name="participant_urn", type=dynamo.AttributeType.STRING
            ),
            sort_key=dynamo.Attribute(
                name="service_id", type=dynamo.AttributeType.STRING
            ),
            removal_policy=cdk.RemovalPolicy(cdk.RemovalPolicy.DESTROY),
        )

        cert_bucket = s3.Bucket(
            self,
            "MyCertificateBucket",
            encryption=s3.BucketEncryption.KMS,
            bucket_key_enabled=True,
            bucket_name=f"{env}-smp-certbucket",
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
        )

        # Bundle lambda python deps into dist assets for upload to AWS Lambda
        smp_asset_path = Bundler("lambda-smp-service").bundle(clean=clean_assets)

        # Build lambda function using asset path
        smp_service = _lambda.Function(
            self,
            "SMPService",
            runtime=_lambda.Runtime.PYTHON_3_8,
            code=_lambda.Code.asset(smp_asset_path),
            handler="main.handler",
            environment={
                "NETWORK_DOMAIN": network_domain,
                "API_KEY": api_key,
                "SMP_REG_TABLE": reg_table.table_name,
                "SMP_CERT_BUCKET": f"{env}-smp-certbucket",
            },
        )

        # Augment Lambda basic execution role with additional permissions
        cert_bucket.grant_read(smp_service.role)
        reg_table.grant_read_write_data(smp_service.role)

        # Construct the API subdomain
        smp_api_fqdn = f"{smp_api_subdomain_prefix}.{network_domain}"

        # Generate a cert for api domain
        api_cert = certmgr.Certificate.from_certificate_arn(
            self, "SMPApiCertificate", certificate_arn=cert_arn
        )

        # Build an API Gateway endpoint backed by the Lambda function
        api_endpoint = apigw.LambdaRestApi(
            self,
            "SMPServiceEndpoint",
            handler=smp_service,
            proxy=True,
            domain_name=apigw.DomainNameOptions(
                certificate=api_cert,
                domain_name=smp_api_fqdn,
                endpoint_type=apigw.EndpointType.REGIONAL,
                security_policy=apigw.SecurityPolicy.TLS_1_2,
            ),
        )

        r53.ARecord(
            self,
            "API-ARecord",
            zone=smp_hosted_zone,
            record_name=smp_api_fqdn,
            target=r53.RecordTarget.from_alias(r53Targets.ApiGateway(api_endpoint)),
        )

        # Report on custom domain
        cdk.CfnOutput(
            self,
            "SMPApiCustomDomain",
            value=smp_api_fqdn,
            export_name="smp-api-custom-domain",
            description="The FQDN of the SMP API Lambda function",
        )

import os

from aws_cdk import (
    aws_route53 as r53,
    aws_route53_targets as r53Targets,
    core as cdk,
    aws_lambda as _lambda,
    aws_apigateway as apigw,
    aws_iam as iam,
    aws_dynamodb as dynamo,
    aws_certificatemanager as certmgr,
    aws_s3 as s3,
    aws_s3_deployment as s3deploy,
)

from .bundler import Bundler


class SmpServiceStack(cdk.Stack):
    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # retrieve context specific settings
        env = os.getenv("ENV_NAME", "dev")
        config = scope.node.try_get_context(env)
        clean_assets = scope.node.try_get_context("clean") or False
        network_domain = config["network_domain"]
        cert_arn = config["cert_arn"]
        api_key = scope.node.try_get_context("api_key") or config["api_key"]
        smp_api_subdomain_prefix = config["smp_api_subdomain_prefix"]
        smp_registrations_table = config["smp_registration_table"]

        # Lookup existing hosted zone
        smp_hosted_zone = r53.HostedZone.from_lookup(
            self, "NetworkHostedZone", domain_name=network_domain
        )

        # Create a Dynamodb table to save requests
        reg_table = dynamo.Table(
            self,
            "SMPRegTable",
            table_name=smp_registrations_table,
            billing_mode=dynamo.BillingMode.PROVISIONED,
            read_capacity=3,
            write_capacity=3,
            point_in_time_recovery=False,
            partition_key=dynamo.Attribute(
                name="participant_urn", type=dynamo.AttributeType.STRING
            ),
            sort_key=dynamo.Attribute(
                name="service_id", type=dynamo.AttributeType.STRING
            ),
            removal_policy=cdk.RemovalPolicy(cdk.RemovalPolicy.DESTROY),
        )

        cert_bucket = s3.Bucket(
            self,
            "MyCertificateBucket",
            encryption=s3.BucketEncryption.KMS,
            bucket_key_enabled=True,
            bucket_name=f"{env}-smp-certbucket",
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
        )

        # Bundle lambda python deps into dist assets for upload to AWS Lambda
        smp_asset_path = Bundler("lambda-smp-service").bundle(clean=clean_assets)

        # Build lambda function using asset path
        smp_service = _lambda.Function(
            self,
            "SMPService",
            runtime=_lambda.Runtime.PYTHON_3_8,
            code=_lambda.Code.asset(smp_asset_path),
            handler="main.handler",
            environment={
                "NETWORK_DOMAIN": network_domain,
                "API_KEY": api_key,
                "SMP_REG_TABLE": reg_table.table_name,
                "SMP_CERT_BUCKET": f"{env}-smp-certbucket",
            },
        )

        # Augment Lambda basic execution role with additional permissions
        cert_bucket.grant_read(smp_service.role)
        reg_table.grant_read_write_data(smp_service.role)

        # Construct the API subdomain
        smp_api_fqdn = f"{smp_api_subdomain_prefix}.{network_domain}"

        # Generate a cert for api domain
        api_cert = certmgr.Certificate.from_certificate_arn(
            self, "SMPApiCertificate", certificate_arn=cert_arn
        )

        # Build an API Gateway endpoint backed by the Lambda function
        api_endpoint = apigw.LambdaRestApi(
            self,
            "SMPServiceEndpoint",
            handler=smp_service,
            proxy=True,
            domain_name=apigw.DomainNameOptions(
                certificate=api_cert,
                domain_name=smp_api_fqdn,
                endpoint_type=apigw.EndpointType.REGIONAL,
                security_policy=apigw.SecurityPolicy.TLS_1_2,
            ),
        )

        r53.ARecord(
            self,
            "API-ARecord",
            zone=smp_hosted_zone,
            record_name=smp_api_fqdn,
            target=r53.RecordTarget.from_alias(r53Targets.ApiGateway(api_endpoint)),
        )

        # Report on custom domain
        cdk.CfnOutput(
            self,
            "SMPApiCustomDomain",
            value=smp_api_fqdn,
            export_name="smp-api-custom-domain",
            description="The FQDN of the SMP API Lambda function",
        )
# retrieve context specific settings # Lookup existing hosted zone # Create a Dynamodb table to save requests # Bundle lambda python deps into dist assets for upload to AWS Lambda # Build lambda function using asset path # Augment Lambda basic execution role with additional permissions # Construct the API subdomain # Generate a cert for api domain # Build an API Gateway endpoint backed by the Lambda function # Report on custom domain