Deploy VMware Cloud on AWS Route Based VPN with API

Gilles Chekroun
Lead VMware Cloud on AWS Specialist
---
Following my articles on AWS Transit Gateway here and here, I found it quite complex to setup the VPN connection and the 2 tunnels from TGW VPN attachment to VMC route based VPN using the GUI.

AWS VPN Naming and VMC VPN relationship

When creating the AWS TGW VPN attachment, AWS gives the possibility to "download configuration file"

AWS - VMC relationship:

Once this is clear, it's time to map these parameters to our API Calls.

Five API calls 

For properly setting a Route Based VPN to AWS TGW we need 5 API calls:
  • Get the NSX-T Proxy URL
  • Get the SDDC Public IP
  • Set Local AS Number
  • Set BGP Neighbour ID
  • Set VPN Tunnels
Before we can do any API calls into VMC we need a few parameter like "Refresh-Token", "Org-ID", "SDDC-ID". Refer to my earlier post here on how to get them.

Get NSX-T Proxy URL

This API call will get "Org-ID, SDDC-ID and Session-Token" and will return the NSX-T Proxy URL you need in the subsequent calls

def getNSXTproxy(org_id, sddc_id, sessiontoken):
    myHeader = {'csp-auth-token': sessiontoken}
    myURL = "{}/vmc/api/orgs/{}/sddcs/{}".format(strProdURL, org_id, sddc_id)
    response = requests.get(myURL, headers=myHeader)
    json_response = response.json()
    proxy_url = json_response['resource_config']['nsx_api_public_endpoint_url']
    overview_url = (proxy_url + "/cloud-service/api/v1/infra/sddc-user-config")
    return overview_url

Get SDDC Public IP

This API Call will retrieve the SDDC Public IP
def getSDDCpublicIP(proxy_url, sessiontoken):
    myHeader = {'csp-auth-token': sessiontoken}
    myURL = proxy_url
    response = requests.get(myURL, headers=myHeader)
    json_response = response.json()
    pub_IP = json_response['vpn_internet_ips'][0]
    return pub_IP

Set Local AS Number

The default Local ASN is 64512 - you can set ASN between 64512 and 65534
This API call will get "Org-ID, SDDC-ID, Session-Token and ASN Number" and will set it.
def set_bgp_asn(proxy_url, org_id, sddc_id, sessiontoken, vmc_asn):
    myHeader = {
        'csp-auth-token': sessiontoken,        'content-type': 'application/json'    }
    myURL = "{}/api/orgs/{}/sddcs/{}/sks-nsxt-manager/policy/api/v1/infra/tier-0s/
vmc/locale-services/default/bgp".format(proxy_url, org_id, sddc_id)
    payload = {
        "local_as_num": vmc_asn
        }
    response = requests.patch(myURL, json=payload, headers=myHeader)
    json_response = response.json()
    print(json_response)
    return

Set BGP Neighbour ID

This API call will set the proper BGP neighbour ID to use on the next call
def setBGPnb(proxy_url, org_id, sddc_id, sessiontoken,neighbor_id, remote_asn, remote_ip):
    myHeader = {'csp-auth-token': sessiontoken}
    myURL = "{}/api/orgs/{}/sddcs/{}/sks-nsxt-manager/policy/api/v1/infra/tier-0s/
vmc/locale-services/default/bgp/neighbors/{}".format(proxy_url, org_id, 
sddc_id, neighbor_id)
    strRequest = {
        "resource_type": "BgpNeighborConfig",
        "id": neighbor_id,
        "remote_as_num": remote_asn,
        "neighbor_address": remote_ip
    }
    response = requests.put(myURL, json=strRequest, headers=myHeader)
    json_response = response.json()
    if str(response.status_code) != "200":
        print(json_response)
    return

Set VPN Tunnels

