Configure AWS Network Manager Connect Peers

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 FREE

Frequently Asked Questions

Protocol & Configuration
What's the difference between GRE and NO_ENCAP protocols for Connect peers?

The protocol determines which properties you need:

  • GRE protocol - Requires insideCidrBlocks for BGP peering IP addresses (tunnel-based)
  • NO_ENCAP protocol - Requires subnetArn instead (tunnel-less, direct connection)

The protocol is set on the Connect attachment, not the Connect peer itself.

What are the minimum required properties to create a Connect peer?
You must provide 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.
Can I use the same Connect peer configuration for both GRE and NO_ENCAP?
No, the two protocols require mutually exclusive properties. GRE uses insideCidrBlocks for tunnel endpoints, while NO_ENCAP uses subnetArn for direct subnet connectivity.
BGP & Networking
How do I configure BGP for my Connect peer?
Set the 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.
What IP addresses do I use for insideCidrBlocks?
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
When do I need to use AttachmentAccepter with my Connect peer?
Use 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.
Why does my Connect peer creation fail with attachment errors?
The Connect attachment must be accepted before creating the peer. If using AttachmentAccepter, add it to the Connect peer’s dependsOn array to ensure proper creation order.
Resource Lifecycle
What properties can't I change after creating a Connect peer?

These properties are immutable and force replacement if changed:

  • bgpOptions
  • connectAttachmentId
  • peerAddress
  • coreNetworkAddress
  • insideCidrBlocks

Plan your configuration carefully before creation.

Can I change the BGP ASN after creating the Connect peer?
No, 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: