For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Python script to install license and configuration for IPSec tunneling on a VE instance

Problem this snippet solves:

This script can be called from the command line and used to reach out to a VE to license it, perform minimum configuration and provision an IPSec interface-mode tunnel.


This is not best practice, not hardened, etc. This is a foundation, not a solution.


How to use this snippet:

The script has built-in CLI help.

Code :

#!/usr/bin/env python3

import argparse,json,requests,time
from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

def icontrol_get(host,username,password,path):
  apiCall = requests.session()
  apiCall.headers.update({'Content-type':'application/json'})
  apiCall.auth = (username,password)
  apiUri = 'https://' + host + path
   try:
  apiResponse = apiCall.get(apiUri,verify=False)
   except requests.exceptions.RequestException as e:
   print('{"responseStatus":"error","action":"get","host":"' + host + '","username":"' + username + '","path":"' + path + '","errorMsg":"' + str(e) + '"}')
   return(apiResponse.text)

def icontrol_post(host,username,password,path,api_payload):
  apiCall = requests.session()
  apiCall.headers.update({'Content-type':'application/json'})
  apiCall.auth = (username,password)
  apiUri = 'https://' + host + path
   try:
  apiResponse = apiCall.post(apiUri,verify=False,data=json.dumps(api_payload))
   except requests.exceptions.RequestException as e:
   print('{"responseStatus":"error","action":"post","host":"' + host + '","username":"' + username + '","path":"' + path + '"},"payload":"' + api_payload + '","errorMsg":"' + str(e) + '"}')
   return(apiResponse.text)

def icontrol_put(host,username,password,path,api_payload):
  apiCall = requests.session()
  apiCall.headers.update({'Content-type':'application/json'})
  apiCall.auth = (username,password)
  apiUri = 'https://' + host + path
   try:
  apiResponse = apiCall.put(apiUri,verify=False,data=json.dumps(api_payload))
   except requests.exceptions.RequestException as e:
   print('{"responseStatus":"error","action":"put","host":"' + host + '","username":"' + username + '","path":"' + path + '"},"payload":"' + api_payload + '","errorMsg":"' + str(e) + '"}')
   return(apiResponse.text)

def icontrol_patch(host,username,password,path,api_payload):
  apiCall = requests.session()
  apiCall.headers.update({'Content-type':'application/json'})
  apiCall.auth = (username,password)
  apiUri = 'https://' + host + path
   try:
  apiResponse = apiCall.patch(apiUri,verify=False,data=json.dumps(api_payload))
   except requests.exceptions.RequestException as e:
   print('{"responseStatus":"error","action":"patch","host":"' + host + '","username":"' + username + '","path":"' + path + '"},"payload":"' + api_payload + '","errorMsg":"' + str(e) + '"}')
   return(apiResponse.text)

def icontrol_delete(host,username,password,path):
  apiCall = requests.session()
  apiCall.headers.update({'Content-type':'application/json'})
  apiCall.auth = (username,password)
  apiUri = 'https://' + host + path
   try:
  apiResponse = apiCall.delete(apiUri,verify=False)
   except requests.exceptions.RequestException as e:
   print('{"responseStatus":"error","action":"delete","host":"' + host + '","username":"' + username + '","path":"' + path + '"},"errorMsg":"' + str(e) + '"}')
   return(apiResponse.text)

## Parse the command line arguments#cmdargs = argparse.ArgumentParser()
cmdargs.add_argument('--f5restip',action='store',required=True,type=str,help='ip of BIG-IP REST interface, typically the mgmt ip')
cmdargs.add_argument('--username',action='store',required=True,type=str,help='username for REST authentication')
cmdargs.add_argument('--password',action='store',required=True,type=str,help='password for REST authentication')
cmdargs.add_argument('--licensekey',action='store',required=False,type=str,help='license key for licensing')
cmdargs.add_argument('--hostname',action='store',required=False,type=str,help='hostname to configure on the BIG-IP (must be FQDN)')
cmdargs.add_argument('--ntpserver',action='store',required=False,type=str,help='NTP server to add to the BIG-IP (IP or FQDN)')
cmdargs.add_argument('--dnsserver',action='store',required=False,type=str,help='DNS server to add to the BIG-IP (IP address)')
cmdargs.add_argument('--newlocalselfip',action='store',required=True,type=str,help='creates the private self-ip address of the VE where the public address is mapped (CIDR notation)')
cmdargs.add_argument('--newlocalselfipgateway',action='store',required=True,type=str,help='creates the private self-ip subnet gateway for server communications')
cmdargs.add_argument('--localserversubnet',action='store',required=True,type=str,help='the local VM subnet in CIDR notation')
cmdargs.add_argument('--localselfip',action='store',required=True,type=str,help='the private self-ip address of the VE where the public address is mapped')
cmdargs.add_argument('--localpublicip',action='store',required=True,type=str,help='the public IP address of the VNA')
cmdargs.add_argument('--remotepublicip',action='store',required=True,type=str,help='the public IP address of the remote IPSec peer')
cmdargs.add_argument('--presharedkey',action='store',required=True,type=str,help='the pre-shared key for encryption')
cmdargs.add_argument('--tunnelsourcenet',action='store',required=True,type=str,help='CIDR notated source network, can be 0.0.0.0/0 to tunnel all traffic')
cmdargs.add_argument('--tunneldestinationnet',action='store',required=True,type=str,help='CIDR notated destination network, the remote destination subnet to tunnel, can be 0.0.0.0/0 to let static routes control tunneling')
cmdargs.add_argument('--tunnelstaticroutenet',action='store',required=True,type=str,help='CIDR notated destination network to statically route across the tunnel (this makes the decision to tunnel or not)')
cmdargs.add_argument('--tunnelselfiplocal',action='store',required=True,type=str,help='CIDR notated tunnel self-IP address, a new address assigned to the tunnel (ie 192.168.1.1/30')
cmdargs.add_argument('--tunnelselfipremote',action='store',required=True,type=str,help='CIDR notated tunnel self-IP address on the remote end, a new address assigned to the tunnel (ie 192.168.1.1/30')
cmdargs.add_argument('--bgpas',action='store',required=True,type=str,help='AS number for BGP process and neighbor')
parsed_args = cmdargs.parse_args()

host = parsed_args.f5restip
username = parsed_args.username
password = parsed_args.password
license_key = parsed_args.licensekey
hostname = parsed_args.hostname
ntpserver = parsed_args.ntpserver
dnsserver = parsed_args.dnsserver
vpn = {}
vpn['local-self-ip'] = parsed_args.localselfip
vpn['local-public-ip'] = parsed_args.localpublicip
vpn['remote-public-ip'] = parsed_args.remotepublicip
vpn['pre-shared-key'] = parsed_args.presharedkey
vpn['tunnel-source-network'] = parsed_args.tunnelsourcenet
vpn['tunnel-destination-network'] = parsed_args.tunneldestinationnet
vpn['tunnel-static-route-network'] = parsed_args.tunnelstaticroutenet
vpn['tunnel-name'] = 'ipsec_peer-' + vpn['remote-public-ip']
vpn['tunnel-self-ip'] = parsed_args.tunnelselfiplocal
vpn['new-local-self-ip'] = parsed_args.newlocalselfip
vpn['new-local-self-ip-gateway'] = parsed_args.newlocalselfipgateway
vpn['local-server-subnet'] = parsed_args.localserversubnet
vpn['tunnel-self-ip-remote'] = parsed_args.tunnelselfipremote
vpn['bgp-as'] = parsed_args.bgpas

# License the VEif license_key is not None:
   print('Licensing ' + host + ' with key ' + license_key)
  apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/sys/license',{"command":"install","registrationKey":license_key})
   if 'New license installed' in apiCallResponse:
   print('License installed successfully. Waiting for service restart.')
  time.sleep(60)
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print("License key not specified - skipping licensing")

# Disable the GUI setup wizard since we're configuring via RESTprint('Disabling the GUI Setup Wizard')
apiCallResponse = icontrol_patch(host,username,password,'/mgmt/tm/sys/global-settings',{"guiSetup":"disabled"})
if '"kind":"tm:sys:global-settings:global-settingsstate"' and '"guiSetup":"disabled"' in apiCallResponse:
   print('Success!')
else:
   print('Error! ' + apiCallResponse)
   quit()

# Set the hostname if specifiedif hostname is not None:
   print('Setting the hostname to ' + hostname + ' on ' + host)
  apiCallResponse = icontrol_patch(host, username, password, '/mgmt/tm/sys/global-settings',{"hostname":hostname})
   if '"kind":"tm:sys:global-settings:global-settingsstate"' and '"hostname":"' + hostname + '"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('Hostname not specified - skipping hostname configuration')

# Set the DNS server if specifiedif dnsserver is not None:
   print('Adding DNS server ' + dnsserver + ' to ' + host)
  apiCallResponse = icontrol_patch(host,username,password,'/mgmt/tm/sys/dns',{"nameServers":[dnsserver]})
   if '"kind":"tm:sys:dns:dnsstate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('DNS server not specified - skipping DNS server configuration')

# Set the NTP server if specifiedif ntpserver is not None:
   print('Adding NTP server ' + ntpserver + ' to ' + host)
  apiCallResponse = icontrol_patch(host,username,password,'/mgmt/tm/sys/ntp',{"servers":[ntpserver]})
   if '"kind":"tm:sys:ntp:ntpstate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('NTP server not specified - skipping NTP server configuration')

# Configure the local VLAN and self-IP if specifiedif vpn['new-local-self-ip'] is not None:
   # create external VLAN untagged   print('Creating the external VLAN')
  apiPayload = {}
  apiPayload['name'] = 'external'   apiPayload['interfaces'] = ['1.1']
  apiPayload['partition'] = 'Common'   apiPayload['mtu'] = 1500   apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/net/vlan',apiPayload)
   if '"kind":"tm:net:vlan:vlanstate"' in apiCallResponse :
   print('Success!')
   elif 'already exists' in apiCallResponse:
   print('Object exists; skipping item configuration')
   else:
   print('Error! ' + apiCallResponse)
   quit()
   # create the data interface self-IP   print('Creating the self-IP address ' + vpn['local-self-ip'])
  apiPayload = {}
  apiPayload['name'] = vpn['new-local-self-ip']
  apiPayload['address'] = vpn['new-local-self-ip']
  apiPayload['allowService'] = 'all'   apiPayload['interfaces'] = ['1.1']
  apiPayload['partition'] = 'Common'   apiPayload['trafficGroup'] = 'traffic-group-local-only'   apiPayload['vlan'] = 'external'   apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/net/self',apiPayload)
   if '"kind":"tm:net:self:selfstate"' in apiCallResponse :
   print('Success!')
   elif 'already exists' in apiCallResponse:
   print('Object exists; skipping item configuration')
   else:
   print('Error! ' + apiCallResponse)
   quit()

## Begin IPSec tunnel configuration steps## Create the IPSec policyprint('Creating the IPSec Policy (' + vpn['tunnel-name'] + ')')
apiPayload = {}
apiPayload['name'] = vpn['tunnel-name']
apiPayload['ikePhase2AuthAlgorithm'] = 'aes-gcm128'apiPayload['ikePhase2EncryptAlgorithm'] = 'aes-gcm128'apiPayload['ikePhase2PerfectForwardSecrecy'] = 'none'apiPayload['ikePhase2Lifetime'] = 1440apiPayload['ikePhase2LifetimeKilobytes'] = 0apiPayload['mode'] = 'interface'apiPayload['protocol'] = 'esp'apiPayload['ipcomp'] = 'none'apiPayload['partition'] = 'Common'apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/net/ipsec/ipsec-policy',apiPayload)
if '"kind":"tm:net:ipsec:ipsec-policy:ipsec-policystate"' in apiCallResponse :
   print('Success!')
elif 'already exists' in apiCallResponse:
   print('Object exists; updating with new configuration')
  apiCallResponse = icontrol_put(host, username, password, '/mgmt/tm/net/ipsec/ipsec-policy/' + vpn['tunnel-name'], apiPayload)
   if '"kind":"tm:net:ipsec:ipsec-policy:ipsec-policystate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('Error! ' + apiCallResponse)
   quit()

# Create the IPSec traffic selectorprint('Creating the IPSec traffic selector (' + vpn['tunnel-name'] + ')')
apiPayload = {}
apiPayload['name'] = vpn['tunnel-name']
apiPayload['partition'] = 'Common'apiPayload['action'] = 'protect'apiPayload['sourceAddress'] = vpn['tunnel-source-network']
apiPayload['sourcePort'] = 0apiPayload['destinationAddress'] = vpn['tunnel-destination-network']
apiPayload['destinationPort'] = 0apiPayload['direction'] = 'both'apiPayload['ipProtocol'] = 255apiPayload['ipsecPolicy'] = vpn['tunnel-name']
apiPayload['order'] = 0apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/net/ipsec/traffic-selector',apiPayload)
if '"kind":"tm:net:ipsec:traffic-selector:traffic-selectorstate"' in apiCallResponse:
   print('Success!')
