aws-cdk-lib#StackProps TypeScript Examples

The following examples show how to use aws-cdk-lib#StackProps. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: go-lambda-stack.ts    From cdk-examples with MIT License 6 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here
    new Function(this, 'goLambda', {
      runtime: Runtime.GO_1_X,
      handler: 'main',
      code: Code.fromAsset(`${__dirname}/../lambda-fns/hello-world/`, {
        bundling: {
          image: Runtime.GO_1_X.bundlingImage,
          user: 'root',
          command: [
            'bash', '-c', [
              'cd /asset-input',
              'go build -o main main.go',
              'mv /asset-input/main /asset-output/'
            ].join(' && ')
          ]
        }
      })
    })    
  }
Example #2
Source File: certificate-stack.ts    From minwiz with BSD 2-Clause "Simplified" License 6 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    this.hostedZone = HostedZone.fromHostedZoneAttributes(
      this,
      "HostedZoneWithAttrs",
      {
        hostedZoneId,
        zoneName: website_domain,
      }
    );

    this.websiteCert = new DnsValidatedCertificate(this, "MinWizSSL", {
      domainName: website_domain,
      subjectAlternativeNames: [`www.${website_domain}`],
      hostedZone: this.hostedZone,
    });

    new CfnOutput(this, "WebsiteCertArn", {
      value: this.websiteCert.certificateArn,
    });
  }
Example #3
Source File: url-shortener.integ.ts    From cloudstructs with Apache License 2.0 6 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const userPool = new cognito.UserPool(this, 'UserPool', {
      removalPolicy: RemovalPolicy.DESTROY,
    });

    const urlShortener = new UrlShortener(this, 'UrlShortener', {
      hostedZone: route53.HostedZone.fromHostedZoneAttributes(this, 'HostedZone', {
        hostedZoneId: 'ZKEU89CLZS8GH',
        zoneName: 'goldex.be',
      }),
      recordName: 'short',
      apiGatewayAuthorizer: new apigateway.CognitoUserPoolsAuthorizer(this, 'Authorizer', {
        cognitoUserPools: [userPool],
      }),
      corsAllowOrigins: ['*'],
    });

    const bucket = urlShortener.node.tryFindChild('Bucket') as s3.Bucket;
    bucket.applyRemovalPolicy(RemovalPolicy.DESTROY);

    new CfnOutput(this, 'ApiEndpoint', { value: urlShortener.apiEndpoint });
  }
Example #4
Source File: slack-app.integ.ts    From cloudstructs with Apache License 2.0 6 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const app = new SlackApp(this, 'MyApp', {
      configurationTokenSecret: secretsmanager.Secret.fromSecretNameV2(this, 'Secret', 'slack-app-config-token'),
      manifest: SlackAppManifestDefinition.fromManifest({
        name: 'My App',
        description: 'A very cool Slack App deployed with CDK',
      }),
    });

    new CfnOutput(this, 'AppId', {
      value: app.appId,
    });
  }
Example #5
Source File: ts-lambda-stack.ts    From cdk-examples with MIT License 6 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    new NodejsFunction(this, 'helloWorldFn', {
      runtime: Runtime.NODEJS_16_X,
      entry: `${__dirname}/../lambda-fns/hello-world/index.ts`,
      handler: 'myFunction',
      memorySize: 128,
      architecture: Architecture.ARM_64,
      bundling: {
        minify: true,
        // tsconfig: `${__dirname}/../lambda-fns/hello-world/tsconfig.json` // if you want to override defaults
      }
    })
  }
Example #6
Source File: lambda-local-stack.ts    From cdk-examples with MIT License 6 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    const oneFn = new Function(this, 'oneFn', {
      runtime: Runtime.NODEJS_16_X,
      code: Code.fromAsset(`${__dirname}/../lambda-fns/one/deployment.zip`),
      handler: 'index.handler'
    })
  }
Example #7
Source File: certificate.ts    From cdk-examples with MIT License 6 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    ///////////////////////////////
    // Part 1
    const hostedZone = HostedZone.fromHostedZoneAttributes(this, 'HostedZoneWithAttrs', {
        hostedZoneId,
        zoneName: website_domain
    })

    const websiteCert = new DnsValidatedCertificate(this, 'WebsiteSSL', {
        domainName: website_domain,
        hostedZone
    })

    new CfnOutput(this, 'WebsiteCertArn', {
        value: websiteCert.certificateArn
    })
    ///////////////////////////////
  }
Example #8
Source File: https-redirect-stack.ts    From cdk-examples with MIT License 6 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    const hostedZone = HostedZone.fromHostedZoneAttributes(this, 'HostedZoneWithAttrs', {
      hostedZoneId: 'myZoneId',
      zoneName: 'example.com'
    })

    new HttpsRedirect(this, 'wwwToNonWww', {
      recordNames: ['www.example.com'],
      targetDomain: 'example.com',
      zone: hostedZone
    })
  }
Example #9
Source File: code-pipeline.ts    From cdk-examples with MIT License 5 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    ///////////////////////////////
    // Part 7
    const websiteBucket = Bucket.fromBucketArn(this, 'websiteBucket', websiteBucketArn)

    const hugoBuildProject = new PipelineProject(this, 'hugoBuild', {
        buildSpec: BuildSpec.fromSourceFilename('buildspec.yml'),
        environment: {
            buildImage: LinuxBuildImage.STANDARD_5_0,
            computeType: ComputeType.SMALL
        }
    })

    const artifactBucket = new Bucket(this, 'websitePipelineArtifactBucket', {
        bucketName: 'hugo-pipeline-artifact-bucket',
        removalPolicy: RemovalPolicy.DESTROY
    })

    const gitOutput = new Artifact('hugoRepoLatestMaster')

    const buildOutput = new Artifact('hugoBuildOutput')

    new Pipeline(this, 'hugoPipeline', {
        artifactBucket,
        pipelineName: 'examplePipeline',
        stages: [
            {
                stageName: 'SourceCode',
                actions: [
                    new CodeCommitSourceAction({
                        actionName: 'readLatestMasterCommit',
                        branch: 'main',
                        output: gitOutput,
                        repository: Repository.fromRepositoryArn(this, 'hugoGitRepo', hugoRepoArn)
                    })
                ]
            },
            {
                stageName: 'Build',
                actions: [
                    new CodeBuildAction({
                        actionName: 'buildHugoWebsite',
                        input: gitOutput,
                        outputs: [buildOutput],
                        project: hugoBuildProject
                    })
                ]
            },
            {
                stageName: 'Deploy',
                actions: [
                    new S3DeployAction({
                        actionName: 'DeployHugoWebsite',
                        input: buildOutput,
                        bucket: websiteBucket
                    })
                ]
            }
        ]
    })
    ///////////////////////////////
  }
