oscap-anaconda-addon package is retired on branch c10s for CS-2551

This commit is contained in:
Johnny Hughes 2024-10-02 16:32:35 +00:00
parent fe02c2fd31
commit 903f8c32b5
19 changed files with 4 additions and 9803 deletions

9
.gitignore vendored
View File

@ -1,9 +0,0 @@
/oscap-anaconda-addon-0.2.tar.gz
/oscap-anaconda-addon-0.3.tar.gz
/oscap-anaconda-addon-0.4.tar.gz
/oscap-anaconda-addon-0.5.tar.gz
/oscap-anaconda-addon-0.6.tar.gz
/oscap-anaconda-addon-0.7.tar.gz
/oscap-anaconda-addon-1.0.tar.gz
/oscap-anaconda-addon-2.0.0.tar.gz
/addon-dbus-data.zip

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Package Not Available
This package is not available on CentOS Stream 10.
It may be available on another branch.

1
dead.package Normal file
View File

@ -0,0 +1 @@
oscap-anaconda-addon package is retired on branch c10s for CS-2551

View File

@ -1,6 +0,0 @@
--- !Policy
product_versions:
- rhel-9
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

8040
lang.patch

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +0,0 @@
From 20843d815a82d10cba773f4e10e9a45c57d5e12e Mon Sep 17 00:00:00 2001
From: Vendula Poncova <vponcova@redhat.com>
Date: Wed, 18 Aug 2021 10:54:20 +0200
Subject: [PATCH] Don't show the OSCAP spoke if the OSCAP DBus module is
disabled
Add-ons can be disabled in the Anaconda configuration files. Without the fix,
the OSCAP DBus module is started on demand by the OSCAP spoke even though it
shouldn't be activated. In the future, it will result in a failure of the
installer.
Related: rhbz#1994003
---
org_fedora_oscap/gui/spokes/oscap.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/org_fedora_oscap/gui/spokes/oscap.py b/org_fedora_oscap/gui/spokes/oscap.py
index 36c8d7a..fe26076 100644
--- a/org_fedora_oscap/gui/spokes/oscap.py
+++ b/org_fedora_oscap/gui/spokes/oscap.py
@@ -36,6 +36,7 @@
from org_fedora_oscap.structures import PolicyData
from pyanaconda.modules.common.constants.services import USERS
+from pyanaconda.modules.common.util import is_module_available
from pyanaconda.threading import threadMgr, AnacondaThread
from pyanaconda.ui.gui.spokes import NormalSpoke
from pyanaconda.ui.communication import hubQ
@@ -203,6 +204,10 @@ class OSCAPSpoke(NormalSpoke):
# as it is displayed inside the spoke as the spoke label,
# and spoke labels are all uppercase by a convention.
+ @classmethod
+ def should_run(cls, environment, data):
+ return is_module_available(OSCAP)
+
# methods defined by API and helper methods #
def __init__(self, data, storage, payload):
"""

View File

@ -1,191 +0,0 @@
From c92205d5a5c788eeac84a6e67956a3e0540ab565 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mat=C4=9Bj=20T=C3=BD=C4=8D?= <matyc@redhat.com>
Date: Mon, 3 Jan 2022 17:31:49 +0100
Subject: [PATCH 1/2] Add oscap sanity check before attempting remediation
If something is obviously wrong with the scanner, then don't attempt to remediate
and try to show relevant information in a dialog window.
---
org_fedora_oscap/common.py | 39 +++++++++++++++++++-----
org_fedora_oscap/service/installation.py | 11 +++++++
tests/test_common.py | 8 +++++
tests/test_installation.py | 3 +-
4 files changed, 52 insertions(+), 9 deletions(-)
diff --git a/org_fedora_oscap/common.py b/org_fedora_oscap/common.py
index c432168..eeb27fc 100644
--- a/org_fedora_oscap/common.py
+++ b/org_fedora_oscap/common.py
@@ -171,7 +171,8 @@ def execute(self, ** kwargs):
proc = subprocess.Popen(self.args, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, ** kwargs)
except OSError as oserr:
- msg = "Failed to run the oscap tool: %s" % oserr
+ msg = ("Failed to execute command '{command_string}': {oserr}"
+ .format(command_string=command_string, oserr=oserr))
raise OSCAPaddonError(msg)
(stdout, stderr) = proc.communicate()
@@ -247,6 +248,34 @@ def _run_oscap_gen_fix(profile, fpath, template, ds_id="", xccdf_id="",
return proc.stdout
+def do_chroot(chroot):
+ """Helper function doing the chroot if requested."""
+ if chroot and chroot != "/":
+ os.chroot(chroot)
+ os.chdir("/")
+
+
+def assert_scanner_works(chroot, executable="oscap"):
+ args = [executable, "--version"]
+ command = " ".join(args)
+
+ try:
+ proc = subprocess.Popen(
+ args, preexec_fn=lambda: do_chroot(chroot),
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdout, stderr) = proc.communicate()
+ stderr = stderr.decode(errors="replace")
+ except OSError as exc:
+ msg = _(f"Basic invocation '{command}' fails: {str(exc)}")
+ raise OSCAPaddonError(msg)
+ if proc.returncode != 0:
+ msg = _(
+ f"Basic scanner invocation '{command}' exited "
+ "with non-zero error code {proc.returncode}: {stderr}")
+ raise OSCAPaddonError(msg)
+ return True
+
+
def run_oscap_remediate(profile, fpath, ds_id="", xccdf_id="", tailoring="",
chroot=""):
"""
@@ -276,12 +305,6 @@ def run_oscap_remediate(profile, fpath, ds_id="", xccdf_id="", tailoring="",
if not profile:
return ""
- def do_chroot():
- """Helper function doing the chroot if requested."""
- if chroot and chroot != "/":
- os.chroot(chroot)
- os.chdir("/")
-
# make sure the directory for the results exists
results_dir = os.path.dirname(RESULTS_PATH)
if chroot:
@@ -306,7 +329,7 @@ def do_chroot():
args.append(fpath)
proc = SubprocessLauncher(args)
- proc.execute(preexec_fn=do_chroot)
+ proc.execute(preexec_fn=lambda: do_chroot(chroot))
proc.log_messages()
if proc.returncode not in (0, 2):
diff --git a/org_fedora_oscap/service/installation.py b/org_fedora_oscap/service/installation.py
index 2da8559..d909c44 100644
--- a/org_fedora_oscap/service/installation.py
+++ b/org_fedora_oscap/service/installation.py
@@ -239,6 +239,17 @@ def name(self):
def run(self):
"""Run the task."""
+ try:
+ common.assert_scanner_works(
+ chroot=self._sysroot, executable="oscap")
+ except Exception as exc:
+ msg_lines = [_(
+ "The 'oscap' scanner doesn't work in the installed system: {error}"
+ .format(error=str(exc)))]
+ msg_lines.append(_("As a result, the installed system can't be hardened."))
+ terminate("\n".join(msg_lines))
+ return
+
common.run_oscap_remediate(
self._policy_data.profile_id,
self._target_content_path,
diff --git a/tests/test_common.py b/tests/test_common.py
index 9f7a16a..4f25379 100644
--- a/tests/test_common.py
+++ b/tests/test_common.py
@@ -77,6 +77,14 @@ def _run_oscap(mock_subprocess, additional_args):
return expected_args, kwargs
+def test_oscap_works():
+ assert common.assert_scanner_works(chroot="/")
+ with pytest.raises(common.OSCAPaddonError, match="No such file"):
+ common.assert_scanner_works(chroot="/", executable="i_dont_exist")
+ with pytest.raises(common.OSCAPaddonError, match="non-zero"):
+ common.assert_scanner_works(chroot="/", executable="false")
+
+
def test_run_oscap_remediate_profile_only(mock_subprocess, monkeypatch):
return run_oscap_remediate_profile(
mock_subprocess, monkeypatch,
diff --git a/tests/test_installation.py b/tests/test_installation.py
index 5749a94..f819c3b 100644
--- a/tests/test_installation.py
+++ b/tests/test_installation.py
@@ -115,4 +115,5 @@ def test_remediate_system_task(sysroot_path, content_path, tailoring_path):
)
assert task.name == "Remediate the system"
- task.run()
+ with pytest.raises(installation.NonCriticalInstallationError, match="No such file"):
+ task.run()
From ea2dbf5017445875b1c0e4ee27899c8dde292c98 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mat=C4=9Bj=20T=C3=BD=C4=8D?= <matyc@redhat.com>
Date: Mon, 3 Jan 2022 17:42:31 +0100
Subject: [PATCH 2/2] Don't raise exceptions in execute()
Those result in tracebacks during the installation,
while a dialog window presents a more useful form of user interaction.
---
org_fedora_oscap/service/installation.py | 27 ++++++++++++++----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/org_fedora_oscap/service/installation.py b/org_fedora_oscap/service/installation.py
index d909c44..290da40 100644
--- a/org_fedora_oscap/service/installation.py
+++ b/org_fedora_oscap/service/installation.py
@@ -210,9 +210,9 @@ def run(self):
)
if ret != 0:
- raise common.ExtractionError(
- "Failed to install content RPM to the target system"
- )
+ msg = _(f"Failed to install content RPM to the target system.")
+ terminate(msg)
+ return
else:
pattern = utils.join_paths(common.INSTALLATION_CONTENT_DIR, "*")
utils.universal_copy(pattern, target_content_dir)
@@ -250,11 +250,16 @@ def run(self):
terminate("\n".join(msg_lines))
return
- common.run_oscap_remediate(
- self._policy_data.profile_id,
- self._target_content_path,
- self._policy_data.datastream_id,
- self._policy_data.xccdf_id,
- self._target_tailoring_path,
- chroot=self._sysroot
- )
+ try:
+ common.run_oscap_remediate(
+ self._policy_data.profile_id,
+ self._target_content_path,
+ self._policy_data.datastream_id,
+ self._policy_data.xccdf_id,
+ self._target_tailoring_path,
+ chroot=self._sysroot
+ )
+ except Exception as exc:
+ msg = _(f"Something went wrong during the final hardening: {str(exc)}.")
+ terminate(msg)
+ return

View File

@ -1,14 +0,0 @@
diff --git a/org_fedora_oscap/content_discovery.py b/org_fedora_oscap/content_discovery.py
index bc14ef1..ccfe6c8 100644
--- a/org_fedora_oscap/content_discovery.py
+++ b/org_fedora_oscap/content_discovery.py
@@ -225,7 +225,8 @@ def _gather_available_files(self, actually_fetched_content, dest_filename):
if not dest_filename: # using scap-security-guide
fpaths = [self.DEFAULT_SSG_DATA_STREAM_PATH]
else: # Using downloaded XCCDF/OVAL/DS/tailoring
- fpaths = glob(str(self.CONTENT_DOWNLOAD_LOCATION / "*.xml"))
+ fpaths = pathlib.Path(self.CONTENT_DOWNLOAD_LOCATION).rglob("*")
+ fpaths = [str(p) for p in fpaths if p.is_file()]
else:
dest_filename = pathlib.Path(dest_filename)
# RPM is an archive at this phase

View File

@ -1,22 +0,0 @@
From c72b95146650b0debc36b8da546b60a9d5482ab3 Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Fri, 15 Oct 2021 15:28:24 +0200
Subject: [PATCH] Fix bad destination for the parsed content fingerprint
---
org_fedora_oscap/service/kickstart.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org_fedora_oscap/service/kickstart.py b/org_fedora_oscap/service/kickstart.py
index d6f22ac..dc1a100 100644
--- a/org_fedora_oscap/service/kickstart.py
+++ b/org_fedora_oscap/service/kickstart.py
@@ -140,7 +140,7 @@ def _parse_fingerprint(self, value):
msg = "Unsupported fingerprint"
raise KickstartValueError(msg)
- self.fingerprint = value
+ self.policy_data.fingerprint = value
def _parse_certificates(self, value):
self.policy_data.certificates = value

View File

@ -1,32 +0,0 @@
From 56806b88b139d62276e8522bb3daf7d4fb02df84 Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Fri, 15 Oct 2021 15:05:55 +0200
Subject: [PATCH] Represent unselected profile by an empty string
None can't be passed via the DBUS interface.
---
org_fedora_oscap/gui/spokes/oscap.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/org_fedora_oscap/gui/spokes/oscap.py b/org_fedora_oscap/gui/spokes/oscap.py
index 4425757..36c8d7a 100644
--- a/org_fedora_oscap/gui/spokes/oscap.py
+++ b/org_fedora_oscap/gui/spokes/oscap.py
@@ -244,7 +244,7 @@ def __init__(self, data, storage, payload):
self.__old_root_pw = None
# used to check if the profile was changed or not
- self._active_profile = None
+ self._active_profile = ""
# prevent multiple simultaneous data fetches
self._fetching = False
@@ -719,7 +719,7 @@ def _unselect_profile(self, profile_id):
self._revert_rootpw_changes()
self._rule_data = None
- self._active_profile = None
+ self._active_profile = ""
@async_action_wait
def _select_profile(self, profile_id):

View File

@ -1,72 +0,0 @@
From 1b96504a8bbc198cce11647a0c3a65e1a3ffaba1 Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Fri, 13 May 2022 14:44:45 +0200
Subject: [PATCH] Fix strings for translations
The input of the _() function has to be a static string,
and it was in those cases a formatted one,
which didn't match the translation data.
---
org_fedora_oscap/rule_handling.py | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/org_fedora_oscap/rule_handling.py b/org_fedora_oscap/rule_handling.py
index 244aac8..635446e 100644
--- a/org_fedora_oscap/rule_handling.py
+++ b/org_fedora_oscap/rule_handling.py
@@ -707,10 +707,11 @@ def eval_rules(self, ksdata, storage, report_only=False):
messages = []
packages_data = get_packages_data()
+ msg_installed_template = _(
+ "package '%s' has been added to the list of to be installed packages")
# add messages for the already added packages
for pkg in self._added_pkgs:
- msg = _("package '%s' has been added to the list of to be installed "
- "packages" % pkg)
+ msg = msg_installed_template % pkg
messages.append(RuleMessage(self.__class__,
common.MESSAGE_TYPE_INFO, msg))
@@ -724,11 +725,12 @@ def eval_rules(self, ksdata, storage, report_only=False):
self._added_pkgs.add(pkg)
packages_data.packages.append(pkg)
- msg = _("package '%s' has been added to the list of to be installed "
- "packages" % pkg)
+ msg = msg_installed_template % pkg
messages.append(RuleMessage(self.__class__,
common.MESSAGE_TYPE_INFO, msg))
+ msg_excluded_template = _(
+ "package '%s' has been added to the list of excluded packages")
# now do the same for the packages that should be excluded
# add messages for the already excluded packages
for pkg in self._removed_pkgs:
@@ -736,13 +738,12 @@ def eval_rules(self, ksdata, storage, report_only=False):
msg = _(
"package '{package}' has been added to the list "
"of excluded packages, but it can't be removed "
- "from the current software selection without breaking the installation."
- .format(package=pkg))
+ "from the current software selection without breaking the installation.")
+ msg = msg.format(package=pkg)
messages.append(RuleMessage(self.__class__,
common.MESSAGE_TYPE_FATAL, msg))
else:
- msg = _("package '%s' has been added to the list of excluded "
- "packages" % pkg)
+ msg = msg_excluded_template % pkg
messages.append(RuleMessage(self.__class__,
common.MESSAGE_TYPE_INFO, msg))
@@ -756,8 +757,7 @@ def eval_rules(self, ksdata, storage, report_only=False):
self._removed_pkgs.add(pkg)
packages_data.excluded_packages.append(pkg)
- msg = _("package '%s' has been added to the list of excluded "
- "packages" % pkg)
+ msg = msg_excluded_template % pkg
messages.append(RuleMessage(self.__class__,
common.MESSAGE_TYPE_INFO, msg))