elif 'already exists' in apiCallResponse:
   print('Object exists; updating with new configuration')
  apiCallResponse = icontrol_put(host, username, password, '/mgmt/tm/net/ipsec/traffic-selector/' + vpn['tunnel-name'], apiPayload)
   if '"kind":"tm:net:ipsec:traffic-selector:traffic-selectorstate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('Error! ' + apiCallResponse)
   quit()

# Set the default IPSec traffic selector to high orderprint('Setting the default IPSec traffic selector to order 100')
apiPayload = {}
apiPayload['order'] = 100apiCallResponse = icontrol_patch(host,username,password,'/mgmt/tm/net/ipsec/traffic-selector/default-traffic-selector-interface',apiPayload)
if '"kind":"tm:net:ipsec:traffic-selector:traffic-selectorstate"' in apiCallResponse:
   print('Success!')
else:
   print('Error! ' + apiCallResponse)
   quit()

# Create the IKE peerprint('Creating the IKE peer (' + vpn['tunnel-name'] + ')')
apiPayload = {}
apiPayload['name'] = vpn['tunnel-name']
apiPayload['myIdType'] = 'address'apiPayload['myIdValue'] = vpn['local-public-ip']
apiPayload['peersIdType'] = 'address'apiPayload['peersIdValue'] = vpn['remote-public-ip']
apiPayload['phase1AuthMethod'] = 'pre-shared-key'apiPayload['phase1EncryptAlgorithm'] = 'aes256'apiPayload['phase1HashAlgorithm'] = 'sha256'apiPayload['phase1PerfectForwardSecrecy'] = 'modp1024'apiPayload['prf'] = 'sha256'apiPayload['presharedKey'] = vpn['pre-shared-key']
apiPayload['remoteAddress'] = vpn['remote-public-ip']
apiPayload['version'] = ['v2']
apiPayload['dpdDelay'] = 30apiPayload['lifetime'] = 1440apiPayload['mode'] = 'main'apiPayload['natTraversal'] = 'off'apiPayload['passive'] = 'false'apiPayload['generatePolicy'] = 'off'apiPayload['trafficSelector'] = [vpn['tunnel-name']]
apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/net/ipsec/ike-peer',apiPayload)
if '"kind":"tm:net:ipsec:ike-peer:ike-peerstate"' in apiCallResponse:
   print('Success!')
elif 'already exists' in apiCallResponse:
   print('Object exists; updating with new configuration')
  apiCallResponse = icontrol_put(host, username, password, '/mgmt/tm/net/ipsec/ike-peer/' + vpn['tunnel-name'], apiPayload)
   if '"kind":"tm:net:ipsec:ike-peer:ike-peerstate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('Error! ' + apiCallResponse)
   quit()

# Create the tunnel profileprint('Creating the tunnel profile (' + vpn['tunnel-name'] + ')')
apiPayload = {}
apiPayload['name'] = vpn['tunnel-name']
apiPayload['defaultsFrom'] = '/Common/ipsec'apiPayload['trafficSelector'] = vpn['tunnel-name']
apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/net/tunnels/ipsec',apiPayload)
if '"kind":"tm:net:tunnels:ipsec:ipsecstate"' in apiCallResponse:
   print('Success!')
elif 'already exists' in apiCallResponse:
   print('Object exists; updating with new configuration')
  apiCallResponse = icontrol_put(host, username, password, '/mgmt/tm/net/tunnels/ipsec/' + vpn['tunnel-name'], apiPayload)
   if '"kind":"tm:net:tunnels:ipsec:ipsecstate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('Error! ' + apiCallResponse)
   quit()

# Create the tunnel objectprint('Creating the tunnel object (' + vpn['tunnel-name'] + ')')
apiPayload = {}
apiPayload['name'] = vpn['tunnel-name']
apiPayload['autoLasthop'] = 'default'apiPayload['idleTimeout'] = 300apiPayload['key'] = 0apiPayload['localAddress'] = vpn['local-self-ip']
apiPayload['mode'] = 'bidirectional'apiPayload['mtu'] = 0apiPayload['profile'] = vpn['tunnel-name']
apiPayload['remoteAddress'] = vpn['remote-public-ip']
apiPayload['tos'] = 'preserve'apiPayload['transparent'] = 'disabled'apiPayload['usePmtu'] = 'enabled'apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/net/tunnels/tunnel',apiPayload)
if '"kind":"tm:net:tunnels:tunnel:tunnelstate"' in apiCallResponse:
   print('Success!')
