Skip to content

Commit

Permalink
Redo object factory using base class. Rename factory fun.
Browse files Browse the repository at this point in the history
  • Loading branch information
progala committed Aug 8, 2023
1 parent f87df18 commit 841070e
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 59 deletions.
21 changes: 5 additions & 16 deletions netutils/nist.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,23 @@
import typing as t


def get_nist_urls_juniper_junos(os_data: dict, api_key: str) -> t.List[str]:
def get_nist_urls_juniper_junos(os_platform_data: dict, api_key: str) -> t.List[str]:
"""Create a list of possible NIST Url strings for JuniperPlatform.
Args:
api_key: NIST-API-KEY - Request here https://nvd.nist.gov/developers/request-an-api-key
Returns:
List of NIST CPE URLs that may contain platform data.
Examples:
>>> JuniperPlatform('junos','12.1R3-S4.3').get_nist_urls('YOURKEY')
['https://services.nvd.nist.gov/rest/json/cpes/1.0?apiKey=YOURKEY&addOns=cves&cpeMatchString=cpe:2.3:o:juniper:junos:12.1R3:S4.3:*:*:*:*:*:*', 'https://services.nvd.nist.gov/rest/json/cpes/1.0?apiKey=YOURKEY&addOns=cves&cpeMatchString=cpe:2.3:o:juniper:junos:12.1R3-S4.3:*:*:*:*:*:*:*']
>>> JuniperPlatform('junos','12.1').get_nist_urls('YOURKEY')
['https://services.nvd.nist.gov/rest/json/cpes/1.0?apiKey=YOURKEY&addOns=cves&cpeMatchString=cpe:2.3:o:juniper:junos:12.1:-:*:*:*:*:*:*']
"""
nist_urls = []
base_url = f"""https://services.nvd.nist.gov/rest/json/cpes/1.0?apiKey={api_key}&addOns=cves&cpeMatchString=cpe:2.3:o:juniper:junos"""

url_args = {"base_url": base_url, **os_data}
url_args = {"base_url": base_url, **os_platform_data}
url_args["delim_six"] = ":*" * 6
url_args["delim_seven"] = ":*" * 7

if os_data.get("isspecial"):
if os_platform_data.get("isspecial"):
url_args["type"] = url_args["type"].lower()
# juniper:junos:12.1x47
base_ext = "{base_url}:{main}.{minor}{type}{build}".format(**url_args)
Expand Down Expand Up @@ -86,7 +79,7 @@ def get_nist_urls_juniper_junos(os_data: dict, api_key: str) -> t.List[str]:
raise []


def get_nist_urls_default(os_data: dict, api_key: str) -> t.List[str]:
def get_nist_urls_default(os_platform_data: dict, api_key: str) -> t.List[str]:
r"""Create a list of possible NIST Url strings.
Child models with NIST URL customizations need their own "get_nist_urls" method.
Expand All @@ -96,17 +89,13 @@ def get_nist_urls_default(os_data: dict, api_key: str) -> t.List[str]:
Returns:
List of NIST CPE URLs that may contain platform data.
Examples:
>>> OSPlatform('cisco','nxos','15.1(7)').get_nist_urls('YOURKEY')
['https://services.nvd.nist.gov/rest/json/cpes/1.0?apiKey=YOURKEY&addOns=cves&cpeMatchString=cpe:2.3:o:cisco:nxos:15.1\\(7\\):*:*:*:*:*:*:*']
"""
nist_urls = []
escape_list = [r"\(", r"\)"]
base_url = (
f"""https://services.nvd.nist.gov/rest/json/cpes/1.0?apiKey={api_key}&addOns=cves&cpeMatchString=cpe:2.3:o:"""
)
url_args = {"base_url": base_url, **os_data}
url_args = {"base_url": base_url, **os_platform_data}
url_args["delim_seven"] = ":*" * 7
url_args["version_string"] = url_args["version_string"].replace("-", ":")