View File

@ -1,26 +0,0 @@
From cdb131f0b1282f833b697ef4cb4eb934ca2e9966 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mat=C4=9Bj=20T=C3=BD=C4=8D?= <matyc@redhat.com>
Date: Mon, 17 Jul 2023 15:27:24 +0200
Subject: [PATCH] Remove obsolete mapping of packages-groups
---
org_fedora_oscap/rule_handling.py | 6 ------
1 file changed, 6 deletions(-)
diff --git a/org_fedora_oscap/rule_handling.py b/org_fedora_oscap/rule_handling.py
index 635446e..7e2077c 100644
--- a/org_fedora_oscap/rule_handling.py
+++ b/org_fedora_oscap/rule_handling.py
@@ -59,12 +59,6 @@
"env": ["graphical-server-environment", "workstation-product-environment"],
"groups": ["workstation-product-environment"],
},
- "tftp": {
- "groups": ["network-server"],
- },
- "abrt": {
- "groups": ["debugging"],
- },
"gssproxy": {
"groups": ["file-server"],
},

View File

@ -1,29 +0,0 @@
From a306b736f144260721dfae25f0b268353d6760c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
Date: Thu, 25 Nov 2021 15:15:14 +0100
Subject: [PATCH] Fix tailoring
Fixes an error during installation caused during tailoring
Addressing:
dasbus.error.DBusError: Content evaluation and remediation with the oscap tool failed: OpenSCAP Error: Unable to open file: '/tmp/openscap_data/usr/share/xml/scap/sc_tailoring/tailoring-xccdf.xml' [/builddir/build/BUILD/openscap-1.3.5/src/source/oscap_source.c:288]
This is proabably a typo coming from 87509fb6ee22b6eeaa66ea4ae85ebf5abd353e14
which is only in rhel9-branch.
---
org_fedora_oscap/service/oscap.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org_fedora_oscap/service/oscap.py b/org_fedora_oscap/service/oscap.py
index 4237a47..65da08b 100755
--- a/org_fedora_oscap/service/oscap.py
+++ b/org_fedora_oscap/service/oscap.py
@@ -221,7 +221,7 @@ def install_with_tasks(self):
sysroot=conf.target.system_root,
policy_data=self.policy_data,
target_content_path=common.get_postinst_content_path(self.policy_data),
- target_tailoring_path=common.get_preinst_tailoring_path(self.policy_data)
+ target_tailoring_path=common.get_postinst_tailoring_path(self.policy_data)
)
]

