From a0832d7ca69c729f63ccc6e98040936a557bda05 Mon Sep 17 00:00:00 2001 From: Nicola Coretti Date: Tue, 24 Oct 2023 12:21:15 +0200 Subject: [PATCH] Restructure security module --- exasol/toolbox/tools/security.py | 159 +++++++++++++++++-------------- test/unit/security_test.py | 42 ++++---- 2 files changed, 108 insertions(+), 93 deletions(-) diff --git a/exasol/toolbox/tools/security.py b/exasol/toolbox/tools/security.py index d2ea6f2ee..c0ccba148 100644 --- a/exasol/toolbox/tools/security.py +++ b/exasol/toolbox/tools/security.py @@ -15,14 +15,40 @@ stdout = Console() stderr = Console(stderr=True) -ISSUE_CLI = typer.Typer() - from dataclasses import ( asdict, dataclass, ) +# Note: +# In the long term we may want to adapt the official CVE json schema, +# support for this could be generated using pydantic. +# See here: https://github.com/CVEProject/cve-schema/blob/master/schema/v5.0/CVE_JSON_5.0_schema.json +@dataclass(frozen=True) +class Issue: + # Note: Add support additional (custom) information e.g. dependency tree etc. + cve: str + cwe: str + description: str + coordinates: str + references: tuple + + +def _issues(input) -> Generator[Issue, None, None]: + issues = input.read() + issues = (line for line in issues.split("\n")) + issues = (json.loads(raw) for raw in issues) + issues = (Issue(**obj) for obj in issues) + yield from issues + + +def _issues_as_json_str(issues): + for issue in issues: + issue = asdict(issue) # type: ignore + yield json.dumps(issue) + + def gh_security_issues() -> Generator[Tuple[str, str], None, None]: """ Yields issue-id, cve-id pairs for all (closed, open) issues associated with CVEs @@ -67,34 +93,6 @@ def gh_security_issues() -> Generator[Tuple[str, str], None, None]: return issues -# Note: -# In the long term we may want to adapt the official CVE json schema, -# support for this could be generated using pydantic. -# See here: https://github.com/CVEProject/cve-schema/blob/master/schema/v5.0/CVE_JSON_5.0_schema.json -@dataclass(frozen=True) -class Issue: - # Note: Add support additional (custom) information e.g. dependency tree etc. - cve: str - cwe: str - description: str - coordinates: str - references: tuple - - -def _issues(input) -> Generator[Issue, None, None]: - issues = input.read() - issues = (line for line in issues.split("\n")) - issues = (json.loads(raw) for raw in issues) - issues = (Issue(**obj) for obj in issues) - yield from issues - - -def _issues_as_json_str(issues): - for issue in issues: - issue = asdict(issue) # type: ignore - yield json.dumps(issue) - - def from_maven(report: str) -> Iterable[Issue]: # Note: Consider adding warnings if there is the same cve with multiple coordinates report = json.loads(report) @@ -111,9 +109,64 @@ def from_maven(report: str) -> Iterable[Issue]: ) +def security_issue_title(issue: Issue) -> str: + return f"🔐 {issue.cve}: {issue.coordinates}" + + +def security_issue_body(issue: Issue) -> str: + def as_markdown_listing(elements: Iterable[str]): + return "\n".join(f"- {element}" for element in elements) + + body = cleandoc( + """ + ## Summary + {description} + + CVE: {cve} + CWE: {cwe} + + ## References + {references} + """ + ) + return body.format( + cve=issue.cve, + cwe=issue.cwe, + description=issue.description, + references=as_markdown_listing(issue.references), + ) + + +def create_security_issue(issue: Issue) -> Tuple[str, str]: + command = [ + "gh", + "issue", + "create", + "--label", + "security", + "--title", + security_issue_title(issue), + "--body", + security_issue_body(issue), + ] + try: + result = subprocess.run(command, check=True) + except: + raise + + stderr = result.stderr.decode("utf-8") + stdout = result.stdout.decode("utf-8") + return stderr, stdout + + +CLI = typer.Typer() +ISSUE_CLI = typer.Typer() +CLI.add_typer(ISSUE_CLI, name="issue") + + @ISSUE_CLI.command(name="convert") def convert( - format: str = typer.Argument(..., help="input format to be converted."), + format: str = typer.Argument(..., help="input format to be converted."), ) -> None: if format == "maven": issues = from_maven(sys.stdin.read()) @@ -126,7 +179,7 @@ def convert( @ISSUE_CLI.command(name="filter") def filter( - type: str = typer.Argument(..., help="filter type to apply"), + type: str = typer.Argument(..., help="filter type to apply"), ) -> None: if type != "github": stderr.print( @@ -146,47 +199,9 @@ def filter( @ISSUE_CLI.command(name="create") def create() -> None: - for line in sys.stdin: - stdout.print(line, end="") - - title = "🔐 {cve}: {coordinates}" + for issue in _issues(sys.stdin): + create_security_issue(issue) - body = cleandoc( - """ - ## Summary - {description} - - CVE: {cve} - CWE: {cwe} - - ## References - {references} - """ - ) - body = "another test" - command = [ - "gh", - "issue", - "create", - "--label", - "security", - "--title", - title.format(cve="CVE-TEST", coordinates="some-package"), - "--body", - body.format( - cve="CVE-TEST", - cwe="CWE-TEST", - description="Some detailed description", - references="\n".join(f"- {ref}" for ref in ''), - ), - ] - - result = subprocess.run(command, check=True) - print(result) - - -CLI = typer.Typer() -CLI.add_typer(ISSUE_CLI, name='issuet s') if __name__ == "__main__": CLI() diff --git a/test/unit/security_test.py b/test/unit/security_test.py index e93b66da6..0a6a74bb9 100644 --- a/test/unit/security_test.py +++ b/test/unit/security_test.py @@ -154,13 +154,13 @@ def test_convert_maven_input(maven_report): cve="CVE-2023-39410", cwe="CWE-502", description="When deserializing untrusted or corrupted data, it is " - "possible for a reader to consume memory beyond the allowed " - "constraints and thus lead to out of memory on the system.\n" - "\n" - "This issue affects Java applications using Apache Avro " - "Java SDK up to and including 1.11.2. Users should update " - "to apache-avro version 1.11.3 which addresses this issue.\n" - "\n", + "possible for a reader to consume memory beyond the allowed " + "constraints and thus lead to out of memory on the system.\n" + "\n" + "This issue affects Java applications using Apache Avro " + "Java SDK up to and including 1.11.2. Users should update " + "to apache-avro version 1.11.3 which addresses this issue.\n" + "\n", coordinates="pkg:maven/org.apache.avro/avro@1.7.7", references=( "https://ossindex.sonatype.org/vulnerability/CVE-2023-39410?component-type=maven&component-name=org.apache.avro%2Favro&utm_source=ossindex-client&utm_medium=integration&utm_content=1.8.1", @@ -174,20 +174,20 @@ def test_convert_maven_input(maven_report): cve="CVE-2020-36641", cwe="CWE-611", description="A vulnerability classified as problematic was found in " - "gturri aXMLRPC up to 1.12.0. This vulnerability affects " - "the function ResponseParser of the file " - "src/main/java/de/timroes/axmlrpc/ResponseParser.java. The " - "manipulation leads to xml external entity reference. " - "Upgrading to version 1.12.1 is able to address this issue. " - "The patch is identified as " - "ad6615b3ec41353e614f6ea5fdd5b046442a832b. It is " - "recommended to upgrade the affected component. VDB-217450 " - "is the identifier assigned to this vulnerability.\n" - "\n" - "Sonatype's research suggests that this CVE's details " - "differ from those defined at NVD. See " - "https://ossindex.sonatype.org/vulnerability/CVE-2020-36641 " - "for details", + "gturri aXMLRPC up to 1.12.0. This vulnerability affects " + "the function ResponseParser of the file " + "src/main/java/de/timroes/axmlrpc/ResponseParser.java. The " + "manipulation leads to xml external entity reference. " + "Upgrading to version 1.12.1 is able to address this issue. " + "The patch is identified as " + "ad6615b3ec41353e614f6ea5fdd5b046442a832b. It is " + "recommended to upgrade the affected component. VDB-217450 " + "is the identifier assigned to this vulnerability.\n" + "\n" + "Sonatype's research suggests that this CVE's details " + "differ from those defined at NVD. See " + "https://ossindex.sonatype.org/vulnerability/CVE-2020-36641 " + "for details", coordinates="pkg:maven/fr.turri/aXMLRPC@1.13.0", references=( "https://ossindex.sonatype.org/vulnerability/CVE-2020-36641?component-type=maven&component-name=fr.turri%2FaXMLRPC&utm_source=ossindex-client&utm_medium=integration&utm_content=1.8.1",