From 69e988df963cb184062814e75c737fe080f303df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= 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?= 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 #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,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?= 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 --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