Avi Load Balancer supports SDKs to use IdP credentials for it and a REST API login. The Python SDK needs a SAML authentication profile set up on the Controller to establish a connection and access resources.

Note:
  • Logging into the Avi Load Balancer CLI using IdP credentials is not yet supported.

  • SAML-based authentication using the Python SDK is supported for Okta and OneLogin.

  • The service provider (SP) never directly interacts with the identity provider. A browser or the Python SDK acts as the agent to carry out all redirections.

  • The service provider needs to know to which identity provider to redirect before it has any idea who the user is.

  • The service provider does not know who the user is until the SAML assertion comes back from the identity provider.

  • The process of SAML authentication is asynchronous. Whether the IdP will finish the entire flow is unknown to the service provider. As a result, the service provider does not keep records of the status of any generated authentication requests. When an IdP responds to the service provider, the response must contain all necessary information.

For more information, see SAML Authentication for Single Sign-On topic.

SAML Python SDK

Under the SDK, a file named saml_avi_api.py contains the IdP class definition for each supported IdP. IdP-specific classes are inherited from the ApiSession base class. An IdP-specific class definition has its own authentication method to be called to authenticate a given user. URL redirection and SAML assertion are handled in this class. This class returns the Controller session after successful authentication from the given IdP.

Example of Okta

In this collection of code snippets, the OktaSAMLApiSession class is used to authenticate a user for Okta IdP, get the Controller session, and create the virtual service.

from avi.sdk.saml_avi_api import OktaSAMLApiSession

Create Avi Load Balancer API Session

api = OktaSAMLApiSession("10.10.10.42", "okta_username", "okta_password")

OR

api = ApiSession.get_session("controller_ip", username="foo", password="foo", idp=OktaSAMLApiSession)

Create VS Using Pool sample_pool
pool_obj = api.get_object_by_name('pool', 'sample_pool')
pool_ref = api.get_obj_ref(pool_obj)
services_obj = [{'port': 80, 'enable_ssl': False}]
vs_obj = {'name': 'sample_vs', 'ip_address': {'addr': '11.11.11.42', 'type': 'V4'},
         'services': services_obj, 'pool_ref': pool_ref}
resp = api.post('virtualservice', data=vs_obj)
Print List of all Virtual Services
resp = api.get('virtualservice')
for vs in resp.json()['results']:
    print vs['name']
Delete a Virtual Service
resp = api.delete_by_name('virtualservice', 'sample_vs')

Example of OneLogin

In this collection of code snippets, the OneloginSAMLApiSession class is used to authenticate a user for OneLogin IdP, get the Controller session, and create the virtual service.

from avi.sdk.saml_avi_api import OneloginSAMLApiSession

Create Avi Load Balancer API Session

api = OneloginSAMLApiSession("10.10.10.42", "onelogin_username", "onelogin_password")

OR

api = ApiSession.get_session("10.10.10.42", "ws1_username", "ws1_password", idp_class=WS1loginSAMLApiSession)

Create VS Using Pool sample_pool
pool_obj = api.get_object_by_name('pool', 'sample_pool')
pool_ref = api.get_obj_ref(pool_obj)
services_obj = [{'port': 80, 'enable_ssl': False}]
vs_obj = {'name': 'sample_vs', 'ip_address': {'addr': '11.11.11.42', 'type': 'V4'},
         'services': services_obj, 'pool_ref': pool_ref}
resp = api.post('virtualservice', data=vs_obj)
Print List of all Virtual Services
resp = api.get('virtualservice')
for vs in resp.json()['results']:
    print vs['name']
Delete a Virtual Service
resp = api.delete_by_name('virtualservice', 'sample_vs')

Example of Workspace ONE Access

In this collection of code snippets, the WS1loginSAMLApiSession class is used to authenticate a user for WS1 IdP, get the Controller session, and create the virtual service.

from avi.sdk.saml_avi_api import WS1loginSAMLApiSession

Create Avi Load Balancer API Session

session = WS1loginSAMLApiSession("10.10.10.42", "ws1_username", "ws1_password")

OR

api = ApiSession.get_session("10.10.10.42", "ws1_username", "ws1_password", idp_class=WS1loginSAMLApiSession)

Create Pool with One Server
pool_obj = {'name': 'sample_pool', 'servers': [{'ip': {'addr': '192.0.0.1', 'type': 'V4'}}]}
pool_resp = session.post('pool', data=pool_obj)
print(pool_resp.json())
Create vsvip
vsvip_obj = {'name': 'sample_vsvip', 'vip': [{'vip_id': '1',
                                             'ip_address': {'addr': '11.11.11.42', 'type': 'V4'}}]}
vsvip_resp = session.post('vsvip', data=vsvip_obj)
print(vsvip_resp.json())
Create Virtual Service using sample_vsvip and sample_pool
pool_ref = '/api/pool?name={}'.format(pool_obj.get('name'))
vsvip_ref = '/api/vsvip?name={}'.format(vsvip_obj.get('name'))
services_obj = [{'port': 80, 'enable_ssl': False}]
vs_obj = {'name': 'sample_vs', 'services': services_obj, 'vsvip_ref': vsvip_ref, 'pool_ref': pool_ref}
resp = session.post('virtualservice', data=vs_obj)
Print List of all Virtual Services
resp = session.get('virtualservice')
for vs in resp.json()['results']:
    print vs['name']
Delete a Virtual Service
resp = session.delete_by_name('virtualservice', 'sample_vs')