question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ECSPatterns: Support switch for http->https redirect

See original GitHub issue

It’s common use case to redirect all http requests to https at the load balancer level. Use cases include UI:s that are served from containers and API implementations as well. Giving https upgrade automatically to your users (end users using application and developers testing your API’s) is a usability issue. It’s like saying: “here I am, but could you talk securely to me?”.

Application Load Balancer has great support for this already, but unfortunately it seems like this use case is not supported in ApplicationLoadBalancedFargateService pattern. Same thing probably affects other ALB based high level patterns as well.

Use Case

If you need to implement http to https redirect with ECS Patterns, you have to do some heavy lifting in order to be able to configure simple redirect. ApplicationLoadBalancedFargateServiceProps builder has loadBalancer(), but it seems like then you have to do the heavy VPC configuration and such.

Workaround seems to be something like following.

        ApplicationLoadBalancer loadBalancer = new ApplicationLoadBalancer(this, "loadBalancer", ApplicationLoadBalancerProps.builder()
                .internetFacing(true)
                .vpc(vpc)
                .build());

        ApplicationListener httpListener = loadBalancer.addListener("httpListener", BaseApplicationListenerProps.builder()
                .protocol(ApplicationProtocol.HTTP)
                .build());

        httpListener.addRedirectResponse("https-redirect", AddRedirectResponseProps.builder().statusCode("HTTP_301").protocol("HTTPS").port("443").build());

        ApplicationLoadBalancedFargateService fargateService = new ApplicationLoadBalancedFargateService(
                this,
                "my-fargate-service",
                ApplicationLoadBalancedFargateServiceProps.builder()
                        .cluster(cluster)
                        .certificate(Certificate.fromCertificateArn(this, "ALB-certificate",
                                "arn:aws:acm:eu-west-1:XXXXXXXXXXXX:certificate/XXXXXXXXX"))
                        .domainName("myservice.acme.com")
                        .domainZone(hostedZone)
                        .loadBalancer(loadBalancer)
                        .taskImageOptions(ApplicationLoadBalancedTaskImageOptions.builder()
                                .image(ContainerImage.fromRegistry("amazon/amazon-ecs-sample"))
                                .build())
                        .build());

This “decorates” used load balancer and merges configuration pretty intelligently and this is totally acceptable workaround for me. I personally feel that this is really common pattern in web applications to be able to listen both http and https traffic and upgrade all http requests to https, and it would help AWS and CDK newcomers to be able to define this really common use case in more easy way.

Proposed Solution

High level constructs could take additional “redirectHttpToHttps(boolean)”, such as

        ApplicationLoadBalancedFargateService fargateService = new ApplicationLoadBalancedFargateService(
                this,
                "my-fargate-service",
                ApplicationLoadBalancedFargateServiceProps.builder()
                        .cluster(cluster)
                        .certificate(Certificate.fromCertificateArn(this, "ALB-certificate",
                                "arn:aws:acm:eu-west-1:XXXXXXXXXXXX:certificate/XXXXXXXXX"))
                        .domainName("myservice.acme.com")
                        .domainZone(hostedZone)
                        .redirectHttpToHttps(true)
                        .taskImageOptions(ApplicationLoadBalancedTaskImageOptions.builder()
                                .image(ContainerImage.fromRegistry("amazon/amazon-ecs-sample"))
                                .build())
                        .build());

If redirectHttpToHttps is called with true, when certificate is not set, synth should fail, because then http listener which redirects traffic to target group is configured.

More advanced option would be the ability to configure http traffic to target group, because there are applications in the wild that want (for some reason…) handle both http and https traffic. This could be done with something like:

httpPolicy(HttpPolicy.NO_LISTENER) No listener for http httpPolicy(HttpPolicy.REDIRECT_TO_HTTPS) Do http->https redirect httpPolicy(HttpPolicy.ROUTE_TO_TARGET_GROUP) Route http traffic to target group

Other

This is just an idea I wanted to share. I don’t mind rejection 😃 I would love to help out, and if this is regarded as a good idea, I just might take some time to investigate how this could be implemented.

  • 👋 I may be able to implement this feature request
  • ⚠️ This feature might incur a breaking change

This is a 🚀 Feature Request

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:13
  • Comments:35 (14 by maintainers)

github_iconTop GitHub Comments

10reactions
cscharuncommented, Mar 25, 2020

I was struggling with the same problem today and found a solution:

You need to create a listener for your load balancer for HTTP on port 80.

    const httpListener = loadBalancer.addListener("app-lb-listener-http", {
        port: 80,
        protocol: ApplicationProtocol.HTTP
    });

And then you can redirect all incoming HTTP requests to HTTPS by adding a RedirectResponse like so:

    httpListener.addRedirectResponse("app-lb-redirect-https", {
        statusCode: 'HTTP_301',
        protocol: ApplicationProtocol.HTTPS,
        port:'443',
    });

I think this is a common problem and an example solution should be inserted to the cdk examples or documentation.

5reactions
merlandcommented, Mar 27, 2020

@08en Your suggestion seems really promising, but since new ecs_patterns.ApplicationLoadBalancedFargateService(...) already creates a loadbalancer with a port 80 listener, I get:

A listener already exists on this port for this load balancer '<arn>' (Service: AmazonElasticLoadBalancingV2; Status Code: 400; Error Code: DuplicateListener; Request ID: <req id>)

I haven’t found a way obtain a reference to the existing port 80 listener. (Something like loadBalancer.getListeners() would have been nice…)

Is there a solution to this?

Read more comments on GitHub >

github_iconTop Results From Across the Web

aws-cdk/aws-ecs-patterns module - AWS Documentation
To define an Amazon ECS service that is behind an application load balancer, ... create a listener on port 80 that redirects HTTP...
Read more >
Enable HTTP to HTTPS Redirect for Application Load Balancers
Redirecting HTTP traffic to HTTPS within your load balancer listeners' configuration simplifies deployments while benefiting from the scale, the availability, ...
Read more >
Set up an HTTP-to-HTTPS redirect for a global external HTTP ...
This page shows you how to set up an HTTP-to-HTTPS redirect for the global external HTTP(S) load balancer (classic). This page is for...
Read more >
Redirections in HTTP - MDN Web Docs - Mozilla
URL redirection, also known as URL forwarding, is a technique to give more than one URL address to a page, a form, or...
Read more >
Configuring an HTTP virtual server to redirect to HTTPS using ...
You want to use an iRule to remove www from the HTTP request and redirect all incoming HTTP virtual server requests to an...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found