Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON output [5] #105

Merged
merged 28 commits into from
Oct 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
75001af
Add format JSON to cli
Honny1 Jun 15, 2022
0b6b97e
Create report_generators sub package
Honny1 Jun 15, 2022
aef33c2
Create a JSON generator shell
Honny1 Jun 15, 2022
74d49dc
Use report_generators sub package
Honny1 Jun 15, 2022
eb5c4b4
Create tests
Honny1 Jun 16, 2022
d43b967
Ignore generated JSON reports
Honny1 Jul 4, 2022
d7bfddc
Generate json output from report structure
Honny1 Jul 4, 2022
7ab6c21
Use buildin function asdict
Honny1 Jul 4, 2022
78ceff9
Create objects Identifier and Reference
Honny1 Jul 4, 2022
8bd62f3
Specify data types of Group
Honny1 Jul 7, 2022
b5b3b54
Specify data types of OvalNode
Honny1 Jul 7, 2022
7561365
Specify data types of OvalObject
Honny1 Jul 7, 2022
f5e12b1
Specify data types of OvalTest
Honny1 Jul 7, 2022
496d2c9
Remove default id of Remediation
Honny1 Jul 7, 2022
26dc6fe
Specify data types of Report
Honny1 Jul 7, 2022
9c5c02a
Specify data types of Rule
Honny1 Jul 7, 2022
f3fffda
Fix test of remediation
Honny1 Jul 7, 2022
2328e18
Remove None value from definition ID
Honny1 Jul 7, 2022
85c6931
Remove None comment
Honny1 Jul 8, 2022
bb2dd41
Rework assembly of OVAL and CPE trees
Honny1 Aug 8, 2022
d77fe50
Rework structure SCAPResultsParser class
Honny1 Aug 8, 2022
62da294
Fix tests according to change of structure of SCAPResultsParser class
Honny1 Aug 8, 2022
f67455f
Break methodes to smaller methods
Honny1 Aug 9, 2022
1d35fca
Rename directory
Honny1 Aug 16, 2022
130d42a
Use filter for generation JSON
Honny1 Aug 22, 2022
1f778fa
Create output format JSON-EVERYTHING
Honny1 Aug 22, 2022
6b312b7
Rename groupe_parser to group_parser and info_of_test_parser to test_…
Honny1 Sep 13, 2022
4f7456c
Fix mixing of Rule class and rule XML element
Honny1 Sep 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ stats

*.log
report*.html
report*.json
24 changes: 16 additions & 8 deletions openscap_report/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@

from . import __version__
from .debug_settings import DebugSetting
from .html_report import ReportGenerator
from .old_html_report_style import OldOSCAPReportGenerator
from .report_generators import (HTMLReportGenerator,
JSONEverythingReportGenerator,
JSONReportGenerator,
OldStyleHTMLReportGenerator)
from .scap_results_parser import SCAPResultsParser

DESCRIPTION = ("Generates an HTML report from an ARF (or XCCDF Result) file with results of "
Expand Down Expand Up @@ -114,7 +116,7 @@ def prepare_parser():
"--format",
action="store",
default="HTML",
choices=["HTML", "OLD-STYLE-HTML"],
choices=["HTML", "OLD-STYLE-HTML", "JSON", "JSON-EVERYTHING"],
help="FORMAT: %(choices)s"
)
parser.add_argument(
Expand Down Expand Up @@ -157,16 +159,22 @@ def _setup_logging(self):
level=self.log_level.upper()
)

def get_report_generator(self, report_parser):
dict_of_report_generators = {
"HTML": HTMLReportGenerator,
"OLD-STYLE-HTML": OldStyleHTMLReportGenerator,
"JSON": JSONReportGenerator,
"JSON-EVERYTHING": JSONEverythingReportGenerator,
}
return dict_of_report_generators[self.output_format](report_parser)

def generate_report(self, report_parser):
logging.info("Generate report")
if self.output_format == "OLD-STYLE-HTML":
report_generator = OldOSCAPReportGenerator(report_parser)
return report_generator.generate_html_report()
report_generator = ReportGenerator(report_parser)
report_generator = self.get_report_generator(report_parser)

self.debug_setting.update_settings_with_debug_flags(self.debug_flags)