Example #10
Source File: cloudfront-http-api-stack.ts    From cdk-examples with MIT License 5 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here
    ///////////////////////////////
    // Part 1
    const hostedZone = HostedZone.fromHostedZoneAttributes(this, 'hostedZoneWithAttributes', {
        hostedZoneId,
        zoneName: website_domain
    })
  
    const certificate = new DnsValidatedCertificate(this, 'ApiSSL', {
        domainName: website_domain,
        hostedZone
    })

    const api = new HttpApi(this, 'apiEndpoint', {
        apiName: 'exampleAPISameDomain',
    })
    
    new CfnOutput(this, 'apiID', {
        value: api.apiEndpoint
    })
    
    const signUpFn = new Function(this, 'signUpFn', {
        runtime: Runtime.NODEJS_16_X,
        code: Code.fromAsset(`${__dirname}/../lambda-fns/sign-up/deployment.zip`),
        handler: 'index.handler',
        memorySize: 512,
        architecture: Architecture.ARM_64
    })
    ///////////////////////////////
    
    ///////////////////////////////
    // Part 2
    api.addRoutes({
        path: '/api/sign-up',
        methods: [HttpMethod.POST],
        integration: new HttpLambdaIntegration('signUpFn', signUpFn)
    })
    
    const apiOriginPolicy = new OriginRequestPolicy(this, 'apiOriginPolicy', {
        cookieBehavior: OriginRequestCookieBehavior.all(),
        headerBehavior: OriginRequestHeaderBehavior.none(),
        queryStringBehavior: OriginRequestQueryStringBehavior.all()
    })
    
    const distribution = new Distribution(this, 'websiteAndAPIDistribution', {
        defaultBehavior: {
            origin: new HttpOrigin('origin-source-code.com'),
        },
        additionalBehaviors: {
            'api/*': {
                origin: new HttpOrigin(api.apiEndpoint.replace('https://', '')),
                allowedMethods: AllowedMethods.ALLOW_ALL,
                cachePolicy: CachePolicy.CACHING_DISABLED,
                compress: false,
                originRequestPolicy: apiOriginPolicy,
                viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS
            }
        },
        domainNames: [website_domain],
        certificate,
        minimumProtocolVersion: SecurityPolicyProtocol.TLS_V1_2_2021,
        enableIpv6: true,
        enabled: true,
        httpVersion: HttpVersion.HTTP2,
        priceClass: PriceClass.PRICE_CLASS_ALL
    })
    ///////////////////////////////

    ///////////////////////////////
    // Part 3
    new ARecord(this, 'AliasForCloudfront', {
        target: RecordTarget.fromAlias(new CloudFrontTarget(distribution)),
        zone: hostedZone,
        recordName: website_domain
    })
    ///////////////////////////////
  }
Example #11
Source File: toolkit-cleaner.integ.ts    From cloudstructs with Apache License 2.0 5 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    new ToolkitCleaner(this, 'ToolkitCleaner', {
      dryRun: true,
      retainAssetsNewerThan: Duration.days(90),
    });
  }
Example #12
Source File: http-api-stack.ts    From cdk-examples with MIT License 5 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    ///////////////////////////////
    // Part 1
    const hostedZone = HostedZone.fromHostedZoneAttributes(this, 'hostedZoneWithAttributes', {
      hostedZoneId,
      zoneName: website_domain
    })

    const apiCert = new DnsValidatedCertificate(this, 'ApiSSL', {
      domainName: api_domain,
      hostedZone
    })
    ///////////////////////////////

    ///////////////////////////////
    // Part 2
    const domain = new DomainName(this, 'api_domain', {
      domainName: api_domain,
      certificate: apiCert
    })

    const api = new HttpApi(this, 'apiEndpoint', {
      defaultDomainMapping: {
        domainName: domain
      },
      corsPreflight: {
        allowCredentials: true,
        allowHeaders: ['Content-Type'],
        allowMethods: [CorsHttpMethod.GET, CorsHttpMethod.POST, CorsHttpMethod.PUT, CorsHttpMethod.DELETE],
        allowOrigins: [
          'https://example.com'
        ]
      },
      apiName: 'exampleAPI',
      disableExecuteApiEndpoint: true
    })

    new CfnOutput(this, 'apiID', {
      value: api.httpApiId
    })

    const signUpFn = new Function(this, 'signUpFn', {
      runtime: Runtime.NODEJS_16_X,
      code: Code.fromAsset(`${__dirname}/../lambda-fns/sign-up/deployment.zip`),
      handler: 'index.handler',
      architecture: Architecture.ARM_64,
      memorySize: 512
    })
    ///////////////////////////////

    // const existingAPI = HttpApi.fromHttpApiAttributes(this, 'existingAPI', {
    //   apiEndpoint: api_domain,
    //   httpApiId: 'myApiId'
    // })
    
    ///////////////////////////////
    // Part 3
    new ARecord(this, 'apiAliasRecord', {
      zone: hostedZone,
      target: RecordTarget.fromAlias(new ApiGatewayv2DomainProperties(domain.regionalDomainName, domain.regionalHostedZoneId))
    })

    api.addRoutes({
      path: '/sign-up',
      methods: [HttpMethod.POST],
      integration: new HttpLambdaIntegration('signUpFn', signUpFn)
    })
    ///////////////////////////////
  }
Example #13
Source File: aws-image-builder-stack.ts    From amazon-ec2-image-builder-samples with MIT No Attribution 5 votes vote down vote up
constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    /**
     * S3 Bucket
     * Hosts the Image builder Installation files code.
     */
    this.imageBuilderToolsBucket = new AWSSecureBucket(
      this,
      "toolsBucket",
      {}
    ).bucket;

    const vpc = Vpc.fromLookup(this, "vpc", {
      isDefault: true,
    });

    /**
     * S3 Deploy
     * Uploads react built code to the S3 bucket and invalidates CloudFront
     */

    new BucketDeployment(this, "Deploy-components", {
      sources: [Source.asset("./image-builder-components")],
      destinationBucket: this.imageBuilderToolsBucket,
      memoryLimit: 3008,
      prune: false,
    });

    // ? Create a SG for a Image builder server
    const imageBuilderSG = new SecurityGroup(this, "image-server-sg", {
      vpc: vpc,
      allowAllOutbound: true,
      description: "security group for a image builder server",
    });
    // Choose the subnet Image builder server - ensure it has internet
    const imageBuilderSubnetId = vpc.selectSubnets({
      subnetType: SubnetType.PUBLIC,
    }).subnetIds[0];

    const imageBuilderPipelineConfigurations =
      this.validAndGetPipelineConfiguration();
    if (!imageBuilderPipelineConfigurations) {
      return;
    }

    for (const imageBuilderPipeline of imageBuilderPipelineConfigurations) {
      this.createImageBuilderByConfig(
        imageBuilderPipeline,
        imageBuilderSubnetId,
        imageBuilderSG,
        vpc
      );
    }
  }
Example #14
Source File: s3cloudfront.ts    From cdk-examples with MIT License 5 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    ///////////////////////////////
    // Part 2
    const bucket = new Bucket(this, 'websiteBucket', {
        removalPolicy: RemovalPolicy.DESTROY,
        bucketName: website_domain,
        autoDeleteObjects: true
    })
    
    new CfnOutput(this, 'websiteBucketArn', {
        value: bucket.bucketArn
    })
    ///////////////////////////////

    ///////////////////////////////
    // Part 3
    const certificate = Certificate.fromCertificateArn(this, 'websiteCert', websiteCertArn)
    
    const cachePolicy = new CachePolicy(this, 'examplePolicy', {
        defaultTtl: Duration.hours(24),
        minTtl: Duration.hours(24),
        maxTtl: Duration.hours(24),
        enableAcceptEncodingGzip: true,
        enableAcceptEncodingBrotli: true
    })

    const distribution = new Distribution(this, 'exampleDistribution', {
        defaultBehavior: {
            origin: new S3Origin(bucket),
            allowedMethods: AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
            cachePolicy,
            compress: true,
            viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS
        },
        domainNames: [website_domain],
        certificate,
        minimumProtocolVersion: SecurityPolicyProtocol.TLS_V1_2_2021,
        defaultRootObject: 'index.html',
        enableIpv6: true,
        enabled: true,
        httpVersion: HttpVersion.HTTP2,
        priceClass: PriceClass.PRICE_CLASS_ALL
    })
    ///////////////////////////////

    ///////////////////////////////
    // Part 4
    const hostedZone = HostedZone.fromHostedZoneAttributes(this, 'hostedZoneWithAttrs', {
        hostedZoneId,
        zoneName: website_domain
    })
    
    new ARecord(this, 'aliasForCloudfront', {
        target: RecordTarget.fromAlias(new CloudFrontTarget(distribution)),
        zone: hostedZone,
        recordName: website_domain
    })
    ///////////////////////////////

    ///////////////////////////////
    // Part 5
    new HttpsRedirect(this, 'wwwToNonWww', {
        recordNames: ['www.example.com'],
        targetDomain: website_domain,
        zone:hostedZone
    })

    const repo = new Repository(this, 'reactSourceCode', {
        repositoryName: 'example',
        description: `react repo for ${website_domain}`
    })

    new CfnOutput(this, 'reactRepoArn', {
        value: repo.repositoryArn
    })
    ///////////////////////////////
  }
Example #15
Source File: code-pipeline.ts    From cdk-examples with MIT License 5 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    ///////////////////////////////
    // Part 7
    const websiteBucket = Bucket.fromBucketArn(this, 'websiteBucket', websiteBucketArn)

    const reactBuildProject = new PipelineProject(this, 'reactBuild', {
        buildSpec: BuildSpec.fromSourceFilename('buildspec.yml'),
        environment: {
            buildImage: LinuxBuildImage.STANDARD_5_0,
            computeType: ComputeType.SMALL
        }
    })

    const artifactBucket = new Bucket(this, 'reactPipelineArtifactBucket', {
        bucketName: 'react-pipeline-artifact-bucket',
        removalPolicy: RemovalPolicy.DESTROY
    })

    const gitOutput = new Artifact('reactRepoLatestMaster')

    const buildOutput = new Artifact('reactBuildOutput')

    new Pipeline(this, 'reactPipeline', {
        artifactBucket,
        pipelineName: 'examplePipeline',
        stages: [
            {
                stageName: 'SourceCode',
                actions: [
                    new CodeCommitSourceAction({
                        actionName: 'readLatestMasterCommit',
                        branch: 'main',
                        output: gitOutput,
                        repository: Repository.fromRepositoryArn(this, 'reactGitRepo', reactRepoArn)
                    })
                ]
            },
            {
                stageName: 'Build',
                actions: [
                    new CodeBuildAction({
                        actionName: 'buildReactApp',
                        input: gitOutput,
                        outputs: [buildOutput],
                        project: reactBuildProject
                    })
                ]
            },
            {
                stageName: 'Deploy',
                actions: [
                    new S3DeployAction({
                        actionName: 'DeployReactApp',
                        input: buildOutput,
                        bucket: websiteBucket
                    })
                ]
            }
        ]
    })
    ///////////////////////////////
  }
Example #16
Source File: witout-load-balancer.ts    From cdk-examples with MIT License 5 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    const vpc = new Vpc(this, 'fargateVpc', {
        maxAzs: 2
      })
  
      const securityGroup = new SecurityGroup(this, 'fargateSecurity', {
        vpc,
        securityGroupName: 'fargateSecurity'
      })
  
      securityGroup.addIngressRule(Peer.anyIpv4(), Port.tcp(80))
  
      const cluster = new Cluster(this, 'nextJSCluster', {
        clusterName: 'exampleCluster',
        containerInsights: true,
        vpc
      })
  
      const taskDefinition = new FargateTaskDefinition(this, 'nextJSTaskDefinition', {
        memoryLimitMiB: 512,
        cpu: 256
      })
  
      const container = taskDefinition.addContainer('nextJSContainer', {
        image: ContainerImage.fromRegistry('public.ecr.aws/abc123xyz/next:prod-v1'),
      })
  
      container.addPortMappings({
        containerPort: 80,
        hostPort: 80
      })
      
      new FargateService(this, 'NextJSService', {
        taskDefinition,
        cluster,
        desiredCount: 1,
        serviceName: 'exampleService',
        assignPublicIp: true,
        securityGroups:[securityGroup]
      })
  }
Example #17
Source File: backend-infra-stack.ts    From cdk-examples with MIT License 5 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here
  }
Example #18
Source File: lambda-layers-stack.ts    From cdk-examples with MIT License 5 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    const layer = new LayerVersion(this, 'uuidLayer', {
      code: Code.fromAsset(`${__dirname}/../lambda-fns/layer/deployment.zip`),
      compatibleRuntimes: [ Runtime.NODEJS_16_X],
      compatibleArchitectures: [Architecture.ARM_64],
      description: 'uuid package and discount for product'
    })

    layer.addPermission('layerPermission', {
      accountId: account
    })

    new CfnOutput(this, 'layerVersionArn', {
      value: layer.layerVersionArn
    })

    const latestLayer = LayerVersion.fromLayerVersionAttributes(this, 'latestLayer', {
      compatibleRuntimes: [Runtime.NODEJS_16_X],
      layerVersionArn
    })

    new Function(this, 'oneFn', { 
      runtime: Runtime.NODEJS_16_X,
      code: Code.fromAsset(`${__dirname}/../lambda-fns/one/deployment.zip`),
      handler: 'index.handler',
      architecture: Architecture.ARM_64,
      layers: [latestLayer]
    })

    new Function(this, 'twoFn', { 
      runtime: Runtime.NODEJS_16_X,
      code: Code.fromAsset(`${__dirname}/../lambda-fns/two/deployment.zip`),
      handler: 'index.handler',
      architecture: Architecture.ARM_64,
      layers: [latestLayer]
    })
  }
Example #19
Source File: lambda-cost-stack.ts    From cdk-examples with MIT License 5 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here
    const powerValues = '128,256,512,1024,2048'

    new CfnApplication(this, 'powerTuner', {
      location: {
          applicationId: 'arn:aws:serverlessrepo:us-east-1:451282441545:applications/aws-lambda-power-tuning',
          semanticVersion: '4.2.0'
      },
      parameters: {
          "lambdaResource": "*",
          "PowerValues": powerValues
      },
      timeoutInMinutes: 15
    })

    const todoTable = new Table(this, 'todoTable', {
      partitionKey: {
        name: 'id',
        type: AttributeType.STRING
      },
      billingMode: BillingMode.PAY_PER_REQUEST,
      removalPolicy: RemovalPolicy.DESTROY
    })
    
    new CfnOutput(this, 'todoTableName', {
      value: todoTable.tableName
    })

    const getTodoFn = new NodejsFunction(this, 'getTodoFn', {
      runtime: Runtime.NODEJS_16_X,
      entry: `${__dirname}/../lambda-fns/get-todo/index.ts`,
      handler: 'getTodo',
      architecture: Architecture.ARM_64,
      environment: {
        TODO_TABLE_NAME: todoTableName
      }
    })

    todoTable.grantReadData(getTodoFn)

    const createTodoFn = new NodejsFunction(this, 'createTodoFn', {
      runtime: Runtime.NODEJS_16_X,
      entry: `${__dirname}/../lambda-fns/create-todo/index.ts`,
      handler: 'createTodo',
      architecture: Architecture.ARM_64,
      environment: {
        TODO_TABLE_NAME: todoTableName
      }
    })

    todoTable.grantReadWriteData(createTodoFn)

    const deleteTodoFn = new NodejsFunction(this, 'deleteTodoFn', {
      runtime: Runtime.NODEJS_16_X,
      entry: `${__dirname}/../lambda-fns/delete-todo/index.ts`,
      handler: 'deleteTodo',
      architecture: Architecture.ARM_64,
      environment: {
        TODO_TABLE_NAME: todoTableName
      }
    })

    todoTable.grantReadWriteData(deleteTodoFn)
  }
Example #20
Source File: password-protect-s3-static-site-stack.ts    From cdk-examples with MIT License 4 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here
    ///////////////////////////////
    // Part 1
    const hostedZone = HostedZone.fromHostedZoneAttributes(this, 'HostedZoneWithAttr', {
      hostedZoneId: hostedZoneId,
      zoneName: website_domain
    })
    
    const previewCert = new DnsValidatedCertificate(this, 'previewSSL', {
      domainName: preview_domain,
      hostedZone
    })
    
    const previewBucket = new Bucket(this, 'previewBucket', {
      removalPolicy: RemovalPolicy.DESTROY,
      bucketName: preview_domain,
      autoDeleteObjects: true,
      websiteIndexDocument: 'index.html',
      websiteErrorDocument: '404.html'
    })

    new CfnOutput(this, 'previewBucketWebsiteUrl', {
      value: previewBucket.bucketWebsiteUrl
    })
    ///////////////////////////////
    
    ///////////////////////////////
    // Part 2
    previewBucket.addToResourcePolicy(new PolicyStatement({
      sid: 'allow request from cloudfront to s3 website',
      effect: Effect.ALLOW,
      principals: [new AnyPrincipal()],
      actions: ['s3:GetObject'],
      resources: [`${previewBucket.bucketArn}/*`],
      conditions: {
        "StringLike": {
          "aws:Referer": [previewSecret]
        }
      }
    }))

    const previewCachePolicy = new CachePolicy(this, 'previewCachePolicy', {
      defaultTtl: Duration.minutes(30),
      minTtl: Duration.minutes(25),
      maxTtl: Duration.minutes(35),
      enableAcceptEncodingBrotli: true,
      enableAcceptEncodingGzip: true,
      headerBehavior: CacheHeaderBehavior.allowList('authorization')
    })

    const edgeAuth = new experimental.EdgeFunction(this, 'edgeAuthFn', {
      runtime: Runtime.NODEJS_14_X,
      handler: 'index.handler',
      code: Code.fromAsset(`${__dirname}/../lambda-fns/basic-auth/deployment.zip`),
      memorySize: 128
    })
    ///////////////////////////////
    
    ///////////////////////////////
    // Part 3
    const previewDistribution = new Distribution(this, 'previewDistribution', {
      defaultBehavior: {
        origin: new HttpOrigin(previewBucketWebsiteUrl, {
          protocolPolicy: OriginProtocolPolicy.HTTP_ONLY,
          customHeaders: {
            'Referer': previewSecret
          }
        }),
        edgeLambdas: [{
          functionVersion: edgeAuth.currentVersion,
          eventType: LambdaEdgeEventType.VIEWER_REQUEST
        }],
        allowedMethods: AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
        cachePolicy: previewCachePolicy,
        compress: true,
        viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS
      },
      domainNames: [preview_domain],
      certificate: previewCert,
      minimumProtocolVersion: SecurityPolicyProtocol.TLS_V1_2_2021,
      httpVersion: HttpVersion.HTTP2,
      priceClass: PriceClass.PRICE_CLASS_ALL
    })
    ///////////////////////////////

    ///////////////////////////////
    // Part 4
    new ARecord(this, 'aliasForPreview', {
      target: RecordTarget.fromAlias(new CloudFrontTarget(previewDistribution)),
      zone: hostedZone,
      recordName: preview_domain
    })
    ///////////////////////////////

  }
Example #21
Source File: backend-infra-stack.ts    From cdk-examples with MIT License 4 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    const ecrRepo = new Repository(this, 'nextJSRepo', {
      repositoryName: 'next-starter',
      removalPolicy: RemovalPolicy.DESTROY,
      imageScanOnPush: true,
      lifecycleRules: [
        {
          tagPrefixList: ['prod'],
          maxImageCount: 5
        },
        {
          maxImageAge: Duration.days(30)
        }
      ]
    })

    new CfnOutput(this, 'repoUrl', {
      value: ecrRepo.repositoryUri
    })

    const vpc = new Vpc(this, 'fargateVpc', {
      maxAzs: 2
    })

    const cluster = new Cluster(this, 'fargateCluster', {
      clusterName: 'fargateCluster',
      containerInsights: true,
      vpc
    })

    const domainZone = HostedZone.fromHostedZoneAttributes(this, 'hostedZoneWithAttributes', {
      zoneName: website_domain,
      hostedZoneId
    })

    const fargateService = new ApplicationLoadBalancedFargateService(this, 'fargateService', {
      cluster,
      assignPublicIp: true,
      cpu: 256,
      desiredCount: 1,
      memoryLimitMiB: 512,
      redirectHTTP: true,
      protocol: ApplicationProtocol.HTTPS,
      deploymentController: {
        type: DeploymentControllerType.ECS
      }, 
      domainName: website_domain,
      domainZone,
      taskImageOptions: {
        // image from docker hub
        // image: ContainerImage.fromRegistry('apoorvmote/next:prod-v1'),
        // image from public ecr registry
        // image: ContainerImage.fromRegistry('public.ecr.aws/abc123xyz/next:prod-v1'),
        // image from private ecr registry
        image: ContainerImage.fromEcrRepository(ecrRepo, 'prod-v1'),
      }
    })

    const scalableTarget = fargateService.service.autoScaleTaskCount({
      minCapacity: 1,
      maxCapacity: 20
    })

    scalableTarget.scaleOnCpuUtilization('cpuScaling', {
      targetUtilizationPercent: 70
    })

    new HttpsRedirect(this, 'wwwToNonWww', {
      recordNames: ['www.example.com'],
      targetDomain: website_domain,
      zone: domainZone
    })

    const nextRepo = new codecommit.Repository(this, 'nextJSSourceCode', {
      repositoryName: 'next-blog',
      description: 'Pipeline source code'
    })

    new CfnOutput(this, 'sourceCodeUrl', {
      value: nextRepo.repositoryCloneUrlSsh
    })

    const containerBuildProject = new PipelineProject(this, 'containerBuild', {
      buildSpec: BuildSpec.fromSourceFilename('buildspec.yml'),
      environment: {
        buildImage: LinuxBuildImage.STANDARD_5_0,
        computeType: ComputeType.SMALL,
        privileged: true
      },
      environmentVariables: {
        'docker_username': {
          value: dockerUsername
        },
        'docker_password': {
          value: dockerPassword
        }
      }
    })

    ecrRepo.grantPullPush(containerBuildProject.grantPrincipal)

    const artifactBucket = new Bucket(this, 'containerBuildArtifactBucket', {
      bucketName: 'example-pipeline-artifact',
      removalPolicy: RemovalPolicy.DESTROY
    })

    const gitOutput = new Artifact('nextJSLatestMaster')

    const buildOutput = new Artifact('ContainerBuildOutput')

    new Pipeline(this, 'containerPipeline', {
      artifactBucket,
      pipelineName: 'examplePipeline',
      stages: [
        {
          stageName: 'SourceCode',
          actions: [
            new CodeCommitSourceAction({
              actionName: 'readCode',
              output: gitOutput,
              repository: nextRepo,
              branch: 'main'
            })
          ]
        },
        {
          stageName: 'build',
          actions: [
            new CodeBuildAction({
              actionName: 'buildContainer',
              input: gitOutput,
              outputs: [buildOutput],
              project: containerBuildProject
            })
          ]
        },
        {
          stageName: 'deploy',
          actions: [
            new EcsDeployAction({
              actionName: 'deployContainer',
              service: fargateService.service,
              input: buildOutput,
              deploymentTimeout: Duration.minutes(30)
            })
          ]
        }
      ]
    })
  }
Example #22
Source File: s3cloudfront.ts    From cdk-examples with MIT License 4 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    ///////////////////////////////
    // Part 2
    const bucket = new Bucket(this, 'websiteBucket', {
        removalPolicy: RemovalPolicy.DESTROY,
        bucketName: website_domain,
        autoDeleteObjects: true,
        websiteIndexDocument: 'index.html',
        websiteErrorDocument: '404.html'
    })
    
    bucket.addToResourcePolicy(new PolicyStatement({
        effect: Effect.ALLOW,
        principals: [new AnyPrincipal()],
        actions: ['s3:GetObject'],
        resources: ['arn:aws:s3:::example.com/*'],
        conditions: {
            "StringLike":{"aws:Referer":[bucketRefererSecret]}
          }
    }))

    new CfnOutput(this, 'websiteBucketArn', {
        value: bucket.bucketArn
    })

    new CfnOutput(this, 'websiteBucketUrl', {
        value: bucket.bucketWebsiteUrl
    })
    ///////////////////////////////

    ///////////////////////////////
    // Part 3
    const certificate = Certificate.fromCertificateArn(this, 'websiteCert', websiteCertArn)
    
    const cachePolicy = new CachePolicy(this, 'examplePolicy', {
        defaultTtl: Duration.hours(24),
        minTtl: Duration.hours(24),
        maxTtl: Duration.hours(24),
        enableAcceptEncodingBrotli: true,
        enableAcceptEncodingGzip: true
    })

    const distribution = new Distribution(this, 'exampleDistribution', {
        defaultBehavior: {
            origin: new HttpOrigin(bucketWebsiteUrl, {
                protocolPolicy: OriginProtocolPolicy.HTTP_ONLY,
                customHeaders: {
                    'Referer': bucketRefererSecret
                }
            }),
            allowedMethods: AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
            cachePolicy,
            compress: true,
            viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS
        },
        domainNames: [website_domain],
        certificate,
        minimumProtocolVersion: SecurityPolicyProtocol.TLS_V1_2_2021,
        enableIpv6: true,
        enabled: true,
        httpVersion: HttpVersion.HTTP2,
        priceClass: PriceClass.PRICE_CLASS_ALL
    })
    ///////////////////////////////

    ///////////////////////////////
    // Part 4
    const hostedZone = HostedZone.fromHostedZoneAttributes(this, 'hostedZoneWithAttrs', {
        hostedZoneId,
        zoneName: website_domain
    })
    
    new ARecord(this, 'aliasForCloudfront', {
        target: RecordTarget.fromAlias(new CloudFrontTarget(distribution)),
        zone: hostedZone,
        recordName: website_domain
    })
    ///////////////////////////////

    ///////////////////////////////
    // Part 5
    new HttpsRedirect(this, 'wwwToNonWww', {
        recordNames: ['www.example.com'],
        targetDomain: website_domain,
        zone:hostedZone
    })

    const repo = new Repository(this, 'hugoSourceCode', {
        repositoryName: 'example',
        description: `hugo repo for ${website_domain}`
    })

    new CfnOutput(this, 'hugoRepoArn', {
        value: repo.repositoryArn
    })
    ///////////////////////////////
  }
Example #23
Source File: test-stack.ts    From cdk-ssm-document with Apache License 2.0 4 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    let file = path.join(
      __dirname,
      '../documents/command/hello-world-yaml.yml'
    );
    const docA = new Document(this, 'SSM-Document-HelloWorld-Yaml', {
      name: `${this.stackName}-HelloWorld-from-yaml-file`,
      content: fs.readFileSync(file).toString(),
    });

    file = path.join(__dirname, '../documents/command/hello-world-json.json');
    const docB = new Document(this, 'SSM-Document-HelloWorld-Json', {
      name: `${this.stackName}-HelloWorld-from-json-file`,
      content: fs.readFileSync(file).toString(),
    });

    file = path.join(
      __dirname,
      '../documents/automation/automation-document.yml'
    );
    const docC = new Document(this, `SSM-Document-Automation`, {
      documentType: 'Automation',
      name: 'Test-Automation',
      content: fs.readFileSync(file).toString(),
    });

    const docD = new Document(this, 'SSM-Document-HelloWorld-Inline', {
      name: `${this.stackName}-HelloWorld-from-inline`,
      content: {
        schemaVersion: '2.2',
        description: 'Echo Hello World!',
        parameters: {
          text: {
            default: 'Hello World!',
            description: 'Text to echo',
            type: 'String',
          },
        },
        mainSteps: [
          {
            name: 'echo',
            action: 'aws:runShellScript',
            inputs: {
              runCommand: ['echo "{{text}}"'],
            },
            precondition: {
              StringEquals: ['platformType', 'Linux'],
            },
          },
        ],
      },
    });

    /**
     * Distributor example.
     *
     * Requires a bucket to hold install/update/uninstall scripts.
     */
    const bucketName = `${Stack.of(this).account}-cdk-ssm-document-storage`;
    const bucket = new aws_s3.Bucket(this, 'DistributorPackages', {
      bucketName: bucketName,
      blockPublicAccess: aws_s3.BlockPublicAccess.BLOCK_ALL,
      enforceSSL: true,
      encryption: aws_s3.BucketEncryption.KMS_MANAGED,
      // Makes for easy destroy and rerun of this stack over and over.
      removalPolicy: RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });
    const packageDeploy = new aws_s3_deployment.BucketDeployment(
      this,
      'distribution-packages',
      {
        sources: [
          aws_s3_deployment.Source.asset('../test/documents/distributor'),
        ],
        destinationBucket: bucket,
      }
    );

    let attachments: { [key: string]: any } = {};
    // flip this condition to test an attachment update
    if (true) {
      file = path.join(__dirname, '../documents/distributor/v1/manifest.json');
      attachments = {
        versionName: '1.0-Custom-Name',
        attachments: [{ key: 'SourceUrl', values: [`s3://${bucketName}/v1`] }],
      };
    } else {
      file = path.join(__dirname, '../documents/distributor/v2/manifest.json');
      attachments = {
        versionName: '2.0-Better-Than_Sliced_Bread',
        attachments: [{ key: 'SourceUrl', values: [`s3://${bucketName}/v2`] }],
      };
    }

    const docE = new Document(this, `SSM-Distribution-Package`, {
      documentType: 'Package',
      name: 'Test-Distribution-Package',
      content: fs.readFileSync(file).toString(),
      ...attachments,
    });

    /**
     * The owner/creator of the document must have read access to the
     * s3 files that make up a distribution. Since that is the lambda in this
     * case we must give it `GetObject` permissions before they will can become
     * `Active`.
     */
    docE.lambda.role?.addToPrincipalPolicy(
      new aws_iam.PolicyStatement({
        actions: ['s3:GetObject'],
        resources: [`${bucket.arnForObjects('*')}`],
      })
    );

    docE.node.addDependency(docD);
    docE.node.addDependency(packageDeploy);
    docD.node.addDependency(docC);
    docC.node.addDependency(docB);
    docB.node.addDependency(docA);

    const dir = path.join(__dirname, '../documents/command');
    const files = fs.readdirSync(dir);

    var last: Document | undefined = undefined;
    for (const i in files) {
      const name = files[i];
      const shortName = name.split('.').slice(0, -1).join('.'); // removes file extension
      const file = `${dir}/${name}`;

      const doc = new Document(this, `SSM-Document-Loop-${shortName}`, {
        name: `${this.stackName}-${shortName}`,
        content: fs.readFileSync(file).toString(),
      });
      if (typeof last !== 'undefined') {
        last.node.addDependency(doc);
      }
      last = doc;
    }
  }
Example #24
Source File: backend2-stack.ts    From flect-chime-sdk-demo with Apache License 2.0 4 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // (1) UserPool
    const { userPool, userPoolClient } = createUserPool(this, id)

    // (2) S3
    const { frontendBucket, frontendCdn } = createFrontendS3(this, id, USE_CDN)

    // (3) DynamoDB
    const { meetingTable } = createMeetingTable(this, id)
    const { attendeeTable } = createAttendeeTable(this, id)
    const { connectionTable } = createConnectionTable(this, id)
    const { slackFederationAuthsTable } = createSlackFederationAuthsTable(this, id)

    // (4) IAM
    const { restApiPolicyStatement } = createRestApiPolicyStatement(userPool.userPoolArn)

    // (5) Lambda
    //// (5-1) Layer
    const { nodeModulesLayer } = createNodeModulesLayer(this, id)
    //// (5-2) Lambda
    const { lambdaFuncRestAPIAuth, lambdaFunctionForRestAPI, lambdaFunctionForSlackFederationRestAPI } = createLambdas(this);
    //// (5-3) Lambda For Websocket
    const { lambdaFuncMessageConnect, lambdaFuncMessageDisconnect, lambdaFuncMessageMessage, lambdaFuncMessageAuth } = createLambdaForWebsocket(this)
    //// (5-4) Configure
    const configureFunctions = (func: lambda.Function) => {
      // (a-1) Table Access
      [meetingTable, attendeeTable, connectionTable, slackFederationAuthsTable].forEach(table => {
        table.grantFullAccess(func)
      })
      // (a-2) Policy
      func.addToRolePolicy(restApiPolicyStatement);
      // (a-3) Environment
      func.addEnvironment("MEETING_TABLE_NAME", meetingTable.tableName);
      func.addEnvironment("ATTENDEE_TABLE_NAME", attendeeTable.tableName);
      func.addEnvironment("CONNECTION_TABLE_NAME", connectionTable.tableName);
      func.addEnvironment("SLACK_FEDERATION_AUTHS_TABLE_NAME", slackFederationAuthsTable.tableName);

      func.addEnvironment("USER_POOL_ID", userPool.userPoolId);
      func.addEnvironment("BUCKET_DOMAIN_NAME", frontendBucket.bucketDomainName);
      func.addEnvironment("BUCKET_ARN", frontendBucket.bucketArn);
      func.addEnvironment("BUCKET_NAME", frontendBucket.bucketName);

      func.addEnvironment("USERPOOL_ID", userPool.userPoolId);
      func.addEnvironment("USERPOOL_CLIENT_ID", userPoolClient.userPoolClientId);

      //// Slack-Chime Connector (slack access)
      func.addEnvironment("SLACK_CLIENT_ID", SLACK_CLIENT_ID);
      func.addEnvironment("SLACK_CLIENT_SECRET", SLACK_CLIENT_SECRET);
      func.addEnvironment("SLACK_SIGNING_SECRET", SLACK_SIGNING_SECRET);
      func.addEnvironment("SLACK_STATE_SECRET", SLACK_STATE_SECRET);
      //// Slack-Chime Connector (db access)
      func.addEnvironment("SLACK_APP_DB_PASSWORD", SLACK_APP_DB_PASSWORD);
      func.addEnvironment("SLACK_APP_DB_SALT", SLACK_APP_DB_SALT);
      func.addEnvironment("SLACK_APP_DB_SECRET", SLACK_APP_DB_SECRET);

      //// DEMO URL
      if (USE_CDN) {
        func.addEnvironment("DEMO_ENDPOINT", `https://${frontendCdn!.distributionDomainName}`);
      } else {
        func.addEnvironment("DEMO_ENDPOINT", `https://${frontendBucket.bucketDomainName}`);
      }

      // (a-4) Layer
      func.addLayers(nodeModulesLayer);
    }
    const functions = [
      lambdaFuncRestAPIAuth, lambdaFunctionForRestAPI, lambdaFunctionForSlackFederationRestAPI, lambdaFuncMessageConnect, lambdaFuncMessageDisconnect, lambdaFuncMessageMessage, lambdaFuncMessageAuth
    ]
    functions.forEach(func => {
      configureFunctions(func)
    })


    // (6) API Gateway
    //// (6-1) APIs
    const { roleForAPIAuthorizer } = createRoleForAPIAuthorizer(this, lambdaFuncRestAPIAuth.functionArn)
    const { restApi } = createRestApi(this, id)
    const authorizerUri = `arn:aws:apigateway:${this.region}:lambda:path/2015-03-31/functions/${lambdaFuncRestAPIAuth.functionArn}/invocations`
    const { authorizer } = createAuthorizer(this, id, roleForAPIAuthorizer.roleArn, restApi.restApiId, authorizerUri)
    let corsOrigin
    if (FRONTEND_LOCAL_DEV) {
      corsOrigin = "'https://localhost:3000'";
      // origin = "'https://192.168.0.4:3000'";
    } else {
      if (USE_CDN) {
        corsOrigin = `'https://${frontendCdn!.distributionDomainName}'`;
      } else {
        corsOrigin = `'https://${frontendBucket.bucketDomainName}'`;
      }
    }

    createApis(id, restApi, authorizer.ref, lambdaFunctionForRestAPI, corsOrigin)
    createApisForSlack(id, restApi, lambdaFunctionForSlackFederationRestAPI, corsOrigin)
    //// (6-2) Websocket
    const { roleForWebsocketAuthorizer } = createRoleForWebsocketAuthorizer(this, lambdaFuncMessageAuth.functionArn, lambdaFuncMessageConnect.functionArn, lambdaFuncMessageDisconnect.functionArn, lambdaFuncMessageMessage.functionArn)
    const { webSocketApi } = createWebsocket(this)
    const websocketAuthorizerUri = `arn:aws:apigateway:${this.region}:lambda:path/2015-03-31/functions/${lambdaFuncMessageAuth.functionArn}/invocations`
    const { websocketAuthorizer } = createWebsocketAuthorizer(this, id, roleForWebsocketAuthorizer.roleArn, webSocketApi.ref, websocketAuthorizerUri)
    createMessages(this, webSocketApi.ref, roleForWebsocketAuthorizer.roleArn, this.region, lambdaFuncMessageConnect.functionArn, lambdaFuncMessageDisconnect.functionArn, lambdaFuncMessageMessage.functionArn, websocketAuthorizer.ref)


    ///////////////////////////////
    //// Output
    ///////////////////////////////
    new CfnOutput(this, "UserPoolId", {
      description: "UserPoolId",
      value: userPool.userPoolId,
    });

    new CfnOutput(this, "UserPoolClientId", {
      description: "UserPoolClientId",
      value: userPoolClient.userPoolClientId,
    });

    new CfnOutput(this, "Bucket", {
      description: "Bucket",
      value: frontendBucket.bucketName,
    });

    new CfnOutput(this, "BucketWebsiteDomainName", {
      description: "BucketWebsiteDomainName",
      value: frontendBucket.bucketWebsiteDomainName,
    });

    new CfnOutput(this, "BucketDomainName", {
      description: "BucketDomainName",
      value: frontendBucket.bucketDomainName,
    });

    new CfnOutput(this, "RestAPIEndpoint", {
      description: "RestAPIEndpoint",
      value: restApi.url,
    });

    new CfnOutput(this, "WebSocketEndpoint", {
      description: "WebSocketEndpoint",
      value: webSocketApi.attrApiEndpoint,
    });

    if (USE_CDN) {
      new CfnOutput(this, "CDNComainName", {
        description: "CDNComainName",
        value: frontendCdn!.distributionDomainName,
      });
    }

    //// DEMO URL
    if (USE_CDN) {
      new CfnOutput(this, "DemoEndpoint", {
        description: "DemoEndpoint",
        value: `https://${frontendCdn!.distributionDomainName}`,
      });
      new CfnOutput(this, "DistributionId", {
        description: "DistributionId",
        value: frontendCdn!.distributionId,
      });
    } else {
      new CfnOutput(this, "DemoEndpoint", {
        description: "DemoEndpoint",
        value: `https://${frontendBucket.bucketDomainName}`,
      });
    }
  }
Example #25
Source File: dynamodb-crud-stack.ts    From cdk-examples with MIT License 4 votes vote down vote up
constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here
    const todoTable = new Table(this, 'todoTable', {
      partitionKey: {
        name: 'id',
        type: AttributeType.STRING
      },
      billingMode: BillingMode.PAY_PER_REQUEST,
      removalPolicy: RemovalPolicy.DESTROY
    })

    todoTable.addGlobalSecondaryIndex({
      indexName: 'ownerIndex',
      partitionKey: {
        name: 'owner',
        type: AttributeType.STRING
      }
    })

    new CfnOutput(this, 'todoTableName', {
      value: todoTable.tableName
    })

    const createTodoFn = new NodejsFunction(this, 'createTodoFn', {
      runtime: Runtime.NODEJS_16_X,
      entry: `${__dirname}/../lambda-fns/create/index.ts`,
      handler: 'createTodo',
      architecture: Architecture.ARM_64,
      environment: {
        TODO_TABLE_NAME: todoTableName
      }
    })

    todoTable.grantReadWriteData(createTodoFn)

    const getAllTodoFn = new NodejsFunction(this, 'getAllTodoFn', {
      runtime: Runtime.NODEJS_16_X,
      entry: `${__dirname}/../lambda-fns/getAll/index.ts`,
      handler: 'getAll',
      architecture: Architecture.ARM_64,
      environment: {
        TODO_TABLE_NAME: todoTableName
      }
    })

    todoTable.grantReadData(getAllTodoFn)

    const getOneTodoFn = new NodejsFunction(this, 'getOneTodoFn', {
      runtime: Runtime.NODEJS_16_X,
      entry: `${__dirname}/../lambda-fns/getOne/index.ts`,
      handler: 'getOne',
      architecture: Architecture.ARM_64,
      environment: {
        TODO_TABLE_NAME: todoTableName
      }
    })

    todoTable.grantReadData(getOneTodoFn)

    const updateTodoFn = new NodejsFunction(this, 'updateTodoFn', {
      runtime: Runtime.NODEJS_16_X,
      entry: `${__dirname}/../lambda-fns/update/index.ts`,
      handler: 'update',
      architecture: Architecture.ARM_64,
      environment: {
        TODO_TABLE_NAME: todoTableName
      }
    })

    todoTable.grantReadWriteData(updateTodoFn)

    const deleteTodoFn = new NodejsFunction(this, 'deleteTodoFn', {
      runtime: Runtime.NODEJS_16_X,
      entry: `${__dirname}/../lambda-fns/delete/index.ts`,
      handler: 'deleteTodo',
      architecture: Architecture.ARM_64,
      environment: {
        TODO_TABLE_NAME: todoTableName
      }
    })

    todoTable.grantReadWriteData(deleteTodoFn)

    const tableWithIndex = Table.fromTableAttributes(this, 'tableWithIndex', {
      tableName: todoTableName,
      globalIndexes: ['ownerIndex']
    })

    const queryTodoFn = new NodejsFunction(this, 'queryTodoFn', {
      runtime: Runtime.NODEJS_16_X,
      entry: `${__dirname}/../lambda-fns/query/index.ts`,
      handler: 'queryTodo',
      architecture: Architecture.ARM_64,
      environment: {
        TODO_TABLE_NAME: todoTableName
      }
    })

    tableWithIndex.grantReadData(queryTodoFn)
  }