Last active
July 17, 2018 23:46
-
-
Save SoarinSen/2f58ac9990d7204e897ae01061c943fd to your computer and use it in GitHub Desktop.
Python functions to support creating or modifying an endpoint in Cisco Identify Services Engine (ISE) with an iPSK.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests, settings, smtplib, logging | |
import xml.etree.ElementTree as ElemTree | |
from bs4 import BeautifulSoup | |
class ISEAPIError(Exception): | |
""" | |
An error with the ISE API call being made. | |
""" | |
pass | |
class ISETools(object): | |
"""Collection of utilities to interface with Cisco ISE. | |
Args: | |
url: Server URL as a string. | |
username: ISE service account username as a string. | |
password: ISE service account password as a string. | |
""" | |
get_headers = {'Accept': | |
'application/vnd.com.cisco.ise.identity.endpoint.1.0+xml'} | |
put_headers = {'Content-Type': | |
'application/vnd.com.cisco.ise.identity.endpoint.1.0+xml'} | |
post_headers = {'Content-Type': | |
'application/vnd.com.cisco.ise.identity.endpoint.1.0+xml'} | |
delete_headers = {'Accept': | |
'application/vnd.com.cisco.ise.identity.endpoint.1.0+xml'} | |
def __init__(self, url, username, password): | |
self.url = url | |
self.auth = (username, password) | |
def get_dev_info(self): | |
#Current development status | |
return "Production" | |
def get_endpointid(self, mac): | |
"""Get the EndpointID for an endpoint MAC address. | |
Args: | |
mac: MAC address as a string. | |
Returns: | |
endpointID: Endpoint ID as a string if endpoint exists, or None | |
type if none exists. | |
responseCode: HTTP status code result of endpointID inquiry. | |
""" | |
url = self.url + "/ers/config/endpoint?filter=mac.EQ." + mac | |
result = requests.get(url, headers=self.get_headers, auth=self.auth) | |
try: | |
root = ElemTree.fromstring(result.text) | |
responseCode = str(result).split('[')[1].split(']')[0] | |
for child in root.iter(): | |
if 'id' in child.attrib: | |
endpointid = child.attrib['id'] | |
return endpointid, responseCode | |
except: | |
soup = BeautifulSoup(result.text, 'html.parser') | |
#get summary of html response | |
errorsummary = soup.body.h1.get_text() | |
#get details of html response | |
errordescription = (soup.body.find('p').findNext('p').get_text( | |
).split('Description ')[1]) | |
#bundle error details for logging | |
logging.error(errorsummary + ": " + errordescription) | |
#raise details as exception | |
raise ISEAPIError(errordescription) | |
def put_psk(self, mac, psk, unid): | |
"""Update an endpoint entry with MAC address, uNID, and PSK. | |
Args: | |
mac: MAC address as a string. | |
psk: PSK as a string. | |
unid: uNID as a string. | |
Returns: | |
responseCode: HTTP status code result of attempted change. | |
""" | |
url = self.url + "/ers/config/endpoint/" + self.get_endpointid(mac)[0] | |
xml = """<?xml version='1.0' encoding='UTF-8' standalone='yes'?> | |
<ns3:endpoint name='name' id='id' description='description' | |
xmlns:ns2='ers.ise.cisco.com' | |
xmlns:ns3='identity.ers.ise.cisco.com'> | |
<customAttributes> | |
<customAttributes> | |
<entry> | |
<key>iPSK</key> | |
<value>psk=""" + psk + """</value> | |
</entry> | |
</customAttributes> | |
</customAttributes> | |
<groupId>""" + settings.GROUP_ID + """</groupId> | |
<identityStore></identityStore> | |
<identityStoreId></identityStoreId> | |
<mac>""" + mac + """</mac> | |
<portalUser>""" + unid + """</portalUser> | |
<profileId></profileId> | |
<ipsk>""" + psk + """</ipsk> | |
<staticGroupAssignment>true</staticGroupAssignment> | |
<staticProfileAssignment>false</staticProfileAssignment> | |
</ns3:endpoint>""" | |
result = (requests.put(url, headers=self.put_headers, data=xml, | |
auth=self.auth)) | |
#perform a split to return just the response code | |
responseCode = str(result).split('[')[1].split(']')[0] | |
return responseCode | |
def create_psk(self, mac, psk, unid): | |
"""Create a new endpoint to add a PSK for a MAC address and uNID. | |
Args: | |
mac: MAC address as a string. | |
psk: PSK as a string. | |
unid: uNID as a string. | |
Returns: | |
responseCode: HTTP status code result of attempted change. | |
""" | |
url = self.url + "/ers/config/endpoint/" | |
xml = """<?xml version='1.0' encoding='UTF-8' standalone='yes'?> | |
<ns3:endpoint name='name' id='id' description='description' | |
xmlns:ns2='ers.ise.cisco.com' | |
xmlns:ns3='identity.ers.ise.cisco.com'> | |
<customAttributes> | |
<customAttributes> | |
<entry> | |
<key>iPSK</key> | |
<value>psk=""" + psk + """</value> | |
</entry> | |
</customAttributes> | |
</customAttributes> | |
<groupId>""" + settings.GROUP_ID + """</groupId> | |
<identityStore></identityStore> | |
<identityStoreId></identityStoreId> | |
<mac>""" + mac + """</mac> | |
<portalUser>""" + unid + """</portalUser> | |
<profileId></profileId> | |
<staticGroupAssignment>true</staticGroupAssignment> | |
<staticProfileAssignment>false</staticProfileAssignment> | |
</ns3:endpoint>""" | |
result = (requests.post(url, headers=self.post_headers, data=xml, | |
auth=self.auth)) | |
#perform a split to return just the response code | |
responseCode = str(result).split('[')[1].split(']')[0] | |
return responseCode | |
def delete_endpoint(self, mac, unid): | |
"""Delete an enpoint. This is useful for when an iPSK needs to be | |
updated. | |
Args: | |
mac: MAC address as a string. | |
unid: uNID as a string. | |
Returns: | |
Response code as a string. | |
""" | |
endpointid = self.get_endpointid(mac)[0] | |
url = self.url + "/ers/config/endpoint/" + endpointid | |
result = (requests.delete(url, headers=self.delete_headers, | |
auth=self.auth)) | |
#perform a split to return just the response code | |
responseCode = str(result).split('[')[1].split(']')[0] | |
return responseCode | |
def set_psk(self, mac, psk, unid): | |
"""Set a PSK for an endpoint, choose to edit existing endpoint or | |
create new one based off of return from get_endpointid(). | |
Args: | |
mac: MAC address as a string. | |
psk: PSK as a string. | |
unid: uNID as a string. | |
Returns: | |
XML details of endpoint. | |
""" | |
endpointid = self.get_endpointid(mac) | |
if not endpointid: | |
return self.create_psk(mac, psk, unid) | |
else: | |
self.delete_endpoint(mac, unid) | |
return self.create_psk(mac, psk, unid) | |
def send_email(self, responseCode, unid, fname, lname, mac): | |
EMAIL_TO = unid + '@domain' | |
# email header details | |
message = ('Content-Type: text/plain; charset="us-ascii"\n' + | |
'MIME-Version: 1.0\nContent-Transfer-Encoding: 7bit\n' + | |
'Subject: Device registration status for: ' + mac + | |
'\nFrom: ' + settings.EMAIL_FROM + '\nTo: ' + EMAIL_TO + | |
'\n\n' + 'Dear ' + fname + ' ' + lname + ', \n\n') | |
#body conditional on response code | |
if responseCode.startswith('2'): | |
message += ('') | |
else: | |
message += ('') | |
#footer | |
message += ('') | |
sm = smtplib.SMTP(settings.SMTP_SERVER) | |
sm.sendmail(settings.EMAIL_FROM, EMAIL_TO, message) | |
sm.quit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment