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