From 25712efbc19ec21e780fe6d8001f4c4170903e67 Mon Sep 17 00:00:00 2001 From: Steve McGrath Date: Wed, 21 Aug 2024 13:25:07 -0500 Subject: [PATCH] Updated testing suite --- pyproject.toml | 22 ++++++++++++++++++++ tenb2jira/jira/field.py | 11 ++++++---- tenb2jira/jira/jira.py | 16 ++++++++++----- tenb2jira/jira/task.py | 2 +- tenb2jira/processor.py | 10 ++++++++-- tenb2jira/version.py | 2 +- tests/jira/test_field.py | 43 +++++++++++++++++++++++++++++++++++++--- tests/jira/test_task.py | 40 ++++++++++++++++++++----------------- 8 files changed, 112 insertions(+), 34 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 537923f..e98ce11 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,3 +55,25 @@ readme = {file = ["README.md"], content-type = "text/markdown"} [tool.setuptools.packages.find] include = ["tenb2jira*"] +[tool.ruff] +target-version = "py312" +exclude = [ + ".nova", + ".github", + ".git", + ".pytest_cache", + "__pycache__" +] + +[tool.ruff.lint] +select = ["E4", "E7", "E9", "F", "B"] +fixable = [ "ALL" ] +unfixable = [ "B" ] + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["E402"] +"**/{tests,docs,tools}/*" = ["E402"] + +[tool.flake8] +max-line-length = 88 +count = true diff --git a/tenb2jira/jira/field.py b/tenb2jira/jira/field.py index 64658d8..568019c 100644 --- a/tenb2jira/jira/field.py +++ b/tenb2jira/jira/field.py @@ -59,12 +59,15 @@ def __repr__(self): @property def attr(self): - if self.attribute: - return self.attribute - if self.static_value: - return self.attribute + """ + Return the appropriate value (either platform_id, static_value, or + attribute) depending on how the field was configured. + """ if self.platform_id: return self.platform_id + if self.static_value: + return self.static_value + return self.attribute def fetch_field_id(self, api) -> bool: """ diff --git a/tenb2jira/jira/jira.py b/tenb2jira/jira/jira.py index b952841..869c630 100644 --- a/tenb2jira/jira/jira.py +++ b/tenb2jira/jira/jira.py @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, Dict import time import logging from box import Box @@ -24,12 +24,18 @@ class Jira: project: dict @property - def field_by_name_map(self): - return {f.name:f for f in self.fields} + def field_by_name_map(self) -> Dict[str, Field]: + """ + Returns the fields in a dictionary with the field name as the key + """ + return {f.name: f for f in self.fields} @property - def field_by_id_map(self): - return {f.id:f for f in self.fields} + def field_by_id_map(self) -> Dict[str, Field]: + """ + Returns the fields in a dictionary with the field id as the key + """ + return {f.id: f for f in self.fields} def __init__(self, config: dict): self.config = config diff --git a/tenb2jira/jira/task.py b/tenb2jira/jira/task.py index 07b4b7d..d55a55e 100644 --- a/tenb2jira/jira/task.py +++ b/tenb2jira/jira/task.py @@ -25,7 +25,7 @@ def __init__(self, issue_def: "Task", is_open: bool = True): self.is_open = is_open def __repr__(self): - return f'Task("{self.jql}", {len(self.fields)})' + return f'Task("{self.jql_stmt}", {len(self.fields)})' @property def jql_stmt(self): diff --git a/tenb2jira/processor.py b/tenb2jira/processor.py index a97e955..cbec51f 100644 --- a/tenb2jira/processor.py +++ b/tenb2jira/processor.py @@ -1,3 +1,4 @@ +from typing import Optional import logging from concurrent.futures import ThreadPoolExecutor from pathlib import Path @@ -29,8 +30,13 @@ class Processor: plugin_id: str closed_map: list[str] - def __init__(self, config: dict, ignore_last_run: bool = False): - dburi = f'sqlite:///{config["mapping_database"].get("path")}' + def __init__(self, + config: dict, + ignore_last_run: bool = False, + dburi: Optional[str] = None, + ): + if not dburi: + dburi = f'sqlite:///{config["mapping_database"].get("path")}' # For situations where we will need to ignore the last_run variable, # This will pull it from the config, forcing the integration to use diff --git a/tenb2jira/version.py b/tenb2jira/version.py index 08bb1e6..03f874b 100644 --- a/tenb2jira/version.py +++ b/tenb2jira/version.py @@ -1 +1 @@ -version = '2.0.9' +version = '2.0.10' diff --git a/tests/jira/test_field.py b/tests/jira/test_field.py index ea0131a..e3d693c 100644 --- a/tests/jira/test_field.py +++ b/tests/jira/test_field.py @@ -18,6 +18,43 @@ def field_config(): } +def test_field_repr(field_config): + f = Field(config=field_config, + platform='tvm', + platform_map={'tvm': 'Test Platform'} + ) + assert repr(f) == 'Field(1: Test Field)' + + +def test_field_attr(field_config): + f = Field(config=field_config, + platform='tvm', + platform_map={'tvm': 'Test Platform'} + ) + assert f.attr == 'test' + + field_config.pop('attr', None) + field_config['platform_id'] = True + f = Field(config=field_config, + platform='tvm', + platform_map={'tvm': 'Test Platform'} + ) + assert f.attribute == None + assert f.platform_id == 'Test Platform' + assert f.attr == 'Test Platform' + + field_config.pop('platform_id', None) + field_config['static_value'] = 'static' + f = Field(config=field_config, + platform='tvm', + platform_map={'tvm': 'Test Platform'} + ) + assert f.attribute == None + assert f.platform_id == None + assert f.static_value == 'static' + assert f.attr == 'static' + + def test_field_noapi(field_config): f = Field(config=field_config, platform='tvm', @@ -130,9 +167,9 @@ def test_field_parse_value_float(field_config): platform_map={'tvm': 'Test Platform'} ) f.type = 'float' - assert f.parse_value({'test': 1}) == '1.0' - assert f.parse_value({'test': 1.0}) == '1.0' - assert f.parse_value({'test': '1'}) == '1.0' + assert f.parse_value({'test': 1}) == 1.0 + assert f.parse_value({'test': 1.0}) == 1.0 + assert f.parse_value({'test': '1'}) == 1.0 def test_field_parse_value_datetime(field_config): diff --git a/tests/jira/test_task.py b/tests/jira/test_task.py index acd93a7..98e7178 100644 --- a/tests/jira/test_task.py +++ b/tests/jira/test_task.py @@ -291,11 +291,11 @@ def test_with_tvm_data(tvm_generator, example_config): 'CVE-2024-4777', 'CVE-2024-4778', ], - 'customfield_13': '9.2', - 'customfield_14': '6.4', - 'customfield_15': '5.0', - 'customfield_16': '6.5', - 'customfield_17': '5.9', + 'customfield_13': 9.2, + 'customfield_14': 6.4, + 'customfield_15': 5.0, + 'customfield_16': 6.5, + 'customfield_17': 5.9, 'customfield_18': '51192', 'customfield_19': 'General', 'customfield_20': 'SSL Certificate Cannot Be Trusted', @@ -369,11 +369,11 @@ def test_with_tvm_data(tvm_generator, example_config): 'CVE-2024-4777', 'CVE-2024-4778', ], - 'customfield_13': '9.2', - 'customfield_14': '6.4', - 'customfield_15': '5.0', - 'customfield_16': '6.5', - 'customfield_17': '5.9', + 'customfield_13': 9.2, + 'customfield_14': 6.4, + 'customfield_15': 5.0, + 'customfield_16': 6.5, + 'customfield_17': 5.9, 'customfield_18': '51192', 'customfield_19': 'General', 'customfield_20': 'SSL Certificate Cannot Be Trusted', @@ -447,6 +447,10 @@ def test_with_tsc_data(tsc_generator, example_config): finding = next(tsc_generator) rtask = task.generate(finding) rsubtask = subtask.generate(finding) + + assert repr(rtask) == ('Task("project = "VULN" AND issuetype = "Task" AND ' + '"Tenable Plugin ID" ~ "123560"", 35)' + ) assert rtask.fields == { 'customfield_1': ['d90cdab5-b745-3e7e-9268-aa0f445ed924'], 'customfield_2': None, @@ -465,10 +469,10 @@ def test_with_tsc_data(tsc_generator, example_config): 'CVE-2019-3863' ], 'customfield_13': None, - 'customfield_14': '9.3', - 'customfield_15': '6.9', - 'customfield_16': '8.8', - 'customfield_17': '7.7', + 'customfield_14': 9.3, + 'customfield_15': 6.9, + 'customfield_16': 8.8, + 'customfield_17': 7.7, 'customfield_18': '123560', 'customfield_19': None, 'customfield_20': 'CentOS 7 : libssh2 (CESA-2019:0679)', @@ -532,10 +536,10 @@ def test_with_tsc_data(tsc_generator, example_config): 'CVE-2019-3863' ], 'customfield_13': None, - 'customfield_14': '9.3', - 'customfield_15': '6.9', - 'customfield_16': '8.8', - 'customfield_17': '7.7', + 'customfield_14': 9.3, + 'customfield_15': 6.9, + 'customfield_16': 8.8, + 'customfield_17': 7.7, 'customfield_18': '123560', 'customfield_19': None, 'customfield_20': 'CentOS 7 : libssh2 (CESA-2019:0679)',