View File

@ -1,32 +0,0 @@
From 2fbde88c29210c48083bd4840661d2af2d00ae69 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mat=C4=9Bj=20T=C3=BD=C4=8D?= <matyc@redhat.com>
Date: Mon, 17 Jul 2023 17:10:41 +0200
Subject: [PATCH] Make tar extraction safer on RHEL9
See also https://bugzilla.redhat.com/show_bug.cgi?id=2218875
---
org_fedora_oscap/common.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/org_fedora_oscap/common.py b/org_fedora_oscap/common.py
index eeb27fc..77d24c1 100644
--- a/org_fedora_oscap/common.py
+++ b/org_fedora_oscap/common.py
@@ -392,7 +392,7 @@ def extract_data(archive, out_dir, ensure_has_files=None):
raise ExtractionError(msg)
utils.ensure_dir_exists(out_dir)
- zfile.extractall(path=out_dir)
+ zfile.extractall(path=out_dir, filter="data")
result = [utils.join_paths(out_dir, info.filename) for info in zfile.filelist]
zfile.close()
elif archive.endswith(".tar"):
@@ -450,7 +450,7 @@ def _extract_tarball(archive, out_dir, ensure_has_files, alg):
raise ExtractionError(msg)
utils.ensure_dir_exists(out_dir)
- tfile.extractall(path=out_dir)
+ tfile.extractall(path=out_dir, filter="data")
result = [utils.join_paths(out_dir, member.path) for member in tfile.getmembers()]
tfile.close()

View File

