From 00bb0875f3b269322a3e59132eb38d53636d3ad1 Mon Sep 17 00:00:00 2001 From: kuba-mazurkiewicz Date: Thu, 14 Nov 2024 10:25:19 +0100 Subject: [PATCH 1/3] initial commit for dnac support --- endpoints_catalystcenter.yaml | 125 ++++++++ endpoints_ise.yaml | 83 ++++++ nac_collector/cisco_client_catalystcenter.py | 296 +++++++++++++++++++ nac_collector/cli/main.py | 3 + nac_collector/cli/options.py | 4 +- nac_collector/github_repo_wrapper.py | 5 +- 6 files changed, 510 insertions(+), 6 deletions(-) create mode 100644 endpoints_catalystcenter.yaml create mode 100644 endpoints_ise.yaml create mode 100644 nac_collector/cisco_client_catalystcenter.py diff --git a/endpoints_catalystcenter.yaml b/endpoints_catalystcenter.yaml new file mode 100644 index 0000000..0782d4b --- /dev/null +++ b/endpoints_catalystcenter.yaml @@ -0,0 +1,125 @@ +- name: transit_network + endpoint: /dna/intent/api/v1/sda/transitNetworks +- name: credentials_snmpv2_write + endpoint: /dna/intent/api/v2/global-credential +# - name: fabric_authentication_profile +# endpoint: /dna/intent/api/v1/business/sda/authentication-profile +# - name: building +# endpoint: /dna/intent/api/v1/site +# - name: fabric_l2_handoff +# endpoint: /dna/intent/api/v1/sda/fabricDevices/layer2Handoffs +# - name: floor +# endpoint: /dna/intent/api/v1/site +# - name: fabric_virtual_network +# endpoint: /dna/intent/api/v1/virtual-network +# - name: role +# endpoint: /dna/system/api/v1/role +# - name: credentials_cli +# endpoint: /dna/intent/api/v2/global-credential +# - name: image_distribution +# endpoint: /dna/intent/api/v1/image/distribution +# - name: discovery +# endpoint: /dna/intent/api/v1/discovery +# - name: wireless_rf_profile +# endpoint: /dna/intent/api/v1/wireless/rf-profile +# - name: area +# endpoint: /dna/intent/api/v1/site +# - name: pnp_device_claim_site +# endpoint: /dna/intent/api/v1/onboarding/pnp-device/site-claim +# - name: credentials_https_write +# endpoint: /dna/intent/api/v2/global-credential +# - name: template_version +# endpoint: /dna/intent/api/v1/template-programmer/template/version +# - name: ip_pool_reservation +# endpoint: /dna/intent/api/v1/reserve-ip-subpool +# - name: ip_pool +# endpoint: /api/v2/ippool +# - name: credentials_snmpv2_read +# endpoint: /dna/intent/api/v2/global-credential +# - name: pnp_import_devices +# endpoint: /dna/intent/api/v1/onboarding/pnp-device/import +# - name: fabric_device +# endpoint: /dna/intent/api/v1/sda/fabricDevices +# - name: device_role +# endpoint: /dna/intent/api/v1/network-device/brief +# - name: wireless_device_provision +# endpoint: /dna/intent/api/v1/wireless/provision +# - name: device +# endpoint: /dna/intent/api/v1/network-device +# - name: fabric_port_assignment +# endpoint: /dna/intent/api/v1/sda/portAssignments +# - name: sp_profile +# endpoint: /dna/intent/api/v2/service-provider +# - name: network +# endpoint: /dna/intent/api/v2/network +# - name: credentials_https_read +# endpoint: /dna/intent/api/v2/global-credential +# - name: credentials_snmpv3 +# endpoint: /dna/intent/api/v2/global-credential +# - name: assign_credentials +# endpoint: /dna/intent/api/v2/credential-to-site +# - name: device_detail +# endpoint: /dna/intent/api/v1/device-detail +# - name: virtual_network_ip_pool +# endpoint: /dna/intent/api/v1/business/sda/virtualnetwork/ippool +# - name: fabric_site +# endpoint: /dna/intent/api/v1/sda/fabricSites +# - name: lan_automation +# endpoint: /dna/intent/api/v1/lan-automation +# - name: user +# endpoint: /dna/system/api/v1/user +# - name: virtual_network_to_fabric_site +# endpoint: /dna/intent/api/v1/business/sda/virtual-network +# - name: wireless_enterprise_ssid +# endpoint: /dna/intent/api/v1/enterprise-ssid +# - name: authentication_policy_server +# endpoint: /dna/intent/api/v1/authentication-policy-servers +# - name: image +# endpoint: /dna/intent/api/v1/image/importation/source/file +# - name: network_profile +# endpoint: /api/v1/siteprofile +# - name: fabric_l3_handoff_ip_transit +# endpoint: /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/ipTransits +# - name: pnp_config_preview +# endpoint: /dna/intent/api/v1/onboarding/pnp-device/site-config-preview +# - name: image_activation +# endpoint: /dna/intent/api/v1/image/activation/device +# - name: wireless_profile +# endpoint: /intent/api/v1/wirelessProfiles +# - name: fabric_provision_device +# endpoint: /dna/intent/api/v1/sda/provisionDevices +# - name: deploy_template +# endpoint: /dna/intent/api/v2/template-programmer/template/deploy +# - name: pnp_device +# endpoint: /dna/intent/api/v1/onboarding/pnp-device +# - name: anycast_gateway +# endpoint: /dna/intent/api/v1/sda/anycastGateways +# - name: network_devices +# endpoint: /dna/intent/api/v1/network-device +# - name: site +# endpoint: /dna/intent/api/v1/sites +# children: +# - name: wireless_ssid +# endpoint: /wirelessSettings/ssids +# - name: aaa_settings +# endpoint: /aaaSettings +# - name: project +# endpoint: /dna/intent/api/v1/template-programmer/project +# children: +# - name: template +# endpoint: /template +# - name: +# endpoint: /dna/intent/api/v1/sda/fabrics +# children: +# - name: fabric_vlan_to_ssid +# endpoint: /vlanToSsids +# - name: +# endpoint: /dna/intent/api/v1/networkprofile +# children: +# - name: associate_site_to_network_profile +# endpoint: /site/%v +# - name: tag +# endpoint: /dna/intent/api/v1/tag +# children: +# - name: assign_templates_to_tag +# endpoint: /member diff --git a/endpoints_ise.yaml b/endpoints_ise.yaml new file mode 100644 index 0000000..7954798 --- /dev/null +++ b/endpoints_ise.yaml @@ -0,0 +1,83 @@ +- name: network_device_group + endpoint: /ers/config/networkdevicegroup +- name: allowed_protocols + endpoint: /ers/config/allowedprotocols +- name: device_admin_authorization_global_exception_rule + endpoint: /api/v1/policy/device-admin/policy-set/global-exception +- name: trustsec_security_group + endpoint: /ers/config/sgt +- name: network_access_dictionary + endpoint: /api/v1/policy/network-access/dictionaries +- name: network_access_condition + endpoint: /api/v1/policy/network-access/condition +- name: trustsec_security_group_acl + endpoint: /ers/config/sgacl +- name: allowed_protocols_tacacs + endpoint: /ers/config/allowedprotocols +- name: license_tier_state + endpoint: /api/v1/license/system/tier-state +- name: endpoint_identity_group + endpoint: /ers/config/endpointgroup +- name: certificate_authentication_profile + endpoint: /ers/config/certificateprofile +- name: device_admin_time_and_date_condition + endpoint: /api/v1/policy/device-admin/time-condition +- name: authorization_profile + endpoint: /ers/config/authorizationprofile +- name: network_access_time_and_date_condition + endpoint: /api/v1/policy/network-access/time-condition +- name: identity_source_sequence + endpoint: /ers/config/idstoresequence +- name: repository + endpoint: /api/v1/repository +- name: endpoint + endpoint: /ers/config/endpoint +- name: tacacs_command_set + endpoint: /ers/config/tacacscommandsets +- name: trustsec_ip_to_sgt_mapping + endpoint: /ers/config/sgmapping +- name: user_identity_group + endpoint: /ers/config/identitygroup +- name: trustsec_egress_matrix_cell + endpoint: /ers/config/egressmatrixcell +- name: device_admin_condition + endpoint: /api/v1/policy/device-admin/condition +- name: downloadable_acl + endpoint: /ers/config/downloadableacl +- name: network_access_authorization_global_exception_rule + endpoint: /api/v1/policy/network-access/policy-set/global-exception +- name: internal_user + endpoint: /ers/config/internaluser +- name: network_device + endpoint: /ers/config/networkdevice +- name: trustsec_ip_to_sgt_mapping_group + endpoint: /ers/config/sgmappinggroup +- name: tacacs_profile + endpoint: /ers/config/tacacsprofile +- name: active_directory_join_point + endpoint: /ers/config/activedirectory + children: + - name: active_directory_add_groups + endpoint: /addGroups + - name: active_directory_join_domain_with_all_nodes + endpoint: /joinAllNodes + - name: active_directory_groups_by_domain + endpoint: /getGroupsByDomain +- name: device_admin_policy_set + endpoint: /api/v1/policy/device-admin/policy-set + children: + - name: device_admin_authentication_rule + endpoint: /authentication + - name: device_admin_authorization_exception_rule + endpoint: /exception + - name: device_admin_authorization_rule + endpoint: /authorization +- name: network_access_policy_set + endpoint: /api/v1/policy/network-access/policy-set + children: + - name: network_access_authentication_rule + endpoint: /authentication + - name: network_access_authorization_exception_rule + endpoint: /exception + - name: network_access_authorization_rule + endpoint: /authorization diff --git a/nac_collector/cisco_client_catalystcenter.py b/nac_collector/cisco_client_catalystcenter.py new file mode 100644 index 0000000..4f86d78 --- /dev/null +++ b/nac_collector/cisco_client_catalystcenter.py @@ -0,0 +1,296 @@ +import logging + +import click +import requests +import urllib3 + +from nac_collector.cisco_client import CiscoClient + +urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) +logger = logging.getLogger("main") + +# Suppress urllib3 warnings +logging.getLogger("urllib3").setLevel(logging.ERROR) + + +class CiscoClientCATALYSTCENTER(CiscoClient): + """ + This class inherits from the abstract class CiscoClient. It's used for authenticating + with the Cisco Catalyst Center API and retrieving data from various endpoints. + Authentication is username/password based and a session is created upon successful + authentication for subsequent requests. + """ + + DNAC_AUTH_ENDPOINT = "/dna/system/api/v1/auth/token" + SOLUTION = "catalystcenter" + + "Used for mapping credentials to the correct endpoint" + mappings = {"credentials_snmpv2_read" : "snmpV2cRead", "credentials_snmpv2_write" : "snmpV2cWrite"} + + def __init__( + self, + username, + password, + base_url, + max_retries, + retry_after, + timeout, + ssl_verify, + ): + super().__init__( + username, password, base_url, max_retries, retry_after, timeout, ssl_verify + ) + + def authenticate(self): + """ + Perform token-based authentication. + + Returns: + bool: True if authentication is successful, False otherwise. + """ + + auth_url = f"{self.base_url}{self.DNAC_AUTH_ENDPOINT}" + + headers = { + "Accept": "application/json", + "Content-Type": "application/json", + "Authorization": "application/json" + } + response = requests.post( + auth_url, + auth=(self.username, self.password), + headers=headers, + verify=self.ssl_verify, + timeout=self.timeout, + ) + + if response and response.status_code == 200: + logger.info("Authentication Successful for URL: %s", auth_url) + + token = response.json()["Token"] + + # Create a session after successful authentication + self.session = requests.Session() + self.session.headers.update( + { + "Content-Type": "application/json", + "x-auth-token": token, + } + ) + return True + + logger.error( + "Authentication failed with status code: %s", + response.status_code, + ) + return False + + def process_endpoint_data(self, endpoint, endpoint_dict, data): + """ + Process the data for a given endpoint and update the endpoint_dict. + + Parameters: + endpoint (dict): The endpoint configuration. + endpoint_dict (dict): The dictionary to store processed data. + data (dict or list): The data fetched from the endpoint. + + Returns: + dict: The updated endpoint dictionary with processed data. + """ + + if data is None: + endpoint_dict[endpoint["name"]].append( + {"data": {}, "endpoint": endpoint["endpoint"]} + ) + + # License API returns a list of dictionaries + elif isinstance(data, list): + endpoint_dict[endpoint["name"]].append( + {"data": data, "endpoint": endpoint["endpoint"]} + ) + elif isinstance(data.get("response"), dict): + for k,v in data.get("response").items(): + if self.mappings(endpoint["name"]) == k: + print(k,v) + print(endpoint["name"]) + input("WWWWWWWWWW") + endpoint_dict[endpoint["name"]].append( + { + "data": v, + "endpoint": endpoint["endpoint"] + + "/" + + self.get_id_value(data.get("response")), + } + ) + elif data.get("response"): + for i in data.get("response"): + endpoint_dict[endpoint["name"]].append( + { + "data": i, + "endpoint": endpoint["endpoint"] + "/" + self.get_id_value(i), + } + ) + + # Pagination for ERS API results + elif data.get("SearchResult"): + ers_data = self.process_ers_api_results(data) + + for i in ers_data: + endpoint_dict[endpoint["name"]].append( + { + "data": i, + "endpoint": endpoint["endpoint"] + "/" + self.get_id_value(i), + } + ) + + return endpoint_dict # Return the processed endpoint dictionary + + def get_from_endpoints(self, endpoints_yaml_file): + """ + Retrieve data from a list of endpoints specified in a YAML file and + run GET requests to download data from controller. + + Parameters: + endpoints_yaml_file (str): The name of the YAML file containing the endpoints. + + Returns: + dict: The final dictionary containing the data retrieved from the endpoints. + """ + + # Load endpoints from the YAML file + logger.info("Loading endpoints from %s", endpoints_yaml_file) + with open(endpoints_yaml_file, "r", encoding="utf-8") as f: + endpoints = self.yaml.load(f) + + # Initialize an empty dictionary + final_dict = {} + + # Iterate over all endpoints + with click.progressbar(endpoints, label="Processing endpoints") as endpoint_bar: + for endpoint in endpoint_bar: + logger.info("Processing endpoint: %s", endpoint["name"]) + + endpoint_dict = CiscoClient.create_endpoint_dict(endpoint) + + data = self.fetch_data(endpoint["endpoint"]) + + # Process the endpoint data and get the updated dictionary + endpoint_dict = self.process_endpoint_data( + endpoint, endpoint_dict, data + ) + + if endpoint.get("children"): + # Create empty list of parent_endpoint_ids + parent_endpoint_ids = [] + + for item in endpoint_dict[endpoint["name"]]: + # Add the item's id to the list + try: + parent_endpoint_ids.append(item["data"]["id"]) + except KeyError: + continue + + for children_endpoint in endpoint["children"]: + logger.info( + "Processing children endpoint: %s", + endpoint["endpoint"] + + "/%v" + + children_endpoint["endpoint"], + ) + + # Iterate over the parent endpoint ids + for id_ in parent_endpoint_ids: + children_endpoint_dict = CiscoClient.create_endpoint_dict( + children_endpoint + ) + + # Replace '%v' in the endpoint with the id + children_joined_endpoint = ( + endpoint["endpoint"] + + "/" + + id_ + + children_endpoint["endpoint"] + ) + + data = self.fetch_data(children_joined_endpoint) + + # Process the children endpoint data and get the updated dictionary + children_endpoint_dict = self.process_endpoint_data( + children_endpoint, children_endpoint_dict, data + ) + + for index, value in enumerate( + endpoint_dict[endpoint["name"]] + ): + if value.get("data").get("id") == id_: + endpoint_dict[endpoint["name"]][index].setdefault( + "children", {} + )[ + children_endpoint["name"] + ] = children_endpoint_dict[ + children_endpoint["name"] + ] + + # Save results to dictionary + final_dict.update(endpoint_dict) + return final_dict + + def process_ers_api_results(self, data): + """ + Process ERS API results and handle pagination. + + Parameters: + data (dict): The data received from the ERS API. + + Returns: + ers_data (list): The processed data. + """ + # Pagination for ERS API results + paginated_data = data["SearchResult"]["resources"] + # Loop through all pages until there are no more pages + while data["SearchResult"].get("nextPage"): + url = data["SearchResult"]["nextPage"]["href"] + # Send a GET request to the URL + response = self.get_request(url) + # Get the JSON content of the response + data = response.json() + paginated_data.extend(data["SearchResult"]["resources"]) + + # For ERS API retrieve details querying all elements from paginated_data + ers_data = [] + for element in paginated_data: + url = element["link"]["href"] + response = self.get_request(url) + # Get the JSON content of the response + data = response.json() + + for _, value in data.items(): + ers_data.append(value) + + return ers_data + + @staticmethod + def get_id_value(i): + """ + Attempts to get the 'id' or 'name' value from a dictionary. + + Parameters: + i (dict): The dictionary to get the 'id' or 'name' value from. + + Returns: + str or None: The 'id' or 'name' value if it exists, None otherwise. + """ + print(i) + input("DDDD") + try: + id_value = i["id"] + except KeyError: + try: + id_value = i["rule"]["id"] + except KeyError: + try: + id_value = i["name"] + except KeyError: + id_value = None + + return id_value diff --git a/nac_collector/cli/main.py b/nac_collector/cli/main.py index 93f6e57..8900370 100644 --- a/nac_collector/cli/main.py +++ b/nac_collector/cli/main.py @@ -8,6 +8,7 @@ import nac_collector from nac_collector.cisco_client_fmc import CiscoClientFMC from nac_collector.cisco_client_ise import CiscoClientISE +from nac_collector.cisco_client_catalystcenter import CiscoClientCATALYSTCENTER from nac_collector.cisco_client_ndo import CiscoClientNDO from nac_collector.cisco_client_sdwan import CiscoClientSDWAN from nac_collector.constants import GIT_TMP, MAX_RETRIES, RETRY_AFTER @@ -97,6 +98,8 @@ def main( cisco_client = CiscoClientNDO elif solution == "FMC": cisco_client = CiscoClientFMC + elif solution == "CATALYSTCENTER": + cisco_client = CiscoClientCATALYSTCENTER if cisco_client: client = cisco_client( diff --git a/nac_collector/cli/options.py b/nac_collector/cli/options.py index 6e8d203..c2364bc 100644 --- a/nac_collector/cli/options.py +++ b/nac_collector/cli/options.py @@ -4,9 +4,9 @@ solution = click.option( "--solution", "-s", - type=click.Choice(["SDWAN", "ISE", "NDO", "FMC"], case_sensitive=False), + type=click.Choice(["SDWAN", "ISE", "NDO", "FMC", "CATALYSTCENTER"], case_sensitive=False), required=True, - help="Solutions supported [SDWAN, ISE, NDO, FMC]", + help="Solutions supported [SDWAN, ISE, NDO, FMC, CATALYSTCENTER]", ) username = click.option( diff --git a/nac_collector/github_repo_wrapper.py b/nac_collector/github_repo_wrapper.py index 1749226..91899cb 100644 --- a/nac_collector/github_repo_wrapper.py +++ b/nac_collector/github_repo_wrapper.py @@ -38,10 +38,7 @@ def __init__(self, repo_url, clone_dir, solution): self.logger = logging.getLogger(__name__) self.logger.debug("Initializing GithubRepoWrapper") self._clone_repo() - # Create an instance of the YAML class - # elf.yaml = YAML(typ="safe", pure=True) - # self.yaml.default_flow_style = False - # self.yaml.sort_keys = False + self.yaml = YAML() self.yaml.default_flow_style = False # Use block style self.yaml.indent(sequence=2) From 78625844aedcaf05819e89081ee99dbe9c6394bd Mon Sep 17 00:00:00 2001 From: kuba-mazurkiewicz Date: Wed, 27 Nov 2024 09:21:31 +0100 Subject: [PATCH 2/3] added catalystcenter support --- .gitignore | 2 +- .../endpoints_catalystcenter.yaml | 16 ++++++------ nac_collector/cisco_client_catalystcenter.py | 26 ++++++++----------- 3 files changed, 20 insertions(+), 24 deletions(-) rename endpoints_catalystcenter.yaml => examples/endpoints_catalystcenter.yaml (92%) diff --git a/.gitignore b/.gitignore index 539c5dd..a71ada0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ /*.json -#/endpoints*.yaml +endpoints*.yaml !examples/*.json !examples/endpoints*.yaml tmp/ diff --git a/endpoints_catalystcenter.yaml b/examples/endpoints_catalystcenter.yaml similarity index 92% rename from endpoints_catalystcenter.yaml rename to examples/endpoints_catalystcenter.yaml index 0782d4b..7a926ec 100644 --- a/endpoints_catalystcenter.yaml +++ b/examples/endpoints_catalystcenter.yaml @@ -34,8 +34,8 @@ # endpoint: /dna/intent/api/v1/reserve-ip-subpool # - name: ip_pool # endpoint: /api/v2/ippool -# - name: credentials_snmpv2_read -# endpoint: /dna/intent/api/v2/global-credential +- name: credentials_snmpv2_read + endpoint: /dna/intent/api/v2/global-credential # - name: pnp_import_devices # endpoint: /dna/intent/api/v1/onboarding/pnp-device/import # - name: fabric_device @@ -52,10 +52,10 @@ # endpoint: /dna/intent/api/v2/service-provider # - name: network # endpoint: /dna/intent/api/v2/network -# - name: credentials_https_read -# endpoint: /dna/intent/api/v2/global-credential -# - name: credentials_snmpv3 -# endpoint: /dna/intent/api/v2/global-credential +- name: credentials_https_read + endpoint: /dna/intent/api/v2/global-credential +- name: credentials_snmpv3 + endpoint: /dna/intent/api/v2/global-credential # - name: assign_credentials # endpoint: /dna/intent/api/v2/credential-to-site # - name: device_detail @@ -92,8 +92,8 @@ # endpoint: /dna/intent/api/v2/template-programmer/template/deploy # - name: pnp_device # endpoint: /dna/intent/api/v1/onboarding/pnp-device -# - name: anycast_gateway -# endpoint: /dna/intent/api/v1/sda/anycastGateways +- name: anycast_gateway + endpoint: /dna/intent/api/v1/sda/anycastGateways # - name: network_devices # endpoint: /dna/intent/api/v1/network-device # - name: site diff --git a/nac_collector/cisco_client_catalystcenter.py b/nac_collector/cisco_client_catalystcenter.py index 4f86d78..422fdf0 100644 --- a/nac_collector/cisco_client_catalystcenter.py +++ b/nac_collector/cisco_client_catalystcenter.py @@ -25,7 +25,7 @@ class CiscoClientCATALYSTCENTER(CiscoClient): SOLUTION = "catalystcenter" "Used for mapping credentials to the correct endpoint" - mappings = {"credentials_snmpv2_read" : "snmpV2cRead", "credentials_snmpv2_write" : "snmpV2cWrite"} + mappings = {"credentials_snmpv3" : "snmpV3", "credentials_snmpv2_read" : "snmpV2cRead", "credentials_snmpv2_write" : "snmpV2cWrite", "credentials_cli" : "cliCredential" , "credentials_https_read" : "httpsRead", "credentials_https_write" : "httpsWrite" } def __init__( self, @@ -110,18 +110,16 @@ def process_endpoint_data(self, endpoint, endpoint_dict, data): ) elif isinstance(data.get("response"), dict): for k,v in data.get("response").items(): - if self.mappings(endpoint["name"]) == k: - print(k,v) - print(endpoint["name"]) - input("WWWWWWWWWW") - endpoint_dict[endpoint["name"]].append( - { - "data": v, - "endpoint": endpoint["endpoint"] - + "/" - + self.get_id_value(data.get("response")), - } - ) + if self.mappings[endpoint["name"]] == k: + for i in v: + endpoint_dict[endpoint["name"]].append( + { + "data": i, + "endpoint": endpoint["endpoint"] + + "/" + + self.get_id_value(i), + } + ) elif data.get("response"): for i in data.get("response"): endpoint_dict[endpoint["name"]].append( @@ -280,8 +278,6 @@ def get_id_value(i): Returns: str or None: The 'id' or 'name' value if it exists, None otherwise. """ - print(i) - input("DDDD") try: id_value = i["id"] except KeyError: From 0d22bf557e67d4797e9cb3879701ebe5cd2ea7b2 Mon Sep 17 00:00:00 2001 From: kuba-mazurkiewicz Date: Wed, 27 Nov 2024 09:22:35 +0100 Subject: [PATCH 3/3] reformat code --- nac_collector/cisco_client_catalystcenter.py | 15 +++++++++++---- nac_collector/cli/options.py | 4 +++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/nac_collector/cisco_client_catalystcenter.py b/nac_collector/cisco_client_catalystcenter.py index 422fdf0..8c8f53e 100644 --- a/nac_collector/cisco_client_catalystcenter.py +++ b/nac_collector/cisco_client_catalystcenter.py @@ -25,7 +25,14 @@ class CiscoClientCATALYSTCENTER(CiscoClient): SOLUTION = "catalystcenter" "Used for mapping credentials to the correct endpoint" - mappings = {"credentials_snmpv3" : "snmpV3", "credentials_snmpv2_read" : "snmpV2cRead", "credentials_snmpv2_write" : "snmpV2cWrite", "credentials_cli" : "cliCredential" , "credentials_https_read" : "httpsRead", "credentials_https_write" : "httpsWrite" } + mappings = { + "credentials_snmpv3": "snmpV3", + "credentials_snmpv2_read": "snmpV2cRead", + "credentials_snmpv2_write": "snmpV2cWrite", + "credentials_cli": "cliCredential", + "credentials_https_read": "httpsRead", + "credentials_https_write": "httpsWrite", + } def __init__( self, @@ -54,7 +61,7 @@ def authenticate(self): headers = { "Accept": "application/json", "Content-Type": "application/json", - "Authorization": "application/json" + "Authorization": "application/json", } response = requests.post( auth_url, @@ -63,7 +70,7 @@ def authenticate(self): verify=self.ssl_verify, timeout=self.timeout, ) - + if response and response.status_code == 200: logger.info("Authentication Successful for URL: %s", auth_url) @@ -109,7 +116,7 @@ def process_endpoint_data(self, endpoint, endpoint_dict, data): {"data": data, "endpoint": endpoint["endpoint"]} ) elif isinstance(data.get("response"), dict): - for k,v in data.get("response").items(): + for k, v in data.get("response").items(): if self.mappings[endpoint["name"]] == k: for i in v: endpoint_dict[endpoint["name"]].append( diff --git a/nac_collector/cli/options.py b/nac_collector/cli/options.py index c2364bc..75c750b 100644 --- a/nac_collector/cli/options.py +++ b/nac_collector/cli/options.py @@ -4,7 +4,9 @@ solution = click.option( "--solution", "-s", - type=click.Choice(["SDWAN", "ISE", "NDO", "FMC", "CATALYSTCENTER"], case_sensitive=False), + type=click.Choice( + ["SDWAN", "ISE", "NDO", "FMC", "CATALYSTCENTER"], case_sensitive=False + ), required=True, help="Solutions supported [SDWAN, ISE, NDO, FMC, CATALYSTCENTER]", )