The aws:alb/listener:Listener resource, part of the Pulumi AWS provider, defines a load balancer listener that accepts incoming connections on a specific port and protocol, then routes traffic based on configured actions. This guide focuses on four capabilities: HTTPS termination and forwarding, HTTP-to-HTTPS redirection, weighted traffic splitting, and authentication integration.
Listeners attach to existing load balancers and reference target groups, TLS certificates, and authentication resources. The examples are intentionally small. Combine them with your own load balancers, target groups, and security configuration.
Route HTTPS traffic to a target group
Most deployments accept HTTPS traffic on port 443 and forward requests to backend instances.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const frontEnd = new aws.lb.LoadBalancer("front_end", {});
const frontEndTargetGroup = new aws.lb.TargetGroup("front_end", {});
const frontEndListener = new aws.lb.Listener("front_end", {
loadBalancerArn: frontEnd.arn,
port: 443,
protocol: "HTTPS",
sslPolicy: "ELBSecurityPolicy-2016-08",
certificateArn: "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
defaultActions: [{
type: "forward",
targetGroupArn: frontEndTargetGroup.arn,
}],
});
import pulumi
import pulumi_aws as aws
front_end = aws.lb.LoadBalancer("front_end")
front_end_target_group = aws.lb.TargetGroup("front_end")
front_end_listener = aws.lb.Listener("front_end",
load_balancer_arn=front_end.arn,
port=443,
protocol="HTTPS",
ssl_policy="ELBSecurityPolicy-2016-08",
certificate_arn="arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
default_actions=[{
"type": "forward",
"target_group_arn": front_end_target_group.arn,
}])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lb"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
frontEnd, err := lb.NewLoadBalancer(ctx, "front_end", nil)
if err != nil {
return err
}
frontEndTargetGroup, err := lb.NewTargetGroup(ctx, "front_end", nil)
if err != nil {
return err
}
_, err = lb.NewListener(ctx, "front_end", &lb.ListenerArgs{
LoadBalancerArn: frontEnd.Arn,
Port: pulumi.Int(443),
Protocol: pulumi.String("HTTPS"),
SslPolicy: pulumi.String("ELBSecurityPolicy-2016-08"),
CertificateArn: pulumi.String("arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4"),
DefaultActions: lb.ListenerDefaultActionArray{
&lb.ListenerDefaultActionArgs{
Type: pulumi.String("forward"),
TargetGroupArn: frontEndTargetGroup.Arn,
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var frontEnd = new Aws.LB.LoadBalancer("front_end");
var frontEndTargetGroup = new Aws.LB.TargetGroup("front_end");
var frontEndListener = new Aws.LB.Listener("front_end", new()
{
LoadBalancerArn = frontEnd.Arn,
Port = 443,
Protocol = "HTTPS",
SslPolicy = "ELBSecurityPolicy-2016-08",
CertificateArn = "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
DefaultActions = new[]
{
new Aws.LB.Inputs.ListenerDefaultActionArgs
{
Type = "forward",
TargetGroupArn = frontEndTargetGroup.Arn,
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.TargetGroup;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var frontEnd = new LoadBalancer("frontEnd");
var frontEndTargetGroup = new TargetGroup("frontEndTargetGroup");
var frontEndListener = new Listener("frontEndListener", ListenerArgs.builder()
.loadBalancerArn(frontEnd.arn())
.port(443)
.protocol("HTTPS")
.sslPolicy("ELBSecurityPolicy-2016-08")
.certificateArn("arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4")
.defaultActions(ListenerDefaultActionArgs.builder()
.type("forward")
.targetGroupArn(frontEndTargetGroup.arn())
.build())
.build());
}
}
resources:
frontEnd:
type: aws:lb:LoadBalancer
name: front_end
frontEndTargetGroup:
type: aws:lb:TargetGroup
name: front_end
frontEndListener:
type: aws:lb:Listener
name: front_end
properties:
loadBalancerArn: ${frontEnd.arn}
port: '443'
protocol: HTTPS
sslPolicy: ELBSecurityPolicy-2016-08
certificateArn: arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4
defaultActions:
- type: forward
targetGroupArn: ${frontEndTargetGroup.arn}
The listener terminates TLS using the certificateArn, then forwards decrypted requests to the target group. The protocol property sets HTTPS for client connections, while sslPolicy controls which cipher suites are allowed. The defaultActions array defines what happens to incoming requests; here, type “forward” sends traffic to the specified targetGroupArn.
Redirect HTTP to HTTPS automatically
Applications requiring encryption redirect HTTP traffic to HTTPS rather than serving unencrypted content.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const frontEnd = new aws.lb.LoadBalancer("front_end", {});
const frontEndListener = new aws.lb.Listener("front_end", {
loadBalancerArn: frontEnd.arn,
port: 80,
protocol: "HTTP",
defaultActions: [{
type: "redirect",
redirect: {
port: "443",
protocol: "HTTPS",
statusCode: "HTTP_301",
},
}],
});
import pulumi
import pulumi_aws as aws
front_end = aws.lb.LoadBalancer("front_end")
front_end_listener = aws.lb.Listener("front_end",
load_balancer_arn=front_end.arn,
port=80,
protocol="HTTP",
default_actions=[{
"type": "redirect",
"redirect": {
"port": "443",
"protocol": "HTTPS",
"status_code": "HTTP_301",
},
}])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lb"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
frontEnd, err := lb.NewLoadBalancer(ctx, "front_end", nil)
if err != nil {
return err
}
_, err = lb.NewListener(ctx, "front_end", &lb.ListenerArgs{
LoadBalancerArn: frontEnd.Arn,
Port: pulumi.Int(80),
Protocol: pulumi.String("HTTP"),
DefaultActions: lb.ListenerDefaultActionArray{
&lb.ListenerDefaultActionArgs{
Type: pulumi.String("redirect"),
Redirect: &lb.ListenerDefaultActionRedirectArgs{
Port: pulumi.String("443"),
Protocol: pulumi.String("HTTPS"),
StatusCode: pulumi.String("HTTP_301"),
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var frontEnd = new Aws.LB.LoadBalancer("front_end");
var frontEndListener = new Aws.LB.Listener("front_end", new()
{
LoadBalancerArn = frontEnd.Arn,
Port = 80,
Protocol = "HTTP",
DefaultActions = new[]
{
new Aws.LB.Inputs.ListenerDefaultActionArgs
{
Type = "redirect",
Redirect = new Aws.LB.Inputs.ListenerDefaultActionRedirectArgs
{
Port = "443",
Protocol = "HTTPS",
StatusCode = "HTTP_301",
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionRedirectArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var frontEnd = new LoadBalancer("frontEnd");
var frontEndListener = new Listener("frontEndListener", ListenerArgs.builder()
.loadBalancerArn(frontEnd.arn())
.port(80)
.protocol("HTTP")
.defaultActions(ListenerDefaultActionArgs.builder()
.type("redirect")
.redirect(ListenerDefaultActionRedirectArgs.builder()
.port("443")
.protocol("HTTPS")
.statusCode("HTTP_301")
.build())
.build())
.build());
}
}
resources:
frontEnd:
type: aws:lb:LoadBalancer
name: front_end
frontEndListener:
type: aws:lb:Listener
name: front_end
properties:
loadBalancerArn: ${frontEnd.arn}
port: '80'
protocol: HTTP
defaultActions:
- type: redirect
redirect:
port: '443'
protocol: HTTPS
statusCode: HTTP_301
When a request arrives on port 80, the listener returns a 301 redirect pointing to port 443 with HTTPS protocol. The redirect action doesn’t forward to a target group; instead, it tells the client to retry with a different URL. The statusCode property controls whether browsers cache the redirect (HTTP_301) or treat it as temporary (HTTP_302).
Split traffic between target groups with weights
Blue-green deployments and canary releases split traffic between multiple target groups to gradually shift load.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const frontEnd = new aws.lb.LoadBalancer("front_end", {});
const frontEndBlue = new aws.lb.TargetGroup("front_end_blue", {});
const frontEndGreen = new aws.lb.TargetGroup("front_end_green", {});
const frontEndListener = new aws.lb.Listener("front_end", {
loadBalancerArn: frontEnd.arn,
port: 443,
protocol: "HTTPS",
sslPolicy: "ELBSecurityPolicy-2016-08",
certificateArn: "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
defaultActions: [{
type: "forward",
forward: {
targetGroups: [
{
arn: frontEndBlue.arn,
weight: 100,
},
{
arn: frontEndGreen.arn,
weight: 0,
},
],
},
}],
});
import pulumi
import pulumi_aws as aws
front_end = aws.lb.LoadBalancer("front_end")
front_end_blue = aws.lb.TargetGroup("front_end_blue")
front_end_green = aws.lb.TargetGroup("front_end_green")
front_end_listener = aws.lb.Listener("front_end",
load_balancer_arn=front_end.arn,
port=443,
protocol="HTTPS",
ssl_policy="ELBSecurityPolicy-2016-08",
certificate_arn="arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
default_actions=[{
"type": "forward",
"forward": {
"target_groups": [
{
"arn": front_end_blue.arn,
"weight": 100,
},
{
"arn": front_end_green.arn,
"weight": 0,
},
],
},
}])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lb"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
frontEnd, err := lb.NewLoadBalancer(ctx, "front_end", nil)
if err != nil {
return err
}
frontEndBlue, err := lb.NewTargetGroup(ctx, "front_end_blue", nil)
if err != nil {
return err
}
frontEndGreen, err := lb.NewTargetGroup(ctx, "front_end_green", nil)
if err != nil {
return err
}
_, err = lb.NewListener(ctx, "front_end", &lb.ListenerArgs{
LoadBalancerArn: frontEnd.Arn,
Port: pulumi.Int(443),
Protocol: pulumi.String("HTTPS"),
SslPolicy: pulumi.String("ELBSecurityPolicy-2016-08"),
CertificateArn: pulumi.String("arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4"),
DefaultActions: lb.ListenerDefaultActionArray{
&lb.ListenerDefaultActionArgs{
Type: pulumi.String("forward"),
Forward: &lb.ListenerDefaultActionForwardArgs{
TargetGroups: lb.ListenerDefaultActionForwardTargetGroupArray{
&lb.ListenerDefaultActionForwardTargetGroupArgs{
Arn: frontEndBlue.Arn,
Weight: pulumi.Int(100),
},
&lb.ListenerDefaultActionForwardTargetGroupArgs{
Arn: frontEndGreen.Arn,
Weight: pulumi.Int(0),
},
},
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var frontEnd = new Aws.LB.LoadBalancer("front_end");
var frontEndBlue = new Aws.LB.TargetGroup("front_end_blue");
var frontEndGreen = new Aws.LB.TargetGroup("front_end_green");
var frontEndListener = new Aws.LB.Listener("front_end", new()
{
LoadBalancerArn = frontEnd.Arn,
Port = 443,
Protocol = "HTTPS",
SslPolicy = "ELBSecurityPolicy-2016-08",
CertificateArn = "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4",
DefaultActions = new[]
{
new Aws.LB.Inputs.ListenerDefaultActionArgs
{
Type = "forward",
Forward = new Aws.LB.Inputs.ListenerDefaultActionForwardArgs
{
TargetGroups = new[]
{
new Aws.LB.Inputs.ListenerDefaultActionForwardTargetGroupArgs
{
Arn = frontEndBlue.Arn,
Weight = 100,
},
new Aws.LB.Inputs.ListenerDefaultActionForwardTargetGroupArgs
{
Arn = frontEndGreen.Arn,
Weight = 0,
},
},
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.TargetGroup;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionForwardArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var frontEnd = new LoadBalancer("frontEnd");
var frontEndBlue = new TargetGroup("frontEndBlue");
var frontEndGreen = new TargetGroup("frontEndGreen");
var frontEndListener = new Listener("frontEndListener", ListenerArgs.builder()
.loadBalancerArn(frontEnd.arn())
.port(443)
.protocol("HTTPS")
.sslPolicy("ELBSecurityPolicy-2016-08")
.certificateArn("arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4")
.defaultActions(ListenerDefaultActionArgs.builder()
.type("forward")
.forward(ListenerDefaultActionForwardArgs.builder()
.targetGroups(
ListenerDefaultActionForwardTargetGroupArgs.builder()
.arn(frontEndBlue.arn())
.weight(100)
.build(),
ListenerDefaultActionForwardTargetGroupArgs.builder()
.arn(frontEndGreen.arn())
.weight(0)
.build())
.build())
.build())
.build());
}
}
resources:
frontEnd:
type: aws:lb:LoadBalancer
name: front_end
frontEndBlue:
type: aws:lb:TargetGroup
name: front_end_blue
frontEndGreen:
type: aws:lb:TargetGroup
name: front_end_green
frontEndListener:
type: aws:lb:Listener
name: front_end
properties:
loadBalancerArn: ${frontEnd.arn}
port: '443'
protocol: HTTPS
sslPolicy: ELBSecurityPolicy-2016-08
certificateArn: arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4
defaultActions:
- type: forward
forward:
targetGroups:
- arn: ${frontEndBlue.arn}
weight: 100
- arn: ${frontEndGreen.arn}
weight: 0
The forward block replaces the simple targetGroupArn with a targetGroups array, each entry specifying an ARN and weight. Weights determine the percentage of traffic each target group receives; here, 100% goes to the blue group while green receives 0%. Adjust weights to gradually shift traffic during deployments.
Authenticate users with Cognito before forwarding
Applications needing user authentication can delegate to Cognito User Pools, verifying identity before routing requests.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const frontEnd = new aws.lb.LoadBalancer("front_end", {});
const frontEndTargetGroup = new aws.lb.TargetGroup("front_end", {});
const pool = new aws.cognito.UserPool("pool", {});
const client = new aws.cognito.UserPoolClient("client", {});
const domain = new aws.cognito.UserPoolDomain("domain", {});
const frontEndListener = new aws.lb.Listener("front_end", {
loadBalancerArn: frontEnd.arn,
port: 80,
protocol: "HTTP",
defaultActions: [
{
type: "authenticate-cognito",
authenticateCognito: {
userPoolArn: pool.arn,
userPoolClientId: client.id,
userPoolDomain: domain.domain,
},
},
{
type: "forward",
targetGroupArn: frontEndTargetGroup.arn,
},
],
});
import pulumi
import pulumi_aws as aws
front_end = aws.lb.LoadBalancer("front_end")
front_end_target_group = aws.lb.TargetGroup("front_end")
pool = aws.cognito.UserPool("pool")
client = aws.cognito.UserPoolClient("client")
domain = aws.cognito.UserPoolDomain("domain")
front_end_listener = aws.lb.Listener("front_end",
load_balancer_arn=front_end.arn,
port=80,
protocol="HTTP",
default_actions=[
{
"type": "authenticate-cognito",
"authenticate_cognito": {
"user_pool_arn": pool.arn,
"user_pool_client_id": client.id,
"user_pool_domain": domain.domain,
},
},
{
"type": "forward",
"target_group_arn": front_end_target_group.arn,
},
])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cognito"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lb"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
frontEnd, err := lb.NewLoadBalancer(ctx, "front_end", nil)
if err != nil {
return err
}
frontEndTargetGroup, err := lb.NewTargetGroup(ctx, "front_end", nil)
if err != nil {
return err
}
pool, err := cognito.NewUserPool(ctx, "pool", nil)
if err != nil {
return err
}
client, err := cognito.NewUserPoolClient(ctx, "client", nil)
if err != nil {
return err
}
domain, err := cognito.NewUserPoolDomain(ctx, "domain", nil)
if err != nil {
return err
}
_, err = lb.NewListener(ctx, "front_end", &lb.ListenerArgs{
LoadBalancerArn: frontEnd.Arn,
Port: pulumi.Int(80),
Protocol: pulumi.String("HTTP"),
DefaultActions: lb.ListenerDefaultActionArray{
&lb.ListenerDefaultActionArgs{
Type: pulumi.String("authenticate-cognito"),
AuthenticateCognito: &lb.ListenerDefaultActionAuthenticateCognitoArgs{
UserPoolArn: pool.Arn,
UserPoolClientId: client.ID(),
UserPoolDomain: domain.Domain,
},
},
&lb.ListenerDefaultActionArgs{
Type: pulumi.String("forward"),
TargetGroupArn: frontEndTargetGroup.Arn,
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var frontEnd = new Aws.LB.LoadBalancer("front_end");
var frontEndTargetGroup = new Aws.LB.TargetGroup("front_end");
var pool = new Aws.Cognito.UserPool("pool");
var client = new Aws.Cognito.UserPoolClient("client");
var domain = new Aws.Cognito.UserPoolDomain("domain");
var frontEndListener = new Aws.LB.Listener("front_end", new()
{
LoadBalancerArn = frontEnd.Arn,
Port = 80,
Protocol = "HTTP",
DefaultActions = new[]
{
new Aws.LB.Inputs.ListenerDefaultActionArgs
{
Type = "authenticate-cognito",
AuthenticateCognito = new Aws.LB.Inputs.ListenerDefaultActionAuthenticateCognitoArgs
{
UserPoolArn = pool.Arn,
UserPoolClientId = client.Id,
UserPoolDomain = domain.Domain,
},
},
new Aws.LB.Inputs.ListenerDefaultActionArgs
{
Type = "forward",
TargetGroupArn = frontEndTargetGroup.Arn,
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.TargetGroup;
import com.pulumi.aws.cognito.UserPool;
import com.pulumi.aws.cognito.UserPoolClient;
import com.pulumi.aws.cognito.UserPoolDomain;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionAuthenticateCognitoArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var frontEnd = new LoadBalancer("frontEnd");
var frontEndTargetGroup = new TargetGroup("frontEndTargetGroup");
var pool = new UserPool("pool");
var client = new UserPoolClient("client");
var domain = new UserPoolDomain("domain");
var frontEndListener = new Listener("frontEndListener", ListenerArgs.builder()
.loadBalancerArn(frontEnd.arn())
.port(80)
.protocol("HTTP")
.defaultActions(
ListenerDefaultActionArgs.builder()
.type("authenticate-cognito")
.authenticateCognito(ListenerDefaultActionAuthenticateCognitoArgs.builder()
.userPoolArn(pool.arn())
.userPoolClientId(client.id())
.userPoolDomain(domain.domain())
.build())
.build(),
ListenerDefaultActionArgs.builder()
.type("forward")
.targetGroupArn(frontEndTargetGroup.arn())
.build())
.build());
}
}
resources:
frontEnd:
type: aws:lb:LoadBalancer
name: front_end
frontEndTargetGroup:
type: aws:lb:TargetGroup
name: front_end
pool:
type: aws:cognito:UserPool
client:
type: aws:cognito:UserPoolClient
domain:
type: aws:cognito:UserPoolDomain
frontEndListener:
type: aws:lb:Listener
name: front_end
properties:
loadBalancerArn: ${frontEnd.arn}
port: '80'
protocol: HTTP
defaultActions:
- type: authenticate-cognito
authenticateCognito:
userPoolArn: ${pool.arn}
userPoolClientId: ${client.id}
userPoolDomain: ${domain.domain}
- type: forward
targetGroupArn: ${frontEndTargetGroup.arn}
The defaultActions array chains multiple actions: first authenticateCognito verifies the user against the specified User Pool, then forward sends authenticated requests to the target group. The authenticateCognito block requires the User Pool ARN, Client ID, and Domain. Unauthenticated requests receive a redirect to the Cognito login page.
Require client certificates with mutual TLS
APIs needing strong client authentication can require client certificates, verifying both parties during the TLS handshake.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.lb.LoadBalancer("example", {loadBalancerType: "application"});
const exampleTargetGroup = new aws.lb.TargetGroup("example", {});
const exampleListener = new aws.lb.Listener("example", {
loadBalancerArn: example.id,
defaultActions: [{
targetGroupArn: exampleTargetGroup.id,
type: "forward",
}],
mutualAuthentication: {
mode: "verify",
trustStoreArn: "...",
},
});
import pulumi
import pulumi_aws as aws
example = aws.lb.LoadBalancer("example", load_balancer_type="application")
example_target_group = aws.lb.TargetGroup("example")
example_listener = aws.lb.Listener("example",
load_balancer_arn=example.id,
default_actions=[{
"target_group_arn": example_target_group.id,
"type": "forward",
}],
mutual_authentication={
"mode": "verify",
"trust_store_arn": "...",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lb"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := lb.NewLoadBalancer(ctx, "example", &lb.LoadBalancerArgs{
LoadBalancerType: pulumi.String("application"),
})
if err != nil {
return err
}
exampleTargetGroup, err := lb.NewTargetGroup(ctx, "example", nil)
if err != nil {
return err
}
_, err = lb.NewListener(ctx, "example", &lb.ListenerArgs{
LoadBalancerArn: example.ID(),
DefaultActions: lb.ListenerDefaultActionArray{
&lb.ListenerDefaultActionArgs{
TargetGroupArn: exampleTargetGroup.ID(),
Type: pulumi.String("forward"),
},
},
MutualAuthentication: &lb.ListenerMutualAuthenticationArgs{
Mode: pulumi.String("verify"),
TrustStoreArn: pulumi.String("..."),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.LB.LoadBalancer("example", new()
{
LoadBalancerType = "application",
});
var exampleTargetGroup = new Aws.LB.TargetGroup("example");
var exampleListener = new Aws.LB.Listener("example", new()
{
LoadBalancerArn = example.Id,
DefaultActions = new[]
{
new Aws.LB.Inputs.ListenerDefaultActionArgs
{
TargetGroupArn = exampleTargetGroup.Id,
Type = "forward",
},
},
MutualAuthentication = new Aws.LB.Inputs.ListenerMutualAuthenticationArgs
{
Mode = "verify",
TrustStoreArn = "...",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lb.LoadBalancer;
import com.pulumi.aws.lb.LoadBalancerArgs;
import com.pulumi.aws.lb.TargetGroup;
import com.pulumi.aws.lb.Listener;
import com.pulumi.aws.lb.ListenerArgs;
import com.pulumi.aws.lb.inputs.ListenerDefaultActionArgs;
import com.pulumi.aws.lb.inputs.ListenerMutualAuthenticationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new LoadBalancer("example", LoadBalancerArgs.builder()
.loadBalancerType("application")
.build());
var exampleTargetGroup = new TargetGroup("exampleTargetGroup");
var exampleListener = new Listener("exampleListener", ListenerArgs.builder()
.loadBalancerArn(example.id())
.defaultActions(ListenerDefaultActionArgs.builder()
.targetGroupArn(exampleTargetGroup.id())
.type("forward")
.build())
.mutualAuthentication(ListenerMutualAuthenticationArgs.builder()
.mode("verify")
.trustStoreArn("...")
.build())
.build());
}
}
resources:
example:
type: aws:lb:LoadBalancer
properties:
loadBalancerType: application
exampleTargetGroup:
type: aws:lb:TargetGroup
name: example
exampleListener:
type: aws:lb:Listener
name: example
properties:
loadBalancerArn: ${example.id}
defaultActions:
- targetGroupArn: ${exampleTargetGroup.id}
type: forward
mutualAuthentication:
mode: verify
trustStoreArn: '...'
The mutualAuthentication block enables certificate-based client authentication. The mode property controls enforcement: “verify” requires valid client certificates, while “passthrough” forwards certificate data to backends without validation. The trustStoreArn points to a trust store containing the CA certificates used to validate client certificates.
Beyond these examples
These snippets focus on specific listener-level features: traffic routing (forwarding, weighted splits, redirects), authentication (Cognito, OIDC, JWT, mutual TLS), and protocol handling (HTTP, HTTPS, TLS, GENEVE). They’re intentionally minimal rather than full load balancing solutions.
The examples reference pre-existing infrastructure such as load balancers (Application, Network, Gateway types), target groups with registered targets, TLS certificates (IAM or ACM), Cognito User Pools and clients (for authentication examples), and trust stores with CA certificates (for mutual TLS). They focus on configuring the listener rather than provisioning everything around it.
To keep things focused, common listener patterns are omitted, including:
- Listener rules for path-based or host-based routing
- ALPN policy configuration for protocol negotiation
- Custom HTTP header manipulation (routing* properties)
- CORS and security headers (routingHttpResponse* properties)
- TCP idle timeout tuning (tcpIdleTimeoutSeconds)
- Fixed-response actions for maintenance pages
These omissions are intentional: the goal is to illustrate how each listener feature is wired, not provide drop-in load balancing modules. See the Load Balancer Listener resource reference for all available configuration options.
Let's configure AWS Application Load Balancer Listeners
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Protocols & Load Balancer Types
HTTP or HTTPS (default: HTTP). For Network Load Balancers, use TCP, TLS, UDP, or TCP_UDP. Gateway Load Balancers don’t use the protocol property. Note that UDP and TCP_UDP aren’t valid if dual-stack mode is enabled.port property isn’t valid for Gateway Load Balancers.SSL/TLS Configuration
HTTPS. Specify it using the certificateArn property.certificateArn property for the default certificate, then use the aws.lb.ListenerCertificate resource to add additional certificates.HTTPS or TLS. The default is ELBSecurityPolicy-2016-08.TLS. Valid values are HTTP1Only, HTTP2Only, HTTP2Optional, HTTP2Preferred, and None.Actions & Routing
forward (to target groups), redirect (URL redirects), fixed-response (static responses), authenticate-cognito (AWS Cognito auth), authenticate-oidc (OpenID Connect auth), and jwt-validation (JWT token validation).forward action with a forward block containing multiple targetGroups, each with an arn and weight property (0-100). For example, set blue to weight 100 and green to weight 0 for initial deployment.routing* properties (CORS headers, security headers, etc.) can only be set if the protocol is HTTP or HTTPS for Application Load Balancers. They’re not supported for Network Load Balancers or Gateway Load Balancers.Configuration Constraints
TCP on a Network Load Balancer or with a Gateway Load Balancer. Valid values are 60 to 6000 seconds, with a default of 350 seconds. It’s not supported for Application Load Balancers.loadBalancerArn property is immutable. You’ll need to recreate the listener to associate it with a different load balancer.Using a different cloud?
Explore networking guides for other cloud providers: