The aws:directconnect/gatewayAssociation:GatewayAssociation resource, part of the Pulumi AWS provider, links a Direct Connect gateway to a VPN gateway or transit gateway, enabling private connectivity between on-premises networks and AWS VPCs. This guide focuses on three capabilities: VPN gateway associations, transit gateway associations, and route advertisement control via allowed prefixes.
Associations require an existing Direct Connect gateway and either a VPN gateway or transit gateway. The examples are intentionally small. Combine them with your own Direct Connect infrastructure and network topology.
Connect a Direct Connect gateway to a VPN gateway
Organizations with on-premises data centers establish private connectivity to AWS VPCs by associating Direct Connect gateways with VPN gateways.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.directconnect.Gateway("example", {
name: "example",
amazonSideAsn: "64512",
});
const exampleVpc = new aws.ec2.Vpc("example", {cidrBlock: "10.255.255.0/28"});
const exampleVpnGateway = new aws.ec2.VpnGateway("example", {vpcId: exampleVpc.id});
const exampleGatewayAssociation = new aws.directconnect.GatewayAssociation("example", {
dxGatewayId: example.id,
associatedGatewayId: exampleVpnGateway.id,
});
import pulumi
import pulumi_aws as aws
example = aws.directconnect.Gateway("example",
name="example",
amazon_side_asn="64512")
example_vpc = aws.ec2.Vpc("example", cidr_block="10.255.255.0/28")
example_vpn_gateway = aws.ec2.VpnGateway("example", vpc_id=example_vpc.id)
example_gateway_association = aws.directconnect.GatewayAssociation("example",
dx_gateway_id=example.id,
associated_gateway_id=example_vpn_gateway.id)
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/directconnect"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := directconnect.NewGateway(ctx, "example", &directconnect.GatewayArgs{
Name: pulumi.String("example"),
AmazonSideAsn: pulumi.String("64512"),
})
if err != nil {
return err
}
exampleVpc, err := ec2.NewVpc(ctx, "example", &ec2.VpcArgs{
CidrBlock: pulumi.String("10.255.255.0/28"),
})
if err != nil {
return err
}
exampleVpnGateway, err := ec2.NewVpnGateway(ctx, "example", &ec2.VpnGatewayArgs{
VpcId: exampleVpc.ID(),
})
if err != nil {
return err
}
_, err = directconnect.NewGatewayAssociation(ctx, "example", &directconnect.GatewayAssociationArgs{
DxGatewayId: example.ID(),
AssociatedGatewayId: exampleVpnGateway.ID(),
})
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.DirectConnect.Gateway("example", new()
{
Name = "example",
AmazonSideAsn = "64512",
});
var exampleVpc = new Aws.Ec2.Vpc("example", new()
{
CidrBlock = "10.255.255.0/28",
});
var exampleVpnGateway = new Aws.Ec2.VpnGateway("example", new()
{
VpcId = exampleVpc.Id,
});
var exampleGatewayAssociation = new Aws.DirectConnect.GatewayAssociation("example", new()
{
DxGatewayId = example.Id,
AssociatedGatewayId = exampleVpnGateway.Id,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.directconnect.Gateway;
import com.pulumi.aws.directconnect.GatewayArgs;
import com.pulumi.aws.ec2.Vpc;
import com.pulumi.aws.ec2.VpcArgs;
import com.pulumi.aws.ec2.VpnGateway;
import com.pulumi.aws.ec2.VpnGatewayArgs;
import com.pulumi.aws.directconnect.GatewayAssociation;
import com.pulumi.aws.directconnect.GatewayAssociationArgs;
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 Gateway("example", GatewayArgs.builder()
.name("example")
.amazonSideAsn("64512")
.build());
var exampleVpc = new Vpc("exampleVpc", VpcArgs.builder()
.cidrBlock("10.255.255.0/28")
.build());
var exampleVpnGateway = new VpnGateway("exampleVpnGateway", VpnGatewayArgs.builder()
.vpcId(exampleVpc.id())
.build());
var exampleGatewayAssociation = new GatewayAssociation("exampleGatewayAssociation", GatewayAssociationArgs.builder()
.dxGatewayId(example.id())
.associatedGatewayId(exampleVpnGateway.id())
.build());
}
}
resources:
example:
type: aws:directconnect:Gateway
properties:
name: example
amazonSideAsn: '64512'
exampleVpc:
type: aws:ec2:Vpc
name: example
properties:
cidrBlock: 10.255.255.0/28
exampleVpnGateway:
type: aws:ec2:VpnGateway
name: example
properties:
vpcId: ${exampleVpc.id}
exampleGatewayAssociation:
type: aws:directconnect:GatewayAssociation
name: example
properties:
dxGatewayId: ${example.id}
associatedGatewayId: ${exampleVpnGateway.id}
The dxGatewayId identifies your Direct Connect gateway, while associatedGatewayId points to the VPN gateway attached to your VPC. Without explicit allowedPrefixes configuration, the association advertises the VPC’s entire CIDR block to your on-premises network.
Connect a Direct Connect gateway to a transit gateway
Transit gateways act as regional network hubs, connecting multiple VPCs and on-premises networks through a single Direct Connect gateway association.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.directconnect.Gateway("example", {
name: "example",
amazonSideAsn: "64512",
});
const exampleTransitGateway = new aws.ec2transitgateway.TransitGateway("example", {});
const exampleGatewayAssociation = new aws.directconnect.GatewayAssociation("example", {
dxGatewayId: example.id,
associatedGatewayId: exampleTransitGateway.id,
allowedPrefixes: [
"10.255.255.0/30",
"10.255.255.8/30",
],
});
import pulumi
import pulumi_aws as aws
example = aws.directconnect.Gateway("example",
name="example",
amazon_side_asn="64512")
example_transit_gateway = aws.ec2transitgateway.TransitGateway("example")
example_gateway_association = aws.directconnect.GatewayAssociation("example",
dx_gateway_id=example.id,
associated_gateway_id=example_transit_gateway.id,
allowed_prefixes=[
"10.255.255.0/30",
"10.255.255.8/30",
])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/directconnect"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2transitgateway"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := directconnect.NewGateway(ctx, "example", &directconnect.GatewayArgs{
Name: pulumi.String("example"),
AmazonSideAsn: pulumi.String("64512"),
})
if err != nil {
return err
}
exampleTransitGateway, err := ec2transitgateway.NewTransitGateway(ctx, "example", nil)
if err != nil {
return err
}
_, err = directconnect.NewGatewayAssociation(ctx, "example", &directconnect.GatewayAssociationArgs{
DxGatewayId: example.ID(),
AssociatedGatewayId: exampleTransitGateway.ID(),
AllowedPrefixes: pulumi.StringArray{
pulumi.String("10.255.255.0/30"),
pulumi.String("10.255.255.8/30"),
},
})
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.DirectConnect.Gateway("example", new()
{
Name = "example",
AmazonSideAsn = "64512",
});
var exampleTransitGateway = new Aws.Ec2TransitGateway.TransitGateway("example");
var exampleGatewayAssociation = new Aws.DirectConnect.GatewayAssociation("example", new()
{
DxGatewayId = example.Id,
AssociatedGatewayId = exampleTransitGateway.Id,
AllowedPrefixes = new[]
{
"10.255.255.0/30",
"10.255.255.8/30",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.directconnect.Gateway;
import com.pulumi.aws.directconnect.GatewayArgs;
import com.pulumi.aws.ec2transitgateway.TransitGateway;
import com.pulumi.aws.directconnect.GatewayAssociation;
import com.pulumi.aws.directconnect.GatewayAssociationArgs;
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 Gateway("example", GatewayArgs.builder()
.name("example")
.amazonSideAsn("64512")
.build());
var exampleTransitGateway = new TransitGateway("exampleTransitGateway");
var exampleGatewayAssociation = new GatewayAssociation("exampleGatewayAssociation", GatewayAssociationArgs.builder()
.dxGatewayId(example.id())
.associatedGatewayId(exampleTransitGateway.id())
.allowedPrefixes(
"10.255.255.0/30",
"10.255.255.8/30")
.build());
}
}
resources:
example:
type: aws:directconnect:Gateway
properties:
name: example
amazonSideAsn: '64512'
exampleTransitGateway:
type: aws:ec2transitgateway:TransitGateway
name: example
exampleGatewayAssociation:
type: aws:directconnect:GatewayAssociation
name: example
properties:
dxGatewayId: ${example.id}
associatedGatewayId: ${exampleTransitGateway.id}
allowedPrefixes:
- 10.255.255.0/30
- 10.255.255.8/30
When associating with a transit gateway, the allowedPrefixes property controls which CIDR ranges are advertised to your on-premises network. This enables selective routing across your multi-VPC topology.
Control route advertisement with allowed prefixes
By default, associations advertise the entire VPC CIDR block. Some deployments need to advertise only specific subnets to control routing and limit exposure.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.directconnect.Gateway("example", {
name: "example",
amazonSideAsn: "64512",
});
const exampleVpc = new aws.ec2.Vpc("example", {cidrBlock: "10.255.255.0/28"});
const exampleVpnGateway = new aws.ec2.VpnGateway("example", {vpcId: exampleVpc.id});
const exampleGatewayAssociation = new aws.directconnect.GatewayAssociation("example", {
dxGatewayId: example.id,
associatedGatewayId: exampleVpnGateway.id,
allowedPrefixes: [
"210.52.109.0/24",
"175.45.176.0/22",
],
});
import pulumi
import pulumi_aws as aws
example = aws.directconnect.Gateway("example",
name="example",
amazon_side_asn="64512")
example_vpc = aws.ec2.Vpc("example", cidr_block="10.255.255.0/28")
example_vpn_gateway = aws.ec2.VpnGateway("example", vpc_id=example_vpc.id)
example_gateway_association = aws.directconnect.GatewayAssociation("example",
dx_gateway_id=example.id,
associated_gateway_id=example_vpn_gateway.id,
allowed_prefixes=[
"210.52.109.0/24",
"175.45.176.0/22",
])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/directconnect"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := directconnect.NewGateway(ctx, "example", &directconnect.GatewayArgs{
Name: pulumi.String("example"),
AmazonSideAsn: pulumi.String("64512"),
})
if err != nil {
return err
}
exampleVpc, err := ec2.NewVpc(ctx, "example", &ec2.VpcArgs{
CidrBlock: pulumi.String("10.255.255.0/28"),
})
if err != nil {
return err
}
exampleVpnGateway, err := ec2.NewVpnGateway(ctx, "example", &ec2.VpnGatewayArgs{
VpcId: exampleVpc.ID(),
})
if err != nil {
return err
}
_, err = directconnect.NewGatewayAssociation(ctx, "example", &directconnect.GatewayAssociationArgs{
DxGatewayId: example.ID(),
AssociatedGatewayId: exampleVpnGateway.ID(),
AllowedPrefixes: pulumi.StringArray{
pulumi.String("210.52.109.0/24"),
pulumi.String("175.45.176.0/22"),
},
})
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.DirectConnect.Gateway("example", new()
{
Name = "example",
AmazonSideAsn = "64512",
});
var exampleVpc = new Aws.Ec2.Vpc("example", new()
{
CidrBlock = "10.255.255.0/28",
});
var exampleVpnGateway = new Aws.Ec2.VpnGateway("example", new()
{
VpcId = exampleVpc.Id,
});
var exampleGatewayAssociation = new Aws.DirectConnect.GatewayAssociation("example", new()
{
DxGatewayId = example.Id,
AssociatedGatewayId = exampleVpnGateway.Id,
AllowedPrefixes = new[]
{
"210.52.109.0/24",
"175.45.176.0/22",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.directconnect.Gateway;
import com.pulumi.aws.directconnect.GatewayArgs;
import com.pulumi.aws.ec2.Vpc;
import com.pulumi.aws.ec2.VpcArgs;
import com.pulumi.aws.ec2.VpnGateway;
import com.pulumi.aws.ec2.VpnGatewayArgs;
import com.pulumi.aws.directconnect.GatewayAssociation;
import com.pulumi.aws.directconnect.GatewayAssociationArgs;
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 Gateway("example", GatewayArgs.builder()
.name("example")
.amazonSideAsn("64512")
.build());
var exampleVpc = new Vpc("exampleVpc", VpcArgs.builder()
.cidrBlock("10.255.255.0/28")
.build());
var exampleVpnGateway = new VpnGateway("exampleVpnGateway", VpnGatewayArgs.builder()
.vpcId(exampleVpc.id())
.build());
var exampleGatewayAssociation = new GatewayAssociation("exampleGatewayAssociation", GatewayAssociationArgs.builder()
.dxGatewayId(example.id())
.associatedGatewayId(exampleVpnGateway.id())
.allowedPrefixes(
"210.52.109.0/24",
"175.45.176.0/22")
.build());
}
}
resources:
example:
type: aws:directconnect:Gateway
properties:
name: example
amazonSideAsn: '64512'
exampleVpc:
type: aws:ec2:Vpc
name: example
properties:
cidrBlock: 10.255.255.0/28
exampleVpnGateway:
type: aws:ec2:VpnGateway
name: example
properties:
vpcId: ${exampleVpc.id}
exampleGatewayAssociation:
type: aws:directconnect:GatewayAssociation
name: example
properties:
dxGatewayId: ${example.id}
associatedGatewayId: ${exampleVpnGateway.id}
allowedPrefixes:
- 210.52.109.0/24
- 175.45.176.0/22
The allowedPrefixes property overrides the default behavior, advertising only the specified CIDR ranges to your on-premises network. This provides fine-grained control over which AWS resources are reachable from your data center.
Beyond these examples
These snippets focus on specific gateway association features: VPN gateway and transit gateway associations, and route advertisement control. They’re intentionally minimal rather than full hybrid network deployments.
The examples assume pre-existing infrastructure such as Direct Connect gateway, VPN gateway or transit gateway, and VPC with configured CIDR blocks. They focus on configuring the association rather than provisioning the underlying network infrastructure.
To keep things focused, common association patterns are omitted, including:
- Cross-account associations (proposalId and associatedGatewayOwnerAccountId)
- Multi-region gateway associations (region property and provider aliases)
These omissions are intentional: the goal is to illustrate how each association feature is wired, not provide drop-in hybrid networking modules. See the Direct Connect Gateway Association resource reference for all available configuration options.
Let's configure AWS Direct Connect Gateway Associations
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Cross-Account & Cross-Region Setup
aws.directconnect.GatewayAssociationProposal in the account owning the VGW or transit gateway. Then, in the account owning the Direct Connect gateway, create an aws.directconnect.GatewayAssociation with proposalId and associatedGatewayOwnerAccountId set.associatedGatewayId is in a different region, create a provider alias for that region and reference it in your resource configuration.dxGatewayId and associatedGatewayId.Configuration & Gateway Types
associatedGatewayType output will be virtualPrivateGateway or transitGateway.Drift Detection & State Management
allowedPrefixes defaults to the VPC CIDR, you must configure it explicitly to enable drift detection. Without this, Pulumi may not detect changes to the allowed prefixes.Immutability & Lifecycle
dxGatewayId, associatedGatewayId, and associatedGatewayOwnerAccountId properties are immutable. Changing any of these requires recreating the association.associatedGatewayId is immutable. To associate a different gateway, you must delete and recreate the association.Using a different cloud?
Explore networking guides for other cloud providers: