CDK. Cloudfront distribution pointing to a private loadbalancer on a VPC

0

The following CDK code creates a Fargate ECS but with a public ApplicationLoadBalancer. I want the application load balancer to be private and only the CloudFront distribution can access to the ApplicationLoadBalancer. Any idea how to do it?

OR can the ALB get a aws free subdomain domain with https? as https://dqewrpnz0dddmw.cloudfront.net on cloudfront.

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs_patterns from 'aws-cdk-lib/aws-ecs-patterns';
import * as cloudFront from 'aws-cdk-lib/aws-cloudfront';	
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';


export class CdkCloudStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const vpc = new ec2.Vpc(this, 'vpc', { maxAzs: 2 });
    const cluster = new ecs.Cluster(this, 'fargate-service-autoscaling', { vpc });
    cluster.addCapacity('fargate-service-autoscaling-capacity', { 
      instanceType: new ec2.InstanceType('t3.micro'),
      desiredCapacity: 1,
      minCapacity: 1,
      maxCapacity: 2,
      spotInstanceDraining: true,
    });
    const repository = ecs.RepositoryImage.fromRegistry("public.ecr.aws/user/repo");
    
    const app = new ecs_patterns.ApplicationLoadBalancedFargateService(this, "FargateService", {
      cluster,
      memoryLimitMiB: 512,
      cpu: 256,
      desiredCount: 1,
      publicLoadBalancer: true,
      circuitBreaker: { rollback: true },
      taskImageOptions: {
        image: repository,
        containerPort: 3000,
        enableLogging: true,
      },
    });

    app.targetGroup.configureHealthCheck({ path: "/api/health" });
  
  	const front = new cloudFront.Distribution(this, "cloudDistribution", {

      defaultBehavior: {
        origin: new origins.LoadBalancerV2Origin(app.loadBalancer, {protocolPolicy: cloudFront.OriginProtocolPolicy.HTTP_ONLY }),
        compress: true,
        cachePolicy: cloudFront.CachePolicy.CACHING_OPTIMIZED,
        allowedMethods: cloudFront.AllowedMethods.ALLOW_ALL,
        viewerProtocolPolicy: cloudFront.ViewerProtocolPolicy.ALLOW_ALL,
        originRequestPolicy: new cloudFront.OriginRequestPolicy(this, "cloudVaultOriginRequestPolicy", 
        { queryStringBehavior: cloudFront.OriginRequestQueryStringBehavior.all(), 
          headerBehavior: cloudFront.OriginRequestHeaderBehavior.all(), 
          cookieBehavior: cloudFront.OriginRequestCookieBehavior.all(),
        }),
      },
    });


    new cdk.CfnOutput(this, "cloudVaultDistributionDomainName", { value: front.distributionDomainName });    
  }
}

1 Answer
2

The CloudFront origin must be accessible from the Internet to be used.
In other words, access is not possible even if an internal ALB (private ALB) is specified as the origin.
So how do we restrict access to the ALB to CloudFront? There are two ways.

The first is to allow CloudFront prefix lists in the ALB security group.
As shown in the following document, there is a list of prefixes for CloudFront, so please configure the ALB security group inbound rules to allow this one.
https://docs.aws.amazon.com/vpc/latest/userguide/working-with-aws-managed-prefix-lists.html
https://aws.amazon.com/about-aws/whats-new/2022/02/amazon-cloudfront-managed-prefix-list/?nc1=h_ls

The second method is to limit the ALB with a custom header in CloudFront.
However, this method is not recommended because it would allow direct access to the ALB if CloudFront custom headers are lost.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/restrict-access-to-load-balancer.html

OR can the ALB get a aws free subdomain domain with https? as https://dqewrpnz0dddmw.cloudfront.net on cloudfront.

The domain "cloudfront.net" belongs to AWS, so we cannot create a subdomain on this domain.

profile picture
EXPERT
answered 2 years ago
profile picture
EXPERT
reviewed 7 months ago
  • Thanks @RIKU! I have found managed prefix lists before, but I could not find any cdk example :(. And on the cloudfront custom headears the same. Do you know any cdk example?

  • The code for creating a security group that allows CloudFront prefix lists would be as follows. Please change "sample-vpc-id" and "cloudfront-prefix-list-id" according to your environment.

    import * as cdk from 'aws-cdk-lib';
    import { Construct } from 'constructs';
    
    import * as ec2 from 'aws-cdk-lib/aws-ec2';
    
    export class SampleStack extends cdk.Stack {
        constructor(scope: Construct, id: string, props?: cdk.StackProps) {
            super(scope, id, props);
    
            const vpc = ec2.Vpc.fromLookup(this, 'VPC', {
                vpcId: 'sample-vpc-id',
            });
    
            const securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
                vpc,
                description: 'for ALB',
                allowAllOutbound: true,
            });
    
            // Allow SSH access on port tcp/22
            securityGroup.addIngressRule(
                ec2.Peer.prefix_list("cloudfront-prefix-list-id"),
                ec2.Port.tcp(443),
                'Allow HTTPS Access',
            );
    

    By setting this security group to ALB, connections can be allowed only from CloudFront.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions