- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Labels:
-
Other Collaboration Applications
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-03-2020 12:59 PM
We were really only trying to get the /e911licensemanager/info.
We were hoping to be able to get the 12.5 Smarts licensing status as the system doesn't currently give any warnings for systems that are in evaluation mode before halting the phone tracking service.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-08-2020 02:37 PM
You totally rock, @Adam Pawlowski
