The aws:networkmanager/connectPeer:ConnectPeer resource, part of the Pulumi AWS provider, establishes BGP peering sessions between AWS Cloud WAN core networks and external networks through Connect attachments. This guide focuses on two capabilities: GRE-based BGP peering and tunnel-less direct subnet connections.
Connect peers depend on a Cloud WAN core network, a VPC attachment as transport, and a Connect attachment with protocol configuration. The examples are intentionally small. Combine them with your own core network, VPC infrastructure, and routing configuration.
Establish BGP peering with GRE encapsulation
Most Connect peer deployments use GRE tunnels to establish BGP sessions between your core network and on-premises routers, providing encrypted routing over existing infrastructure.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.networkmanager.VpcAttachment("example", {
subnetArns: exampleAwsSubnet.map(__item => __item.arn),
coreNetworkId: exampleAwsccNetworkmanagerCoreNetwork.id,
vpcArn: exampleAwsVpc.arn,
});
const exampleConnectAttachment = new aws.networkmanager.ConnectAttachment("example", {
coreNetworkId: exampleAwsccNetworkmanagerCoreNetwork.id,
transportAttachmentId: example.id,
edgeLocation: example.edgeLocation,
options: {
protocol: "GRE",
},
});
const exampleConnectPeer = new aws.networkmanager.ConnectPeer("example", {
connectAttachmentId: exampleConnectAttachment.id,
peerAddress: "127.0.0.1",
bgpOptions: {
peerAsn: "65000",
},
insideCidrBlocks: ["172.16.0.0/16"],
});
import pulumi
import pulumi_aws as aws
example = aws.networkmanager.VpcAttachment("example",
subnet_arns=[__item["arn"] for __item in example_aws_subnet],
core_network_id=example_awscc_networkmanager_core_network["id"],
vpc_arn=example_aws_vpc["arn"])
example_connect_attachment = aws.networkmanager.ConnectAttachment("example",
core_network_id=example_awscc_networkmanager_core_network["id"],
transport_attachment_id=example.id,
edge_location=example.edge_location,
options={
"protocol": "GRE",
})
example_connect_peer = aws.networkmanager.ConnectPeer("example",
connect_attachment_id=example_connect_attachment.id,
peer_address="127.0.0.1",
bgp_options={
"peer_asn": "65000",
},
inside_cidr_blocks=["172.16.0.0/16"])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/networkmanager"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
var splat0 []interface{}
for _, val0 := range exampleAwsSubnet {
splat0 = append(splat0, val0.Arn)
}
example, err := networkmanager.NewVpcAttachment(ctx, "example", &networkmanager.VpcAttachmentArgs{
SubnetArns: toPulumiArray(splat0),
CoreNetworkId: pulumi.Any(exampleAwsccNetworkmanagerCoreNetwork.Id),
VpcArn: pulumi.Any(exampleAwsVpc.Arn),
})
if err != nil {
return err
}
exampleConnectAttachment, err := networkmanager.NewConnectAttachment(ctx, "example", &networkmanager.ConnectAttachmentArgs{
CoreNetworkId: pulumi.Any(exampleAwsccNetworkmanagerCoreNetwork.Id),
TransportAttachmentId: example.ID(),
EdgeLocation: example.EdgeLocation,
Options: &networkmanager.ConnectAttachmentOptionsArgs{
Protocol: pulumi.String("GRE"),
},
})
if err != nil {
return err
}
_, err = networkmanager.NewConnectPeer(ctx, "example", &networkmanager.ConnectPeerArgs{
ConnectAttachmentId: exampleConnectAttachment.ID(),
PeerAddress: pulumi.String("127.0.0.1"),
BgpOptions: &networkmanager.ConnectPeerBgpOptionsArgs{
PeerAsn: pulumi.String("65000"),
},
InsideCidrBlocks: pulumi.StringArray{
pulumi.String("172.16.0.0/16"),
},
})
if err != nil {
return err
}
return nil
})
}
func toPulumiArray(arr []) pulumi.Array {
var pulumiArr pulumi.Array
for _, v := range arr {
pulumiArr = append(pulumiArr, pulumi.(v))
}
return pulumiArr
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.NetworkManager.VpcAttachment("example", new()
{
SubnetArns = exampleAwsSubnet.Select(__item => __item.Arn).ToList(),
CoreNetworkId = exampleAwsccNetworkmanagerCoreNetwork.Id,
VpcArn = exampleAwsVpc.Arn,
});
var exampleConnectAttachment = new Aws.NetworkManager.ConnectAttachment("example", new()
{
CoreNetworkId = exampleAwsccNetworkmanagerCoreNetwork.Id,
TransportAttachmentId = example.Id,
EdgeLocation = example.EdgeLocation,
Options = new Aws.NetworkManager.Inputs.ConnectAttachmentOptionsArgs
{
Protocol = "GRE",
},
});
var exampleConnectPeer = new Aws.NetworkManager.ConnectPeer("example", new()
{
ConnectAttachmentId = exampleConnectAttachment.Id,
PeerAddress = "127.0.0.1",
BgpOptions = new Aws.NetworkManager.Inputs.ConnectPeerBgpOptionsArgs
{
PeerAsn = "65000",
},
InsideCidrBlocks = new[]
{
"172.16.0.0/16",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.networkmanager.VpcAttachment;
import com.pulumi.aws.networkmanager.VpcAttachmentArgs;
import com.pulumi.aws.networkmanager.ConnectAttachment;
import com.pulumi.aws.networkmanager.ConnectAttachmentArgs;
import com.pulumi.aws.networkmanager.inputs.ConnectAttachmentOptionsArgs;
import com.pulumi.aws.networkmanager.ConnectPeer;
import com.pulumi.aws.networkmanager.ConnectPeerArgs;
import com.pulumi.aws.networkmanager.inputs.ConnectPeerBgpOptionsArgs;
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 VpcAttachment("example", VpcAttachmentArgs.builder()
.subnetArns(exampleAwsSubnet.stream().map(element -> element.arn()).collect(toList()))
.coreNetworkId(exampleAwsccNetworkmanagerCoreNetwork.id())
.vpcArn(exampleAwsVpc.arn())
.build());
var exampleConnectAttachment = new ConnectAttachment("exampleConnectAttachment", ConnectAttachmentArgs.builder()
.coreNetworkId(exampleAwsccNetworkmanagerCoreNetwork.id())
.transportAttachmentId(example.id())
.edgeLocation(example.edgeLocation())
.options(ConnectAttachmentOptionsArgs.builder()
.protocol("GRE")
.build())
.build());
var exampleConnectPeer = new ConnectPeer("exampleConnectPeer", ConnectPeerArgs.builder()
.connectAttachmentId(exampleConnectAttachment.id())
.peerAddress("127.0.0.1")
.bgpOptions(ConnectPeerBgpOptionsArgs.builder()
.peerAsn("65000")
.build())
.insideCidrBlocks("172.16.0.0/16")
.build());
}
}
The Connect peer establishes a BGP session with your on-premises router at the specified peerAddress. The bgpOptions block configures the peer’s ASN for BGP negotiation. The insideCidrBlocks property defines the IP ranges used inside the GRE tunnel for BGP peering. The Connect attachment’s protocol must be set to “GRE” for this configuration.
Connect without GRE using direct subnet attachment
Some deployments bypass GRE encapsulation by connecting directly to a subnet, reducing overhead when tunneling isn’t required.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.networkmanager.VpcAttachment("example", {
subnetArns: exampleAwsSubnet.map(__item => __item.arn),
coreNetworkId: exampleAwsccNetworkmanagerCoreNetwork.id,
vpcArn: exampleAwsVpc.arn,
});
const exampleConnectAttachment = new aws.networkmanager.ConnectAttachment("example", {
coreNetworkId: exampleAwsccNetworkmanagerCoreNetwork.id,
transportAttachmentId: example.id,
edgeLocation: example.edgeLocation,
options: {
protocol: "NO_ENCAP",
},
});
const exampleConnectPeer = new aws.networkmanager.ConnectPeer("example", {
connectAttachmentId: exampleConnectAttachment.id,
peerAddress: "127.0.0.1",
bgpOptions: {
peerAsn: "65000",
},
subnetArn: example2.arn,
});
import pulumi
import pulumi_aws as aws
example = aws.networkmanager.VpcAttachment("example",
subnet_arns=[__item["arn"] for __item in example_aws_subnet],
core_network_id=example_awscc_networkmanager_core_network["id"],
vpc_arn=example_aws_vpc["arn"])
example_connect_attachment = aws.networkmanager.ConnectAttachment("example",
core_network_id=example_awscc_networkmanager_core_network["id"],
transport_attachment_id=example.id,
edge_location=example.edge_location,
options={
"protocol": "NO_ENCAP",
})
example_connect_peer = aws.networkmanager.ConnectPeer("example",
connect_attachment_id=example_connect_attachment.id,
peer_address="127.0.0.1",
bgp_options={
"peer_asn": "65000",
},
subnet_arn=example2["arn"])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/networkmanager"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
var splat0 []interface{}
for _, val0 := range exampleAwsSubnet {
splat0 = append(splat0, val0.Arn)
}
example, err := networkmanager.NewVpcAttachment(ctx, "example", &networkmanager.VpcAttachmentArgs{
SubnetArns: toPulumiArray(splat0),
CoreNetworkId: pulumi.Any(exampleAwsccNetworkmanagerCoreNetwork.Id),
VpcArn: pulumi.Any(exampleAwsVpc.Arn),
})
if err != nil {
return err
}
exampleConnectAttachment, err := networkmanager.NewConnectAttachment(ctx, "example", &networkmanager.ConnectAttachmentArgs{
CoreNetworkId: pulumi.Any(exampleAwsccNetworkmanagerCoreNetwork.Id),
TransportAttachmentId: example.ID(),
EdgeLocation: example.EdgeLocation,
Options: &networkmanager.ConnectAttachmentOptionsArgs{
Protocol: pulumi.String("NO_ENCAP"),
},
})
if err != nil {
return err
}
_, err = networkmanager.NewConnectPeer(ctx, "example", &networkmanager.ConnectPeerArgs{
ConnectAttachmentId: exampleConnectAttachment.ID(),
PeerAddress: pulumi.String("127.0.0.1"),
BgpOptions: &networkmanager.ConnectPeerBgpOptionsArgs{
PeerAsn: pulumi.String("65000"),
},
SubnetArn: pulumi.Any(example2.Arn),
})
if err != nil {
return err
}
return nil
})
}
func toPulumiArray(arr []) pulumi.Array {
var pulumiArr pulumi.Array
for _, v := range arr {
pulumiArr = append(pulumiArr, pulumi.(v))
}
return pulumiArr
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.NetworkManager.VpcAttachment("example", new()
{
SubnetArns = exampleAwsSubnet.Select(__item => __item.Arn).ToList(),
CoreNetworkId = exampleAwsccNetworkmanagerCoreNetwork.Id,
VpcArn = exampleAwsVpc.Arn,
});
var exampleConnectAttachment = new Aws.NetworkManager.ConnectAttachment("example", new()
{
CoreNetworkId = exampleAwsccNetworkmanagerCoreNetwork.Id,
TransportAttachmentId = example.Id,
EdgeLocation = example.EdgeLocation,
Options = new Aws.NetworkManager.Inputs.ConnectAttachmentOptionsArgs
{
Protocol = "NO_ENCAP",
},
});
var exampleConnectPeer = new Aws.NetworkManager.ConnectPeer("example", new()
{
ConnectAttachmentId = exampleConnectAttachment.Id,
PeerAddress = "127.0.0.1",
BgpOptions = new Aws.NetworkManager.Inputs.ConnectPeerBgpOptionsArgs
{
PeerAsn = "65000",
},
SubnetArn = example2.Arn,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.networkmanager.VpcAttachment;
import com.pulumi.aws.networkmanager.VpcAttachmentArgs;
import com.pulumi.aws.networkmanager.ConnectAttachment;
import com.pulumi.aws.networkmanager.ConnectAttachmentArgs;
import com.pulumi.aws.networkmanager.inputs.ConnectAttachmentOptionsArgs;
import com.pulumi.aws.networkmanager.ConnectPeer;
import com.pulumi.aws.networkmanager.ConnectPeerArgs;
import com.pulumi.aws.networkmanager.inputs.ConnectPeerBgpOptionsArgs;
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 VpcAttachment("example", VpcAttachmentArgs.builder()
.subnetArns(exampleAwsSubnet.stream().map(element -> element.arn()).collect(toList()))
.coreNetworkId(exampleAwsccNetworkmanagerCoreNetwork.id())
.vpcArn(exampleAwsVpc.arn())
.build());
var exampleConnectAttachment = new ConnectAttachment("exampleConnectAttachment", ConnectAttachmentArgs.builder()
.coreNetworkId(exampleAwsccNetworkmanagerCoreNetwork.id())
.transportAttachmentId(example.id())
.edgeLocation(example.edgeLocation())
.options(ConnectAttachmentOptionsArgs.builder()
.protocol("NO_ENCAP")
.build())
.build());
var exampleConnectPeer = new ConnectPeer("exampleConnectPeer", ConnectPeerArgs.builder()
.connectAttachmentId(exampleConnectAttachment.id())
.peerAddress("127.0.0.1")
.bgpOptions(ConnectPeerBgpOptionsArgs.builder()
.peerAsn("65000")
.build())
.subnetArn(example2.arn())
.build());
}
}
When the Connect attachment uses the “NO_ENCAP” protocol, the Connect peer attaches directly to a subnet via subnetArn instead of using insideCidrBlocks. This eliminates GRE tunnel overhead while still establishing BGP peering with your external router.
Beyond these examples
These snippets focus on specific Connect peer features: GRE and tunnel-less BGP peering, and Connect attachment integration. They’re intentionally minimal rather than full Cloud WAN deployments.
The examples rely on pre-existing infrastructure such as AWS Cloud WAN core network, VPC attachments as transport, and subnets for NO_ENCAP protocol. They focus on configuring the Connect peer rather than provisioning the surrounding Cloud WAN infrastructure.
To keep things focused, common Connect peer patterns are omitted, including:
- Attachment acceptance workflows (AttachmentAccepter)
- Core network address configuration (coreNetworkAddress)
- Resource tagging (tags)
These omissions are intentional: the goal is to illustrate how each Connect peer feature is wired, not provide drop-in Cloud WAN modules. See the Connect Peer resource reference for all available configuration options.
Let's configure AWS Network Manager Connect Peers
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Protocol & Configuration
The protocol determines which properties you need:
- GRE protocol - Requires
insideCidrBlocksfor BGP peering IP addresses (tunnel-based) - NO_ENCAP protocol - Requires
subnetArninstead (tunnel-less, direct connection)
The protocol is set on the Connect attachment, not the Connect peer itself.
connectAttachmentId, peerAddress, and bgpOptions (with peerAsn). Additionally, you need either insideCidrBlocks (for GRE) or subnetArn (for NO_ENCAP) depending on your Connect attachment’s protocol.insideCidrBlocks for tunnel endpoints, while NO_ENCAP uses subnetArn for direct subnet connectivity.BGP & Networking
bgpOptions property with at minimum a peerAsn value (the BGP Autonomous System Number for your peer). This establishes the BGP session between your core network and on-premises network.insideCidrBlocks specifies the inside IP addresses used for BGP peering when using GRE protocol. These are the tunnel endpoint addresses, such as 172.16.0.0/16 shown in the examples.Attachment Management
aws.networkmanager.AttachmentAccepter when your attachments require explicit acceptance (typically in cross-account scenarios). Add dependsOn to your Connect peer to ensure it waits for attachment acceptance before creation.AttachmentAccepter, add it to the Connect peer’s dependsOn array to ensure proper creation order.Resource Lifecycle
These properties are immutable and force replacement if changed:
bgpOptionsconnectAttachmentIdpeerAddresscoreNetworkAddressinsideCidrBlocks
Plan your configuration carefully before creation.
bgpOptions is immutable. Changing the peer ASN requires destroying and recreating the Connect peer.Using a different cloud?
Explore networking guides for other cloud providers: