From 428cf3c0a57ba5ec6171e66b25335e9f3f4a49c1 Mon Sep 17 00:00:00 2001 From: Packit Date: Sep 07 2020 13:11:35 +0000 Subject: Apply patch scap-workbench-1.2.2-generate-result-based-remediation-from-tailored-profile.patch patch_name: scap-workbench-1.2.2-generate-result-based-remediation-from-tailored-profile.patch present_in_specfile: true --- diff --git a/CMakeLists.txt b/CMakeLists.txt index f3dac6f..ea9ef53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,12 +41,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/doc/user_manual.adoc b/doc/user_manual.adoc index 1fffed7..d97aa6f 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 --result-id '' --tailoring-file . -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 diff --git a/include/Config.h.in b/include/Config.h.in index 58ba306..0ef124f 100644 --- a/include/Config.h.in +++ b/include/Config.h.in @@ -39,7 +39,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 1681b90..95938db 100644 --- a/include/RemediationRoleSaver.h +++ b/include/RemediationRoleSaver.h @@ -93,76 +93,38 @@ 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& saveMessage, const QString& filetypeExtension, const QString& filetypeTemplate, const QString& fixType); - - private: - virtual void saveToFile(const QString& filename); - SpacelessQTemporaryFile mArfFile; -}; - - -class BashResultRemediationSaver : public ResultBasedProcessRemediationSaver -{ - public: - BashResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents); -}; - - -class AnsibleResultRemediationSaver : public ResultBasedProcessRemediationSaver -{ - public: - AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents); -}; - - -class PuppetResultRemediationSaver : public ResultBasedProcessRemediationSaver -{ - public: - PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents); -}; - -#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: - 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 - #endif // SCAP_WORKBENCH_REMEDIATION_ROLE_SAVER_H_ diff --git a/include/ResultViewer.h b/include/ResultViewer.h index a6da89d..2ec8d57 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 900a221..a986673 100644 --- a/src/RemediationRoleSaver.cpp +++ b/src/RemediationRoleSaver.cpp @@ -35,11 +35,7 @@ extern "C" #include #include #include -#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 -#endif } @@ -163,82 +159,8 @@ 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& 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(); -} - -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(""); - - 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): - ResultBasedProcessRemediationSaver(parentWindow, arfContents, - bashSaveMessage, bashFiletypeExtension, bashFiletypeTemplate, bashFixTemplate) -{} - -AnsibleResultRemediationSaver::AnsibleResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents): - ResultBasedProcessRemediationSaver(parentWindow, arfContents, - ansibleSaveMessage, ansibleFiletypeExtension, ansibleFiletypeTemplate, ansibleFixType) -{} - -PuppetResultRemediationSaver::PuppetResultRemediationSaver(QWidget* parentWindow, const QByteArray& arfContents): - ResultBasedProcessRemediationSaver(parentWindow, arfContents, - 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 +168,7 @@ ResultBasedLibraryRemediationSaver::ResultBasedLibraryRemediationSaver(QWidget* mArfFile.open(); mArfFile.write(arfContents); mArfFile.close(); + tailoring = tailoringFilePath; } void ResultBasedLibraryRemediationSaver::saveToFile(const QString& filename) @@ -282,6 +205,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,19 +242,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) {} -#endif // SCAP_WORKBENCH_USE_LIBRARY_FOR_RESULT_BASED_REMEDIATION_ROLES_GENERATION diff --git a/src/ResultViewer.cpp b/src/ResultViewer.cpp index 1e730e9..c544474 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(); }