How to correctly code AWS ALB redirection in CDK (python)

Question:

Learning AWS CDK (coming from terraform). I’m currently struggling, how to write a piece of code with will allow me to create redirection as in below screenshot:
enter image description here

Code so far which I have:

class LoadBalancer(core.Construct):

def __init__(self, scope: core.Construct, construct_id: str, props):
    super().__init__(scope, construct_id)
    self.props = props

def load_balancer(self, security_group, fargate_service, arn_certificates_list):
    load_balancer = alb.ApplicationLoadBalancer(
        self,
        "TestFargateALB",
        vpc=self.props["vpc"],
        deletion_protection=True if self.props["environment"].lower() == "prod" else False,
        http2_enabled=True,
        internet_facing=True,
        security_group=security_group
    )

    load_balancer.set_attribute(key="routing.http.drop_invalid_header_fields.enabled", value="true")

    http_load_balancer_listener = load_balancer.add_listener(
        'http_listener', port=80, open=False
    )

    https_load_balancer_listener = load_balancer.add_listener(
        "https_listener", port=443, open=False, certificate_arns=arn_certificates_list
    )

    https_target_group = https_load_balancer_listener.add_targets(
        'ecs_target_group',
        targets=[fargate_service],
        port=80,
        protocol=alb.ApplicationProtocol.HTTP,
        deregistration_delay=core.Duration.seconds(amount=10)
    )

    https_target_group.configure_health_check(
        healthy_http_codes="200,301,302",
        healthy_threshold_count=3,
        interval=core.Duration.seconds(10),
        timeout=core.Duration.seconds(5),
        unhealthy_threshold_count=5,
        path="/"
    )

    http_load_balancer_listener.add_action(
        'DefaultAction',
        action=alb.ListenerAction(action_json=alb.CfnListener.ActionProperty(
            type="redirect",
            redirect_config=alb.CfnListener.RedirectConfigProperty(
                status_code="HTTP_301",
                host="#{host}",
                protocol="HTTPS",
                port="443",
                path="#{path}",
                query="#{query}"
            )
        ))
    )

    alb.ApplicationListenerRule(self, "HttpsRule",
                                listener=https_load_balancer_listener,
                                priority=1,
                                path_pattern="/",
                                target_groups=[https_target_group]
                                )

    return load_balancer

Error which CDK is throwing during deployment:

5:04:16 PM | CREATE_FAILED | AWS::ElasticLoadBalancingV2::Listener | TestALBTestFargate...tplistener3A9BAD2E The Path parameter must be a valid path, should start with a '/', and may contain up to one of each of these placeholders: '#{path}', '#{host}', '#{port}'. (Service: ElasticLoadBalancingV2, Status Code: 400, Request ID: 9cc3b04c-0787-4455-a7ee-2a1b3e9a30b3, Exten ded Request ID: null)

Can someone could help me out on how to write this piece correctly?

Asked By: Maciej

||

Answers:

We just need to call addRedirect method on loadbalancer.

Default parameters for method already has

{
   sourcePort: 80,
   targetPort: 443,
   sourceProtocol: elbv2.ApplicationProtocol.HTTP,
   targetProtocol: elbv2.ApplicationProtocol.HTTPS,
}

These are default Options for the method anyhow. so, all we need is one line lb.addRedirect();

const vpc = ec2.Vpc.fromLookup(this, "myVpc", {
  isDefault: false,
  vpcId: "vpc-0cb67dd096388f8ca",
});

const lb = new elbv2.ApplicationLoadBalancer(this, "LB", {
  vpc,
  internetFacing: true,
});

lb.addRedirect();

Python method will be something similar documented here:

lb.add_redirect(
    source_protocol=elbv2.ApplicationProtocol.HTTPS,
    source_port=80,
    target_protocol=elbv2.ApplicationProtocol.HTTP,
    target_port=443
)

This will add listener rule to redirect 80 to 443 with status HTTP 301

enter image description here

Answered By: Balu Vyamajala

You are missing the / in the value of the parameter, it would look like this:

path="/#{path}"
Answered By: Lumar Ramones

To add a certificate you can do something like this:

from aws_cdk import (
  aws_certificatemanager as acm
)

CERTIFICATE = 'arn:aws:acm:us-east-1:123456:certificate/183b69f1-10fb-4060-9a0f-bfbfdgrrwe'

class LoadBalancer(core.Construct):

def __init__(self, scope: core.Construct, construct_id: str, props):
    super().__init__(scope, construct_id)
    self.props = props

        #...

        # Use existing Certificate
        certificate = acm.Certificate.from_certificate_arn(
            self, "certificate",
            certificate_arn=CERTIFICATE
        )

        #...
         
        https_load_balancer_listener =load_balancer.add_listener("https_listener", port=443, open=False, certificates=[certificate], protocol=elb.ApplicationProtocol.HTTPS)
Answered By: Lumar Ramones