Automating a Skype for Business Reverse Proxy Deployment with the KEMP SDK

This post will be about automating the deployment of KEMP load balancers for Skype for Business. More specifically, it’s about using the fairly new KEMP Python SDK to script it.

If you have not yet heard of this SDK I did write an introductory post about it awhile ago. I suggest starting there.

Deployment Scenario

For this example I’ll be doing the following for an enterprise edition pool with an associated OWA pool:

  • Uploading the Skype for Business template if it’s not already installed
  • Adding the following virtual services and front end servers
    • Internal Web Services
      • port 80/443 => 80/443 to all front ends
    • Internal Mobility Services
      • port 80/443 => 8080/4443 to all front ends
    • Internal OWA
      • port 443 => 443 to all OWA servers
    • External Web Services
      • port 80/443 => 8080/4443 to all front ends
    • External OWA
      • port 443 => 443 to all OWA servers

Since I am using the KEMP templates for deploying these virtual services, the deployment script is pretty simple as the template takes care of most settings (like tcp timeout, port checks, etc).

The configuration script is in my sfb-tools repo, but I’ll also paste the initial script below. However, any improvements I make to it will be in Git for sure but not necessarily on this post so use the script in Git as a reference. The script can be found here: https://github.com/matthew-hickok/sfb-tools/blob/master/deploy-kemp-sfb.py


import urllib.request
from python_kemptech_api import LoadMaster

# connection parameters
LoadMaster_IP = '10.0.3.72' # Your LoadMaster’s administrative IP
LoadMaster_User = 'bal' # Your LoadMaster’s Login User
LoadMaster_Password = 'my_pass' # Your LoadMaster’s User’s Password
LoadMaster_Port = '443' # By default this is 443.

# build the LoadMaster object
lm = LoadMaster(LoadMaster_IP, LoadMaster_User, LoadMaster_Password, LoadMaster_Port)

# templates to use
vs_web_services_template = 'Skype Front End Reverse Proxy'
vs_owa_template = 'Skype Office Web App Servers'

# url for the KEMP SFB template
template_url = 'https://kemptechnologies.com/files/assets/templates/SfB_2015.tmpl'

# front end servers
fe_servers = ('10.0.3.202', '10.0.3.203', '10.0.3.204')
# OWA/OOS servers
owa_servers = ('10.0.3.220')

# internal web services VIP
int_web_ip = '10.0.3.88'
# internal mobility VIP
int_mob_ip = '10.0.3.89'
# internal OWA VIP
int_owa_ip = '10.0.3.90'
# external web services VIP
ext_web_ip = '10.0.4.11'
# external OWA VIP
ext_owa_ip = '10.0.4.12'

# check for the SFB template, upload it if it's not there
ws_temp = lm.get_template(vs_web_services_template)
owa_temp = lm.get_template(vs_owa_template)
if (ws_temp is None) or (owa_temp is None):
    print('Missing a necessary template -- attempting to add it')
    urllib.request.urlretrieve(template_url, 'sfb.tmpl')
    lm.upload_template('sfb.tmpl')
else:
    print('Required templates are already installed')

# build the virtual Services using the appropriate template
lm.apply_template(int_web_ip, 80, 'tcp', vs_web_services_template, 'Internal Web Services')
lm.apply_template(ext_web_ip, 80, 'tcp', vs_web_services_template, 'External Web Services')
lm.apply_template(int_mob_ip, 443, 'tcp', vs_web_services_template, 'Internal Mobility')
lm.apply_template(int_owa_ip, 443, 'tcp', vs_owa_template, 'Internal OWA')
lm.apply_template(ext_owa_ip, 443, 'tcp', vs_owa_template, 'External OWA')

# store each virtual service in order to add real servers to each
int_web_vs_http = lm.get_virtual_service(address=int_web_ip, port='80', protocol='tcp')
int_web_vs_https = lm.get_virtual_service(address=int_web_ip, port='443', protocol='tcp')
ext_web_vs_http = lm.get_virtual_service(address=ext_web_ip, port='80', protocol='tcp')
ext_web_vs_https = lm.get_virtual_service(address=ext_web_ip, port='443', protocol='tcp')
int_mob_vs = lm.get_virtual_service(address=int_mob_ip, port='443', protocol='tcp')
int_owa_vs = lm.get_virtual_service(address=int_owa_ip, port='443', protocol='tcp')
ext_owa_vs = lm.get_virtual_service(address=ext_owa_ip, port='443', protocol='tcp')

# add the fe real servers to each appropriate virtual service
for item in fe_servers:
    int_web_rs_http = int_web_vs_http.create_real_server(item, port=80)
    int_web_rs_http.save()
    int_web_rs_https = int_web_vs_https.create_real_server(item, port=443)
    int_web_rs_https.save()
    ext_web_rs_http = ext_web_vs_http.create_real_server(item, port=8080)
    ext_web_rs_http.save()
    ext_web_rs_https = ext_web_vs_https.create_real_server(item, port=4443)
    ext_web_rs_https.save()
    int_mob_rs = int_mob_vs.create_real_server(item, port=4443)
    int_mob_rs.save()

# add the owa real servers to each appropriate virtual service
for item in owa_servers:
    int_owa_rs = int_owa_vs.create_real_server(item, port=443)
    int_owa_rs.save()
    ext_owa_rs = ext_owa_vs.create_real_server(item, port=443)
    ext_owa_rs.save()

After running that you can go to the load balancer’s web interface and refresh virtual services page. It should show all of the newly created services and real servers:

vs_wui

(ignore the OWA real servers being down as I haven’t gotten around to deploying them yet)

Quick Note

This is meant to be an example of how you could use this SDK, but this script is far from ideal.

Some improvements I’m adding soon:

  • General code improvements
    • exception catching
    • better variable names
  • Backing up the configuration at the beginning of the script
  • Adding some parameters to customize what it’s deploying
  • Add a certificate to the external web services

The last point is the most important since that’s a requirement for the external web services. I’ll add this in the very near future.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s