import scap-workbench-1.2.1-13.el9

This commit is contained in:
CentOS Sources 2022-01-11 11:53:37 -05:00 committed by Stepan Oksanichenko
parent 073336824e
commit 87273e5220
7 changed files with 1532 additions and 4 deletions

View File

@ -0,0 +1,73 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 77bb3ae9..5c42e733 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -263,14 +263,14 @@ install(FILES "man/scap-workbench.8"
install(DIRECTORY "share/scap-workbench"
DESTINATION "${CMAKE_INSTALL_DATADIR}")
-install(FILES "scap-workbench.desktop"
+install(FILES "scap_workbench.desktop"
DESTINATION "${CMAKE_INSTALL_DATADIR}/applications")
install(FILES "share/pixmaps/scap-workbench.png"
DESTINATION "${CMAKE_INSTALL_DATADIR}/pixmaps")
install(FILES "share/pixmaps/scap-workbench.svg"
DESTINATION "${CMAKE_INSTALL_DATADIR}/pixmaps")
-install(FILES "scap-workbench.appdata.xml"
- DESTINATION "${CMAKE_INSTALL_DATADIR}/appdata")
+install(FILES "org.open-scap.scap-workbench.appdata.xml"
+ DESTINATION "${CMAKE_INSTALL_DATADIR}/metainfo")
if (ASCIIDOC_EXECUTABLE)
file(GLOB USER_MANUAL_SCREENSHOTS "${CMAKE_CURRENT_SOURCE_DIR}/doc/user_manual/*.png")
diff --git a/scap-workbench.appdata.xml b/org.open-scap.scap-workbench.appdata.xml
similarity index 65%
rename from scap-workbench.appdata.xml
rename to org.open-scap.scap-workbench.appdata.xml
index d4288f3d..bed9b05c 100644
--- a/scap-workbench.appdata.xml
+++ b/org.open-scap.scap-workbench.appdata.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
-<application>
- <id type="desktop">scap-workbench.desktop</id>
+<component type="desktop">
+ <id>org.openscap.scap_workbench.desktop</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0+</project_license>
<name>SCAP Workbench</name>
@@ -23,10 +23,16 @@
</ul>
</description>
<screenshots>
- <screenshot type="default" width="1280" height="720">https://github.com/OpenSCAP/scap-workbench/raw/v1-1/doc/user_manual/default_content_opened.png</screenshot>
- <screenshot width="1280" height="720">https://github.com/OpenSCAP/scap-workbench/raw/v1-1/doc/user_manual/intro_screenshot.png</screenshot>
- <screenshot width="1280" height="720">https://github.com/OpenSCAP/scap-workbench/raw/v1-1/doc/user_manual/tailoring_undo_history.png</screenshot>
+ <screenshot type="default">
+ <image type="source" width="1280" height="720">https://github.com/OpenSCAP/scap-workbench/raw/v1-1/doc/user_manual/default_content_opened.png</image>
+ </screenshot>
+ <screenshot>
+ <image type="source" width="1280" height="720">https://github.com/OpenSCAP/scap-workbench/raw/v1-1/doc/user_manual/intro_screenshot.png</image>
+ </screenshot>
+ <screenshot>
+ <image type="source" width="1280" height="720">https://github.com/OpenSCAP/scap-workbench/raw/v1-1/doc/user_manual/tailoring_undo_history.png</image>
+ </screenshot>
</screenshots>
<url type="homepage">https://www.open-scap.org/tools/scap-workbench</url>
- <updatecontact>open-scap-list@redhat.com</updatecontact>
-</application>
+ <update_contact>open-scap-list@redhat.com</update_contact>
+</component>
diff --git a/scap-workbench.desktop b/scap_workbench.desktop
similarity index 95%
rename from scap-workbench.desktop
rename to scap_workbench.desktop
index 60b67e49..5b4bb899 100644
--- a/scap-workbench.desktop
+++ b/scap_workbench.desktop
@@ -7,4 +7,5 @@ TryExec=scap-workbench
Exec=scap-workbench
Icon=scap-workbench
Categories=System;
+Keywords=scap;
X-Desktop-File-Install-Version=0.3

View File

@ -0,0 +1,81 @@
From 408019f129027c120b71db3c029d5291e3275ea2 Mon Sep 17 00:00:00 2001
From: Evgeny Kolesnikov <ekolesni@redhat.com>
Date: Tue, 16 Nov 2021 00:08:32 +0100
Subject: [PATCH] Fix appdata, desktop and icons for Linux (Freedesktop)
Satisfy:
https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#install_icons
https://freedesktop.org/software/appstream/docs/chap-Quickstart.html
---
CMakeLists.txt | 6 +++---
...ppdata.xml => org.open_scap.scap_workbench.appdata.xml | 5 +++--
...kbench.desktop => org.open_scap.scap_workbench.desktop | 8 ++++----
3 files changed, 10 insertions(+), 9 deletions(-)
rename org.open-scap.scap-workbench.appdata.xml => org.open_scap.scap_workbench.appdata.xml (92%)
rename scap_workbench.desktop => org.open_scap.scap_workbench.desktop (67%)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5c42e733..55eed972 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -263,13 +263,13 @@ install(FILES "man/scap-workbench.8"
install(DIRECTORY "share/scap-workbench"
DESTINATION "${CMAKE_INSTALL_DATADIR}")
-install(FILES "scap_workbench.desktop"
+install(FILES "org.open_scap.scap_workbench.desktop"
DESTINATION "${CMAKE_INSTALL_DATADIR}/applications")
install(FILES "share/pixmaps/scap-workbench.png"
DESTINATION "${CMAKE_INSTALL_DATADIR}/pixmaps")
install(FILES "share/pixmaps/scap-workbench.svg"
- DESTINATION "${CMAKE_INSTALL_DATADIR}/pixmaps")
-install(FILES "org.open-scap.scap-workbench.appdata.xml"
+ DESTINATION "${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps")
+install(FILES "org.open_scap.scap_workbench.appdata.xml"
DESTINATION "${CMAKE_INSTALL_DATADIR}/metainfo")
if (ASCIIDOC_EXECUTABLE)
diff --git a/org.open-scap.scap-workbench.appdata.xml b/org.open_scap.scap_workbench.appdata.xml
similarity index 92%
rename from org.open-scap.scap-workbench.appdata.xml
rename to org.open_scap.scap_workbench.appdata.xml
index bed9b05c..191796b2 100644
--- a/org.open-scap.scap-workbench.appdata.xml
+++ b/org.open_scap.scap_workbench.appdata.xml
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
-<component type="desktop">
- <id>org.openscap.scap_workbench.desktop</id>
+<component type="desktop-application">
+ <id>org.open_scap.scap_workbench</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0+</project_license>
<name>SCAP Workbench</name>
<summary>A GUI tool that serves as an SCAP scanner and provides tailoring functionality for SCAP content</summary>
+ <launchable type="desktop-id">org.open_scap.scap_workbench.desktop</launchable>
<description>
<p>
The main goal of this application is to lower the initial barrier of using SCAP.
diff --git a/scap_workbench.desktop b/org.open_scap.scap_workbench.desktop
similarity index 67%
rename from scap_workbench.desktop
rename to org.open_scap.scap_workbench.desktop
index 5b4bb899..0d568b1d 100644
--- a/scap_workbench.desktop
+++ b/org.open_scap.scap_workbench.desktop
@@ -1,11 +1,11 @@
[Desktop Entry]
+Version=1.0
Type=Application
Name=SCAP Workbench
GenericName=SCAP Scanner and Profile Editor
-Comment=GUI tool that allows scanning both local and remote computers using SCAP content of your choice.
+Comment=GUI tool that allows scanning both local and remote computers using SCAP content of your choice
TryExec=scap-workbench
Exec=scap-workbench
Icon=scap-workbench
-Categories=System;
-Keywords=scap;
-X-Desktop-File-Install-Version=0.3
+Categories=System;Security;
+Keywords=SCAP;

View File

@ -0,0 +1,519 @@
From 69e988df963cb184062814e75c737fe080f303df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
Date: Tue, 25 Feb 2020 10:50:46 +0100
Subject: [PATCH] Generate result-based remediation from tailored profile
Users can generate remediation script from scan results
of a tailored profile.
Unfortunately, the current design of SCAP Workbench doesn't allow
a clear way of doing this. The scan is run in a separated oscap
process. SCAP Workbench doesn't have access to oscap internal
xccdf_session which creates the ARF. It can't obtain the Tailoring
component reference ID.
Instead, we will save the tailoring document to a temporary file
and use the temporary file when generating the remediation.
Resolves: RHBZ#1640715
---
include/RemediationRoleSaver.h | 19 +++++++++-------
include/ResultViewer.h | 2 ++
src/RemediationRoleSaver.cpp | 40 ++++++++++++++++++++++------------
src/ResultViewer.cpp | 9 +++++---
4 files changed, 45 insertions(+), 25 deletions(-)
diff --git a/include/RemediationRoleSaver.h b/include/RemediationRoleSaver.h
index 1681b901..dfeea0c9 100644
--- a/include/RemediationRoleSaver.h
+++ b/include/RemediationRoleSaver.h
@@ -98,33 +98,35 @@ class PuppetProfileRemediationSaver : public ProfileBasedRemediationSaver
class ResultBasedProcessRemediationSaver : public RemediationSaverBase
{
public:
- ResultBasedProcessRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents,
+ ResultBasedProcessRemediationSaver(
+ QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath,
const QString& saveMessage, const QString& filetypeExtension, const QString& filetypeTemplate, const QString& fixType);
private:
virtual void saveToFile(const QString& filename);
SpacelessQTemporaryFile mArfFile;
+ QString tailoring;
};
class BashResultRemediationSaver : public ResultBasedProcessRemediationSaver
{
public:
- BashResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents);
+ BashResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath);
};
class AnsibleResultRemediationSaver : public ResultBasedProcessRemediationSaver
{
public:
- AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents);
+ AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath);
};
class PuppetResultRemediationSaver : public ResultBasedProcessRemediationSaver
{
public:
- PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents);
+ PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath);
};
#else // i.e. SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION is defined
@@ -133,33 +135,34 @@ class PuppetResultRemediationSaver : public ResultBasedProcessRemediationSaver
class ResultBasedLibraryRemediationSaver : public RemediationSaverBase
{
public:
- ResultBasedLibraryRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents,
+ ResultBasedLibraryRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath,
const QString& saveMessage, const QString& filetypeExtension, const QString& filetypeTemplate, const QString& fixType);
private:
virtual void saveToFile(const QString& filename);
SpacelessQTemporaryFile mArfFile;
+ QString tailoring;
};
class BashResultRemediationSaver : public ResultBasedLibraryRemediationSaver
{
public:
- BashResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents);
+ BashResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath);
};
class AnsibleResultRemediationSaver : public ResultBasedLibraryRemediationSaver
{
public:
- AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents);
+ AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath);
};
class PuppetResultRemediationSaver : public ResultBasedLibraryRemediationSaver
{
public:
- PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents);
+ PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath);
};
#endif // SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION
diff --git a/include/ResultViewer.h b/include/ResultViewer.h
index a6da89da..2ec8d576 100644
--- a/include/ResultViewer.h
+++ b/include/ResultViewer.h
@@ -99,6 +99,8 @@ class ResultViewer : public QWidget
/// If user requests to open the file via desktop services
SpacelessQTemporaryFile* mReportFile;
QByteArray mARF;
+
+ QString tailoringFilePath;
};
#endif
diff --git a/src/RemediationRoleSaver.cpp b/src/RemediationRoleSaver.cpp
index 900a221d..28389dbb 100644
--- a/src/RemediationRoleSaver.cpp
+++ b/src/RemediationRoleSaver.cpp
@@ -164,7 +164,8 @@ PuppetProfileRemediationSaver::PuppetProfileRemediationSaver(QWidget* parentWind
{}
#ifndef SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION
-ResultBasedProcessRemediationSaver::ResultBasedProcessRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents,
+ResultBasedProcessRemediationSaver::ResultBasedProcessRemediationSaver(
+ QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath,
const QString& saveMessage, const QString& filetypeExtension, const QString& filetypeTemplate, const QString& fixType):
RemediationSaverBase(parentWindow, saveMessage, filetypeExtension, filetypeTemplate, fixType)
{
@@ -172,6 +173,7 @@ ResultBasedProcessRemediationSaver::ResultBasedProcessRemediationSaver(QWidget*
mArfFile.open();
mArfFile.write(arfContents);
mArfFile.close();
+ tailoring = tailoringFilePath;
}
void ResultBasedProcessRemediationSaver::saveToFile(const QString& filename)
@@ -191,6 +193,11 @@ void ResultBasedProcessRemediationSaver::saveToFile(const QString& filename)
args.append("--result-id");
args.append("");
+ if (!tailoring.isNull()) {
+ args.append("--tailoring-file");
+ args.append(tailoring.toUtf8().constData());
+ }
+
args.append(mArfFile.fileName());
// Launching a process and going through its output is something we do already in OscapScannerLocal::evaluate()
@@ -222,23 +229,24 @@ void ResultBasedProcessRemediationSaver::saveToFile(const QString& filename)
}
}
-BashResultRemediationSaver::BashResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents):
- ResultBasedProcessRemediationSaver(parentWindow, arfContents,
+BashResultRemediationSaver::BashResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath):
+ ResultBasedProcessRemediationSaver(parentWindow, arfContents, tailoringFilePath,
bashSaveMessage, bashFiletypeExtension, bashFiletypeTemplate, bashFixTemplate)
{}
-AnsibleResultRemediationSaver::AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents):
- ResultBasedProcessRemediationSaver(parentWindow, arfContents,
+AnsibleResultRemediationSaver::AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath):
+ ResultBasedProcessRemediationSaver(parentWindow, arfContents, tailoringFilePath,
ansibleSaveMessage, ansibleFiletypeExtension, ansibleFiletypeTemplate, ansibleFixType)
{}
-PuppetResultRemediationSaver::PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents):
- ResultBasedProcessRemediationSaver(parentWindow, arfContents,
+PuppetResultRemediationSaver::PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath):
+ ResultBasedProcessRemediationSaver(parentWindow, arfContents, tailoringFilePath,
puppetSaveMessage, puppetFiletypeExtension, puppetFiletypeTemplate, puppetFixType)
{}
#else // i.e. SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION is defined
-ResultBasedLibraryRemediationSaver::ResultBasedLibraryRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents,
+ResultBasedLibraryRemediationSaver::ResultBasedLibraryRemediationSaver(
+ QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath,
const QString& saveMessage, const QString& filetypeExtension, const QString& filetypeTemplate, const QString& fixType):
RemediationSaverBase(parentWindow, saveMessage, filetypeExtension, filetypeTemplate, fixType)
{
@@ -246,6 +254,7 @@ ResultBasedLibraryRemediationSaver::ResultBasedLibraryRemediationSaver(QWidget*
mArfFile.open();
mArfFile.write(arfContents);
mArfFile.close();
+ tailoring = tailoringFilePath;
}
void ResultBasedLibraryRemediationSaver::saveToFile(const QString& filename)
@@ -282,6 +291,9 @@ void ResultBasedLibraryRemediationSaver::saveToFile(const QString& filename)
if (session == NULL)
throw std::runtime_error("Couldn't get XCCDF session from the report source");
+ if (!tailoring.isNull()) {
+ xccdf_session_set_user_tailoring_file(session, tailoring.toUtf8().constData());
+ }
xccdf_session_set_loading_flags(session, XCCDF_SESSION_LOAD_XCCDF);
if (xccdf_session_load(session) != 0)
@@ -316,18 +328,18 @@ void ResultBasedLibraryRemediationSaver::saveToFile(const QString& filename)
}
}
-BashResultRemediationSaver::BashResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents):
- ResultBasedLibraryRemediationSaver(parentWindow, arfContents,
+BashResultRemediationSaver::BashResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath):
+ ResultBasedLibraryRemediationSaver(parentWindow, arfContents, tailoringFilePath,
bashSaveMessage, bashFiletypeExtension, bashFiletypeTemplate, bashFixTemplate)
{}
-AnsibleResultRemediationSaver::AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents):
- ResultBasedLibraryRemediationSaver(parentWindow, arfContents,
+AnsibleResultRemediationSaver::AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath):
+ ResultBasedLibraryRemediationSaver(parentWindow, arfContents, tailoringFilePath,
ansibleSaveMessage, ansibleFiletypeExtension, ansibleFiletypeTemplate, ansibleFixType)
{}
-PuppetResultRemediationSaver::PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents):
- ResultBasedLibraryRemediationSaver(parentWindow, arfContents,
+PuppetResultRemediationSaver::PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath):
+ ResultBasedLibraryRemediationSaver(parentWindow, arfContents, tailoringFilePath,
puppetSaveMessage, puppetFiletypeExtension, puppetFiletypeTemplate, puppetFixType)
{}
diff --git a/src/ResultViewer.cpp b/src/ResultViewer.cpp
index 1e730e99..c5444746 100644
--- a/src/ResultViewer.cpp
+++ b/src/ResultViewer.cpp
@@ -114,6 +114,9 @@ void ResultViewer::loadContent(Scanner* scanner)
if (mInputBaseName.endsWith("-xccdf"))
mInputBaseName.chop(QString("-xccdf").length());
}
+ if (session->isSelectedProfileTailoring()) {
+ tailoringFilePath = session->getTailoringFilePath();
+ }
mReport.clear();
scanner->getReport(mReport);
@@ -173,19 +176,19 @@ void ResultViewer::openReport()
void ResultViewer::generateBashRemediationRole()
{
- BashResultRemediationSaver remediation(this, mARF);
+ BashResultRemediationSaver remediation(this, mARF, tailoringFilePath);
remediation.selectFilenameAndSaveRole();
}
void ResultViewer::generateAnsibleRemediationRole()
{
- AnsibleResultRemediationSaver remediation(this, mARF);
+ AnsibleResultRemediationSaver remediation(this, mARF, tailoringFilePath);
remediation.selectFilenameAndSaveRole();
}
void ResultViewer::generatePuppetRemediationRole()
{
- PuppetResultRemediationSaver remediation(this, mARF);
+ PuppetResultRemediationSaver remediation(this, mARF, tailoringFilePath);
remediation.selectFilenameAndSaveRole();
}
From e97539b824202e91c9cd551316836935046e53ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
Date: Mon, 2 Mar 2020 14:14:49 +0100
Subject: [PATCH] Use only library calls to generate remediation
Removes CMake option
SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION
and removes the code that is used when this option is not set.
That means the remediations will be generated using libopenscap
library calls. The removed code executed "oscap" command to
do the same thing.
---
CMakeLists.txt | 8 +---
include/Config.h.in | 1 -
include/RemediationRoleSaver.h | 41 ----------------
src/RemediationRoleSaver.cpp | 87 ----------------------------------
4 files changed, 2 insertions(+), 135 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 060df785..8d16d3c5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,12 +49,8 @@ endif()
# Local scanning tools
option(SCAP_WORKBENCH_LOCAL_SCAN_ENABLED "If enabled, scanning of local machine is possible from workbench. Else the option is disabled in the GUI." TRUE)
-option(SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION "If enabled, result-based remediation roles will be generated by calls to the libopenscap library (instead of being generated by the oscap subprocess). Requires openscap>=1.2.16" FALSE)
-
-if (SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION)
- if(${OPENSCAP_VERSION_MAJOR} LESS 2 AND ${OPENSCAP_VERSION_MINOR} LESS 3 AND ${OPENSCAP_VERSION_PATCH} LESS 16) # i.e. oscap<1.2.16
- message(FATAL_ERROR "Library-powered generation of result-based remediation roles is supported only if you have oscap>=1.2.16, whereas you have oscap==${OPENSCAP_VERSION}")
- endif()
+if(${OPENSCAP_VERSION_MAJOR} LESS 2 AND ${OPENSCAP_VERSION_MINOR} LESS 3 AND ${OPENSCAP_VERSION_PATCH} LESS 16) # i.e. oscap<1.2.16
+ message(FATAL_ERROR "Library-powered generation of result-based remediation roles is supported only if you have oscap>=1.2.16, whereas you have oscap==${OPENSCAP_VERSION}")
endif()
find_program(NICE_EXECUTABLE NAMES nice) # fully optional, local scan still available when missing
diff --git a/include/Config.h.in b/include/Config.h.in
index 21b3f373..a9bc718f 100644
--- a/include/Config.h.in
+++ b/include/Config.h.in
@@ -40,7 +40,6 @@
#define SCAP_WORKBENCH_LOCAL_PKEXEC_OSCAP_PATH "@CMAKE_INSTALL_FULL_LIBEXECDIR@/scap-workbench-pkexec-oscap.sh"
#define SCAP_WORKBENCH_LOCAL_RPM_EXTRACT_PATH "@CMAKE_INSTALL_FULL_LIBEXECDIR@/scap-workbench-rpm-extract.sh"
#define SCAP_WORKBENCH_REMOTE_OSCAP_PATH "oscap"
-#cmakedefine SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION
#cmakedefine SCAP_WORKBENCH_LOCAL_SSH_FOUND
#define SCAP_WORKBENCH_LOCAL_SSH_PATH "@SSH_EXECUTABLE@"
#cmakedefine SCAP_WORKBENCH_LOCAL_SETSID_FOUND
diff --git a/include/RemediationRoleSaver.h b/include/RemediationRoleSaver.h
index dfeea0c9..95938db8 100644
--- a/include/RemediationRoleSaver.h
+++ b/include/RemediationRoleSaver.h
@@ -93,45 +93,6 @@ class PuppetProfileRemediationSaver : public ProfileBasedRemediationSaver
};
-#ifndef SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION
-/// Base for all result-based remediation generators that uses oscap process
-class ResultBasedProcessRemediationSaver : public RemediationSaverBase
-{
- public:
- ResultBasedProcessRemediationSaver(
- QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath,
- const QString& saveMessage, const QString& filetypeExtension, const QString& filetypeTemplate, const QString& fixType);
-
- private:
- virtual void saveToFile(const QString& filename);
- SpacelessQTemporaryFile mArfFile;
- QString tailoring;
-};
-
-
-class BashResultRemediationSaver : public ResultBasedProcessRemediationSaver
-{
- public:
- BashResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath);
-};
-
-
-class AnsibleResultRemediationSaver : public ResultBasedProcessRemediationSaver
-{
- public:
- AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath);
-};
-
-
-class PuppetResultRemediationSaver : public ResultBasedProcessRemediationSaver
-{
- public:
- PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath);
-};
-
-#else // i.e. SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION is defined
-
-/// Base for all result-based remediation generators that uses the openscap library
class ResultBasedLibraryRemediationSaver : public RemediationSaverBase
{
public:
@@ -165,7 +126,5 @@ class PuppetResultRemediationSaver : public ResultBasedLibraryRemediationSaver
PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath);
};
-#endif // SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION
-
#endif // SCAP_WORKBENCH_REMEDIATION_ROLE_SAVER_H_
diff --git a/src/RemediationRoleSaver.cpp b/src/RemediationRoleSaver.cpp
index 28389dbb..a9866738 100644
--- a/src/RemediationRoleSaver.cpp
+++ b/src/RemediationRoleSaver.cpp
@@ -35,11 +35,7 @@ extern "C"
#include <xccdf_benchmark.h>
#include <xccdf_policy.h>
#include <xccdf_session.h>
-#ifdef SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION
- // vvv This include is used only for library-based generation of result-base remediation roles
- // vvv and it requires (relatively recent) openscap 1.2.16
#include <ds_rds_session.h>
-#endif
}
@@ -163,88 +159,6 @@ PuppetProfileRemediationSaver::PuppetProfileRemediationSaver(QWidget* parentWind
puppetSaveMessage, puppetFiletypeExtension, puppetFiletypeTemplate, puppetFixType)
{}
-#ifndef SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION
-ResultBasedProcessRemediationSaver::ResultBasedProcessRemediationSaver(
- QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath,
- const QString& saveMessage, const QString& filetypeExtension, const QString& filetypeTemplate, const QString& fixType):
- RemediationSaverBase(parentWindow, saveMessage, filetypeExtension, filetypeTemplate, fixType)
-{
- mArfFile.setAutoRemove(true);
- mArfFile.open();
- mArfFile.write(arfContents);
- mArfFile.close();
- tailoring = tailoringFilePath;
-}
-
-void ResultBasedProcessRemediationSaver::saveToFile(const QString& filename)
-{
- QStringList args;
- args.append("xccdf");
- args.append("generate");
- args.append("fix");
-
- args.append("--template");
- args.append(mTemplateString);
- args.append("--output");
- args.append(filename);
-
- // vvv This will work, if there is only one result ID in the ARF file, it will be picked no matter what the argument value is.
- // However, ommitting --result-id "" won't work.
- args.append("--result-id");
- args.append("");
-
- if (!tailoring.isNull()) {
- args.append("--tailoring-file");
- args.append(tailoring.toUtf8().constData());
- }
-
- args.append(mArfFile.fileName());
-
- // Launching a process and going through its output is something we do already in OscapScannerLocal::evaluate()
- // This is a lightweight launch though.
- QProcess process(mParentWindow);
-
- SpacelessQTemporaryDir workingDir;
- process.setWorkingDirectory(workingDir.path());
- QString program(SCAP_WORKBENCH_LOCAL_OSCAP_PATH);
-
- process.start(program, args);
- process.waitForStarted();
-
- const unsigned int remediationGenerationTimeout = 10000;
-
- const int process_finished_on_time = process.waitForFinished(remediationGenerationTimeout);
-
- if (!process_finished_on_time)
- {
- QString message = QObject::tr("The process that was supposed to generate remediations didn't finish on time (i.e. within %1 secs), so it was terminated.").arg(remediationGenerationTimeout / 1000);
- process.kill();
- throw std::runtime_error(message.toUtf8().constData());
- }
-
- if (process.exitCode() != 0)
- {
- QString completeErrorMessage(QObject::tr("Exit code of 'oscap' was %1: %2"));
- throw std::runtime_error(completeErrorMessage.arg(process.exitCode()).arg(QString(process.readAllStandardError())).toUtf8().constData());
- }
-}
-
-BashResultRemediationSaver::BashResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath):
- ResultBasedProcessRemediationSaver(parentWindow, arfContents, tailoringFilePath,
- bashSaveMessage, bashFiletypeExtension, bashFiletypeTemplate, bashFixTemplate)
-{}
-
-AnsibleResultRemediationSaver::AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath):
- ResultBasedProcessRemediationSaver(parentWindow, arfContents, tailoringFilePath,
- ansibleSaveMessage, ansibleFiletypeExtension, ansibleFiletypeTemplate, ansibleFixType)
-{}
-
-PuppetResultRemediationSaver::PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath):
- ResultBasedProcessRemediationSaver(parentWindow, arfContents, tailoringFilePath,
- puppetSaveMessage, puppetFiletypeExtension, puppetFiletypeTemplate, puppetFixType)
-{}
-
-#else // i.e. SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION is defined
ResultBasedLibraryRemediationSaver::ResultBasedLibraryRemediationSaver(
QWidget* parentWindow, const QByteArray& arfContents, const QString& tailoringFilePath,
const QString& saveMessage, const QString& filetypeExtension, const QString& filetypeTemplate, const QString& fixType):
@@ -343,4 +257,3 @@ PuppetResultRemediationSaver::PuppetResultRemediationSaver(QWidget* parentWindow
puppetSaveMessage, puppetFiletypeExtension, puppetFiletypeTemplate, puppetFixType)
{}
-#endif // SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION
From 550fc786d2cdec391544cd7bc3a33325ba545803 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
Date: Tue, 3 Mar 2020 09:36:20 +0100
Subject: [PATCH] Remove known issue
This issue has been fixed by 69e988df963cb184062814e75c737fe080f303df.
---
doc/user_manual.adoc | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/doc/user_manual.adoc b/doc/user_manual.adoc
index fa47d4fc..48933dd9 100644
--- a/doc/user_manual.adoc
+++ b/doc/user_manual.adoc
@@ -524,20 +524,6 @@ Both while opening the files and when scanning. This option is discouraged and
should only be used by content creators and/or people who really know what they
are doing.
-== Known issues
-
-=== Result-based remediations of tailored profiles
-
-Saving remediation roles to the disk may not work for a customized profile. Specifically, it won't work if you add additional rules to it.
-If this limitation affects you, follow these steps:
-
-Remark: You will need to use the oscap command-line utility, which is bundled together with scap-workbench.
-
-1. Save the scan results
-2. Save your profile customization to a file using the "File->Save customization only" option.
-3. Run this command: oscap xccdf generate fix --output <role filename> --result-id '' --tailoring-file <saved-customization> <saved-result>.
-Refer to oscap xccdf generate fix -h if you want other than Bash output.
-
== Where to Get Help?
You ask for help with the application using

View File

@ -0,0 +1,196 @@
From 7786cd8b020ab3aa4a9720e6fa8f60285486a48b Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Wed, 27 Jan 2021 14:28:57 +0100
Subject: [PATCH] Refactored handling of scanner messages.
- Better detection of errors and warnings using leading E: and W: that
oscap emits.
- Possibility to expand the message filtering using inheritance.
---
include/OscapScannerBase.h | 15 +++++
src/OscapScannerBase.cpp | 132 ++++++++++++++++++++++++++++++++-----
2 files changed, 130 insertions(+), 17 deletions(-)
diff --git a/include/OscapScannerBase.h b/include/OscapScannerBase.h
index 00f67699..f82379be 100644
--- a/include/OscapScannerBase.h
+++ b/include/OscapScannerBase.h
@@ -77,6 +77,21 @@ class OscapScannerBase : public Scanner
ReadingState mReadingState;
+ enum MessageType
+ {
+ MSG_INFO, MSG_WARNING, MSG_ERROR, MSG_UNKNOWN
+ };
+
+ virtual void filterStdErr(QString& errorText);
+ void emitMessage(MessageType kind, QString& message);
+ virtual void selectWarning(MessageType& kind, const QString& message);
+ virtual void processWarning(QString& message);
+ virtual void selectInfo(MessageType& kind, const QString& message);
+ virtual void processInfo(QString& message);
+ virtual void selectError(MessageType& kind, const QString& message);
+ virtual void processError(QString& message);
+ virtual void processUnknown(QString& message);
+
/// We keep filling this buffer until we reach : or \n
QString mReadBuffer;
diff --git a/src/OscapScannerBase.cpp b/src/OscapScannerBase.cpp
index bdb02e74..0ec4575e 100644
--- a/src/OscapScannerBase.cpp
+++ b/src/OscapScannerBase.cpp
@@ -418,6 +418,117 @@ void OscapScannerBase::readStdOut(QProcess& process)
while (tryToReadStdOutChar(process));
}
+
+void OscapScannerBase::emitMessage(MessageType kind, QString& message)
+{
+ QString rawMessage = QObject::tr(message.toUtf8().constData());
+ switch (kind)
+ {
+ case MSG_INFO:
+ {
+ emit infoMessage(message);
+ break;
+ }
+ case MSG_WARNING:
+ {
+ emit warningMessage(message);
+ break;
+ }
+ default:
+ emit errorMessage(message);
+ }
+}
+
+
+void OscapScannerBase::selectWarning(MessageType& kind, const QString& message)
+{
+ if (message.contains("WARNING: "))
+ {
+ kind = MSG_WARNING;
+ }
+ if (message.contains(QRegExp("^W:\\s")))
+ {
+ kind = MSG_WARNING;
+ }
+}
+
+
+void OscapScannerBase::processWarning(QString& message)
+{
+ message = guiFriendlyMessage(message);
+}
+
+
+void OscapScannerBase::selectInfo(MessageType& kind, const QString& message)
+{
+ if (message.contains(QRegExp("^Downloading: .+ \\.{3} \\w+\\n")))
+ {
+ kind = MSG_INFO;
+ }
+}
+
+
+void OscapScannerBase::processInfo(QString& message)
+{
+ (void)message; // suppress the unused arg warning
+}
+
+
+void OscapScannerBase::selectError(MessageType& kind, const QString& message)
+{
+ if (message.contains(QRegExp("^E:\\s")))
+ {
+ kind = MSG_ERROR;
+ }
+}
+
+
+void OscapScannerBase::processError(QString& message)
+{
+ message.remove(QRegExp("Error:\\s*"));
+ message.remove(QRegExp("^E:\\s*"));
+ message.remove(QRegExp("\\n"));
+}
+
+
+void OscapScannerBase::processUnknown(QString& message)
+{
+ message = QString("The 'oscap' process has written the following content to stderr:\n%1").arg(message);
+}
+
+
+void OscapScannerBase::filterStdErr(QString& errorText)
+{
+ MessageType type = MSG_UNKNOWN;
+ // let detection of a more severe type of message (error) overrule a benign one (info)
+ selectInfo(type, errorText);
+ selectWarning(type, errorText);
+ selectError(type, errorText);
+ switch(type)
+ {
+ case MSG_INFO:
+ {
+ processInfo(errorText);
+ break;
+ }
+ case MSG_WARNING:
+ {
+ processWarning(errorText);
+ break;
+ }
+ case MSG_ERROR:
+ {
+ processError(errorText);
+ break;
+ }
+ default:
+ {
+ processUnknown(errorText);
+ }
+ }
+ emitMessage(type, errorText);
+}
+
void OscapScannerBase::watchStdErr(QProcess& process)
{
process.setReadChannel(QProcess::StandardError);
@@ -433,21 +544,7 @@ void OscapScannerBase::watchStdErr(QProcess& process)
if (!stdErrOutput.isEmpty())
{
- if (stdErrOutput.contains("WARNING: "))
- {
- QString guiMessage = guiFriendlyMessage(stdErrOutput);
- emit warningMessage(QObject::tr(guiMessage.toUtf8().constData()));
- }
- // Openscap >= 1.2.11 (60fb9f0c98eee) sends this message through stderr
- else if (stdErrOutput.contains(QRegExp("^Downloading: .+ \\.{3} \\w+\\n")))
- {
- emit infoMessage(stdErrOutput);
- }
- else
- {
- emit errorMessage(QObject::tr("The 'oscap' process has written the following content to stderr:\n"
- "%1").arg(stdErrOutput));
- }
+ filterStdErr(stdErrOutput);
}
}
@@ -458,8 +555,9 @@ QString OscapScannerBase::guiFriendlyMessage(const QString& cliMessage)
{
QString guiMessage = cliMessage;
- // Remove "WARNING:" prefix and trailing \n
- guiMessage.remove(QRegExp("(WARNING: )|\n"));
+ guiMessage.remove(QRegExp("WARNING:\\s*"));
+ guiMessage.remove(QRegExp("^W:\\s*"));
+ guiMessage.remove(QRegExp("\\n"));
if (cliMessage.contains("--fetch-remote-resources"))
guiMessage = QString("Remote resources might be necessary for this profile to work properly. Please select \"Fetch remote resources\" for complete scan");

View File

@ -0,0 +1,560 @@
From 0e48a7161be7fbabc02ba05407131be2595e9b6d Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Tue, 1 Dec 2020 18:46:20 +0100
Subject: [PATCH 1/4] Implement possibility to scan by sudoers.
- The remote scanning dialog got a "user is sudoer" checkbox.
- Dry run can make use of sudo in connection with oscap-ssh.
- The scanning procedure uses sudo invocation as part of the ssh command.
---
include/OscapScannerRemoteSsh.h | 2 ++
include/RemoteMachineComboBox.h | 2 ++
src/MainWindow.cpp | 4 ++++
src/OscapScannerRemoteSsh.cpp | 28 +++++++++++++++++++------
src/RemoteMachineComboBox.cpp | 7 +++++++
ui/RemoteMachineComboBox.ui | 36 +++++++++++++++++++++++++++++----
6 files changed, 69 insertions(+), 10 deletions(-)
diff --git a/include/OscapScannerRemoteSsh.h b/include/OscapScannerRemoteSsh.h
index d2aa7013..69eedfe4 100644
--- a/include/OscapScannerRemoteSsh.h
+++ b/include/OscapScannerRemoteSsh.h
@@ -36,6 +36,7 @@ class OscapScannerRemoteSsh : public OscapScannerBase
OscapScannerRemoteSsh();
virtual ~OscapScannerRemoteSsh();
+ void setUserIsSudoer(bool userIsSudoer);
virtual void setTarget(const QString& target);
virtual void setSession(ScanningSession* session);
@@ -57,6 +58,7 @@ class OscapScannerRemoteSsh : public OscapScannerBase
void removeRemoteDirectory(const QString& path, const QString& desc);
SshConnection mSshConnection;
+ bool mUserIsSudoer;
};
#endif
diff --git a/include/RemoteMachineComboBox.h b/include/RemoteMachineComboBox.h
index 41a9643c..3b338127 100644
--- a/include/RemoteMachineComboBox.h
+++ b/include/RemoteMachineComboBox.h
@@ -44,6 +44,7 @@ class RemoteMachineComboBox : public QWidget
void setRecentMachineCount(unsigned int count);
unsigned int getRecentMachineCount() const;
+ bool userIsSudoer() const;
public slots:
void notifyTargetUsed(const QString& target);
@@ -65,6 +66,7 @@ class RemoteMachineComboBox : public QWidget
QStringList mRecentTargets;
QComboBox* mRecentComboBox;
+ QCheckBox* mUserIsSudoer;
};
#endif
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index c9a0937b..236cfde1 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -678,6 +678,7 @@ void MainWindow::scanAsync(ScannerMode scannerMode)
// In the OscapScannerRemoteSsh class the port will be parsed out again...
const QString target = mUI.localMachineRadioButton->isChecked() ?
"localhost" : mUI.remoteMachineDetails->getTarget();
+ const bool userIsSudoer = mUI.remoteMachineDetails->userIsSudoer();
bool fetchRemoteResources = mUI.fetchRemoteResourcesCheckbox->isChecked();
try
@@ -689,7 +690,10 @@ void MainWindow::scanAsync(ScannerMode scannerMode)
if (target == "localhost")
mScanner = new OscapScannerLocal();
else
+ {
mScanner = new OscapScannerRemoteSsh();
+ ((OscapScannerRemoteSsh *)mScanner)->setUserIsSudoer(userIsSudoer);
+ }
mScanner->setTarget(target);
diff --git a/src/OscapScannerRemoteSsh.cpp b/src/OscapScannerRemoteSsh.cpp
index dcfd6d5f..d20faf59 100644
--- a/src/OscapScannerRemoteSsh.cpp
+++ b/src/OscapScannerRemoteSsh.cpp
@@ -37,7 +37,8 @@ extern "C"
OscapScannerRemoteSsh::OscapScannerRemoteSsh():
OscapScannerBase(),
- mSshConnection(this)
+ mSshConnection(this),
+ mUserIsSudoer(false)
{
mSshConnection.setCancelRequestSource(&mCancelRequested);
}
@@ -87,6 +88,11 @@ void OscapScannerRemoteSsh::setTarget(const QString& target)
mSshConnection.setPort(port);
}
+void OscapScannerRemoteSsh::setUserIsSudoer(bool userIsSudoer)
+{
+ mUserIsSudoer = userIsSudoer;
+}
+
void OscapScannerRemoteSsh::setSession(ScanningSession* session)
{
OscapScannerBase::setSession(session);
@@ -99,6 +105,10 @@ void OscapScannerRemoteSsh::setSession(ScanningSession* session)
QStringList OscapScannerRemoteSsh::getCommandLineArgs() const
{
QStringList args("oscap-ssh");
+ if (mUserIsSudoer)
+ {
+ args.append("--sudo");
+ }
args.append(mSshConnection.getTarget());
args.append(QString::number(mSshConnection.getPort()));
@@ -235,19 +245,19 @@ void OscapScannerRemoteSsh::evaluate()
if (mScannerMode == SM_OFFLINE_REMEDIATION)
{
- args = buildOfflineRemediationArgs(inputFile,
+ args.append(buildOfflineRemediationArgs(inputFile,
resultFile,
reportFile,
- arfFile);
+ arfFile));
}
else
{
- args = buildEvaluationArgs(inputFile,
+ args.append(buildEvaluationArgs(inputFile,
tailoringFile,
resultFile,
reportFile,
arfFile,
- mScannerMode == SM_SCAN_ONLINE_REMEDIATION);
+ mScannerMode == SM_SCAN_ONLINE_REMEDIATION));
}
const QString sshCmd = args.join(" ");
@@ -255,8 +265,14 @@ void OscapScannerRemoteSsh::evaluate()
emit infoMessage(QObject::tr("Starting the remote process..."));
QProcess process(this);
+ QString sudo;
+ if (mUserIsSudoer)
+ {
+ // tell sudo not to bother to read password from the terminal
+ sudo = " sudo -n";
+ }
- process.start(SCAP_WORKBENCH_LOCAL_SSH_PATH, baseArgs + QStringList(QString("cd '%1'; " SCAP_WORKBENCH_REMOTE_OSCAP_PATH " %2").arg(workingDir).arg(sshCmd)));
+ process.start(SCAP_WORKBENCH_LOCAL_SSH_PATH, baseArgs + QStringList(QString("cd '%1';" "%2 " SCAP_WORKBENCH_REMOTE_OSCAP_PATH " %3").arg(workingDir).arg(sudo).arg(sshCmd)));
process.waitForStarted();
if (process.state() != QProcess::Running)
diff --git a/src/RemoteMachineComboBox.cpp b/src/RemoteMachineComboBox.cpp
index 46d1b7d1..7b402344 100644
--- a/src/RemoteMachineComboBox.cpp
+++ b/src/RemoteMachineComboBox.cpp
@@ -41,6 +41,8 @@ RemoteMachineComboBox::RemoteMachineComboBox(QWidget* parent):
this, SLOT(updateHostPort(int))
);
+ mUserIsSudoer = mUI.userIsSudoer;
+
setRecentMachineCount(5);
syncFromQSettings();
@@ -51,6 +53,11 @@ RemoteMachineComboBox::~RemoteMachineComboBox()
delete mQSettings;
}
+bool RemoteMachineComboBox::userIsSudoer() const
+{
+ return mUserIsSudoer->isChecked();
+}
+
QString RemoteMachineComboBox::getTarget() const
{
return QString("%1:%2").arg(mUI.host->text()).arg(mUI.port->value());
diff --git a/ui/RemoteMachineComboBox.ui b/ui/RemoteMachineComboBox.ui
index 780d06ce..f9e9665c 100644
--- a/ui/RemoteMachineComboBox.ui
+++ b/ui/RemoteMachineComboBox.ui
@@ -6,15 +6,24 @@
<rect>
<x>0</x>
<y>0</y>
- <width>553</width>
- <height>29</height>
+ <width>609</width>
+ <height>42</height>
</rect>
</property>
<property name="windowTitle">
<string>RemoteMachineComboBox</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item>
@@ -73,8 +82,17 @@
</item>
<item>
<widget class="QSpinBox" name="port">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="buttonSymbols">
- <enum>QAbstractSpinBox::UpDownArrows</enum>
+ <enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="minimum">
<number>1</number>
@@ -87,6 +105,16 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="QCheckBox" name="userIsSudoer">
+ <property name="toolTip">
+ <string>Check if the remote user doesn't have root privileges, but they can perform administrative tasks using paswordless sudo.</string>
+ </property>
+ <property name="text">
+ <string>user is sudoer</string>
+ </property>
+ </widget>
+ </item>
<item>
<widget class="QComboBox" name="recentComboBox">
<property name="sizePolicy">
From 1fd9bc807f1c76452c0803436efd311000d7470b Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Wed, 27 Jan 2021 14:33:04 +0100
Subject: [PATCH 2/4] Updated message handling of sudo-related issues.
---
include/OscapScannerRemoteSsh.h | 5 +++++
src/OscapScannerRemoteSsh.cpp | 23 +++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/include/OscapScannerRemoteSsh.h b/include/OscapScannerRemoteSsh.h
index 69eedfe4..280a69da 100644
--- a/include/OscapScannerRemoteSsh.h
+++ b/include/OscapScannerRemoteSsh.h
@@ -43,6 +43,11 @@ class OscapScannerRemoteSsh : public OscapScannerBase
virtual QStringList getCommandLineArgs() const;
virtual void evaluate();
+ protected:
+
+ virtual void selectError(MessageType& kind, const QString& message);
+ virtual void processError(QString& message);
+
private:
void ensureConnected();
diff --git a/src/OscapScannerRemoteSsh.cpp b/src/OscapScannerRemoteSsh.cpp
index d20faf59..69b51373 100644
--- a/src/OscapScannerRemoteSsh.cpp
+++ b/src/OscapScannerRemoteSsh.cpp
@@ -344,6 +344,29 @@ void OscapScannerRemoteSsh::evaluate()
signalCompletion(mCancelRequested);
}
+void OscapScannerRemoteSsh::selectError(MessageType& kind, const QString& message)
+{
+ OscapScannerBase::selectError(kind, message);
+ if (mUserIsSudoer)
+ {
+ if (message.contains(QRegExp("^sudo:")))
+ {
+ kind = MSG_ERROR;
+ }
+ }
+
+}
+
+void OscapScannerRemoteSsh::processError(QString& message)
+{
+ OscapScannerBase::processError(message);
+ if (mUserIsSudoer && message.contains(QRegExp("^sudo:")))
+ {
+ message.replace(QRegExp("^sudo:"), "Error invoking sudo on the host:");
+ message += ".\nOnly passwordless sudo setup on the remote host is supported by scap-workbench.";
+ }
+}
+
void OscapScannerRemoteSsh::ensureConnected()
{
if (mSshConnection.isConnected())
From 57097b3b9d6f85caa96ab2940c29e94f16382252 Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Thu, 28 Jan 2021 17:12:08 +0100
Subject: [PATCH 3/4] Added documentation about setting up passwordless sudo.
---
doc/user_manual.adoc | 11 +++++++++++
src/OscapScannerRemoteSsh.cpp | 2 ++
2 files changed, 13 insertions(+)
diff --git a/doc/user_manual.adoc b/doc/user_manual.adoc
index 29ebd919..2c8501a0 100644
--- a/doc/user_manual.adoc
+++ b/doc/user_manual.adoc
@@ -363,6 +363,17 @@ files are not supported yet!
.Selecting a remote machine for scanning
image::scanning_remote_machine.png[align="center"]
+The remote user doesn't have to be a superuser - you can setup the remote
+`/etc/sudoers` file (using `visudo`) to enable the paswordless sudo for that particular user,
+and you check the "user is sudoer" checkbox.
+
+For example, if the scanning user is `oscap-user`, that would involve putting
+
+ oscap-user ALL=(root) NOPASSWD: /usr/bin/oscap xccdf eval *
+
+user specification into the `sudoers` file, or into a separate file
+that is included by `sudoers` s.a. `/etc/sudoers.d/99-oscap-user`.
+
=== Enable Online Remediation (optional)
****
diff --git a/src/OscapScannerRemoteSsh.cpp b/src/OscapScannerRemoteSsh.cpp
index 69b51373..7fa38b2e 100644
--- a/src/OscapScannerRemoteSsh.cpp
+++ b/src/OscapScannerRemoteSsh.cpp
@@ -364,6 +364,8 @@ void OscapScannerRemoteSsh::processError(QString& message)
{
message.replace(QRegExp("^sudo:"), "Error invoking sudo on the host:");
message += ".\nOnly passwordless sudo setup on the remote host is supported by scap-workbench.";
+ message += " \nTo configure a non-privileged user oscap-user to run only the oscap binary as root, "
+ "add this User Specification to your sudoers file: oscap-user ALL=(root) NOPASSWD: /usr/bin/oscap xccdf eval *";
}
}
From e8daecc80ad54e95de764728f0cbe4863a67be0d Mon Sep 17 00:00:00 2001
From: Matej Tyc <matyc@redhat.com>
Date: Thu, 28 Jan 2021 17:45:09 +0100
Subject: [PATCH 4/4] Added suport for the sudoers checkbox to history.
Recent remote scans now encode the sudo mode into the "target" that is
stored in the recent remote hosts list.
---
include/OscapScannerRemoteSsh.h | 3 ++-
include/RemoteMachineComboBox.h | 2 +-
src/MainWindow.cpp | 5 ++++-
src/OscapScannerRemoteSsh.cpp | 30 +++++++++++++++++++++++-------
src/RemoteMachineComboBox.cpp | 17 +++++++++++------
5 files changed, 41 insertions(+), 16 deletions(-)
diff --git a/include/OscapScannerRemoteSsh.h b/include/OscapScannerRemoteSsh.h
index 280a69da..50214b80 100644
--- a/include/OscapScannerRemoteSsh.h
+++ b/include/OscapScannerRemoteSsh.h
@@ -31,11 +31,12 @@ class OscapScannerRemoteSsh : public OscapScannerBase
Q_OBJECT
public:
- static void splitTarget(const QString& in, QString& target, unsigned short& port);
+ static void splitTarget(const QString& in, QString& target, unsigned short& port, bool& userIsSudoer);
OscapScannerRemoteSsh();
virtual ~OscapScannerRemoteSsh();
+ bool getUserIsSudoer() const;
void setUserIsSudoer(bool userIsSudoer);
virtual void setTarget(const QString& target);
virtual void setSession(ScanningSession* session);
diff --git a/include/RemoteMachineComboBox.h b/include/RemoteMachineComboBox.h
index 3b338127..c2d946c9 100644
--- a/include/RemoteMachineComboBox.h
+++ b/include/RemoteMachineComboBox.h
@@ -47,7 +47,7 @@ class RemoteMachineComboBox : public QWidget
bool userIsSudoer() const;
public slots:
- void notifyTargetUsed(const QString& target);
+ void notifyTargetUsed(const QString& target, bool userIsSudoer);
void clearHistory();
protected slots:
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 236cfde1..496e1724 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -763,7 +763,10 @@ void MainWindow::scanAsync(ScannerMode scannerMode)
);
if (target != "localhost")
- mUI.remoteMachineDetails->notifyTargetUsed(mScanner->getTarget());
+ {
+ bool userIsSudoer = ((OscapScannerRemoteSsh *)mScanner)->getUserIsSudoer();
+ mUI.remoteMachineDetails->notifyTargetUsed(mScanner->getTarget(), userIsSudoer);
+ }
mScanThread->start();
}
diff --git a/src/OscapScannerRemoteSsh.cpp b/src/OscapScannerRemoteSsh.cpp
index 7fa38b2e..b1c4426f 100644
--- a/src/OscapScannerRemoteSsh.cpp
+++ b/src/OscapScannerRemoteSsh.cpp
@@ -46,7 +46,7 @@ OscapScannerRemoteSsh::OscapScannerRemoteSsh():
OscapScannerRemoteSsh::~OscapScannerRemoteSsh()
{}
-void OscapScannerRemoteSsh::splitTarget(const QString& in, QString& target, unsigned short& port)
+void OscapScannerRemoteSsh::splitTarget(const QString& in, QString& target, unsigned short& port, bool& userIsSudoer)
{
// NB: We dodge a bullet here because the editor will always pass a port
// as the last component. A lot of checking and parsing does not need
@@ -56,10 +56,19 @@ void OscapScannerRemoteSsh::splitTarget(const QString& in, QString& target, unsi
// being there and always being the last component.
// FIXME: Ideally, this should split from the right side and stop after one split
- QStringList split = in.split(':');
+ userIsSudoer = false;
+ QStringList sudoerSplit = in.split(' ');
+ if (sudoerSplit.size() > 1)
+ {
+ if (sudoerSplit.at(1) == "sudo")
+ {
+ userIsSudoer = true;
+ }
+ }
+ QStringList hostPortSplit = sudoerSplit.at(0).split(':');
- const QString portString = split.back();
- split.removeLast();
+ const QString portString = hostPortSplit.back();
+ hostPortSplit.removeLast();
{
bool status = false;
@@ -69,25 +78,32 @@ void OscapScannerRemoteSsh::splitTarget(const QString& in, QString& target, unsi
port = status ? portCandidate : 22;
}
- target = split.join(":");
+ target = hostPortSplit.join(":");
}
void OscapScannerRemoteSsh::setTarget(const QString& target)
{
- OscapScannerBase::setTarget(target);
+ QStringList sudoerSplit = target.split(' ');
+ OscapScannerBase::setTarget(sudoerSplit.at(0));
if (mSshConnection.isConnected())
mSshConnection.disconnect();
QString cleanTarget;
unsigned short port;
+ bool userIsSudoer;
- splitTarget(target, cleanTarget, port);
+ splitTarget(target, cleanTarget, port, userIsSudoer);
mSshConnection.setTarget(cleanTarget);
mSshConnection.setPort(port);
}
+bool OscapScannerRemoteSsh::getUserIsSudoer() const
+{
+ return mUserIsSudoer;
+}
+
void OscapScannerRemoteSsh::setUserIsSudoer(bool userIsSudoer)
{
mUserIsSudoer = userIsSudoer;
diff --git a/src/RemoteMachineComboBox.cpp b/src/RemoteMachineComboBox.cpp
index 7b402344..127bdac7 100644
--- a/src/RemoteMachineComboBox.cpp
+++ b/src/RemoteMachineComboBox.cpp
@@ -30,7 +30,7 @@ RemoteMachineComboBox::RemoteMachineComboBox(QWidget* parent):
#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0))
// placeholder text is only supported in Qt 4.7 onwards
- mUI.host->setPlaceholderText(QObject::tr("username@hostname"));
+ mUI.host->setPlaceholderText(QObject::tr("username@hostname [sudo]"));
#endif
mQSettings = new QSettings(this);
@@ -77,11 +77,12 @@ unsigned int RemoteMachineComboBox::getRecentMachineCount() const
return mRecentTargets.size();
}
-void RemoteMachineComboBox::notifyTargetUsed(const QString& target)
+void RemoteMachineComboBox::notifyTargetUsed(const QString& target, bool userIsSudoer)
{
QString host;
unsigned short port;
- OscapScannerRemoteSsh::splitTarget(target, host, port);
+ bool placeholder;
+ OscapScannerRemoteSsh::splitTarget(target, host, port, placeholder);
// skip invalid suggestions
if (host.isEmpty() || port == 0)
@@ -90,7 +91,8 @@ void RemoteMachineComboBox::notifyTargetUsed(const QString& target)
const unsigned int machineCount = getRecentMachineCount();
// this moves target to the beginning of the list if it was in the list already
- mRecentTargets.prepend(target);
+ QString targetWithSudo = target + (userIsSudoer ? " sudo" : "");
+ mRecentTargets.prepend(targetWithSudo);
mRecentTargets.removeDuplicates();
setRecentMachineCount(machineCount);
@@ -106,6 +108,7 @@ void RemoteMachineComboBox::clearHistory()
{
mUI.host->setText("");
mUI.port->setValue(22);
+ mUI.userIsSudoer->setChecked(false);
const unsigned int machineCount = getRecentMachineCount();
mRecentTargets.clear();
@@ -167,6 +170,7 @@ void RemoteMachineComboBox::updateHostPort(int index)
{
mUI.host->setText("");
mUI.port->setValue(22);
+ mUI.userIsSudoer->setChecked(false);
return;
}
@@ -179,10 +183,11 @@ void RemoteMachineComboBox::updateHostPort(int index)
QString host;
unsigned short port;
+ bool userIsSudoer;
- OscapScannerRemoteSsh::splitTarget(target, host, port);
+ OscapScannerRemoteSsh::splitTarget(target, host, port, userIsSudoer);
mUI.host->setText(host);
mUI.port->setValue(port);
-
+ mUI.userIsSudoer->setChecked(userIsSudoer);
}

View File

@ -0,0 +1,87 @@
diff --git a/ui/SSGIntegrationDialog.ui b/ui/SSGIntegrationDialog.ui
index 2e613740..519773f1 100644
--- a/ui/SSGIntegrationDialog.ui
+++ b/ui/SSGIntegrationDialog.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>889</width>
- <height>288</height>
+ <height>330</height>
</rect>
</property>
<property name="sizePolicy">
@@ -28,6 +28,9 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
+ <property name="spacing">
+ <number>12</number>
+ </property>
<item>
<widget class="QLabel" name="ssgLogo">
<property name="sizePolicy">
@@ -52,15 +55,19 @@
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMinimumSize</enum>
+ </property>
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
- <property name="font">
- <font>
- <pointsize>11</pointsize>
- </font>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;SCAP Security Guide was found installed on this machine.&lt;/p&gt;&lt;p&gt;The content provided by SCAP Security Guide allows you to quickly scan your machine according to well stablished security baselines.&lt;/p&gt;&lt;p&gt;Also, these guides are a good starting point if you'd like to customize a policy or profile for your own needs.&lt;/p&gt;&lt;p&gt;Select one of the default guides to load, or select Other SCAP Content option to load your own content.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -111,10 +118,13 @@
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
- <height>40</height>
+ <height>20</height>
</size>
</property>
</spacer>
@@ -157,24 +167,6 @@
</item>
</layout>
</item>
- <item>
- <widget class="QWidget" name="widget" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="spacing">
- <number>6</number>
- </property>
- <property name="margin">
- <number>0</number>
- </property>
- </layout>
- </widget>
- </item>
</layout>
</widget>
<resources/>

View File

@ -2,7 +2,7 @@
Name: scap-workbench
Version: 1.2.1
Release: 11%{?dist}
Release: 13%{?dist}
Summary: Scanning, tailoring, editing and validation tool for SCAP content
License: GPLv3+
@ -12,6 +12,12 @@ Patch1: scap-workbench-1.2.2-fix-qt-deprecated-pr-259.patch
Patch2: scap-workbench-1.2.2-replace-obsolete-Qstring-SkipEmptyParts-pr-266.patch
Patch3: %{name}-gcc11.patch
Patch4: scap-workbench-1.2.2-no-rpath-pr-285.patch
Patch5: scap-workbench-1.2.2-fix-appdata-pr-288.diff
Patch6: scap-workbench-1.2.2-fix-appdata-pr-295.patch
Patch7: scap-workbench-1.2.2-generate-result-based-remediation-from-tailored-profile.patch
Patch8: scap-workbench-1.2.2-ui_dimensions.patch
Patch9: scap-workbench-1.2.2-refactor_messages-PR_271.patch
Patch10: scap-workbench-1.2.2-remote_sudo-PR_270.patch
BuildRequires: cmake >= 2.6
BuildRequires: qt5-qtbase-devel >= 5.0.0
@ -52,7 +58,7 @@ content. The tool is based on OpenSCAP library.
%files
%{_bindir}/scap-workbench
%{_datadir}/applications/scap-workbench.desktop
%{_datadir}/applications/org.open_scap.scap_workbench.desktop
%{_datadir}/scap-workbench/*.png
%{_datadir}/scap-workbench/translations/*
%{_libexecdir}/scap-workbench-oscap.sh
@ -60,14 +66,20 @@ content. The tool is based on OpenSCAP library.
%{_libexecdir}/scap-workbench-rpm-extract.sh
%{_datadir}/polkit-1/actions/scap-workbench-oscap.policy
%{_datadir}/pixmaps/scap-workbench.png
%{_datadir}/pixmaps/scap-workbench.svg
%{_datadir}/appdata/scap-workbench.appdata.xml
%{_datadir}/icons/hicolor/scalable/apps/scap-workbench.svg
%{_datadir}/metainfo/org.open_scap.scap_workbench.appdata.xml
%doc %{_mandir}/man8/scap-workbench.8.gz
%doc %{_pkgdocdir}/user_manual.html
%doc %{_pkgdocdir}/COPYING
%doc %{_pkgdocdir}/README.md
%changelog
* Wed Dec 01 2021 Matej Tyc <matyc@redhat.com> - 1.2.1-13
- Ported 1.2.2 patches that we are present in el8 packages (rhbz#2029381)
* Mon Nov 08 2021 Evgenii Kolesnikov <ekolesni@redhat.com> - 1.2.1-12
- Fix appdata (rhbz#2021212)
* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 1.2.1-11
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688