@ -1,460 +0,0 @@
From aeb0e2ed5a524c5d4e5b72b2b11ea74a5119d45a Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Mon, 2 Aug 2021 17:23:17 +0200
Subject: [PATCH 1/3] Improve logging
Make all log entries identifiable easily.
---
org_fedora_oscap/common.py | 4 ++--
org_fedora_oscap/content_discovery.py | 16 +++++++++++-----
org_fedora_oscap/gui/spokes/oscap.py | 19 ++++++++++++-------
org_fedora_oscap/rule_handling.py | 8 ++++----
org_fedora_oscap/service/installation.py | 6 +++---
org_fedora_oscap/service/kickstart.py | 2 +-
org_fedora_oscap/service/oscap.py | 12 ++++++------
7 files changed, 39 insertions(+), 28 deletions(-)
diff --git a/org_fedora_oscap/common.py b/org_fedora_oscap/common.py
index a307baa..c432168 100644
--- a/org_fedora_oscap/common.py
+++ b/org_fedora_oscap/common.py
@@ -564,7 +564,7 @@ def get_content_name(data):
def get_raw_preinst_content_path(data):
"""Path to the raw (unextracted, ...) pre-installation content file"""
if data.content_type == "scap-security-guide":
- log.debug("Using scap-security-guide, no single content file")
+ log.debug("OSCAP addon: Using scap-security-guide, no single content file")
return None
content_name = get_content_name(data)
@@ -667,7 +667,7 @@ def set_packages_data(data: PackagesConfigurationData):
payload_proxy = get_payload_proxy()
if payload_proxy.Type != PAYLOAD_TYPE_DNF:
- log.debug("The payload doesn't support packages.")
+ log.debug("OSCAP addon: The payload doesn't support packages.")
return
return payload_proxy.SetPackages(
diff --git a/org_fedora_oscap/content_discovery.py b/org_fedora_oscap/content_discovery.py
index 894f3e1..bc14ef1 100644
--- a/org_fedora_oscap/content_discovery.py
+++ b/org_fedora_oscap/content_discovery.py
@@ -98,7 +98,7 @@ def fetch_content(self, what_if_fail, ca_certs_path=""):
def _fetch_files(self, scheme, path, destdir, ca_certs_path, what_if_fail):
with self.activity_lock:
if self.now_fetching_or_processing:
- msg = "Strange, it seems that we are already fetching something."
+ msg = "OSCAP Addon: Strange, it seems that we are already fetching something."
log.warn(msg)
return
self.now_fetching_or_processing = True
@@ -175,7 +175,7 @@ def finish_content_fetch(self, fetching_thread_name, fingerprint, report_callbac
def _verify_fingerprint(self, dest_filename, fingerprint=""):
if not fingerprint:
- log.info("No fingerprint provided, skipping integrity check")
+ log.info("OSCAP Addon: No fingerprint provided, skipping integrity check")
return
hash_obj = utils.get_hashing_algorithm(fingerprint)
@@ -183,15 +183,19 @@ def _verify_fingerprint(self, dest_filename, fingerprint=""):
hash_obj)
if digest != fingerprint:
log.error(
+ "OSCAP Addon: "
f"File {dest_filename} failed integrity check - assumed a "
f"{hash_obj.name} hash and '{fingerprint}', got '{digest}'"
)
- msg = _(f"Integrity check of the content failed - {hash_obj.name} hash didn't match")
+ msg = _(f"OSCAP Addon: Integrity check of the content failed - {hash_obj.name} hash didn't match")
raise content_handling.ContentCheckError(msg)
log.info(f"Integrity check passed using {hash_obj.name} hash")
def _finish_actual_fetch(self, wait_for, fingerprint, report_callback, dest_filename):
- threadMgr.wait(wait_for)
+ if wait_for:
+ log.info(f"OSCAP Addon: Waiting for thread {wait_for}")
+ threadMgr.wait(wait_for)
+ log.info(f"OSCAP Addon: Finished waiting for thread {wait_for}")
actually_fetched_content = wait_for is not None
if fingerprint and dest_filename:
@@ -201,6 +205,7 @@ def _finish_actual_fetch(self, wait_for, fingerprint, report_callback, dest_file
structured_content = ObtainedContent(self.CONTENT_DOWNLOAD_LOCATION)
content_type = self.get_content_type(str(dest_filename))
+ log.info(f"OSCAP Addon: started to look at the content")
if content_type in ("archive", "rpm"):
structured_content.add_content_archive(dest_filename)
@@ -211,6 +216,7 @@ def _finish_actual_fetch(self, wait_for, fingerprint, report_callback, dest_file
if fingerprint and dest_filename:
structured_content.record_verification(dest_filename)
+ log.info(f"OSCAP Addon: finished looking at the content")
return structured_content
def _gather_available_files(self, actually_fetched_content, dest_filename):
@@ -232,7 +238,7 @@ def _gather_available_files(self, actually_fetched_content, dest_filename):
)
except common.ExtractionError as err:
msg = f"Failed to extract the '{dest_filename}' archive: {str(err)}"
- log.error(msg)
+ log.error("OSCAP Addon: " + msg)
raise err
elif content_type == "file":
diff --git a/org_fedora_oscap/gui/spokes/oscap.py b/org_fedora_oscap/gui/spokes/oscap.py
index 76e508f..332e956 100644
--- a/org_fedora_oscap/gui/spokes/oscap.py
+++ b/org_fedora_oscap/gui/spokes/oscap.py
@@ -331,6 +331,7 @@ def initialize(self):
# if no content was specified and SSG is available, use it
if not self._policy_data.content_type and common.ssg_available():
+ log.info("OSCAP Addon: Defaulting to local content")
self._policy_data.content_type = "scap-security-guide"
self._policy_data.content_path = common.SSG_DIR + common.SSG_CONTENT
@@ -351,7 +352,7 @@ def initialize(self):
self._fetch_data_and_initialize()
def _handle_error(self, exception):
- log.error(str(exception))
+ log.error("OSCAP Addon: " + str(exception))
if isinstance(exception, KickstartValueError):
self._invalid_url()
elif isinstance(exception, common.OSCAPaddonNetworkError):
@@ -365,7 +366,7 @@ def _handle_error(self, exception):
elif isinstance(exception, content_handling.ContentCheckError):
self._integrity_check_failed()
else:
- log.exception("Unknown exception occurred", exc_info=exception)
+ log.exception("OSCAP Addon: Unknown exception occurred", exc_info=exception)
self._general_content_problem()
def _render_selected(self, column, renderer, model, itr, user_data=None):
@@ -385,6 +386,7 @@ def _fetch_data_and_initialize(self):
thread_name = None
if self._policy_data.content_url and self._policy_data.content_type != "scap-security-guide":
+ log.info(f"OSCAP Addon: Actually fetching content from somewhere")
thread_name = self.content_bringer.fetch_content(
self._handle_error, self._policy_data.certificates)
@@ -442,7 +444,7 @@ def update_progress_label(msg):
msg += f" with tailoring {preinst_tailoring_path}"
else:
msg += " without considering tailoring"
- log.info(msg)
+ log.info("OSCAP Addon: " + msg)
self._content_handler = scap_content_handler.SCAPContentHandler(
preinst_content_path,
@@ -456,7 +458,7 @@ def update_progress_label(msg):
return
- log.info("OAA: Done with analysis")
+ log.info("OSCAP Addon: Done with analysis")
self._ds_checklists = self._content_handler.get_data_streams_checklists()
if self._using_ds:
@@ -592,7 +594,7 @@ def _update_profiles_store(self):
try:
profiles = self._content_handler.get_profiles()
except scap_content_handler.SCAPContentHandlerError as e:
- log.warning(str(e))
+ log.warning("OSCAP Addon: " + str(e))
self._invalid_content()
for profile in profiles:
@@ -736,7 +738,7 @@ def _select_profile(self, profile_id):
ds, xccdf, common.get_preinst_tailoring_path(self._policy_data))
except common.OSCAPaddonError as exc:
log.error(
- "Failed to get rules for the profile '{}': {}"
+ "OSCAP Addon: Failed to get rules for the profile '{}': {}"
.format(profile_id, str(exc)))
self._set_error(
"Failed to get rules for the profile '{}'"
@@ -908,6 +910,7 @@ def refresh(self):
def _refresh_ui(self):
"""Refresh the UI elements."""
if not self._content_defined:
+ log.info("OSCAP Addon: Content not defined")
# hide the control buttons
really_hide(self._control_buttons)
@@ -1156,7 +1159,9 @@ def on_fetch_button_clicked(self, *args):
with self._fetch_flag_lock:
if self._fetching:
# some other fetching/pre-processing running, give up
- log.warn("Clicked the fetch button, although the GUI is in the fetching mode.")
+ log.warn(
+ "OSCAP Addon: "
+ "Clicked the fetch button, although the GUI is in the fetching mode.")
return
# prevent user from changing the URL in the meantime
diff --git a/org_fedora_oscap/rule_handling.py b/org_fedora_oscap/rule_handling.py
index c478aa0..244aac8 100644
--- a/org_fedora_oscap/rule_handling.py
+++ b/org_fedora_oscap/rule_handling.py
@@ -261,7 +261,7 @@ def new_rule(self, rule):
try:
actions[first_word](rule)
except (ModifiedOptionParserException, KeyError) as e:
- log.warning("Unknown OSCAP Addon rule '{}': {}".format(rule, e))
+ log.warning("OSCAP Addon: Unknown OSCAP Addon rule '{}': {}".format(rule, e))
def eval_rules(self, ksdata, storage, report_only=False):
""":see: RuleHandler.eval_rules"""
@@ -565,7 +565,7 @@ def eval_rules(self, ksdata, storage, report_only=False):
# root password set
if users_proxy.IsRootPasswordCrypted:
msg = _("cannot check root password length (password is crypted)")
- log.warning("cannot check root password length (password is crypted)")
+ log.warning("OSCAP Addon: cannot check root password length (password is crypted)")
return [RuleMessage(self.__class__,
common.MESSAGE_TYPE_WARNING, msg)]
elif len(users_proxy.RootPassword) < self._minlen:
@@ -880,7 +880,7 @@ def eval_rules(self, ksdata, storage, report_only=False):
kdump_proxy.KdumpEnabled = self._kdump_enabled
else:
- log.warning("com_redhat_kdump is not installed. "
+ log.warning("OSCAP Addon: com_redhat_kdump is not installed. "
"Skipping kdump configuration")
return messages
@@ -894,7 +894,7 @@ def revert_changes(self, ksdata, storage):
if self._kdump_enabled is not None:
kdump_proxy.KdumpEnabled = self._kdump_default_enabled
else:
- log.warning("com_redhat_kdump is not installed. "
+ log.warning("OSCAP Addon: com_redhat_kdump is not installed. "
"Skipping reverting kdump configuration")
self._kdump_enabled = None
diff --git a/org_fedora_oscap/service/installation.py b/org_fedora_oscap/service/installation.py
index e3a1d0f..2da8559 100644
--- a/org_fedora_oscap/service/installation.py
+++ b/org_fedora_oscap/service/installation.py
@@ -28,14 +28,14 @@
from org_fedora_oscap.content_handling import ContentCheckError
from org_fedora_oscap import content_discovery
-log = logging.getLogger(__name__)
+log = logging.getLogger("anaconda")
REQUIRED_PACKAGES = ("openscap", "openscap-scanner",)
def _handle_error(exception):
- log.error("Failed to fetch and initialize SCAP content!")
+ log.error("OSCAP Addon: Failed to fetch and initialize SCAP content!")
if isinstance(exception, ContentCheckError):
msg = _("The integrity check of the security content failed.")
@@ -87,7 +87,7 @@ def run(self):
content = self.content_bringer.finish_content_fetch(
fetching_thread_name, self._policy_data.fingerprint,
- lambda msg: log.info(msg), content_dest, _handle_error)
+ lambda msg: log.info("OSCAP Addon: " + msg), content_dest, _handle_error)
if not content:
# this shouldn't happen because error handling is supposed to
diff --git a/org_fedora_oscap/service/kickstart.py b/org_fedora_oscap/service/kickstart.py
index 341c6c5..d6f22ac 100644
--- a/org_fedora_oscap/service/kickstart.py
+++ b/org_fedora_oscap/service/kickstart.py
@@ -25,7 +25,7 @@
from org_fedora_oscap import common, utils
from org_fedora_oscap.structures import PolicyData
-log = logging.getLogger(__name__)
+log = logging.getLogger("anaconda")
__all__ = ["OSCAPKickstartSpecification"]
diff --git a/org_fedora_oscap/service/oscap.py b/org_fedora_oscap/service/oscap.py
index d491060..4237a47 100755
--- a/org_fedora_oscap/service/oscap.py
+++ b/org_fedora_oscap/service/oscap.py
@@ -34,7 +34,7 @@
from org_fedora_oscap.service.oscap_interface import OSCAPInterface
from org_fedora_oscap.structures import PolicyData
-log = logging.getLogger(__name__)
+log = logging.getLogger("anaconda")
__all__ = ["OSCAPService"]
@@ -71,7 +71,7 @@ def policy_enabled(self, value):
"""
self._policy_enabled = value
self.policy_enabled_changed.emit()
- log.debug("Policy enabled is set to '%s'.", value)
+ log.debug("OSCAP Addon: Policy enabled is set to '%s'.", value)
@property
def policy_data(self):
@@ -89,7 +89,7 @@ def policy_data(self, value):
"""
self._policy_data = value
self.policy_data_changed.emit()
- log.debug("Policy data is set to '%s'.", value)
+ log.debug("OSCAP Addon: Policy data is set to '%s'.", value)
@property
def installation_enabled(self):
@@ -150,7 +150,7 @@ def collect_requirements(self):
:return: a list of requirements
"""
if not self.installation_enabled:
- log.debug("The installation is disabled. Skip the requirements.")
+ log.debug("OSCAP Addon: The installation is disabled. Skip the requirements.")
return []
requirements = [
@@ -180,7 +180,7 @@ def configure_with_tasks(self):
:return: a list of tasks
"""
if not self.installation_enabled:
- log.debug("The installation is disabled. Skip the configuration.")
+ log.debug("OSCAP Addon: The installation is disabled. Skip the configuration.")
return []
tasks = [
@@ -205,7 +205,7 @@ def install_with_tasks(self):
:return: a list of tasks
"""
if not self.installation_enabled:
- log.debug("The installation is disabled. Skip the installation.")
+ log.debug("OSCAP Addon: The installation is disabled. Skip the installation.")
return []
tasks = [
From b081e32012b93177167d3f7d0cc2024deb50e965 Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Mon, 2 Aug 2021 17:24:15 +0200
Subject: [PATCH 2/3] Save addon data when using local content
Addon loads its data from the shared storage upon refresh,
which caused it to overwrite clicking on the "use SSG content" button.
Now the data is saved after clicking that button, and convenience
load/save methods were introduced.
---
org_fedora_oscap/gui/spokes/oscap.py | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/org_fedora_oscap/gui/spokes/oscap.py b/org_fedora_oscap/gui/spokes/oscap.py
index 332e956..4425757 100644
--- a/org_fedora_oscap/gui/spokes/oscap.py
+++ b/org_fedora_oscap/gui/spokes/oscap.py
@@ -232,11 +232,8 @@ def __init__(self, data, storage, payload):
# the proxy to OSCAP DBus module
self._oscap_module = OSCAP.get_proxy()
- # the security policy data
- self._policy_enabled = self._oscap_module.PolicyEnabled
- self._policy_data = PolicyData.from_structure(
- self._oscap_module.PolicyData
- )
+ self._policy_data = PolicyData()
+ self._load_policy_data()
# used for changing profiles
self._rule_data = None
@@ -334,6 +331,7 @@ def initialize(self):
log.info("OSCAP Addon: Defaulting to local content")
self._policy_data.content_type = "scap-security-guide"
self._policy_data.content_path = common.SSG_DIR + common.SSG_CONTENT
+ self._save_policy_data()
if not self._content_defined:
# nothing more to be done now, the spoke is ready
@@ -351,6 +349,16 @@ def initialize(self):
# else fetch data
self._fetch_data_and_initialize()
+ def _save_policy_data(self):
+ self._oscap_module.PolicyData = PolicyData.to_structure(self._policy_data)
+ self._oscap_module.PolicyEnabled = self._policy_enabled
+
+ def _load_policy_data(self):
+ self._policy_data.update_from(PolicyData.from_structure(
+ self._oscap_module.PolicyData
+ ))
+ self._policy_enabled = self._oscap_module.PolicyEnabled
+
def _handle_error(self, exception):
log.error("OSCAP Addon: " + str(exception))
if isinstance(exception, KickstartValueError):
@@ -897,13 +905,7 @@ def refresh(self):
:see: pyanaconda.ui.common.UIObject.refresh
"""
- # update the security policy data
- self._policy_enabled = self._oscap_module.PolicyEnabled
- fresh_data = PolicyData.from_structure(
- self._oscap_module.PolicyData
- )
-
- self._policy_data.update_from(fresh_data)
+ self._load_policy_data()
# update the UI elements
self._refresh_ui()
@@ -1202,4 +1204,5 @@ def on_change_content_clicked(self, *args):
def on_use_ssg_clicked(self, *args):
self.content_bringer.use_system_content()
+ self._save_policy_data()
self._fetch_data_and_initialize()
From fee170f54aeb9f649ab891781532012a7b069f8f Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Tue, 3 Aug 2021 11:01:59 +0200
Subject: [PATCH 3/3] Refactor content identification
Don't use the multiprocessing pool - it sometimes creates probems during
its initialization:
https://bugzilla.redhat.com/show_bug.cgi?id=1989434
---
org_fedora_oscap/content_handling.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/org_fedora_oscap/content_handling.py b/org_fedora_oscap/content_handling.py
index f2af22f..65d5a28 100644
--- a/org_fedora_oscap/content_handling.py
+++ b/org_fedora_oscap/content_handling.py
@@ -111,9 +111,8 @@ def parse_HTML_from_content(content):
def identify_files(fpaths):
- with multiprocessing.Pool(os.cpu_count()) as p:
- labels = p.map(get_doc_type, fpaths)
- return {path: label for (path, label) in zip(fpaths, labels)}
+ result = {path: get_doc_type(path) for path in fpaths}
+ return result
def get_doc_type(file_path):
@@ -131,7 +130,9 @@ def get_doc_type(file_path):
except UnicodeDecodeError:
# 'oscap info' supplied weird output, which happens when it tries
# to explain why it can't examine e.g. a JPG.
- return None
+ pass
+ except Exception as e:
+ log.warning(f"OSCAP addon: Unexpected error when looking at {file_path}: {str(e)}")
log.info("OSCAP addon: Identified {file_path} as {content_type}"
.format(file_path=file_path, content_type=content_type))
return content_type

View File

@ -1,380 +0,0 @@
From a1b983b4b5f8e49daa978aec6f9d28ba6dcea20c Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Wed, 12 Oct 2022 11:37:04 +0200
Subject: [PATCH 1/5] Add capability to preselect content from archives
Users can specify content path and tailoring path in kickstarts,
and the addon should be able to assure that those files are available,
and that they have precedence over other files.
---
org_fedora_oscap/content_discovery.py | 35 +++++++++++++++++++
tests/test_content_discovery.py | 48 +++++++++++++++++++++++++++
2 files changed, 83 insertions(+)
create mode 100644 tests/test_content_discovery.py
diff --git a/org_fedora_oscap/content_discovery.py b/org_fedora_oscap/content_discovery.py
index ccfe6c8..9ef144e 100644
--- a/org_fedora_oscap/content_discovery.py
+++ b/org_fedora_oscap/content_discovery.py
@@ -12,6 +12,7 @@
from org_fedora_oscap import data_fetch, utils
from org_fedora_oscap import common
from org_fedora_oscap import content_handling
+from org_fedora_oscap.content_handling import CONTENT_TYPES
from org_fedora_oscap import rule_handling
from org_fedora_oscap.common import _
@@ -191,6 +192,38 @@ def _verify_fingerprint(self, dest_filename, fingerprint=""):
raise content_handling.ContentCheckError(msg)
log.info(f"Integrity check passed using {hash_obj.name} hash")
+ def filter_discovered_content(self, labelled_files):
+ expected_path = self._addon_data.content_path
+ categories = (CONTENT_TYPES["DATASTREAM"], CONTENT_TYPES["XCCDF_CHECKLIST"])
+ if expected_path:
+ labelled_files = self.reduce_files(labelled_files, expected_path, categories)
+
+ expected_path = self._addon_data.tailoring_path
+ categories = (CONTENT_TYPES["TAILORING"], )
+ if expected_path:
+ labelled_files = self.reduce_files(labelled_files, expected_path, categories)
+
+ expected_path = self._addon_data.cpe_path
+ categories = (CONTENT_TYPES["CPE_DICT"], )
+ if expected_path:
+ labelled_files = self.reduce_files(labelled_files, expected_path, categories)
+
+ return labelled_files
+
+ def reduce_files(self, labelled_files, expected_path, categories):
+ reduced_files = dict()
+ if expected_path not in labelled_files:
+ msg = (
+ f"Expected a file {expected_path} to be part of the supplied content, "
+ f"but it was not the case, got only {list(labelled_files.keys())}"
+ )
+ raise RuntimeError(msg)
+ for path, label in labelled_files.items():
+ if label in categories and path != expected_path:
+ continue
+ reduced_files[path] = label
+ return reduced_files
+
def _finish_actual_fetch(self, wait_for, fingerprint, report_callback, dest_filename):
if wait_for:
log.info(f"OSCAP Addon: Waiting for thread {wait_for}")
@@ -210,6 +243,8 @@ def _finish_actual_fetch(self, wait_for, fingerprint, report_callback, dest_file
structured_content.add_content_archive(dest_filename)
labelled_files = content_handling.identify_files(fpaths)
+ labelled_files = self.filter_discovered_content(labelled_files)
+
for fname, label in labelled_files.items():
structured_content.add_file(fname, label)
diff --git a/tests/test_content_discovery.py b/tests/test_content_discovery.py
new file mode 100644
index 0000000..5463c9a
--- /dev/null
+++ b/tests/test_content_discovery.py
@@ -0,0 +1,48 @@
+import pytest
+
+import org_fedora_oscap.content_discovery as tested_module
+
+
+@pytest.fixture
+def labelled_files():
+ return {
+ "dir/datastream": "D",
+ "dir/datastream2": "D",
+ "dir/dir/datastream3": "D",
+ "dir/dir/datastream3": "D",
+ "dir/XCCDF": "X",
+ "XCCDF2": "X",
+ "cpe": "C",
+ "t1": "T",
+ "dir3/t2": "T",
+ }
+
+
+def test_reduce(labelled_files):
+ bringer = tested_module.ContentBringer(None)
+
+ d_count = 0
+ x_count = 0
+ for l in labelled_files.values():
+ if l == "D":
+ d_count += 1
+ elif l == "X":
+ x_count += 1
+
+ reduced = bringer.reduce_files(labelled_files, "dir/datastream", ["D"])
+ assert len(reduced) == len(labelled_files) - d_count + 1
+ assert "dir/datastream" in reduced
+
+ reduced = bringer.reduce_files(labelled_files, "dir/datastream", ["D", "X"])
+ assert len(reduced) == len(labelled_files) - d_count - x_count + 1
+ assert "dir/datastream" in reduced
+
+ reduced = bringer.reduce_files(labelled_files, "dir/XCCDF", ["D", "X"])
+ assert len(reduced) == len(labelled_files) - d_count - x_count + 1
+ assert "dir/XCCDF" in reduced
+
+ with pytest.raises(RuntimeError, match="dir/datastream4"):
+ bringer.reduce_files(labelled_files, "dir/datastream4", ["D"])
+
+ reduced = bringer.reduce_files(labelled_files, "cpe", ["C"])
+ assert reduced == labelled_files
From 2a536a8ec4cdf20e4f19e8175898b7ace3fc7ca4 Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Wed, 12 Oct 2022 11:40:11 +0200
Subject: [PATCH 2/5] Handle changes in content identification
The code is able to handle changes in the way how oscap identifies
content much more gracefully.
---
org_fedora_oscap/content_discovery.py | 13 +++++++++----
org_fedora_oscap/content_handling.py | 5 +++++
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/org_fedora_oscap/content_discovery.py b/org_fedora_oscap/content_discovery.py
index 9ef144e..9ed643b 100644
--- a/org_fedora_oscap/content_discovery.py
+++ b/org_fedora_oscap/content_discovery.py
@@ -2,6 +2,7 @@
import logging
import pathlib
import shutil
+import os
from glob import glob
from typing import List
@@ -242,11 +243,15 @@ def _finish_actual_fetch(self, wait_for, fingerprint, report_callback, dest_file
if content_type in ("archive", "rpm"):
structured_content.add_content_archive(dest_filename)
- labelled_files = content_handling.identify_files(fpaths)
- labelled_files = self.filter_discovered_content(labelled_files)
+ labelled_filenames = content_handling.identify_files(fpaths)
+ labelled_relative_filenames = {
+ os.path.relpath(path, self.CONTENT_DOWNLOAD_LOCATION): label
+ for path, label in labelled_filenames.items()}
+ labelled_relative_filenames = self.filter_discovered_content(labelled_relative_filenames)
- for fname, label in labelled_files.items():
- structured_content.add_file(fname, label)
+ for rel_fname, label in labelled_relative_filenames.items():
+ fname = self.CONTENT_DOWNLOAD_LOCATION / rel_fname
+ structured_content.add_file(str(fname), label)
if fingerprint and dest_filename:
structured_content.record_verification(dest_filename)
diff --git a/org_fedora_oscap/content_handling.py b/org_fedora_oscap/content_handling.py
index 65d5a28..3e2ecae 100644
--- a/org_fedora_oscap/content_handling.py
+++ b/org_fedora_oscap/content_handling.py
@@ -122,6 +122,11 @@ def get_doc_type(file_path):
if line.startswith("Document type:"):
_prefix, _sep, type_info = line.partition(":")
content_type = type_info.strip()
+ if content_type not in CONTENT_TYPES.values():
+ log.info(
+ f"File {file_path} labelled by oscap as {content_type}, "
+ "which is an unexpected type.")
+ content_type = f"unknown - {content_type}"
break
except OSError:
# 'oscap info' exitted with a non-zero exit code -> unknown doc
From 17f80b71d17ce5a2bdbed87730133cdabec2e22b Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Wed, 12 Oct 2022 11:38:51 +0200
Subject: [PATCH 3/5] Remove unused code
The function is not referenced anywhere in the project
---
org_fedora_oscap/content_handling.py | 40 ----------------------------
1 file changed, 40 deletions(-)
diff --git a/org_fedora_oscap/content_handling.py b/org_fedora_oscap/content_handling.py
index 3e2ecae..5096bab 100644
--- a/org_fedora_oscap/content_handling.py
+++ b/org_fedora_oscap/content_handling.py
@@ -141,43 +141,3 @@ def get_doc_type(file_path):
log.info("OSCAP addon: Identified {file_path} as {content_type}"
.format(file_path=file_path, content_type=content_type))
return content_type
-
-
-def explore_content_files(fpaths):
- """
- Function for finding content files in a list of file paths. SIMPLY PICKS
- THE FIRST USABLE CONTENT FILE OF A PARTICULAR TYPE AND JUST PREFERS DATA
- STREAMS OVER STANDALONE BENCHMARKS.
-
- :param fpaths: a list of file paths to search for content files in
- :type fpaths: [str]
- :return: ContentFiles instance containing the file names of the XCCDF file,
- CPE dictionary and tailoring file or "" in place of those items
- if not found
- :rtype: ContentFiles
-
- """
- xccdf_file = ""
- cpe_file = ""
- tailoring_file = ""
- found_ds = False
-
- for fpath in fpaths:
- doc_type = get_doc_type(fpath)
- if not doc_type:
- continue
-
- # prefer DS over standalone XCCDF
- if doc_type == "Source Data Stream" and (not xccdf_file or not found_ds):
- xccdf_file = fpath
- found_ds = True
- elif doc_type == "XCCDF Checklist" and not xccdf_file:
- xccdf_file = fpath
- elif doc_type == "CPE Dictionary" and not cpe_file:
- cpe_file = fpath
- elif doc_type == "XCCDF Tailoring" and not tailoring_file:
- tailoring_file = fpath
-
- # TODO: raise exception if no xccdf_file is found?
- files = ContentFiles(xccdf_file, cpe_file, tailoring_file)
- return files
From 3aff547e2689a1ede4236c9166b11c99f272e3f7 Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Thu, 13 Oct 2022 14:11:25 +0200
Subject: [PATCH 4/5] Dont use tailoring if it is not expected
Take tailorings into account only if it is specified in the kickstart.
Compulsive usage of tailoring may be unwanted.
---
org_fedora_oscap/content_discovery.py | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/org_fedora_oscap/content_discovery.py b/org_fedora_oscap/content_discovery.py
index 9ed643b..4235af7 100644
--- a/org_fedora_oscap/content_discovery.py
+++ b/org_fedora_oscap/content_discovery.py
@@ -193,16 +193,25 @@ def _verify_fingerprint(self, dest_filename, fingerprint=""):
raise content_handling.ContentCheckError(msg)
log.info(f"Integrity check passed using {hash_obj.name} hash")
+ def allow_one_expected_tailoring_or_no_tailoring(self, labelled_files):
+ expected_tailoring = self._addon_data.tailoring_path
+ tailoring_label = CONTENT_TYPES["TAILORING"]
+ if expected_tailoring:
+ labelled_files = self.reduce_files(labelled_files, expected_tailoring, [tailoring_label])
+ else:
+ labelled_files = {
+ path: label for path, label in labelled_files.items()
+ if label != tailoring_label
+ }
+ return labelled_files
+
def filter_discovered_content(self, labelled_files):
expected_path = self._addon_data.content_path
categories = (CONTENT_TYPES["DATASTREAM"], CONTENT_TYPES["XCCDF_CHECKLIST"])
if expected_path:
labelled_files = self.reduce_files(labelled_files, expected_path, categories)
- expected_path = self._addon_data.tailoring_path
- categories = (CONTENT_TYPES["TAILORING"], )
- if expected_path:
- labelled_files = self.reduce_files(labelled_files, expected_path, categories)
+ labelled_files = self.allow_one_expected_tailoring_or_no_tailoring(labelled_files)
expected_path = self._addon_data.cpe_path
categories = (CONTENT_TYPES["CPE_DICT"], )
From 56d8e497e0a4c394784b1c950bd1a148a6dc42ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mat=C4=9Bj=20T=C3=BD=C4=8D?= <matyc@redhat.com>
Date: Thu, 10 Nov 2022 12:46:46 +0100
Subject: [PATCH 5/5] Make the content RPM installation robust
If a package manager fails to install the package,
use the rpm command directly and skip deps.
---
org_fedora_oscap/service/installation.py | 48 +++++++++++++++++-------
1 file changed, 34 insertions(+), 14 deletions(-)
diff --git a/org_fedora_oscap/service/installation.py b/org_fedora_oscap/service/installation.py
index 255b992..f667479 100644
--- a/org_fedora_oscap/service/installation.py
+++ b/org_fedora_oscap/service/installation.py
@@ -18,6 +18,7 @@
import logging
import os
import shutil
+import io
from pyanaconda.core import util
from pyanaconda.modules.common.task import Task
@@ -198,21 +199,11 @@ def run(self):
elif self._policy_data.content_type == "datastream":
shutil.copy2(self._content_path, target_content_dir)
elif self._policy_data.content_type == "rpm":
- # copy the RPM to the target system
- shutil.copy2(self._file_path, target_content_dir)
+ try:
+ self._copy_rpm_to_target_and_install(target_content_dir)
- # get the path of the RPM
- content_name = common.get_content_name(self._policy_data)
- package_path = utils.join_paths(self._target_directory, content_name)
-
- # and install it with yum
- ret = util.execInSysroot(
- "yum", ["-y", "--nogpg", "install", package_path]
- )
-
- if ret != 0:
- msg = _(f"Failed to install content RPM to the target system.")
- terminate(msg)
+ except Exception as exc:
+ terminate(str(exc))
return
else:
pattern = utils.join_paths(common.INSTALLATION_CONTENT_DIR, "*")
@@ -221,6 +212,35 @@ def run(self):
if os.path.exists(self._tailoring_path):
shutil.copy2(self._tailoring_path, target_content_dir)
+ def _attempt_rpm_installation(self, chroot_package_path):
+ log.info("OSCAP addon: Installing the security content RPM to the installed system.")
+ stdout = io.StringIO()
+ ret = util.execWithRedirect(
+ "dnf", ["-y", "--nogpg", "install", chroot_package_path],
+ stdout=stdout, root=self._sysroot)
+ stdout.seek(0)
+ if ret != 0:
+ log.error(
+ "OSCAP addon: Error installing security content RPM using yum: {0}",
+ stdout.read())
+
+ stdout = io.StringIO()
+ ret = util.execWithRedirect(
+ "rpm", ["--install", "--nodeps", chroot_package_path],
+ stdout=stdout, root=self._sysroot)
+ if ret != 0:
+ log.error(
+ "OSCAP addon: Error installing security content RPM using rpm: {0}",
+ stdout.read())
+ msg = _(f"Failed to install content RPM to the target system.")
+ raise RuntimeError(msg)
+
+ def _copy_rpm_to_target_and_install(self, target_content_dir):
+ shutil.copy2(self._file_path, target_content_dir)
+ content_name = common.get_content_name(self._policy_data)
+ chroot_package_path = utils.join_paths(self._target_directory, content_name)
+ self._attempt_rpm_installation(chroot_package_path)
+
class RemediateSystemTask(Task):
"""The installation task for running the remediation."""

View File

@ -1,74 +0,0 @@
From 99fc53d3691b24c6724c1cf3e7281c181b31cf45 Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Tue, 11 Oct 2022 17:07:28 +0200
Subject: [PATCH 1/2] Remove redundant message
The send_ready already performs what the removed call
could aim to accomplish.
---
org_fedora_oscap/gui/spokes/oscap.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/org_fedora_oscap/gui/spokes/oscap.py b/org_fedora_oscap/gui/spokes/oscap.py
index 6d0aa5c..37b9681 100644
--- a/org_fedora_oscap/gui/spokes/oscap.py
+++ b/org_fedora_oscap/gui/spokes/oscap.py
@@ -151,7 +151,6 @@ def decorated(self, *args, **kwargs):
self._ready = True
# pylint: disable-msg=E1101
hubQ.send_ready(self.__class__.__name__)
- hubQ.send_message(self.__class__.__name__, self.status)
return ret
From 24787f02e80162129256dc57dc3d491f00080370 Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Thu, 13 Oct 2022 17:19:17 +0200
Subject: [PATCH 2/2] Increase robustness of fetching state detection
It is not completely practical to rely on locks alone,
and we can elliminate some corner cases by looking
whether well-known UI threads exist.
---
org_fedora_oscap/gui/spokes/oscap.py | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/org_fedora_oscap/gui/spokes/oscap.py b/org_fedora_oscap/gui/spokes/oscap.py
index 37b9681..97c4553 100644
--- a/org_fedora_oscap/gui/spokes/oscap.py
+++ b/org_fedora_oscap/gui/spokes/oscap.py
@@ -389,11 +389,14 @@ def _render_selected(self, column, renderer, model, itr, user_data=None):
else:
renderer.set_property("stock-id", None)
+ def _still_fetching(self):
+ return self._fetching or threadMgr.get('OSCAPguiWaitForDataFetchThread')
+
def _fetch_data_and_initialize(self):
"""Fetch data from a specified URL and initialize everything."""
with self._fetch_flag_lock:
- if self._fetching:
+ if self._still_fetching():
# prevent multiple fetches running simultaneously
return
self._fetching = True
@@ -940,7 +943,7 @@ def _refresh_ui(self):
# hide the progress box, no progress now
with self._fetch_flag_lock:
- if not self._fetching:
+ if not self._still_fetching():
really_hide(self._progress_box)
self._content_url_entry.set_sensitive(True)
@@ -1165,7 +1168,7 @@ def on_fetch_button_clicked(self, *args):
"""Handler for the Fetch button"""
with self._fetch_flag_lock:
- if self._fetching:
+ if self._still_fetching():
# some other fetching/pre-processing running, give up
log.warn(
"OSCAP Addon: "

View File

@ -1,325 +0,0 @@
From e2c47422b0ecfd561a8fe203b53e4a3831ae0ff7 Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Tue, 22 Nov 2022 11:45:11 +0100
Subject: [PATCH 1/3] Fix handling of content paths
Archives and ready-to-use content use paths differently.
Archives get unpacked into a directory, where they need to be unpacked,
analyzed, and cross-checked with e.g. the supplied content path,
whereas ready-to-use content can be used directly.
As the current codebase doesn't untangle all possible ways how to obtain
existing content in a way of decomposing those into layers, this change
just makes the current code working at the expense of making it worse to
maintain.
---
org_fedora_oscap/content_discovery.py | 34 ++++++++++++++++++---------
org_fedora_oscap/service/kickstart.py | 10 +++++++-
tests/test_content_discovery.py | 21 +++++++++++++++++
3 files changed, 53 insertions(+), 12 deletions(-)
diff --git a/org_fedora_oscap/content_discovery.py b/org_fedora_oscap/content_discovery.py
index 4235af7..ebef618 100644
--- a/org_fedora_oscap/content_discovery.py
+++ b/org_fedora_oscap/content_discovery.py
@@ -46,6 +46,14 @@ def clear_all(data):
data.dry_run = False
+def path_is_present_among_paths(path, paths):
+ absolute_path = os.path.abspath(path)
+ for second_path in paths:
+ if absolute_path == os.path.abspath(second_path):
+ return True
+ return False
+
+
class ContentBringer:
CONTENT_DOWNLOAD_LOCATION = pathlib.Path(common.INSTALLATION_CONTENT_DIR)
DEFAULT_SSG_DATA_STREAM_PATH = f"{common.SSG_DIR}/{common.SSG_CONTENT}"
@@ -194,7 +202,7 @@ def _verify_fingerprint(self, dest_filename, fingerprint=""):
log.info(f"Integrity check passed using {hash_obj.name} hash")
def allow_one_expected_tailoring_or_no_tailoring(self, labelled_files):
- expected_tailoring = self._addon_data.tailoring_path
+ expected_tailoring = common.get_preinst_tailoring_path(self._addon_data)
tailoring_label = CONTENT_TYPES["TAILORING"]
if expected_tailoring:
labelled_files = self.reduce_files(labelled_files, expected_tailoring, [tailoring_label])
@@ -206,7 +214,7 @@ def allow_one_expected_tailoring_or_no_tailoring(self, labelled_files):
return labelled_files
def filter_discovered_content(self, labelled_files):
- expected_path = self._addon_data.content_path
+ expected_path = common.get_preinst_content_path(self._addon_data)
categories = (CONTENT_TYPES["DATASTREAM"], CONTENT_TYPES["XCCDF_CHECKLIST"])
if expected_path:
labelled_files = self.reduce_files(labelled_files, expected_path, categories)
@@ -222,7 +230,7 @@ def filter_discovered_content(self, labelled_files):
def reduce_files(self, labelled_files, expected_path, categories):
reduced_files = dict()
- if expected_path not in labelled_files:
+ if not path_is_present_among_paths(expected_path, labelled_files.keys()):
msg = (
f"Expected a file {expected_path} to be part of the supplied content, "
f"but it was not the case, got only {list(labelled_files.keys())}"
@@ -253,13 +261,9 @@ def _finish_actual_fetch(self, wait_for, fingerprint, report_callback, dest_file
structured_content.add_content_archive(dest_filename)
labelled_filenames = content_handling.identify_files(fpaths)
- labelled_relative_filenames = {
- os.path.relpath(path, self.CONTENT_DOWNLOAD_LOCATION): label
- for path, label in labelled_filenames.items()}
- labelled_relative_filenames = self.filter_discovered_content(labelled_relative_filenames)
+ labelled_filenames = self.filter_discovered_content(labelled_filenames)
- for rel_fname, label in labelled_relative_filenames.items():
- fname = self.CONTENT_DOWNLOAD_LOCATION / rel_fname
+ for fname, label in labelled_filenames.items():
structured_content.add_file(str(fname), label)
if fingerprint and dest_filename:
@@ -303,11 +307,18 @@ def use_downloaded_content(self, content):
# We know that we have ended up with a datastream-like content,
# but if we can't convert an archive to a datastream.
# self._addon_data.content_type = "datastream"
- self._addon_data.content_path = str(preferred_content.relative_to(content.root))
+ content_type = self._addon_data.content_type
+ if content_type in ("archive", "rpm"):
+ self._addon_data.content_path = str(preferred_content.relative_to(content.root))
+ else:
+ self._addon_data.content_path = str(preferred_content)
preferred_tailoring = self.get_preferred_tailoring(content)
if content.tailoring:
- self._addon_data.tailoring_path = str(preferred_tailoring.relative_to(content.root))
+ if content_type in ("archive", "rpm"):
+ self._addon_data.tailoring_path = str(preferred_tailoring.relative_to(content.root))
+ else:
+ self._addon_data.tailoring_path = str(preferred_tailoring)
def use_system_content(self, content=None):
clear_all(self._addon_data)
@@ -403,6 +414,7 @@ def _xccdf_content(self):
def find_expected_usable_content(self, relative_expected_content_path):
content_path = self.root / relative_expected_content_path
+ content_path = content_path.resolve()
eligible_main_content = (self._datastream_content(), self._xccdf_content())
if content_path in eligible_main_content:
diff --git a/org_fedora_oscap/service/kickstart.py b/org_fedora_oscap/service/kickstart.py
index ce049d1..6698978 100644
--- a/org_fedora_oscap/service/kickstart.py
+++ b/org_fedora_oscap/service/kickstart.py
@@ -17,6 +17,7 @@
#
import logging
import re
+import os
from pyanaconda.core.kickstart import KickstartSpecification
from pyanaconda.core.kickstart.addon import AddonData
@@ -146,7 +147,14 @@ def _parse_profile_id(self, value):
self.policy_data.profile_id = value
def _parse_content_path(self, value):
- # need to be checked?
+ absolute_content_path_in_archive_like_file = (
+ self.policy_data.content_type in ("archive", "rpm")
+ and os.path.isabs(value))
+ if absolute_content_path_in_archive_like_file:
+ msg = (
+ "When using archives-like content input, the corresponding content path "
+ "has to be relative, but got '{value}'.")
+ raise KickstartValueError(msg)
self.policy_data.content_path = value
def _parse_cpe_path(self, value):
diff --git a/tests/test_content_discovery.py b/tests/test_content_discovery.py
index 5463c9a..d6e14d9 100644
--- a/tests/test_content_discovery.py
+++ b/tests/test_content_discovery.py
@@ -1,3 +1,5 @@
+import os
+
import pytest
import org_fedora_oscap.content_discovery as tested_module
@@ -46,3 +48,22 @@ def test_reduce(labelled_files):
reduced = bringer.reduce_files(labelled_files, "cpe", ["C"])
assert reduced == labelled_files
+
+
+def test_path_presence_detection():
+ list_of_paths = ["file1", os.path.abspath("file2"), os.path.abspath("dir///file3")]
+
+ list_of_paths_in_list = [
+ "file1", os.path.abspath("file1"), "./file1",
+ "file2", "dir/..//file2",
+ "dir/../dir/file3", "dir/file3",
+ ]
+ list_of_paths_not_in_list = [
+ "../file1", "file3"
+ ]
+
+ for path in list_of_paths_in_list:
+ assert tested_module.path_is_present_among_paths(path, list_of_paths)
+
+ for path in list_of_paths_not_in_list:
+ assert not tested_module.path_is_present_among_paths(path, list_of_paths)
From 9808e21ff4e6a4ce878d556f26cfddede04c870f Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Wed, 16 Nov 2022 15:35:09 +0100
Subject: [PATCH 2/3] Compare paths according to their equivalence
not according their arbitrary string form
---
org_fedora_oscap/content_discovery.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/org_fedora_oscap/content_discovery.py b/org_fedora_oscap/content_discovery.py
index ebef618..9da44e7 100644
--- a/org_fedora_oscap/content_discovery.py
+++ b/org_fedora_oscap/content_discovery.py
@@ -46,10 +46,14 @@ def clear_all(data):
data.dry_run = False
+def paths_are_equivalent(p1, p2):
+ return os.path.abspath(p1) == os.path.abspath(p2)
+
+
def path_is_present_among_paths(path, paths):
absolute_path = os.path.abspath(path)
for second_path in paths:
- if absolute_path == os.path.abspath(second_path):
+ if paths_are_equivalent(path, second_path):
return True
return False
@@ -237,7 +241,7 @@ def reduce_files(self, labelled_files, expected_path, categories):
)
raise RuntimeError(msg)
for path, label in labelled_files.items():
- if label in categories and path != expected_path:
+ if label in categories and not paths_are_equivalent(path, expected_path):
continue
reduced_files[path] = label
return reduced_files
From b422abba29a9304225c97e79945cf0f1a21de810 Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Tue, 22 Nov 2022 15:44:13 +0100
Subject: [PATCH 3/3] Fix tests when relative content paths are enforced
---
org_fedora_oscap/content_discovery.py | 2 +-
org_fedora_oscap/service/installation.py | 7 ++++++-
tests/test_content_discovery.py | 3 ++-
tests/test_installation.py | 2 +-
tests/test_kickstart.py | 6 +++---
tests/test_service_kickstart.py | 19 +++++++++++++++----
6 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/org_fedora_oscap/content_discovery.py b/org_fedora_oscap/content_discovery.py
index 9da44e7..61c4930 100644
--- a/org_fedora_oscap/content_discovery.py
+++ b/org_fedora_oscap/content_discovery.py
@@ -239,7 +239,7 @@ def reduce_files(self, labelled_files, expected_path, categories):
f"Expected a file {expected_path} to be part of the supplied content, "
f"but it was not the case, got only {list(labelled_files.keys())}"
)
- raise RuntimeError(msg)
+ raise content_handling.ContentHandlingError(msg)
for path, label in labelled_files.items():
if label in categories and not paths_are_equivalent(path, expected_path):
continue
diff --git a/org_fedora_oscap/service/installation.py b/org_fedora_oscap/service/installation.py
index f667479..5ca102c 100644
--- a/org_fedora_oscap/service/installation.py
+++ b/org_fedora_oscap/service/installation.py
@@ -23,10 +23,11 @@
from pyanaconda.core import util
from pyanaconda.modules.common.task import Task
from pyanaconda.modules.common.errors.installation import NonCriticalInstallationError
+from pykickstart.errors import KickstartValueError
from org_fedora_oscap import common, data_fetch, rule_handling, utils
from org_fedora_oscap.common import _, get_packages_data, set_packages_data
-from org_fedora_oscap.content_handling import ContentCheckError
+from org_fedora_oscap.content_handling import ContentCheckError, ContentHandlingError
from org_fedora_oscap import content_discovery
log = logging.getLogger("anaconda")
@@ -48,6 +49,10 @@ def _handle_error(exception):
msg = _("There was an error fetching and loading the security content:\n" +
f"{str(exception)}")
terminate(msg)
+ elif isinstance(exception, ContentHandlingError):
+ msg = _("There was a problem with the supplied security content:\n" +
+ f"{str(exception)}")
+ terminate(msg)
else:
msg = _("There was an unexpected problem with the supplied content.")
diff --git a/tests/test_content_discovery.py b/tests/test_content_discovery.py
index d6e14d9..d664ede 100644
--- a/tests/test_content_discovery.py
+++ b/tests/test_content_discovery.py
@@ -3,6 +3,7 @@
import pytest
import org_fedora_oscap.content_discovery as tested_module
+from org_fedora_oscap import content_handling
@pytest.fixture
@@ -43,7 +44,7 @@ def test_reduce(labelled_files):
assert len(reduced) == len(labelled_files) - d_count - x_count + 1
assert "dir/XCCDF" in reduced
- with pytest.raises(RuntimeError, match="dir/datastream4"):
+ with pytest.raises(content_handling.ContentHandlingError, match="dir/datastream4"):
bringer.reduce_files(labelled_files, "dir/datastream4", ["D"])
reduced = bringer.reduce_files(labelled_files, "cpe", ["C"])
diff --git a/tests/test_installation.py b/tests/test_installation.py
index 302f5ed..2cf78db 100644
--- a/tests/test_installation.py
+++ b/tests/test_installation.py
@@ -76,7 +76,7 @@ def test_fetch_content_task(caplog, file_path, content_path):
assert task.name == "Fetch the content, and optionally perform check or archive extraction"
- with pytest.raises(NonCriticalInstallationError, match="Couldn't find a valid datastream"):
+ with pytest.raises(NonCriticalInstallationError, match="Expected a file"):
task.run()
diff --git a/tests/test_kickstart.py b/tests/test_kickstart.py
index d4cfda2..60fe63d 100644
--- a/tests/test_kickstart.py
+++ b/tests/test_kickstart.py
@@ -163,7 +163,7 @@ def test_rpm(service):
content-url = http://example.com/oscap_content.rpm
content-type = RPM
profile = Web Server
- xccdf-path = /usr/share/oscap/xccdf.xml
+ xccdf-path = usr/share/oscap/xccdf.xml
%end
"""
check_ks_input(service, ks_in)
@@ -198,7 +198,7 @@ def test_rpm_with_wrong_suffix(service):
content-url = http://example.com/oscap_content.xml
content-type = RPM
profile = Web Server
- xccdf-path = /usr/share/oscap/xccdf.xml
+ xccdf-path = usr/share/oscap/xccdf.xml
%end
"""
check_ks_input(service, ks_in, errors=[

View File

@ -1,52 +0,0 @@
From 3d7a943969d542392134f55078eadb0793b094dc Mon Sep 17 00:00:00 2001
From: Vendula Poncova <vponcova@redhat.com>
Date: Wed, 22 Sep 2021 17:52:03 +0200
Subject: [PATCH 1/2] Specify a unique screen id
All spokes and hubs should provide a unique id.
---
org_fedora_oscap/gui/spokes/oscap.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/org_fedora_oscap/gui/spokes/oscap.py b/org_fedora_oscap/gui/spokes/oscap.py
index fe26076..44c7ced 100644
--- a/org_fedora_oscap/gui/spokes/oscap.py
+++ b/org_fedora_oscap/gui/spokes/oscap.py
@@ -204,6 +204,11 @@ class OSCAPSpoke(NormalSpoke):
# as it is displayed inside the spoke as the spoke label,
# and spoke labels are all uppercase by a convention.
+ @staticmethod
+ def get_screen_id():
+ """Return a unique id of this UI screen."""
+ return "security-policy-selection"
+
@classmethod
def should_run(cls, environment, data):
return is_module_available(OSCAP)
From ae9fdc9e6e189db215aeb39f2881311e5281587b Mon Sep 17 00:00:00 2001
From: Vendula Poncova <vponcova@redhat.com>
Date: Wed, 22 Sep 2021 17:52:51 +0200
Subject: [PATCH 2/2] Remove the help_id attribute
The help_id attribute is no longer used. Specify a screen id
or redefine the help handler to provide the built-in help.
---
org_fedora_oscap/gui/spokes/oscap.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/org_fedora_oscap/gui/spokes/oscap.py b/org_fedora_oscap/gui/spokes/oscap.py
index 44c7ced..6d0aa5c 100644
--- a/org_fedora_oscap/gui/spokes/oscap.py
+++ b/org_fedora_oscap/gui/spokes/oscap.py
@@ -185,9 +185,6 @@ class OSCAPSpoke(NormalSpoke):
# name of the .glade file in the same directory as this source
uiFile = "oscap.glade"
- # id of the help content for this spoke
- help_id = "SecurityPolicySpoke"
-
# domain of oscap-anaconda-addon translations
translationDomain = "oscap-anaconda-addon"