|
|
0b628f |
diff --git a/src/XCCDF/benchmark.c b/src/XCCDF/benchmark.c
|
|
|
0b628f |
index f561736d4..d6560b7c9 100644
|
|
|
0b628f |
--- a/src/XCCDF/benchmark.c
|
|
|
0b628f |
+++ b/src/XCCDF/benchmark.c
|
|
|
0b628f |
@@ -866,6 +866,19 @@ xccdf_benchmark_find_target_htable(const struct xccdf_benchmark *benchmark, xccd
|
|
|
0b628f |
return XITEM(benchmark)->sub.benchmark.items_dict;
|
|
|
0b628f |
}
|
|
|
0b628f |
|
|
|
0b628f |
+int xccdf_benchmark_include_tailored_profiles(struct xccdf_benchmark *benchmark)
|
|
|
0b628f |
+{
|
|
|
0b628f |
+ struct oscap_list *profiles = XITEM(benchmark)->sub.benchmark.profiles;
|
|
|
0b628f |
+ struct oscap_htable_iterator *it = oscap_htable_iterator_new(XITEM(benchmark)->sub.benchmark.profiles_dict);
|
|
|
0b628f |
+ while(oscap_htable_iterator_has_more(it)) {
|
|
|
0b628f |
+ struct xccdf_profile *profile = oscap_htable_iterator_next_value(it);
|
|
|
0b628f |
+ if (xccdf_profile_get_tailoring(profile)) {
|
|
|
0b628f |
+ oscap_list_add(profiles, xccdf_profile_clone(profile));
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+ oscap_htable_iterator_free(it);
|
|
|
0b628f |
+ return 0;
|
|
|
0b628f |
+}
|
|
|
0b628f |
|
|
|
0b628f |
struct xccdf_plain_text *xccdf_plain_text_new(void)
|
|
|
0b628f |
{
|
|
|
0b628f |
diff --git a/src/XCCDF/item.h b/src/XCCDF/item.h
|
|
|
0b628f |
index 35204744f..da76f854d 100644
|
|
|
0b628f |
--- a/src/XCCDF/item.h
|
|
|
0b628f |
+++ b/src/XCCDF/item.h
|
|
|
0b628f |
@@ -437,6 +437,7 @@ void xccdf_item_dump(struct xccdf_item *item, int depth);
|
|
|
0b628f |
struct xccdf_item* xccdf_item_get_benchmark_internal(struct xccdf_item* item);
|
|
|
0b628f |
bool xccdf_benchmark_parse(struct xccdf_item *benchmark, xmlTextReaderPtr reader);
|
|
|
0b628f |
void xccdf_benchmark_dump(struct xccdf_benchmark *benchmark);
|
|
|
0b628f |
+int xccdf_benchmark_include_tailored_profiles(struct xccdf_benchmark *benchmark);
|
|
|
0b628f |
struct oscap_htable_iterator *xccdf_benchmark_get_cluster_items(struct xccdf_benchmark *benchmark, const char *cluster_id);
|
|
|
0b628f |
bool xccdf_benchmark_register_item(struct xccdf_benchmark *benchmark, struct xccdf_item *item);
|
|
|
0b628f |
bool xccdf_benchmark_unregister_item(struct xccdf_item *item);
|
|
|
0b628f |
diff --git a/src/XCCDF/public/xccdf_session.h b/src/XCCDF/public/xccdf_session.h
|
|
|
0b628f |
index ac96e2036..026432693 100644
|
|
|
0b628f |
--- a/src/XCCDF/public/xccdf_session.h
|
|
|
0b628f |
+++ b/src/XCCDF/public/xccdf_session.h
|
|
|
0b628f |
@@ -558,6 +558,14 @@ OSCAP_API int xccdf_session_build_policy_from_testresult(struct xccdf_session *s
|
|
|
0b628f |
*/
|
|
|
0b628f |
OSCAP_API int xccdf_session_add_report_from_source(struct xccdf_session *session, struct oscap_source *report_source);
|
|
|
0b628f |
|
|
|
0b628f |
+/**
|
|
|
0b628f |
+ * Generate HTML guide form a loaded XCCDF session
|
|
|
0b628f |
+ * @param session XCCDF Session
|
|
|
0b628f |
+ * @param outfile path to the output file
|
|
|
0b628f |
+ * @returns zero on success
|
|
|
0b628f |
+ */
|
|
|
0b628f |
+OSCAP_API int xccdf_session_generate_guide(struct xccdf_session *session, const char *outfile);
|
|
|
0b628f |
+
|
|
|
0b628f |
/// @}
|
|
|
0b628f |
/// @}
|
|
|
0b628f |
#endif
|
|
|
0b628f |
diff --git a/src/XCCDF/xccdf_session.c b/src/XCCDF/xccdf_session.c
|
|
|
0b628f |
index 1005a030a..d38905f77 100644
|
|
|
0b628f |
--- a/src/XCCDF/xccdf_session.c
|
|
|
0b628f |
+++ b/src/XCCDF/xccdf_session.c
|
|
|
0b628f |
@@ -1746,3 +1746,44 @@ int xccdf_session_add_report_from_source(struct xccdf_session *session, struct o
|
|
|
0b628f |
session->xccdf.result = result;
|
|
|
0b628f |
return 0;
|
|
|
0b628f |
}
|
|
|
0b628f |
+
|
|
|
0b628f |
+int xccdf_session_generate_guide(struct xccdf_session *session, const char *outfile)
|
|
|
0b628f |
+{
|
|
|
0b628f |
+ struct xccdf_policy *policy = xccdf_session_get_xccdf_policy(session);
|
|
|
0b628f |
+ if (policy == NULL) {
|
|
|
0b628f |
+ oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not get XCCDF policy.");
|
|
|
0b628f |
+ return 1;
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+ struct xccdf_policy_model *model = xccdf_policy_get_model(policy);
|
|
|
0b628f |
+ if (model == NULL) {
|
|
|
0b628f |
+ oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not get XCCDF policy model.");
|
|
|
0b628f |
+ return 1;
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+ struct xccdf_benchmark *benchmark = xccdf_policy_model_get_benchmark(model);
|
|
|
0b628f |
+ if (benchmark == NULL) {
|
|
|
0b628f |
+ oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not get XCCDF benchmark.");
|
|
|
0b628f |
+ return 1;
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+ xccdf_benchmark_include_tailored_profiles(benchmark);
|
|
|
0b628f |
+ const char *params[] = {
|
|
|
0b628f |
+ "oscap-version", oscap_get_version(),
|
|
|
0b628f |
+ "benchmark_id", xccdf_benchmark_get_id(benchmark),
|
|
|
0b628f |
+ "profile_id", xccdf_session_get_profile_id(session),
|
|
|
0b628f |
+ NULL
|
|
|
0b628f |
+ };
|
|
|
0b628f |
+ struct oscap_source *benchmark_source = xccdf_benchmark_export_source(benchmark, NULL);
|
|
|
0b628f |
+ if (benchmark_source == NULL) {
|
|
|
0b628f |
+ oscap_seterr(OSCAP_EFAMILY_OSCAP,
|
|
|
0b628f |
+ "Failed to export source from XCCDF benchmark %s.",
|
|
|
0b628f |
+ xccdf_benchmark_get_id(benchmark));
|
|
|
0b628f |
+ return 1;
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+ int ret = oscap_source_apply_xslt_path(benchmark_source,
|
|
|
0b628f |
+ "xccdf-guide.xsl", outfile, params, oscap_path_to_xslt());
|
|
|
0b628f |
+ oscap_source_free(benchmark_source);
|
|
|
0b628f |
+ if (ret < 0) {
|
|
|
0b628f |
+ oscap_seterr(OSCAP_EFAMILY_OSCAP, "Could not apply XSLT.");
|
|
|
0b628f |
+ return 1;
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+ return 0;
|
|
|
0b628f |
+}
|
|
|
0b628f |
\ No newline at end of file
|
|
|
0b628f |
diff --git a/tests/API/XCCDF/tailoring/all.sh b/tests/API/XCCDF/tailoring/all.sh
|
|
|
0b628f |
index dbed97a87..fc2ccd743 100755
|
|
|
0b628f |
--- a/tests/API/XCCDF/tailoring/all.sh
|
|
|
0b628f |
+++ b/tests/API/XCCDF/tailoring/all.sh
|
|
|
0b628f |
@@ -134,6 +134,21 @@ function test_api_xccdf_tailoring_profile_generate_fix {
|
|
|
0b628f |
rm -f $tailoring_result $fix_result
|
|
|
0b628f |
}
|
|
|
0b628f |
|
|
|
0b628f |
+function test_api_xccdf_tailoring_profile_generate_guide {
|
|
|
0b628f |
+ local INPUT=$srcdir/$1
|
|
|
0b628f |
+ local TAILORING=$srcdir/$2
|
|
|
0b628f |
+
|
|
|
0b628f |
+ guide=`mktemp`
|
|
|
0b628f |
+ # tailoring profile only with "always fail" rule and generate HTML guide
|
|
|
0b628f |
+ $OSCAP xccdf generate guide --tailoring-file $TAILORING --profile "xccdf_com.example.www_profile_customized" --output $guide $INPUT
|
|
|
0b628f |
+
|
|
|
0b628f |
+ grep -q "Baseline Testing Profile 1 \[CUSTOMIZED\]" $guide
|
|
|
0b628f |
+ # profile 'customized' selects first rule and deselects the second
|
|
|
0b628f |
+ grep -q "xccdf_com.example.www_rule_first" $guide
|
|
|
0b628f |
+ grep -v "xccdf_com.example.www_rule_second" $guide
|
|
|
0b628f |
+ rm -f $guide
|
|
|
0b628f |
+}
|
|
|
0b628f |
+
|
|
|
0b628f |
# Testing.
|
|
|
0b628f |
|
|
|
0b628f |
test_init "test_api_xccdf_tailoring.log"
|
|
|
0b628f |
@@ -154,6 +169,7 @@ test_run "test_api_xccdf_tailoring_autonegotiation" test_api_xccdf_tailoring_aut
|
|
|
0b628f |
test_run "test_api_xccdf_tailoring_simple_include_in_arf" test_api_xccdf_tailoring_simple_include_in_arf simple-xccdf.xml simple-tailoring.xml
|
|
|
0b628f |
test_run "test_api_xccdf_tailoring_profile_include_in_arf" test_api_xccdf_tailoring_profile_include_in_arf baseline.xccdf.xml baseline.tailoring.xml
|
|
|
0b628f |
test_run "test_api_xccdf_tailoring_profile_generate_fix" test_api_xccdf_tailoring_profile_generate_fix baseline.xccdf.xml baseline.tailoring.xml
|
|
|
0b628f |
+test_run "test_api_xccdf_tailoring_profile_generate_guide" test_api_xccdf_tailoring_profile_generate_guide baseline.xccdf.xml baseline.tailoring.xml
|
|
|
0b628f |
|
|
|
0b628f |
|
|
|
0b628f |
test_exit
|
|
|
0b628f |
diff --git a/utils/oscap-xccdf.c b/utils/oscap-xccdf.c
|
|
|
0b628f |
index 472a2cc6f..87a0c7ad1 100644
|
|
|
0b628f |
--- a/utils/oscap-xccdf.c
|
|
|
0b628f |
+++ b/utils/oscap-xccdf.c
|
|
|
0b628f |
@@ -77,6 +77,7 @@ static bool getopt_xccdf(int argc, char **argv, struct oscap_action *action);
|
|
|
0b628f |
static bool getopt_generate(int argc, char **argv, struct oscap_action *action);
|
|
|
0b628f |
static int app_xccdf_xslt(const struct oscap_action *action);
|
|
|
0b628f |
static int app_generate_fix(const struct oscap_action *action);
|
|
|
0b628f |
+static int app_generate_guide(const struct oscap_action *action);
|
|
|
0b628f |
|
|
|
0b628f |
#define XCCDF_SUBMODULES_NUM 7
|
|
|
0b628f |
#define XCCDF_GEN_SUBMODULES_NUM 5 /* See actual arrays
|
|
|
0b628f |
@@ -244,12 +245,18 @@ static struct oscap_module XCCDF_GEN_GUIDE = {
|
|
|
0b628f |
.help = GEN_OPTS
|
|
|
0b628f |
"\nGuide Options:\n"
|
|
|
0b628f |
" --output <file> - Write the document into file.\n"
|
|
|
0b628f |
- " --hide-profile-info - Do not output additional information about selected profile.\n"
|
|
|
0b628f |
+ " --hide-profile-info - This option has no effect.\n"
|
|
|
0b628f |
" --benchmark-id <id> - ID of XCCDF Benchmark in some component in the datastream that should be used.\n"
|
|
|
0b628f |
+ " (only applicable for source datastreams)\n"
|
|
|
0b628f |
+ " --xccdf-id <id> - ID of component-ref with XCCDF in the datastream that should be evaluated.\n"
|
|
|
0b628f |
+ " (only applicable for source datastreams)\n"
|
|
|
0b628f |
+ " --tailoring-file <file> - Use given XCCDF Tailoring file.\n"
|
|
|
0b628f |
+ " (only applicable for source datastreams)\n"
|
|
|
0b628f |
+ " --tailoring-id <component-id> - Use given DS component as XCCDF Tailoring file.\n"
|
|
|
0b628f |
" (only applicable for source datastreams)\n",
|
|
|
0b628f |
.opt_parser = getopt_xccdf,
|
|
|
0b628f |
- .user = "xccdf-guide.xsl",
|
|
|
0b628f |
- .func = app_xccdf_xslt
|
|
|
0b628f |
+ .user = NULL,
|
|
|
0b628f |
+ .func = app_generate_guide
|
|
|
0b628f |
};
|
|
|
0b628f |
|
|
|
0b628f |
static struct oscap_module XCCDF_GEN_FIX = {
|
|
|
0b628f |
@@ -973,6 +980,50 @@ int app_generate_fix(const struct oscap_action *action)
|
|
|
0b628f |
return ret;
|
|
|
0b628f |
}
|
|
|
0b628f |
|
|
|
0b628f |
+int app_generate_guide(const struct oscap_action *action)
|
|
|
0b628f |
+{
|
|
|
0b628f |
+ int ret = OSCAP_ERROR;
|
|
|
0b628f |
+
|
|
|
0b628f |
+ struct oscap_source *source = oscap_source_new_from_file(action->f_xccdf);
|
|
|
0b628f |
+ struct xccdf_session *session = xccdf_session_new_from_source(source);
|
|
|
0b628f |
+ if (session == NULL) {
|
|
|
0b628f |
+ goto cleanup;
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+
|
|
|
0b628f |
+ xccdf_session_set_validation(session, action->validate, getenv("OSCAP_FULL_VALIDATION") != NULL);
|
|
|
0b628f |
+ xccdf_session_set_remote_resources(session, action->remote_resources, download_reporting_callback);
|
|
|
0b628f |
+ xccdf_session_set_user_tailoring_file(session, action->tailoring_file);
|
|
|
0b628f |
+ xccdf_session_set_user_tailoring_cid(session, action->tailoring_id);
|
|
|
0b628f |
+ if (xccdf_session_is_sds(session)) {
|
|
|
0b628f |
+ xccdf_session_set_component_id(session, action->f_xccdf_id);
|
|
|
0b628f |
+ xccdf_session_set_benchmark_id(session, action->f_benchmark_id);
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+ xccdf_session_set_loading_flags(session, XCCDF_SESSION_LOAD_XCCDF);
|
|
|
0b628f |
+
|
|
|
0b628f |
+ if (xccdf_session_load(session) != 0) {
|
|
|
0b628f |
+ goto cleanup;
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+
|
|
|
0b628f |
+ if (!xccdf_session_set_profile_id(session, action->profile)) {
|
|
|
0b628f |
+ if (action->profile != NULL) {
|
|
|
0b628f |
+ if (xccdf_set_profile_or_report_bad_id(session, action->profile, action->f_xccdf) == OSCAP_ERROR)
|
|
|
0b628f |
+ goto cleanup;
|
|
|
0b628f |
+ } else {
|
|
|
0b628f |
+ fprintf(stderr, "No Policy was found for default profile.\n");
|
|
|
0b628f |
+ goto cleanup;
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+
|
|
|
0b628f |
+ if (xccdf_session_generate_guide(session, action->f_results) == 0) {
|
|
|
0b628f |
+ ret = OSCAP_OK;
|
|
|
0b628f |
+ }
|
|
|
0b628f |
+
|
|
|
0b628f |
+cleanup:
|
|
|
0b628f |
+ xccdf_session_free(session);
|
|
|
0b628f |
+ oscap_print_error();
|
|
|
0b628f |
+ return ret;
|
|
|
0b628f |
+}
|
|
|
0b628f |
+
|
|
|
0b628f |
int app_xccdf_xslt(const struct oscap_action *action)
|
|
|
0b628f |
{
|
|
|
0b628f |
const char *oval_template = action->oval_template;
|
|
|
0b628f |
diff --git a/utils/oscap.8 b/utils/oscap.8
|
|
|
0b628f |
index 1b05f8c9e..3a50d1df5 100644
|
|
|
0b628f |
--- a/utils/oscap.8
|
|
|
0b628f |
+++ b/utils/oscap.8
|
|
|
0b628f |
@@ -331,10 +331,19 @@ Generate a HTML document containing a security guide from an XCCDF Benchmark. Un
|
|
|
0b628f |
Write the guide to this file instead of standard output.
|
|
|
0b628f |
.TP
|
|
|
0b628f |
\fB\-\-hide-profile-info\fR
|
|
|
0b628f |
-Information on chosen profile (e.g. rules selected by the profile) will be excluded from the document.
|
|
|
0b628f |
+This option has no effect and is kept only for backward compatibility purposes.
|
|
|
0b628f |
.TP
|
|
|
0b628f |
\fB\-\-benchmark-id ID\fR
|
|
|
0b628f |
Selects a component ref from any datastream that references a component with XCCDF Benchmark such that its @id attribute matches given string exactly.
|
|
|
0b628f |
+.TP
|
|
|
0b628f |
+\fB\-\-xccdf-id ID\fR
|
|
|
0b628f |
+Takes component ref with given ID from checklists. This allows to select a particular XCCDF component even in cases where there are 2 XCCDFs in one datastream. If none is given, the first component from the checklists element is used.
|
|
|
0b628f |
+.TP
|
|
|
0b628f |
+\fB\-\-tailoring-file TAILORING_FILE\fR
|
|
|
0b628f |
+Use given file for XCCDF tailoring. Select profile from tailoring file to apply using --profile. If both --tailoring-file and --tailoring-id are specified, --tailoring-file takes priority.
|
|
|
0b628f |
+.TP
|
|
|
0b628f |
+\fB\-\-tailoring-id COMPONENT_REF_ID\fR
|
|
|
0b628f |
+Use tailoring component in input source datastream for XCCDF tailoring. The tailoring component must be specified by its Ref-ID (value of component-ref/@id attribute in input source datastream). Select profile from tailoring component to apply using --profile. If both --tailoring-file and --tailoring-id are specified, --tailoring-file takes priority.
|
|
|
0b628f |
.RE
|
|
|
0b628f |
.TP
|
|
|
0b628f |
.B \fBreport\fR [\fIoptions\fR] xccdf-file
|