elif 'already exists' in apiCallResponse:
   print('Object exists; updating with new configuration')
  apiCallResponse = icontrol_put(host, username, password, '/mgmt/tm/net/tunnels/tunnel/' + vpn['tunnel-name'], apiPayload)
   if '"kind":"tm:net:tunnels:tunnel:tunnelstate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('Error! ' + apiCallResponse)
   quit()

# Create the self-IP for the tunnel-routeprint('Creating the local tunnel interface self-IP (' + vpn['tunnel-name'] + ')')
apiPayload = {}
apiPayload['name'] = vpn['tunnel-name']
apiPayload['address'] = vpn['tunnel-self-ip']
apiPayload['vlan'] = vpn['tunnel-name']
apiPayload['traffic-group'] = 'traffic-group-local-only'apiPayload['allowService'] = 'all'apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/net/self',apiPayload)
if '"kind":"tm:net:self:selfstate"' in apiCallResponse:
   print('Success!')
elif 'already exists' in apiCallResponse:
   print('Object exists; updating with new configuration')
  apiCallResponse = icontrol_put(host, username, password, '/mgmt/tm/net/self/' + vpn['tunnel-name'], apiPayload)
   if '"kind":"tm:net:self:selfstate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('Error! ' + apiCallResponse)
   quit()

# Point the peer route over the tunnelprint('Creating the peer static route (' + vpn['tunnel-name'] + ')')
apiPayload = {}
apiPayload['name'] = vpn['tunnel-name']
apiPayload['tmInterface'] = vpn['tunnel-name']
apiPayload['network'] = vpn['tunnel-self-ip-remote'] + '/32'apiPayload['mtu'] = 0apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/net/route',apiPayload)
if '"kind":"tm:net:route:routestate"' in apiCallResponse:
   print('Success!')
elif 'already exists' in apiCallResponse:
   print('Object exists; updating with new configuration')
  apiCallResponse = icontrol_put(host, username, password, '/mgmt/tm/net/route/~Common~'+vpn['tunnel-name'], apiPayload)
   if '"kind":"tm:net:route:routestate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('Error! ' + apiCallResponse)
   quit()

# Create the local server routeprint('Creating the default static route to ' + vpn['new-local-self-ip-gateway'])
apiPayload = {}
apiPayload['name'] = 'local-servers'apiPayload['gw'] = vpn['new-local-self-ip-gateway']
apiPayload['network'] = vpn['local-server-subnet']
apiCallResponse = icontrol_post(host, username, password, '/mgmt/tm/net/route', apiPayload)
if '"kind":"tm:net:route:routestate"' in apiCallResponse:
   print('Success!')
elif 'already exists' in apiCallResponse:
   print('Object exists; updating with new configuration')
  apiCallResponse = icontrol_put(host, username, password, '/mgmt/tm/net/route/~Common~local-servers', apiPayload)
   if '"kind":"tm:net:route:routestate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('Error! ' + apiCallResponse)
   quit()

# Create the remote peer routerprint('Creating the IPSec peer route to ' + vpn['remote-public-ip'])
apiPayload = {}
apiPayload['name'] = 'remote-peer'apiPayload['gw'] = vpn['new-local-self-ip-gateway']
apiPayload['network'] = vpn['remote-public-ip']
apiCallResponse = icontrol_post(host, username, password, '/mgmt/tm/net/route', apiPayload)
if '"kind":"tm:net:route:routestate"' in apiCallResponse:
   print('Success!')
elif 'already exists' in apiCallResponse:
   print('Object exists; updating with new configuration')
  apiCallResponse = icontrol_put(host, username, password, '/mgmt/tm/net/route/~Common~remote-peer', apiPayload)
   if '"kind":"tm:net:route:routestate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('Error! ' + apiCallResponse)
   quit()


# Create the default IP forwarding virtual serverprint('Creating the default IP forwarding virtual server')
apiPayload = {}
apiPayload['name'] = 'ipsec_forwarding_vs'apiPayload['destination'] = '/Common/0.0.0.0:0'apiPayload['ipProtocol'] = 'any'apiPayload['mask'] = '0.0.0.0'apiPayload['source'] = '0.0.0.0/0'apiPayload['ipForward'] = TrueapiPayload['sourceAddressTranslation'] = {'type':'none'}
apiPayload['sourcePort'] = 'preserve-strict'apiPayload['profiles'] = ['/Common/fastL4']
apiPayload['enabled'] = TrueapiPayload['translateAddress'] = 'disabled'apiPayload['translatePort'] = 'disabled'apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/ltm/virtual',apiPayload)
if '"kind":"tm:ltm:virtual:virtualstate"' in apiCallResponse:
   print('Success!')
elif 'already exists' in apiCallResponse:
   print('Object exists; updating with new configuration')
  apiCallResponse = icontrol_put(host, username, password, '/mgmt/tm/ltm/virtual/~Common~ipsec_forwarding_vs', apiPayload)
   if '"kind":"tm:ltm:virtual:virtualstate"' in apiCallResponse:
   print('Success!')
   else:
   print('Error! ' + apiCallResponse)
   quit()
else:
   print('Error! ' + apiCallResponse)
   quit()

# Disable the ipsec.if.checkpolicy db variableprint('Disabling the db variable ipsec.if.checkpolicy to allow BGP routing')
apiPayload = {}
apiPayload['value'] = 'disable'apiCallResponse = icontrol_put(host,username,password,'/mgmt/tm/sys/db/ipsec.if.checkpolicy',apiPayload)
if '"kind":"tm:sys:db:dbstate"' in apiCallResponse:
   print('Success!')
else:
   print('Error! ' + apiCallResponse)
   quit()

# Enable BGP and BFD on route domain 0print('Enabling routing protocols on default route domain 0')
apiPayload['routingProtocol'] = ['BFD','BGP']
apiCallResponse = icontrol_patch(host,username,password,'/mgmt/tm/net/route-domain/~Common~0',apiPayload)
if '"kind":"tm:net:route-domain:route-domainstate"' in apiCallResponse:
   print('Success!')
else:
   print('Error!' + apiCallResponse)
   quit()

# Sleep to let BGP start upprint('Waiting for BGP to start')
time.sleep(15)

# Create the BGP configuration CLI scriptprint('Creating the BGP configuration CLI script on the BIG-IP')
apiPayload = {}
apiPayload['kind'] = 'kind":"tm:cli:script:scriptstate'apiPayload['name'] = 'bgp_configuration'apiPayload['partition'] = 'Common'apiPayload['apiAnonymous'] = 'proc script::init {} {\n}\n\nproc script::run {} {\n  set neighboraddr [lindex $tmsh::argv 1]\n  set asnumber [lindex $tmsh::argv 2]\n  set imishscript [open "/var/tmp/imish_script.tmp" "w"]\n  puts $imishscript "enable"\n  puts $imishscript "configure terminal"\n  puts $imishscript "router bgp $asnumber"\n  puts $imishscript "neighbor $neighboraddr remote-as $asnumber"\n  puts $imishscript "neighbor $neighboraddr activate"\n  puts $imishscript "neighbor $neighboraddr soft-reconfiguration inbound"\n  puts $imishscript "neighbor $neighboraddr timers 10 30"\n  puts $imishscript "neighbor $neighboraddr timers connect 10"\n  puts $imishscript "end"\n  puts $imishscript "write mem"\n  close $imishscript\n  set rc [ catch { exec imish -f /var/tmp/imish_script.tmp } result ]\n  puts $rc\n  puts $result\n}\n\nproc script::help {} {\n}\n\nproc script::tabc {} {\n}\n'apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/cli/script',apiPayload)
if '"kind":"tm:cli:script:scriptstate"' in apiCallResponse:
   print('Success!')
elif 'already exists' in apiCallResponse:
   print('Script already exists! Skipping creation')
else:
   print('Error! ' + apiCallResponse)

# Create the BGP configurationprint('Creating BGP AS ' + vpn['bgp-as'] + ' with neighbor ' + vpn['tunnel-self-ip-remote'])
apiPayload = {}
apiPayload['command'] = 'run'apiPayload['name'] = 'bgp_configuration'apiPayload['utilCmdArgs'] = vpn['tunnel-self-ip-remote'] + ' ' + vpn['bgp-as']
apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/cli/script',apiPayload)
print('Script executed but BGP configuration should be manually confirmed!')

# Save the configurationprint('Saving the configuration')
apiPayload = {}
apiPayload['command'] = 'save'apiCallResponse = icontrol_post(host,username,password,'/mgmt/tm/sys/config',apiPayload)
if '"kind":"tm:sys:config:savestate","command":"save"' in apiCallResponse:
   print('Success!')
else:
   print('Error! ' + apiCallResponse)
   quit()

Tested this on version:

12.1
Published Aug 13, 2019
Version 1.0
No CommentsBe the first to comment