This API call will create one VPN Tunnel using the parameters from the AWS side configuration file.
def setVPN(proxy_url, org_id, sddc_id, sessiontoken, name, public_ip, remote_ip, local_ip, 
passw, neighbor_id):
    myHeader = {'csp-auth-token': sessiontoken}
    myURL = "{}/api/orgs/{}/sddcs/{}/sks-nsxt-manager/policy/api/v1/infra/tier-0s/
vmc/locale-services/default/l3vpns/{}".format(proxy_url, org_id, sddc_id, name)
    strRequest = {
        "display_name": name,
        "enabled": "true",
        "local_address": public_ip,
        "remote_private_address": remote_ip,
        "remote_public_address": remote_ip,
        "passphrases": [passw],
        "tunnel_digest_algorithms": ["SHA2_256"],
        "ike_digest_algorithms": ["SHA2_256"],
        "ike_encryption_algorithms": ["AES_256"],
        "enable_perfect_forward_secrecy": "true",
        "dh_groups": ["GROUP14"],
        "ike_version": "IKE_V1",
        "l3vpn_session": {
            "resource_type": "RouteBasedL3VpnSession",
            "tunnel_subnets": [
                {
                    "ip_addresses": [
                        local_ip
                    ],
                    "prefix_length": 30
                }
            ],
            "default_rule_logging": "false",
            "force_whitelisting": "false",
            "routing_config_path": "/infra/tier-0s/vmc/locale-services/default/bgp/neighbors/{}"
.format(neighbor_id)
        },
        "tunnel_encryption_algorithms": ["AES_256"]
    }
    response = requests.put(myURL, json=strRequest, headers=myHeader)
    json_response = response.json()
    if str(response.status_code) != "200":
        print(json_response)
    return

Main procedure for setting up the VPN Tunnels


# --------------------------------------------
# ---------------- Main ----------------------
# --------------------------------------------
session_token = getAccessToken(Refresh_Token)
sddcID = getSDDC_ID(ORG_ID, session_token)
proxy = getNSXTproxy(ORG_ID, sddcID, session_token)
set_bgp_asn(proxy, ORG_ID, sddcID, session_token, VMC_ASN)
Public_IP = getSDDCpublicIP(proxy,session_token)
neighbor_1 = "IPSEC_T1"
neighbor_2 = "IPSEC_T2"
setBGPnb(proxy,ORG_ID, sddcID,session_token, neighbor_1, T1_BGP_remote_ASN, T1_BGP_remote_ip)
print("Tunnel 1 IPsec OK")
setVPN(proxy, ORG_ID, sddcID, session_token, "Tunnel-1", Public_IP, T1_remote_public_ip, T1_BGP_local_ip, T1_pass, neighbor_1)
print("Tunnel 1 route based VPN OK")
setBGPnb(proxy,ORG_ID, sddcID,session_token, neighbor_2, T2_BGP_remote_ASN, T2_BGP_remote_ip)
print("Tunnel 2 IPsec OK")
setVPN(proxy, ORG_ID, sddcID, session_token, "Tunnel-2", Public_IP, T2_remote_public_ip, T2_BGP_local_ip, T2_pass, neighbor_2)
print("Tunnel 2 route based VPN OK")




Results on the VMware Cloud on AWS SDDC GUI

Note:
The following networks are reserved for internal use. The network you specify for BGP Local IP/Prefix Length must not overlap any of them.
169.254.0.2/28
169.254.10.1/24
169.254.11.1/24
169.254.12.1/24
169.254.13.1/24

169.254.101.253/30

THANK YOU !!

Comments

  1. Interesting! I have never thought about using API. This would open a lot of cool things, I would definitely try and let you know. May I ask you a question, please? What's the name of the tool you are using for designing the illustration?

    ReplyDelete
    Replies
    1. Great stuff, Gilles!
      By any chance, do you have any blog post showing how to set up a policy-based VPN?

      Delete
    2. I did the powerCLI module for it. Use the search in the blog. You will find it

      Delete

Post a Comment

Populars

Egress VPC and AWS Transit Gateway (Part1)

AWS Transitive routing with Transit Gateways in the same region

Build a VMware Cloud on AWS Content Library using AWS S3