< Summary - Envilder IaC (CDK)

Information
Class: src/iac/lib/stacks/publicFilesStack.ts
Assembly: Default
File(s): src/iac/lib/stacks/publicFilesStack.ts
Tag: 558_41035824231
Line coverage
100%
Covered lines: 11
Uncovered lines: 0
Coverable lines: 11
Total lines: 118
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

File(s)

src/iac/lib/stacks/publicFilesStack.ts

#LineLine coverage
 1import { CfnOutput, RemovalPolicy } from "aws-cdk-lib";
 2import { Certificate } from "aws-cdk-lib/aws-certificatemanager";
 3import {
 4  AllowedMethods,
 5  CachePolicy,
 6  Distribution,
 7  HttpVersion,
 8  PriceClass,
 9  ResponseHeadersPolicy,
 10  ViewerProtocolPolicy,
 11} from "aws-cdk-lib/aws-cloudfront";
 12import { S3BucketOrigin } from "aws-cdk-lib/aws-cloudfront-origins";
 13import {
 14  AaaaRecord,
 15  ARecord,
 16  HostedZone,
 17  RecordTarget,
 18} from "aws-cdk-lib/aws-route53";
 19import { CloudFrontTarget } from "aws-cdk-lib/aws-route53-targets";
 20import {
 21  BlockPublicAccess,
 22  Bucket,
 23  BucketEncryption,
 24  ObjectOwnership,
 25} from "aws-cdk-lib/aws-s3";
 26import type { Construct } from "constructs";
 27import { CustomStack, type CustomStackProps } from "./customStack";
 28
 29export interface PublicFilesStackProps extends CustomStackProps {
 30  subdomain: string;
 31  domainName: string;
 32  hostedZoneId: string;
 33  /** ACM certificate in us-east-1 covering the subdomain (CloudFront requirement) */
 34  certificateId: string;
 35}
 36
 37/**
 38 * Public, shareable files served from <subdomain>.<domainName>.
 39 * Objects are uploaded by hand; the stack never deploys or prunes them.
 40 * Kept close to zero cost: no logging, no versioning, cheapest price class.
 41 */
 42export class PublicFilesStack extends CustomStack {
 43  constructor(scope: Construct, props: PublicFilesStackProps) {
 444    super(scope, props);
 45
 46    const fullDomainName =
 447      `${props.subdomain}.${props.domainName}`.toLowerCase();
 48
 449    const hostedZone = HostedZone.fromHostedZoneAttributes(
 50      this,
 51      "hosted-zone",
 52      {
 53        zoneName: props.domainName.toLowerCase(),
 54        hostedZoneId: props.hostedZoneId,
 55      },
 56    );
 57
 458    const certificate = Certificate.fromCertificateArn(
 59      this,
 60      "certificate",
 61      `arn:aws:acm:us-east-1:${this.account}:certificate/${props.certificateId}`,
 62    );
 63
 464    const bucket = new Bucket(this, "public-files-bucket", {
 65      bucketName: fullDomainName,
 66      publicReadAccess: false,
 67      blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
 68      objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED,
 69      encryption: BucketEncryption.S3_MANAGED,
 70      enforceSSL: true,
 71      versioned: false,
 72      // Shared files are uploaded by hand: never delete them with the stack
 73      removalPolicy: RemovalPolicy.RETAIN,
 74    });
 75
 476    const distribution = new Distribution(this, "distribution", {
 77      domainNames: [fullDomainName],
 78      certificate,
 79      defaultBehavior: {
 80        origin: S3BucketOrigin.withOriginAccessControl(bucket),
 81        viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
 82        allowedMethods: AllowedMethods.ALLOW_GET_HEAD,
 83        cachePolicy: CachePolicy.CACHING_OPTIMIZED,
 84        responseHeadersPolicy: ResponseHeadersPolicy.SECURITY_HEADERS,
 85        compress: true,
 86      },
 87      priceClass: PriceClass.PRICE_CLASS_100,
 88      httpVersion: HttpVersion.HTTP2_AND_3,
 89      enableLogging: false,
 90    });
 91
 492    const aliasTarget = RecordTarget.fromAlias(
 93      new CloudFrontTarget(distribution),
 94    );
 95
 496    new ARecord(this, "public-files-record", {
 97      zone: hostedZone,
 98      recordName: fullDomainName,
 99      target: aliasTarget,
 100    });
 101
 4102    new AaaaRecord(this, "public-files-record-ipv6", {
 103      zone: hostedZone,
 104      recordName: fullDomainName,
 105      target: aliasTarget,
 106    });
 107
 4108    new CfnOutput(this, "PublicFilesBucketName", {
 109      value: bucket.bucketName,
 110      description: "Bucket to upload shareable files to",
 111    });
 112
 4113    new CfnOutput(this, "PublicFilesUrl", {
 114      value: `https://${fullDomainName}`,
 115      description: "Base URL of the shareable files",
 116    });
 117  }
 118}

Methods/Properties

constructor