Expand Down
69 changes: 29 additions & 40 deletions netutils/platform_mapper.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Platform Mappers."""
# The intent of this script is to take a given platform, determine the format, and reformat it for another purpose
# An example of this is a platform being formatted for NIST Database Query
## from dataclasses import asdict, field, make_dataclass
import dataclasses

from netutils.nist import get_nist_url_funcs
Expand Down Expand Up @@ -31,7 +30,26 @@
}


def create_platform_object(vendor: str, platform: str, version: str) -> object:
@dataclasses.dataclass
class OsPlatform:
@property
def asdict(self):
return dataclasses.asdict(self)

def get_nist_urls(self, api_key):
return self.get_nist_urls_fn(api_key)

def get(self, key):
return self.__getitem__(key)

def keys(self):
return self.__annotations__.keys()

def __getitem__(self, key):
return getattr(self, key)


def os_platform_object_builder(vendor: str, platform: str, version: str) -> object:
"""Creates a platform object relative to its need and definition.
Args:
Expand All @@ -41,15 +59,13 @@ def create_platform_object(vendor: str, platform: str, version: str) -> object:
A platform object
Examples:
>>> jp = create_platform_object("juniper", "junos", "12.1R3-S4.1")
>>> jp = os_platform_object_builder("juniper", "junos", "12.1R3-S4.1")
>>> jp.get_nist_urls("AAA-BBB-CCC-DDD")
['https://services.nvd.nist.gov/rest/json/cpes/1.0?apiKey=AAA-BBB-CCC-DDD&addOns=cves&cpeMatchString=cpe:2.3:o:juniper:junos:12.1R3:S4.1:*:*:*:*:*:*', 'https://services.nvd.nist.gov/rest/json/cpes/1.0?apiKey=AAA-BBB-CCC-DDD&addOns=cves&cpeMatchString=cpe:2.3:o:juniper:junos:12.1R3-S4.1:*:*:*:*:*:*:*']
"""
platform = platform.lower()
platform_obj = None

class_fields = []
class_fields.extend(PLATFORM_FIELDS["default"])
class_fields = [*PLATFORM_FIELDS["default"]]
vendor_platform_fields = PLATFORM_FIELDS.get(vendor, {}).get(platform, [])
class_fields.extend(vendor_platform_fields)

Expand All @@ -62,42 +78,15 @@ def create_platform_object(vendor: str, platform: str, version: str) -> object:
if version_parser:
field_values.update(version_parser(version))

base_class = OsPlatform
class_name = f"{vendor.capitalize()}{platform.capitalize()}"
get_nist_url_fn = get_nist_url_funcs.get(vendor, {}).get(platform, None) or get_nist_url_funcs["default"]
get_item_fn = lambda self, key: getattr(self, key)
keys_fn = lambda self: self.__annotations__.keys()
get_nist_urls_fn = get_nist_url_funcs.get(vendor, {}).get(platform, None) or get_nist_url_funcs["default"]
base_class.get_nist_urls_fn = get_nist_urls_fn

platform_obj = dataclasses.make_dataclass(
platform_cls = dataclasses.make_dataclass(
cls_name=class_name,
fields=class_fields,
namespace={
"get_nist_urls": get_nist_url_fn,
"asdict": dataclasses.asdict,
"__getitem__": get_item_fn,
"get": get_item_fn,
"keys": keys_fn,
},
bases=(OsPlatform,),
)
return platform_obj(**field_values)


version = "12.3R4"
jp = create_platform_object("juniper", "junos", version)
print(version, jp.asdict())
print(jp.get_nist_urls("aaa"))
version = "12.1x47:d40"
jp = create_platform_object("juniper", "junos", version)
print(version, jp.asdict())
print(jp.get_nist_urls("aa"))
version = "12.1R3-S4.1"
jp = create_platform_object("juniper", "junos", version)
print(version, jp.asdict())
print(jp.get_nist_urls("aa"))
version = "12.1"
jp = create_platform_object("juniper", "junos", version)
print(version, jp.asdict())
print(jp.get_nist_urls("aa"))
version = "16.7md"
jp = create_platform_object("cisco", "ios", version)
print(version, jp.asdict())
print(jp.get_nist_urls("aa"))

return platform_cls(**field_values)
2 changes: 1 addition & 1 deletion netutils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"uptime_seconds_to_string": "time.uptime_seconds_to_string",
"uptime_string_to_seconds": "time.uptime_string_to_seconds",
"get_napalm_getters": "lib_helpers.get_napalm_getters",
"create_platform_object": "platform_mapper.create_platform_object",
"os_platform_object_builder": "platform_mapper.os_platform_object_builder",
"juniper_junos_version_parser": "os_version_parser.juniper_junos_version_parser",
}

Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_platform_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
# Testing the parsing of a Vendor, Platform, Version into vendor standardized sections
@pytest.mark.parametrize("data", platform_data)
def test_platform_parsing(data):
platform_obj = platform_mapper.create_platform_object(
platform_obj = platform_mapper.os_platform_object_builder(
data["sent"]["vendor"], data["sent"]["platform"], data["sent"]["version"]
)
assert platform_obj.asdict() == data["received"]
Expand All @@ -136,7 +136,7 @@ def test_platform_parsing(data):
# Testing the composition of the nist url(s) created for a platform
@pytest.mark.parametrize("data", platform_nist_urls)
def test_platform_nist(data):
platform_obj = platform_mapper.create_platform_object(
platform_obj = platform_mapper.os_platform_object_builder(
data["sent"]["vendor"], data["sent"]["platform"], data["sent"]["version"]
)
assert platform_obj.get_nist_urls("AAA-BBB-CCC-DDD") == data["received"]

0 comments on commit 841070e

Please sign in to comment.