return report_generator.generate_html_report(self.debug_setting)
return report_generator.generate_report(self.debug_setting)

def load_file(self):
logging.info("Loading file: %s", self.report_file)
Expand Down
4 changes: 0 additions & 4 deletions openscap_report/old_html_report_style/__init__.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later

from .exceptions import FilterNotSupportDataStructureException
from .html import HTMLReportGenerator
from .json import JSONEverythingReportGenerator, JSONReportGenerator
from .old_style_html import OldStyleHTMLReportGenerator
from .report_generator import ReportGenerator
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,21 @@

from ..scap_results_parser.data_structures import Rule
from .exceptions import FilterNotSupportDataStructureException
from .report_generator import ReportGenerator


class ReportGenerator():
def __init__(self, parser):
class HTMLReportGenerator(ReportGenerator):
def __init__(self, parser): # pylint: disable=W0231
self.report = parser.parse_report()
self.file_loader = FileSystemLoader(str(Path(__file__).parent / "templates"))
self.file_loader = FileSystemLoader(str(Path(__file__).parent / "html_templates"))
self.env = Environment(loader=self.file_loader)
self.env.globals['include_file_in_base64'] = self.include_file_in_base64
self.env.filters['set_css_for_list'] = self.set_css_for_list
self.env.filters['get_selected_rules'] = self.get_selected_rules
self.env.trim_blocks = True
self.env.lstrip_blocks = True

def generate_html_report(self, debug_setting):
def generate_report(self, debug_setting):
template = self.env.get_template("template_report.html")
html_report = template.render(report=self.report, debug_setting=debug_setting)
if debug_setting.no_minify:
Expand Down
25 changes: 25 additions & 0 deletions openscap_report/report_generators/json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2022, Red Hat, Inc.
# SPDX-License-Identifier: LGPL-2.1-or-later
import json
import logging
from io import BytesIO

from .report_generator import ReportGenerator


class JSONReportGenerator(ReportGenerator):
def __init__(self, parser):
super().__init__(parser)
self.get_report_dict = self.report.as_dict_for_default_json

def generate_report(self, debug_setting):
logging.warning("JSON Format is experimental output!")
indent = "\t" if debug_setting.no_minify else None
json_data = json.dumps(self.get_report_dict(), indent=indent)
return BytesIO(json_data.encode())


class JSONEverythingReportGenerator(JSONReportGenerator):
def __init__(self, parser):
super().__init__(parser)
self.get_report_dict = self.report.as_dict
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@

from lxml import etree

from .report_generator import ReportGenerator

XSL_DIR = Path(__file__).parent / "xsl"


class ReportGenerator():
def __init__(self, parser):
class OldStyleHTMLReportGenerator(ReportGenerator):
def __init__(self, parser): # pylint: disable=W0231
self.xml_report = parser.root
self.xslt_doc = etree.parse(str(XSL_DIR / "xccdf-report.xsl"))
self.xslt_transformer = etree.XSLT(self.xslt_doc)

def generate_html_report(self):
def generate_report(self, debug_setting):
html_report = self.xslt_transformer(self.xml_report)
result_html = etree.tostring(
html_report,
Expand All @@ -25,5 +27,5 @@ def generate_html_report(self):
standalone=False,
with_tail=False,
method="html",
pretty_print=False)
pretty_print=debug_setting.no_minify)
return BytesIO(result_html)
13 changes: 13 additions & 0 deletions openscap_report/report_generators/report_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2022, Red Hat, Inc.
# SPDX-License-Identifier: LGPL-2.1-or-later

from abc import ABC, abstractmethod


class ReportGenerator(ABC):
def __init__(self, parser):
self.report = parser.parse_report()

@abstractmethod
def generate_report(self, debug_setting):
raise NotImplementedError
70 changes: 0 additions & 70 deletions openscap_report/scap_results_parser/cpe_tree_builder.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
# SPDX-License-Identifier: LGPL-2.1-or-later

from .group import Group
from .identifier import Identifier
from .oval_node import OvalNode
from .oval_object import OvalObject
from .oval_result_eval import (EMPTY_RESULT, FULL_RESULT_TO_SHORT_RESULT,
SHORT_RESULT_TO_FULL_RESULT, OvalResult)
from .oval_test import OvalTest
from .reference import Reference
from .remediation import Remediation
from .report import Report
from .rule import Rule
28 changes: 6 additions & 22 deletions openscap_report/scap_results_parser/data_structures/group.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,17 @@
# Copyright 2022, Red Hat, Inc.
# SPDX-License-Identifier: LGPL-2.1-or-later

from dataclasses import dataclass
from dataclasses import asdict, dataclass, field


@dataclass
class Group:
group_id: str = ""
group_id: str
title: str = ""
description: str = ""
platforms: list = None
rules_ids: list = None
sub_groups: list = None
platforms: list[str] = field(default_factory=list)
rules_ids: list[str] = field(default_factory=list)
sub_groups: list['Group'] = field(default_factory=list)

def as_dict(self):
if not self.sub_groups:
return {
"group_id": self.group_id,
"title": self.title,
"description": self.description,
"platforms": self.platforms,
"rules_ids": self.rules_ids,
"sub_groups": None,
}
return {
"group_id": self.group_id,
"title": self.title,
"description": self.description,
"platforms": self.platforms,
"rules_ids": self.rules_ids,
"sub_groups": [sub_group.as_dict() for sub_group in self.sub_groups],
}
return asdict(self)
13 changes: 13 additions & 0 deletions openscap_report/scap_results_parser/data_structures/identifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2022, Red Hat, Inc.
# SPDX-License-Identifier: LGPL-2.1-or-later

from dataclasses import asdict, dataclass


@dataclass
class Identifier:
system: str
text: str

def as_dict(self):
return asdict(self)
26 changes: 3 additions & 23 deletions openscap_report/scap_results_parser/data_structures/oval_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import json
import logging
from collections import Counter
from dataclasses import dataclass
from dataclasses import asdict, dataclass, field

from .oval_result_eval import (EMPTY_RESULT, FULL_RESULT_TO_SHORT_RESULT,
SHORT_RESULT_TO_FULL_RESULT, OvalResult)
Expand All @@ -19,31 +19,11 @@ class OvalNode: # pylint: disable=R0902
negation: bool = False
comment: str = ""
tag: str = ""
children: list = None
children: list['OvalNode'] = field(default_factory=list)
test_info: OvalTest = None

def as_dict(self):
if not self.children:
return {
'node_id': self.node_id,
'node_type': self.node_type,
'value': self.value,
'negation': self.negation,
'comment': self.comment,
'tag': self.tag,
'test_info': self.test_info.as_dict(),
'children': None
}
return {
'node_id': self.node_id,
'node_type': self.node_type,
'value': self.value,
'negation': self.negation,
'comment': self.comment,
'tag': self.tag,
'test_info': None,
'children': [child.as_dict() for child in self.children]
}
return asdict(self)

def as_json(self):
return json.dumps(self.as_dict())
Expand Down
15 changes: 5 additions & 10 deletions openscap_report/scap_results_parser/data_structures/oval_object.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
# Copyright 2022, Red Hat, Inc.
# SPDX-License-Identifier: LGPL-2.1-or-later

from dataclasses import dataclass
from dataclasses import asdict, dataclass, field


@dataclass
class OvalObject():
object_id: str = ""
class OvalObject:
object_id: str
flag: str = ""
object_type: str = ""
object_data: dict = None
object_data: list[dict[str, str]] = field(default_factory=list)

def as_dict(self):
return {
"object_id": self.object_id,
"flag": self.flag,
"object_type": self.object_type,
"object_data": self.object_data,
}
return asdict(self)
13 changes: 4 additions & 9 deletions openscap_report/scap_results_parser/data_structures/oval_test.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
# Copyright 2022, Red Hat, Inc.
# SPDX-License-Identifier: LGPL-2.1-or-later

from dataclasses import dataclass
from dataclasses import asdict, dataclass

from .oval_object import OvalObject


@dataclass
class OvalTest():
test_id: str = ""
class OvalTest:
test_id: str
test_type: str = ""
comment: str = ""
oval_object: OvalObject = None

def as_dict(self):
return {
"test_id": self.test_id,
"test_type": self.test_type,
"comment": self.comment,
"oval_object": self.oval_object.as_dict(),
}
return asdict(self)
Loading