Configuring VNS3 via the API

Configuring your controller requires the following:

  1. Upload a license with PUT /license
  2. Configuring and accepting the license parameters with PUT /license/parameters
  3. Generating a keyset with PUT /keyset

The following variables will be referred to in shell scripts:

apiuser="api"
apipassword="youvns3password"
vns3host="55.55.55.55"

Upload license

The license is an encrypted file provided to you by Cohesive Networks. Contact us @ support@cohesive.net for a license. We’ll get you up and running in a day. The license contains information about the topology such as allowed number of controllers and clientpacks. Upgrading simply requires uploading a new license. It also contains default topology information such as the network range to use for your clientpacks and overlay network.

Using cURL

curl -k -X PUT -u $apiuser:$apipassword \
    -H 'Content-Type: text/plain' \
    --data-binary @/home/user/vns3/vns3-license.txt \
    https://$vns3host:8000/api/license > license-upload.resp.log

Explanation:

  • -k: Do not verify SSL (pre-licensed controllers do not have SSL installed yet)
  • -X PUT: perform a PUT request
  • -u $apiuser:$apipassword: authenticate with Basic authentication
  • -H 'Content-Type: text/plain': inform API of content-type
  • > license-upload.resp.log: capture output in log file

Response:

{
  "response": {
    "license": "accepted",
    "finalized": false,
    "license_present": true,
    "capabilities": [
      "IPsec",
      "eBGP",
      "LinearAddressing",
      "LinearAddressingConfigurable",
      "CloudWAN",
      "Containers"
    ],
    "default_topology": {
      "managers": [
        {
          "manager_id": 1,
          "overlay_ipaddress": {
            "ip_address": "100.127.255.253",
            "octets": [
              100,
              127,
              255,
              253
            ]
          },
          "asn": 65001
        },
        {
          "manager_id": 2,
          "overlay_ipaddress": {
            "ip_address": "100.127.255.252",
            "octets": [
              100,
              127,
              255,
              252
            ]
          },
          "asn": 65002
        },
        {
          "manager_id": 3,
          "overlay_ipaddress": {
            "ip_address": "100.127.255.251",
            "octets": [
              100,
              127,
              255,
              251
            ]
          },
          "asn": 65003
        },
        {
          "manager_id": 4,
          "overlay_ipaddress": {
            "ip_address": "100.127.255.250",
            "octets": [
              100,
              127,
              255,
              250
            ]
          },
          "asn": 65004
        }
      ],
      "clients": [
        {
          "ip_address": "100.127.255.193",
          "octets": [
            100,
            127,
            255,
            193
          ]
        }
      ],
      "total_clients": 25,
      "overlay_max_clients": 25,
      "overlay_subnet": "100.127.255.192/26",
      "ipsec_max_endpoints": 4,
      "ipsec_max_subnets": 16
    }
  }
}

Using Python SDK

from cohesivenet import VNS3Client, Configuration

license_file = "/home/user/vns3/vns3-license.txt"
vns3_client = VNS3Client(
    Configuration(
        host=host,
        username=username,
        password=password,
        verify_ssl=False
    )
)

with open(license_file) as f:
    license_file_data = f.read().strip()
    resp = vns3_client.licensing.upload_license(license_file_data)
    print(resp.json())

Configure and accept license parameters

The license contains VNS3 parameters that can be configured before generating your keyset. These include the subnet to be used by VNS3 for the overlay network or ASNs to assign to controllers. You can view the optional parameters on our API docs. Here we are just going to accept the default network configuration.

Using cURL

curl -k -X PUT -u $apiuser:$apipassword \
    -H 'Content-Type: application/json' \
    -d '{"default":"true"}' \
    https://$vns3host:8000/api/license/parameters > license-params.resp.log

We pass the params with -d '{"default":"true"}'.

Response:

{
  "response": {
    "license": "accepted",
    "finalized": true,
    "parameters": {}
  }
}

Accepting the license parameters will trigger a system reboot as VNS3 configures itself with the finalized parameters. To continue in our automation, we’ll need to poll on VNS3 until its available again:

function wait_for_api () {
    local apiuser=$1
    local apipassword=$2
    local host=$3
    local timeout=${4:-2}
    local sleeptime=${5:-3}
    local successString="vns3_version\|UnauthorizedError"
    echo "Start: Waiting for API. host=$host"
    while :
        do
            apistatus=`curl -k -m $timeout -X GET -u $apiuser:$apipassword https://$host:8000/api/config 2>/dev/null`
            echo $apistatus | grep $successString > /dev/null 2>&1
            if [ $? == 0 ] ; then
                break
            fi

            echo "Sleep: Waiting for API. host=$host sleep=${sleeptime}s"
            sleep $sleeptime
        done
}

wait_for_api $apiuser $apipassword $vns3host

Using Python SDK

resp = vns3_client.licensing.put_set_license_parameters(
    default=True
)
print(resp.json())
# Waiting for system to configure and reboot.
vns3_client.sys_admin.wait_for_api(
    timeout=reboot_timeout,
    wait_for_reboot=True
)

Generating keyset

Finally, you must generate a keyset for use by VNS3. This keyset is the set of x509 credentials that VNS3 will use in its encrypted connections with VPN clients and other VNS3 controllers. These credentials are stored on the locked down device and are completely inaccessible and secure.

Using cURL

curl -k -X PUT -u $apiuser:$apipassword \
    -d "{\"token\":\"mysupersecrettoken\"}" \
    -H 'Content-Type: application/json' \
    https://$vns3host:8000/api/keyset > keyset.resp.log

Response:

{
  "response": {
    "keyset_present": false,
    "in_progress": true,
    "started_at": "2020-05-28T16:50:36.684+00:00",
    "started_at_i": 1590684636,
    "running": 0
  }
}

Keyset generation happens in the background and so we must poll on the result with GET /keyset. We can write a little bash function for that:

function wait_for_keyset () {
    local apiuser=$1
    local apipassword=$2
    local host=$3
    echo "== Start: Waiting for keyset"
    while :
        do
        apistatus=`curl -k -X GET -u $apiuser:$apipassword https://$host:8000/api/keyset 2>&1`
            echo $apistatus | grep '"keyset_present":false'
            if [ $? != 0 ] ; then
                break
            fi
            
            echo "=== Sleep: Waiting for keyset"
            sleep 1
        done
}

Using Python SDK

The python SDK makes this a little easier with some polling logic built in:


resp = vns3_client.config.put_keyset(token="mysupersecrettoken")
print(resp.json())
keyset_resp = vns3_client.config.wait_for_keyset(timeout=keyset_timeout)
print(keyset_resp.json())

Fetching configuration from another controller

When your topology has more than 1 VNS3 controller meshed together, you will need to configure all controllers with the same keyset. This is done by configuring one controller as we’ve done above by uploading and configuring a license and then generating the keyset. Then for each of the other controllers, you will fetch the topology configuration from the first VNS3 controller.

For example, for a VNS3 topology with 2 controllers:

IDController IP
154.36.10.2
248.90.23.1

We can configure controller 1 as detailed above. For controller 2, we can fetch the configuration with PUT /keyset by passing a “source” argument:

# Must provide the secret token
curl -k -X PUT -u $apiuser:$apipassword \
    -d "{\"token\":\"mysupersecrettoken\", \"source\": \"54.36.10.2\"}" \
    -H 'Content-Type: application/json' \
    https://$vns3host:8000/api/keyset > keyset.resp.log

And with the python SDK:

resp = client.config.put_keyset(
    source="54.36.10.2",
    token="mysupersecrettoken"
)

Helper functions in the SDK

We provide some helper functions in the Python SDK for configuring controllers:

cohesivenet.macros.config.setup_controller: This will handle uploading your license, setting parameters and generating the keyset. It will handle polling on VNS3 until configuration is complete.

from cohesivenet.macros import config

resp = config.setup_controller(
    root_client,
    "My topology name",
    "/home/user/vns3/vns3-license.txt",
    license_parameters={"default": True},
    keyset_parameters={"token": "mysupersecrettoken"},
    reboot_timeout=240,
    keyset_timeout=240,
)

cohesivenet.macros.config.fetch_keysets: Fetch keysets for the other controllers in your mesh after configuring your first controller.

from cohesivenet.macros import config, connect

# Connect to all peer controllers
hosts_connection_params = [
  {"host": "48.90.23.1", "password": controller_password}
]
peer_clients = connect.get_clients(hosts_connection_params)
responses = config.fetch_keysets(
    peer_clients, "54.36.10.2", "mysupersecrettoken"
)