09-02-2020 01:48 PM
Does anyone know if the CER API will be supported in 12.5? So far we have found that only the /discovery status provides a 200 OK message. All other references generate a 404 message.
Looking at https://developer.cisco.com/site/CER/documents/api-reference/
Solved! Go to Solution.
09-04-2020 06:42 AM
# Cisco Emergency Responder API # Get License Status # 1.0 - ajp26@acsu.buffalo.edu from requests import Session from requests.auth import HTTPBasicAuth from hashlib import sha256 from getpass import getpass import xmltodict import os # Configuration debug = 0 # Output debug logging for the HTTP transaction local_input = 0 # Allow local username and password prompting def get_license_status(username, password, host): if debug: import logging try: import http.client as http_client except ImportError: # Python 2 import httplib as http_client http_client.HTTPConnection.debuglevel = 1 # You must initialize logging, otherwise you'll not see debug output. logging.basicConfig() logging.getLogger().setLevel(logging.DEBUG) requests_log = logging.getLogger("requests.packages.urllib3") requests_log.setLevel(logging.DEBUG) requests_log.propagate = True # Main password = sha256(password.encode('utf-8')).hexdigest() session = Session() session.auth = HTTPBasicAuth(username, password) # This is the typical format for an authenticated endpoint url = f'https://{host}/cerappservices/export/e911licensemanager/info/{username}/{password}' response = session.get(url) xml = xmltodict.parse(response.text) if xml['E911LicenseManager']['Status'] != "Exporting the info": print(f"License data export failed: {xml['E911LicenseManager']['Status']}") else: print(f"Gathered license data for {host}:\n") # I have to assume all these fields show up, the API documentation doesn't describe what happens when you're not registered or whatever cer_number_discovered_phones = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesDiscovered'] cer_manually_configured_phones = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesManuallyConfigured'] cer_users_tracked = xml['E911LicenseManager']['SmartLicenseManager']['TotalUsersTracked'] cer_phones_not_tracked = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesNotToBeTracked'] cer_licenses_used = xml['E911LicenseManager']['SmartLicenseManager']['User_license_usage_count'] slm_registration_status = xml['E911LicenseManager']['SmartLicenseManager']['RegistrationStatus'] slm_authorization_status = xml['E911LicenseManager']['SmartLicenseManager']['AuthorizationStatus'] slm_compliance_status = xml['E911LicenseManager']['SmartLicenseManager']['LicenseStatus'] slm_transport_type = xml['E911LicenseManager']['SmartLicenseManager']['TransportSettings'] slm_license_type = xml['E911LicenseManager']['SmartLicenseManager']['LicenseMode'] slm_smart_account_name = xml['E911LicenseManager']['SmartLicenseManager']['SmartAccountName'] slm_virtual_account_name = xml['E911LicenseManager']['SmartLicenseManager']['VirtualAccountName'] slm_last_sync_time = xml['E911LicenseManager']['SmartLicenseManager']['LastSynchronizationTime'] slm_export_allowed = xml['E911LicenseManager']['SmartLicenseManager']['ExportControlledFunctionality'] if slm_export_allowed == "Allowed": export_allowed = True else: export_allowed = False # Print some details: if slm_compliance_status == "InCompliance": print(f"This CER System's license status is: In Compliance") else: print(f"*** This CER System has a license issue: {slm_compliance_status} ***") print("\n") print(f"Authoriztion Status: {slm_authorization_status}") print(f"Last Synchronization Time: {slm_last_sync_time}") print("\n") if slm_registration_status != "Registered": print(f"*** This CER System is not registered to a Smart License Account ***") else: if slm_transport_type == "Direct": print(f"This system is directly connected to {slm_license_type} licensing.") else: print(f"This system is connected using the {slm_transport_type} method to {slm_license_type} licensing.") print(f"This system is registered to the {slm_smart_account_name} Smart Account.") print(f"Licensing is drawn from virtual account {slm_virtual_account_name}.") print("\nLicense Details:\n") print(f"This system has discovered {cer_number_discovered_phones}, of those {cer_phones_not_tracked} will not be tracked due to address exclusion or peer tracking.") print(f"This system also tracks {cer_manually_configured_phones} manually configured phones.") print(f"This system is tracking a total of {cer_users_tracked} users/devices.") print(f"As of last update, this system is using a total of {cer_licenses_used} licenses.") if export_allowed: print("Export-Controlled Functionality is allowed") else: print("Export-Controlled Functionality is NOT allowed") return 1 if __name__ == "__main__": if local_input: print("Cisco Emergency Responder Authentication (Local User Accounts Only)") hostname = input("Hostname: ") username = input("Username: ") password = sha256((getpass()).encode('utf-8')).hexdigest() get_license_status(username, password, hostname) else: get_license_status(os.getenv("CER_API_USER"), os.getenv("CER_API_PASSWORD"), os.getenv("CER_API_HOST"))
Here is a sample mess that works for me.
I know Smart License will email when it doesn't check in, but if it's in eval then it won't. I assume the "InCompliance" will be "Evaluation" but I don't know. Should be easy enough to grab it. Hope this helps.
09-03-2020 12:12 PM
It works, the documentation is wrong. I've asked Cisco if it could be updated several times including opening a ticket with devnet on it and looking now it's been marked Solved but the documentation is actually worse.
What do you want to do ?
Most of the URLs are going to be in the format of https://{host}/cerappservices/export/switchport/info/{username}/{password} type endpoints. The password is actually a SHA256 hash of the password, but basic auth appears to be required as well. I have no idea who wrote this API.
I wrote some lousy python to pull erls, ports, switches, unlocated phones - the API is read only so they're all pretty similar to parse.
09-03-2020 12:59 PM
09-04-2020 06:40 AM
Okay, it works if you follow that hashed password format:
https://{host}/cerappservices/export/e911licensemanager/info/{username}/{password}
A "GET" on that will produce XML output that you can parse out. Don't set the content type like the doc does/did say or you get an error back from it.
09-04-2020 06:42 AM
# Cisco Emergency Responder API # Get License Status # 1.0 - ajp26@acsu.buffalo.edu from requests import Session from requests.auth import HTTPBasicAuth from hashlib import sha256 from getpass import getpass import xmltodict import os # Configuration debug = 0 # Output debug logging for the HTTP transaction local_input = 0 # Allow local username and password prompting def get_license_status(username, password, host): if debug: import logging try: import http.client as http_client except ImportError: # Python 2 import httplib as http_client http_client.HTTPConnection.debuglevel = 1 # You must initialize logging, otherwise you'll not see debug output. logging.basicConfig() logging.getLogger().setLevel(logging.DEBUG) requests_log = logging.getLogger("requests.packages.urllib3") requests_log.setLevel(logging.DEBUG) requests_log.propagate = True # Main password = sha256(password.encode('utf-8')).hexdigest() session = Session() session.auth = HTTPBasicAuth(username, password) # This is the typical format for an authenticated endpoint url = f'https://{host}/cerappservices/export/e911licensemanager/info/{username}/{password}' response = session.get(url) xml = xmltodict.parse(response.text) if xml['E911LicenseManager']['Status'] != "Exporting the info": print(f"License data export failed: {xml['E911LicenseManager']['Status']}") else: print(f"Gathered license data for {host}:\n") # I have to assume all these fields show up, the API documentation doesn't describe what happens when you're not registered or whatever cer_number_discovered_phones = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesDiscovered'] cer_manually_configured_phones = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesManuallyConfigured'] cer_users_tracked = xml['E911LicenseManager']['SmartLicenseManager']['TotalUsersTracked'] cer_phones_not_tracked = xml['E911LicenseManager']['SmartLicenseManager']['NoPhonesNotToBeTracked'] cer_licenses_used = xml['E911LicenseManager']['SmartLicenseManager']['User_license_usage_count'] slm_registration_status = xml['E911LicenseManager']['SmartLicenseManager']['RegistrationStatus'] slm_authorization_status = xml['E911LicenseManager']['SmartLicenseManager']['AuthorizationStatus'] slm_compliance_status = xml['E911LicenseManager']['SmartLicenseManager']['LicenseStatus'] slm_transport_type = xml['E911LicenseManager']['SmartLicenseManager']['TransportSettings'] slm_license_type = xml['E911LicenseManager']['SmartLicenseManager']['LicenseMode'] slm_smart_account_name = xml['E911LicenseManager']['SmartLicenseManager']['SmartAccountName'] slm_virtual_account_name = xml['E911LicenseManager']['SmartLicenseManager']['VirtualAccountName'] slm_last_sync_time = xml['E911LicenseManager']['SmartLicenseManager']['LastSynchronizationTime'] slm_export_allowed = xml['E911LicenseManager']['SmartLicenseManager']['ExportControlledFunctionality'] if slm_export_allowed == "Allowed": export_allowed = True else: export_allowed = False # Print some details: if slm_compliance_status == "InCompliance": print(f"This CER System's license status is: In Compliance") else: print(f"*** This CER System has a license issue: {slm_compliance_status} ***") print("\n") print(f"Authoriztion Status: {slm_authorization_status}") print(f"Last Synchronization Time: {slm_last_sync_time}") print("\n") if slm_registration_status != "Registered": print(f"*** This CER System is not registered to a Smart License Account ***") else: if slm_transport_type == "Direct": print(f"This system is directly connected to {slm_license_type} licensing.") else: print(f"This system is connected using the {slm_transport_type} method to {slm_license_type} licensing.") print(f"This system is registered to the {slm_smart_account_name} Smart Account.") print(f"Licensing is drawn from virtual account {slm_virtual_account_name}.") print("\nLicense Details:\n") print(f"This system has discovered {cer_number_discovered_phones}, of those {cer_phones_not_tracked} will not be tracked due to address exclusion or peer tracking.") print(f"This system also tracks {cer_manually_configured_phones} manually configured phones.") print(f"This system is tracking a total of {cer_users_tracked} users/devices.") print(f"As of last update, this system is using a total of {cer_licenses_used} licenses.") if export_allowed: print("Export-Controlled Functionality is allowed") else: print("Export-Controlled Functionality is NOT allowed") return 1 if __name__ == "__main__": if local_input: print("Cisco Emergency Responder Authentication (Local User Accounts Only)") hostname = input("Hostname: ") username = input("Username: ") password = sha256((getpass()).encode('utf-8')).hexdigest() get_license_status(username, password, hostname) else: get_license_status(os.getenv("CER_API_USER"), os.getenv("CER_API_PASSWORD"), os.getenv("CER_API_HOST"))
Here is a sample mess that works for me.
I know Smart License will email when it doesn't check in, but if it's in eval then it won't. I assume the "InCompliance" will be "Evaluation" but I don't know. Should be easy enough to grab it. Hope this helps.
09-04-2020 11:41 AM
Thanks Adam! We were able to get our Postman query to work with the authorization information that you provided!
09-08-2020 02:37 PM
You totally rock, @Adam Pawlowski
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide