From b4595073e9464314e9ef706f9638bfce70a19845 Mon Sep 17 00:00:00 2001 From: Brandon Minnix Date: Mon, 25 Mar 2024 16:54:03 -0400 Subject: [PATCH] Updated user documentation for nist, platform_mapper, and os_version parser. --- docs/dev/code_reference/nist.md | 13 ------ docs/user/lib_use_cases.md | 2 + docs/user/lib_use_cases_nist.md | 23 ++++++++++ docs/user/lib_use_cases_os_version.md | 30 +++++++++++++ docs/user/lib_use_cases_platform_mapper.md | 49 ++++++++++++++++++++++ netutils/os_version.py | 3 +- netutils/platform_mapper.py | 1 + 7 files changed, 107 insertions(+), 14 deletions(-) create mode 100644 docs/user/lib_use_cases_nist.md create mode 100644 docs/user/lib_use_cases_os_version.md create mode 100644 docs/user/lib_use_cases_platform_mapper.md diff --git a/docs/dev/code_reference/nist.md b/docs/dev/code_reference/nist.md index 8a81dcda..e8999ca8 100644 --- a/docs/dev/code_reference/nist.md +++ b/docs/dev/code_reference/nist.md @@ -3,16 +3,3 @@ ::: netutils.nist options: show_submodules: True - -**Notes:** - -In order to use the URLs generated by netutils.nist.get_nist_urls*, you will need an api key provided by NIST [here]('https://nvd.nist.gov/developers/request-an-api-key'). This key will need to be passed in as an additional header in your request in the form of `{"apiKey": ""}` as stated by NIST in their [Getting Started]('https://nvd.nist.gov/developers/start-here') section. - -This module currently only supports the following OS platforms: - -- Arista EOS -- Cisco IOS -- Cisco IOS XR -- Cisco IOS XE -- Cisco NXOS -- Juniper JunOS diff --git a/docs/user/lib_use_cases.md b/docs/user/lib_use_cases.md index 5f7b7bb8..f01b8c79 100644 --- a/docs/user/lib_use_cases.md +++ b/docs/user/lib_use_cases.md @@ -21,9 +21,11 @@ Functions are grouped with like functions, such as IP or MAC address based funct - Library Helpers - Provides helpers to pull useful information, e.g. NAPALM getters. - Library Mapper - Provides mappings in expected vendor names between Netmiko, NAPALM, pyntc, ntc-templates, pyats, and scrapli. - MAC Address - Provides the ability to work with MAC addresses such as validating or converting to integer. +- NIST - Provides the ability to obtain a URL formatted for NIST CPE Query. - OS Version - Provides the ability to work with OS version, such as defining an upgrade path. - Password - Provides the ability to compare and encrypt common password schemas such as type5 and type7 Cisco passwords. - Ping - Provides the ability to ping, currently only tcp ping. +- Platform Mapper - Provides custom parsers for breakdown of OS Software Versions/Revisions. - Protocol Mapper - Provides a mapping for protocol names to numbers and vice versa. - Regex - Provide convenience methods for regex to be used in Jinja2. - Route - Provides the ability to provide a list of routes and an IP Address and return the longest prefix matched route. diff --git a/docs/user/lib_use_cases_nist.md b/docs/user/lib_use_cases_nist.md new file mode 100644 index 00000000..ddce88e3 --- /dev/null +++ b/docs/user/lib_use_cases_nist.md @@ -0,0 +1,23 @@ +# NIST + +The NIST utility is used for functionality based around NIST DB Queries, and is primarily used to create URLs for the API based queries. + +In order to use the URLs generated by `netutils.nist.get_nist_urls*`, you will need an api key provided by NIST [here]('https://nvd.nist.gov/developers/request-an-api-key'). This key will need to be passed in as an additional header in your request in the form of `{"apiKey": ""}` as stated by NIST in their [Getting Started]('https://nvd.nist.gov/developers/start-here') section. + +The NIST utility can be used as a standalone module to create generic and defined custom NIST URLs as seen below: +```python +from nist import get_nist_url_funcs + +# Generic URLs only require vendor, os_type, and version_string +generic = get_nist_url_funcs['default']({"vendor": "Cisco", "os_type": "IOS", "version_string": "15.5"}) +# ['https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:o:Cisco:IOS:15.5:*'] + +# Custom URL builds require a more defined dictionary. +# See the documentation on platform_mapper.os_platform_object_builder, it may be more useful. +juniper_junos = get_nist_url_funcs['juniper']['junos']({'isservice': False, 'ismaintenance': False, 'isfrs': True, 'isspecial': False, 'service': None, 'service_build': None, 'service_respin': None, 'main': '12', 'minor': '4', 'type': 'R', 'build': None}) +# ['https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:o:juniper:junos:12.4r:*:*:*:*:*:*:*'] +``` + +Current OS/Other Platform types that require a custom NIST URL: + +- Juniper JunOS diff --git a/docs/user/lib_use_cases_os_version.md b/docs/user/lib_use_cases_os_version.md new file mode 100644 index 00000000..aab71273 --- /dev/null +++ b/docs/user/lib_use_cases_os_version.md @@ -0,0 +1,30 @@ +# OS Version Tools + +The OS Version Tools are used for working with versioning systems. + +## Version Parsing/Deconstruction +Version parsing takes the software version given as a string, and deconstructs that value into the standards of the vendor. The version parsing takes place in the `netutils.os_version` module. This is necessary when specific values or flags from a software version are required to make a logical decision. + +Current Version Parsers: + +- Juniper JunOS + +**See the following Juniper JunOS parsed version:** + +```python +>>> from os_version import juniper_junos_version_parser +>>> juniper_junos_version_parser("12.2x50:d41.1") +{ + "isservice": false, + "ismaintenance": false, + "isfrs": false, + "isspecial": true, + "service": "d", + "service_build": "41", + "service_respin": "1", + "main": "12", + "minor": "2", + "type": "x", + "build": "50" +} +``` diff --git a/docs/user/lib_use_cases_platform_mapper.md b/docs/user/lib_use_cases_platform_mapper.md new file mode 100644 index 00000000..ef1e61a8 --- /dev/null +++ b/docs/user/lib_use_cases_platform_mapper.md @@ -0,0 +1,49 @@ +# Platform Mapper + +The platform mapper is used as an abstract class builder to provide unified multi-platform service functionality. + +Methods available to custom and generic classes: + +- get_nist_urls() + +Here are a few examples showing how you would use this in your python code. + +```python + +from netutils.platform_mapper import os_platform_object_builder + +# Create the platform objects to get NIST query URL(s) for. +cisco_ios = os_platform_object_builder("Cisco", "IOS", "15.5(2)S1c") +juniper_junos = os_platform_object_builder("Juniper", "JunOS", "10.2R2.11") + +# Get NIST URL for the Cisco IOS object +cisco_ios.get_nist_urls() +# ['https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:o:cisco:ios:15.5\\(2\\)s1c:*'] + +# Get NIST URL(s) for the Juniper JunOS object +juniper_junos.get_nist_urls() +# ['https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:o:juniper:junos:10.2r2:*:*:*:*:*:*:*', 'https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:o:juniper:junos:10.2:r2:*:*:*:*:*:*'] +``` + +## Custom Parsers + +As stated above, this mapper is meant to provided unified utility usage between different platforms/services. In order to do this, custom parsers are needed so that data can be normalized into values that the services need. There are two parts **potentially** needed for this to work. +- Version Parsing - Document: [netutils.os_version](lib_use_cases_os_version.md) +- Service Ready Output + +### Service Ready Output + +"Service Ready Output" means that the utility is providing a readily usable value for the service it is meant to use. + +Using NIST as the example, the URL building utility responsible for "Service Ready Output" is `netutils.nist`. Some popular vendors do not follow NIST standards in regard to how their CPE are defined using delimiters of `:`. + +- **Cisco IOS CPE String** - `cpe:2.3:o:cisco:ios:15.5\\(2\\)s1c:*` + - `15.5\\(2\\)s1c:*` - As seen here, Cisco uses CPE strings that do not include the `:` delimiter, which can be queried using escape characters in the search string. This is the format of ALL "generic" OS/Other platforms that do not have their own custom NIST URL builder when querying NIST. + - Service Ready Output - `'https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:o:cisco:ios:15.5\\(2\\)s1c:*'` + +- **Juniper JunOS CPE String** - `cpe:2.3:o:juniper:junos:10.2:r2:*:*:*:*:*:*` + - `10.2:r2:*:*:*:*:*:*` - As noted here, one of the provided URLs to query for this Juniper JunOS OS platform includes additional values that follow NIST delimiter structures. In the case where the parser provides multiple URLs, they will both be evaluated and the CVE from both will be added and associated. + - Service Ready Output - `['https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:o:juniper:junos:10.2r2:*:*:*:*:*:*:*', 'https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:o:juniper:junos:10.2:r2:*:*:*:*:*:*']` + +## Important Notes +Please see [here](lib_use_cases_nist.md) for documentation on using the NIST utility on its own, as well as information on additional requirements such as obtaining an API Key. diff --git a/netutils/os_version.py b/netutils/os_version.py index bb04b222..9b88213b 100644 --- a/netutils/os_version.py +++ b/netutils/os_version.py @@ -140,7 +140,8 @@ def juniper_junos_version_parser(version: str) -> t.Dict[str, t.Any]: A dictionary containing parsed version information Examples: - >>> parsed_version = juniper_junos_version_parser("12.3R4") + >>> juniper_junos_version_parser("12.3R4") + {'isservice': False, 'ismaintenance': True, 'isfrs': False, 'isspecial': False, 'service': None, 'service_build': None, 'service_respin': None, 'main': '12', 'minor': '3', 'type': 'R', 'build': '4'} """ # Use regex to group the main, minor, type and build into useable pieces # re_main_minor_type_build = re.search(r"^(\d+)\.(\d+)([xXrRsS])?(\d+)?", split_version[0]) diff --git a/netutils/platform_mapper.py b/netutils/platform_mapper.py index fe43fe90..b7f66779 100644 --- a/netutils/platform_mapper.py +++ b/netutils/platform_mapper.py @@ -72,6 +72,7 @@ def os_platform_object_builder(vendor: str, platform: str, version: str) -> obje ['https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:o:juniper:junos:12.1r3:s4.1:*:*:*:*:*:*', 'https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:o:juniper:junos:12.1r3-s4.1:*:*:*:*:*:*:*'] """ platform = platform.lower() + vendor = vendor.lower() class_fields = [*PLATFORM_FIELDS["default"]] vendor_platform_fields = PLATFORM_FIELDS.get(vendor, {}).get(platform, [])