5ad69e624b
Resolves: rhbz#2020052
584 lines
23 KiB
Diff
584 lines
23 KiB
Diff
From b0b7626dca08acd4563ae42c1c27ccc0777b5357 Mon Sep 17 00:00:00 2001
|
|
From: Evgeny Kolesnikov <ekolesni@redhat.com>
|
|
Date: Thu, 23 Sep 2021 00:58:29 +0200
|
|
Subject: [PATCH] Add proper Blueprint's remediation snippets handling for
|
|
generation of the final TOML document.
|
|
|
|
As the final Blueprint could not be created by just gluing up all
|
|
the snippets together we have to get a bit more creative.
|
|
---
|
|
docs/manual/manual.adoc | 15 ++
|
|
src/XCCDF_POLICY/xccdf_policy_remediate.c | 216 ++++++++++++++++--
|
|
src/common/list.c | 19 ++
|
|
src/common/list.h | 1 +
|
|
tests/API/XCCDF/unittests/CMakeLists.txt | 1 +
|
|
.../unittests/test_remediation_blueprint.sh | 27 +++
|
|
.../unittests/test_remediation_blueprint.toml | 45 ++++
|
|
.../test_remediation_blueprint.xccdf.xml | 102 +++++++++
|
|
8 files changed, 405 insertions(+), 21 deletions(-)
|
|
create mode 100755 tests/API/XCCDF/unittests/test_remediation_blueprint.sh
|
|
create mode 100644 tests/API/XCCDF/unittests/test_remediation_blueprint.toml
|
|
create mode 100644 tests/API/XCCDF/unittests/test_remediation_blueprint.xccdf.xml
|
|
|
|
diff --git a/docs/manual/manual.adoc b/docs/manual/manual.adoc
|
|
index e8664eb920..90e2cc2c63 100644
|
|
--- a/docs/manual/manual.adoc
|
|
+++ b/docs/manual/manual.adoc
|
|
@@ -1084,6 +1084,21 @@ scanned during this command. If you want to generate remediation only for the
|
|
failed rules based on scan results, refer to <<_reviewing_remediations,Reviewing
|
|
remediations>>.
|
|
|
|
+=== Generating Image Builder Blueprints
|
|
+
|
|
+OpenSCAP can also create a remediation in form of Image Builder (OSBuild) Blueprint. This remeditaion
|
|
+is intendeded to be used as a bootstrap for image creation and usually it will contain only essential
|
|
+elements of the configuration, elements that would be hard or impossible to change after the image
|
|
+is created, like partitioning or set of installed packages.
|
|
+
|
|
+It is recommended to combine this type of remediation with other types, executed on the running system.
|
|
+
|
|
+For example, to generate a blueprint remediation for RHEL 8 OSPP profile, run:
|
|
+
|
|
+----
|
|
+$ oscap xccdf generate fix --profile ospp --fix-type blueprint /usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml > blueprint.toml
|
|
+----
|
|
+
|
|
== Details on SCAP conformance
|
|
|
|
=== Check Engines
|
|
diff --git a/src/XCCDF_POLICY/xccdf_policy_remediate.c b/src/XCCDF_POLICY/xccdf_policy_remediate.c
|
|
index 0b3a037a5f..6033c3b54b 100644
|
|
--- a/src/XCCDF_POLICY/xccdf_policy_remediate.c
|
|
+++ b/src/XCCDF_POLICY/xccdf_policy_remediate.c
|
|
@@ -656,6 +656,78 @@ static int _write_fix_missing_warning_to_fd(const char *sys, int output_fd, stru
|
|
}
|
|
}
|
|
|
|
+struct blueprint_entries {
|
|
+ const char *pattern;
|
|
+ struct oscap_list *list;
|
|
+ pcre *re;
|
|
+};
|
|
+
|
|
+static inline int _parse_blueprint_fix(const char *fix_text, struct oscap_list *generic, struct oscap_list *services_enable, struct oscap_list *services_disable, struct oscap_list *kernel_append)
|
|
+{
|
|
+ const char *err;
|
|
+ int errofs;
|
|
+ int ret = 0;
|
|
+
|
|
+ struct blueprint_entries tab[] = {
|
|
+ {"\\[customizations\\.services\\]\\s+enabled[=\\s]+\\[([^\\]]+)\\]\\s+", services_enable, NULL},
|
|
+ {"\\[customizations\\.services\\]\\s+disabled[=\\s]+\\[([^\\]]+)\\]\\s+", services_disable, NULL},
|
|
+ {"\\[customizations\\.kernel\\]\\s+append[=\\s\"]+([^\"]+)[\\s\"]+", kernel_append, NULL},
|
|
+ // We do this only to pop the 'distro' entry to the top of the generic list,
|
|
+ // effectively placing it to the root of the TOML document.
|
|
+ {"\\s+(distro[=\\s\"]+[^\"]+[\\s\"]+)", generic, NULL},
|
|
+ {NULL, NULL, NULL}
|
|
+ };
|
|
+
|
|
+ for (int i = 0; tab[i].pattern != NULL; i++) {
|
|
+ tab[i].re = pcre_compile(tab[i].pattern, PCRE_UTF8, &err, &errofs, NULL);
|
|
+ if (tab[i].re == NULL) {
|
|
+ dE("Unable to compile /%s/ regex pattern, pcre_compile() returned error (offset: %d): '%s'.\n", tab[i].pattern, errofs, err);
|
|
+ ret = 1;
|
|
+ goto exit;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ const size_t fix_text_len = strlen(fix_text);
|
|
+ size_t start_offset = 0;
|
|
+ int ovector[6] = {0};
|
|
+
|
|
+ for (int i = 0; tab[i].pattern != NULL; i++) {
|
|
+ while (true) {
|
|
+ const int match = pcre_exec(tab[i].re, NULL, fix_text, fix_text_len, start_offset,
|
|
+ 0, ovector, sizeof(ovector) / sizeof(ovector[0]));
|
|
+ if (match == -1)
|
|
+ break;
|
|
+
|
|
+ if (match != 2) {
|
|
+ dE("Expected 1 capture group matches per entry. Found %i!", match - 1);
|
|
+ ret = 1;
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ char *val = malloc((ovector[3] - ovector[2] + 1) * sizeof(char));
|
|
+ memcpy(val, &fix_text[ovector[2]], ovector[3] - ovector[2]);
|
|
+ val[ovector[3] - ovector[2]] = '\0';
|
|
+
|
|
+ if (!oscap_list_contains(kernel_append, val, (oscap_cmp_func) oscap_streq)) {
|
|
+ oscap_list_prepend(tab[i].list, val);
|
|
+ } else {
|
|
+ free(val);
|
|
+ }
|
|
+
|
|
+ start_offset = ovector[1];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (start_offset < fix_text_len-1) {
|
|
+ oscap_list_add(generic, strdup(fix_text + start_offset));
|
|
+ }
|
|
+
|
|
+exit:
|
|
+ for (int i = 0; tab[i].pattern != NULL; i++)
|
|
+ pcre_free(tab[i].re);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
|
|
static inline int _parse_ansible_fix(const char *fix_text, struct oscap_list *variables, struct oscap_list *tasks)
|
|
{
|
|
@@ -793,6 +865,18 @@ static int _xccdf_policy_rule_generate_fix(struct xccdf_policy *policy, struct x
|
|
return ret;
|
|
}
|
|
|
|
+static int _xccdf_policy_rule_generate_blueprint_fix(struct xccdf_policy *policy, struct xccdf_rule *rule, const char *template, struct oscap_list *generic, struct oscap_list *services_enable, struct oscap_list *services_disable, struct oscap_list *kernel_append)
|
|
+{
|
|
+ char *fix_text = NULL;
|
|
+ int ret = _xccdf_policy_rule_get_fix_text(policy, rule, template, &fix_text);
|
|
+ if (fix_text == NULL) {
|
|
+ return ret;
|
|
+ }
|
|
+ ret = _parse_blueprint_fix(fix_text, generic, services_enable, services_disable, kernel_append);
|
|
+ free(fix_text);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int _xccdf_policy_rule_generate_ansible_fix(struct xccdf_policy *policy, struct xccdf_rule *rule, const char *template, struct oscap_list *variables, struct oscap_list *tasks)
|
|
{
|
|
char *fix_text = NULL;
|
|
@@ -914,25 +998,45 @@ static char *_comment_multiline_text(char *text)
|
|
static int _write_script_header_to_fd(struct xccdf_policy *policy, struct xccdf_result *result, const char *sys, int output_fd)
|
|
{
|
|
if (!(oscap_streq(sys, "") || oscap_streq(sys, "urn:xccdf:fix:script:sh") || oscap_streq(sys, "urn:xccdf:fix:commands") ||
|
|
- oscap_streq(sys, "urn:xccdf:fix:script:ansible")))
|
|
+ oscap_streq(sys, "urn:xccdf:fix:script:ansible") || oscap_streq(sys, "urn:redhat:osbuild:blueprint")))
|
|
return 0; // no header required
|
|
|
|
- const bool ansible_script = strcmp(sys, "urn:xccdf:fix:script:ansible") == 0;
|
|
- const char *how_to_apply = ansible_script ?
|
|
- "# $ ansible-playbook -i \"localhost,\" -c local playbook.yml\n"
|
|
- "# $ ansible-playbook -i \"192.168.1.155,\" playbook.yml\n"
|
|
- "# $ ansible-playbook -i inventory.ini playbook.yml" :
|
|
- "# $ sudo ./remediation-script.sh";
|
|
const char *oscap_version = oscap_get_version();
|
|
- const char *format = ansible_script ? "ansible" : "bash";
|
|
- const char *remediation_type = ansible_script ? "Ansible Playbook" : "Bash Remediation Script";
|
|
- const char *shebang_with_newline = ansible_script ? "" : "#!/usr/bin/env bash\n";
|
|
+ char *how_to_apply = "";
|
|
+ char *format = (char *)sys;
|
|
+ char *remediation_type = "Unknown";
|
|
+ char *shebang_with_newline = "";
|
|
+
|
|
+ if (oscap_streq(sys, "urn:xccdf:fix:script:ansible")) {
|
|
+ how_to_apply = "# $ ansible-playbook -i \"localhost,\" -c local playbook.yml\n"
|
|
+ "# $ ansible-playbook -i \"192.168.1.155,\" playbook.yml\n"
|
|
+ "# $ ansible-playbook -i inventory.ini playbook.yml";
|
|
+ format = "ansible";
|
|
+ remediation_type = "Ansible Playbook";
|
|
+ }
|
|
+
|
|
+ if (oscap_streq(sys, "urn:redhat:osbuild:blueprint")) {
|
|
+ how_to_apply = "# composer-cli blueprints push blueprint.toml";
|
|
+ format = "blueprint";
|
|
+ remediation_type = "Blueprint";
|
|
+ }
|
|
+
|
|
+ if (oscap_streq(sys, "") || oscap_streq(sys, "urn:xccdf:fix:script:sh") || oscap_streq(sys, "urn:xccdf:fix:commands")) {
|
|
+ how_to_apply = "# $ sudo ./remediation-script.sh";
|
|
+ format = "bash";
|
|
+ remediation_type = "Bash Remediation Script";
|
|
+ shebang_with_newline = "#!/usr/bin/env bash\n";
|
|
+ }
|
|
|
|
char *fix_header;
|
|
|
|
struct xccdf_profile *profile = xccdf_policy_get_profile(policy);
|
|
const char *profile_id = xccdf_profile_get_id(profile);
|
|
|
|
+ struct xccdf_benchmark *benchmark = xccdf_policy_get_benchmark(policy);
|
|
+ const char *benchmark_version_info = benchmark ? xccdf_benchmark_get_version(benchmark) : "Unknown";
|
|
+ const char *benchmark_id = benchmark ? xccdf_benchmark_get_id(benchmark) : "Unknown";
|
|
+
|
|
// Title
|
|
struct oscap_text_iterator *title_iterator = xccdf_profile_get_title(profile);
|
|
char *raw_profile_title = oscap_textlist_get_preferred_plaintext(title_iterator, NULL);
|
|
@@ -942,11 +1046,6 @@ static int _write_script_header_to_fd(struct xccdf_policy *policy, struct xccdf_
|
|
|
|
if (result == NULL) {
|
|
// Profile-based remediation fix
|
|
- struct xccdf_benchmark *benchmark = xccdf_policy_get_benchmark(policy);
|
|
- if (benchmark == NULL) {
|
|
- free(profile_title);
|
|
- return 1;
|
|
- }
|
|
// Description
|
|
struct oscap_text_iterator *description_iterator = xccdf_profile_get_description(profile);
|
|
char *profile_description = description_iterator != NULL ?
|
|
@@ -955,10 +1054,8 @@ static int _write_script_header_to_fd(struct xccdf_policy *policy, struct xccdf_
|
|
char *commented_profile_description = _comment_multiline_text(profile_description);
|
|
free(profile_description);
|
|
|
|
- const char *benchmark_version_info = xccdf_benchmark_get_version(benchmark);
|
|
- const char *benchmark_id = xccdf_benchmark_get_id(benchmark);
|
|
- const struct xccdf_version_info *xccdf_version = xccdf_benchmark_get_schema_version(benchmark);
|
|
- const char *xccdf_version_name = xccdf_version_info_get_version(xccdf_version);
|
|
+ const struct xccdf_version_info *xccdf_version = benchmark ? xccdf_benchmark_get_schema_version(benchmark) : NULL;
|
|
+ const char *xccdf_version_name = xccdf_version ? xccdf_version_info_get_version(xccdf_version) : "Unknown";
|
|
|
|
fix_header = oscap_sprintf(
|
|
"%s"
|
|
@@ -1026,9 +1123,8 @@ static int _write_script_header_to_fd(struct xccdf_policy *policy, struct xccdf_
|
|
result_id, format, remediation_type, remediation_type, how_to_apply
|
|
);
|
|
}
|
|
- free(profile_title);
|
|
|
|
- if (ansible_script) {
|
|
+ if (oscap_streq(sys, "urn:xccdf:fix:script:ansible")) {
|
|
char *ansible_fix_header = oscap_sprintf(
|
|
"---\n"
|
|
"%s\n"
|
|
@@ -1036,9 +1132,85 @@ static int _write_script_header_to_fd(struct xccdf_policy *policy, struct xccdf_
|
|
fix_header);
|
|
free(fix_header);
|
|
return _write_text_to_fd_and_free(output_fd, ansible_fix_header);
|
|
+ } else if (oscap_streq(sys, "urn:redhat:osbuild:blueprint")) {
|
|
+ char *blueprint_fix_header = oscap_sprintf(
|
|
+ "%s"
|
|
+ "name = \"%s\"\n"
|
|
+ "description = \"%s\"\n"
|
|
+ "version = \"%s\"\n",
|
|
+ fix_header, profile_id, profile_title, benchmark_version_info);
|
|
+ free(fix_header);
|
|
+ return _write_text_to_fd_and_free(output_fd, blueprint_fix_header);
|
|
} else {
|
|
return _write_text_to_fd_and_free(output_fd, fix_header);
|
|
}
|
|
+
|
|
+ free(profile_title);
|
|
+}
|
|
+
|
|
+static int _xccdf_policy_generate_fix_blueprint(struct oscap_list *rules_to_fix, struct xccdf_policy *policy, const char *sys, int output_fd)
|
|
+{
|
|
+ int ret = 0;
|
|
+ struct oscap_list *generic = oscap_list_new();
|
|
+ struct oscap_list *services_enable = oscap_list_new();
|
|
+ struct oscap_list *services_disable = oscap_list_new();
|
|
+ struct oscap_list *kernel_append = oscap_list_new();
|
|
+ struct oscap_iterator *rules_to_fix_it = oscap_iterator_new(rules_to_fix);
|
|
+ while (oscap_iterator_has_more(rules_to_fix_it)) {
|
|
+ struct xccdf_rule *rule = (struct xccdf_rule*)oscap_iterator_next(rules_to_fix_it);
|
|
+ ret = _xccdf_policy_rule_generate_blueprint_fix(policy, rule, sys, generic, services_enable, services_disable, kernel_append);
|
|
+ if (ret != 0)
|
|
+ break;
|
|
+ }
|
|
+ oscap_iterator_free(rules_to_fix_it);
|
|
+
|
|
+ struct oscap_iterator *generic_it = oscap_iterator_new(generic);
|
|
+ while(oscap_iterator_has_more(generic_it)) {
|
|
+ char *var_line = (char *) oscap_iterator_next(generic_it);
|
|
+ _write_text_to_fd(output_fd, var_line);
|
|
+ }
|
|
+ _write_text_to_fd(output_fd, "\n");
|
|
+ oscap_iterator_free(generic_it);
|
|
+ oscap_list_free(generic, free);
|
|
+
|
|
+ _write_text_to_fd(output_fd, "[customizations.kernel]\nappend = \"");
|
|
+ struct oscap_iterator *kernel_append_it = oscap_iterator_new(kernel_append);
|
|
+ while(oscap_iterator_has_more(kernel_append_it)) {
|
|
+ char *var_line = (char *) oscap_iterator_next(kernel_append_it);
|
|
+ _write_text_to_fd(output_fd, var_line);
|
|
+ if (oscap_iterator_has_more(kernel_append_it))
|
|
+ _write_text_to_fd(output_fd, " ");
|
|
+ }
|
|
+ _write_text_to_fd(output_fd, "\"\n\n");
|
|
+ oscap_iterator_free(kernel_append_it);
|
|
+ oscap_list_free(kernel_append, free);
|
|
+
|
|
+ _write_text_to_fd(output_fd, "[customizations.services]\n");
|
|
+ _write_text_to_fd(output_fd, "enabled = [");
|
|
+ struct oscap_iterator *services_enable_it = oscap_iterator_new(services_enable);
|
|
+ while(oscap_iterator_has_more(services_enable_it)) {
|
|
+ char *var_line = (char *) oscap_iterator_next(services_enable_it);
|
|
+ _write_text_to_fd(output_fd, var_line);
|
|
+ if (oscap_iterator_has_more(services_enable_it))
|
|
+ _write_text_to_fd(output_fd, ",");
|
|
+ }
|
|
+ _write_text_to_fd(output_fd, "]\n");
|
|
+ oscap_iterator_free(services_enable_it);
|
|
+ oscap_list_free(services_enable, free);
|
|
+
|
|
+ _write_text_to_fd(output_fd, "disabled = [");
|
|
+ struct oscap_iterator *services_disable_it = oscap_iterator_new(services_disable);
|
|
+ while(oscap_iterator_has_more(services_disable_it)) {
|
|
+ char *var_line = (char *) oscap_iterator_next(services_disable_it);
|
|
+ _write_text_to_fd(output_fd, var_line);
|
|
+ if (oscap_iterator_has_more(services_disable_it))
|
|
+ _write_text_to_fd(output_fd, ",");
|
|
+ }
|
|
+ _write_text_to_fd(output_fd, "]\n\n");
|
|
+ oscap_iterator_free(services_disable_it);
|
|
+ oscap_list_free(services_disable, free);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static int _xccdf_policy_generate_fix_ansible(struct oscap_list *rules_to_fix, struct xccdf_policy *policy, const char *sys, int output_fd)
|
|
@@ -1145,6 +1317,8 @@ int xccdf_policy_generate_fix(struct xccdf_policy *policy, struct xccdf_result *
|
|
// in Ansible we have to generate variables first and then tasks
|
|
if (strcmp(sys, "urn:xccdf:fix:script:ansible") == 0) {
|
|
ret = _xccdf_policy_generate_fix_ansible(rules_to_fix, policy, sys, output_fd);
|
|
+ } else if (strcmp(sys, "urn:redhat:osbuild:blueprint") == 0) {
|
|
+ ret = _xccdf_policy_generate_fix_blueprint(rules_to_fix, policy, sys, output_fd);
|
|
} else {
|
|
ret = _xccdf_policy_generate_fix_other(rules_to_fix, policy, sys, output_fd);
|
|
}
|
|
diff --git a/src/common/list.c b/src/common/list.c
|
|
index 2516d0f2f0..90381069f8 100644
|
|
--- a/src/common/list.c
|
|
+++ b/src/common/list.c
|
|
@@ -66,6 +66,25 @@ bool oscap_list_add(struct oscap_list * list, void *value)
|
|
return true;
|
|
}
|
|
|
|
+bool oscap_list_prepend(struct oscap_list * list, void *value)
|
|
+{
|
|
+ __attribute__nonnull__(list);
|
|
+ if (value == NULL) return false;
|
|
+
|
|
+ struct oscap_list_item *item = malloc(sizeof(struct oscap_list_item));
|
|
+ item->next = NULL;
|
|
+ item->data = value;
|
|
+ ++list->itemcount;
|
|
+
|
|
+ if (list->first == NULL) {
|
|
+ list->last = list->first = item;
|
|
+ } else {
|
|
+ item->next = list->first;
|
|
+ list->first = item;
|
|
+ }
|
|
+ return true;
|
|
+}
|
|
+
|
|
bool oscap_list_push(struct oscap_list *list, void *value)
|
|
{
|
|
return oscap_list_add(list,value);
|
|
diff --git a/src/common/list.h b/src/common/list.h
|
|
index 7a0694dc8a..3179c514f0 100644
|
|
--- a/src/common/list.h
|
|
+++ b/src/common/list.h
|
|
@@ -62,6 +62,7 @@ struct oscap_list *oscap_list_new(void);
|
|
void oscap_create_lists(struct oscap_list **first, ...);
|
|
bool oscap_list_add(struct oscap_list *list, void *value);
|
|
bool oscap_list_push(struct oscap_list *list, void *value);
|
|
+bool oscap_list_prepend(struct oscap_list *list, void *value);
|
|
bool oscap_list_pop(struct oscap_list *list, oscap_destruct_func destructor);
|
|
bool oscap_list_remove(struct oscap_list *list, void *value, oscap_cmp_func compare, oscap_destruct_func destructor);
|
|
struct oscap_list *oscap_list_clone(const struct oscap_list * list, oscap_clone_func cloner);
|
|
diff --git a/tests/API/XCCDF/unittests/CMakeLists.txt b/tests/API/XCCDF/unittests/CMakeLists.txt
|
|
index 52645834c4..9c17ebb78a 100644
|
|
--- a/tests/API/XCCDF/unittests/CMakeLists.txt
|
|
+++ b/tests/API/XCCDF/unittests/CMakeLists.txt
|
|
@@ -75,6 +75,7 @@ add_oscap_test("test_single_rule_stigw.sh")
|
|
add_oscap_test("test_remediation_simple.sh")
|
|
add_oscap_test("test_remediation_offline.sh")
|
|
add_oscap_test("test_remediation_metadata.sh")
|
|
+add_oscap_test("test_remediation_blueprint.sh")
|
|
add_oscap_test("test_remediation_bad_fix.sh")
|
|
add_oscap_test("test_remediation_subs_plain_text.sh")
|
|
add_oscap_test("test_remediation_subs_plain_text_empty.sh")
|
|
diff --git a/tests/API/XCCDF/unittests/test_remediation_blueprint.sh b/tests/API/XCCDF/unittests/test_remediation_blueprint.sh
|
|
new file mode 100755
|
|
index 0000000000..7c79822529
|
|
--- /dev/null
|
|
+++ b/tests/API/XCCDF/unittests/test_remediation_blueprint.sh
|
|
@@ -0,0 +1,27 @@
|
|
+#!/usr/bin/env bash
|
|
+. $builddir/tests/test_common.sh
|
|
+
|
|
+set -e
|
|
+set -o pipefail
|
|
+
|
|
+name=$(basename $0 .sh)
|
|
+result=$(make_temp_file /tmp ${name}.out)
|
|
+stderr=$(make_temp_file /tmp ${name}.out)
|
|
+
|
|
+ret=0
|
|
+
|
|
+input_xml="$srcdir/${name}.xccdf.xml"
|
|
+valid_toml="$srcdir/${name}.toml"
|
|
+
|
|
+echo "Stderr file = $stderr"
|
|
+echo "Result file = $result"
|
|
+[ -f $stderr ]; [ ! -s $stderr ]; :> $stderr
|
|
+
|
|
+# The $valid_toml file was generated without ' # This file was generated by OpenSCAP 1.3.5 using:' line
|
|
+# to make the test independent from the scanner version. We have to filter this line from the output as well.
|
|
+
|
|
+$OSCAP xccdf generate fix --fix-type blueprint --profile 'common' "$input_xml" | grep -v "OpenSCAP" > "$result"
|
|
+
|
|
+diff $valid_toml $result
|
|
+
|
|
+rm "$result"
|
|
diff --git a/tests/API/XCCDF/unittests/test_remediation_blueprint.toml b/tests/API/XCCDF/unittests/test_remediation_blueprint.toml
|
|
new file mode 100644
|
|
index 0000000000..e189adca9d
|
|
--- /dev/null
|
|
+++ b/tests/API/XCCDF/unittests/test_remediation_blueprint.toml
|
|
@@ -0,0 +1,45 @@
|
|
+###############################################################################
|
|
+#
|
|
+# Blueprint for Profile title on one line
|
|
+#
|
|
+# Profile Description:
|
|
+# Profile description
|
|
+#
|
|
+# Profile ID: xccdf_moc.elpmaxe.www_profile_common
|
|
+# Benchmark ID: xccdf_moc.elpmaxe.www_benchmark_test
|
|
+# Benchmark Version: 1.0
|
|
+# XCCDF Version: 1.2
|
|
+#
|
|
+# $ oscap xccdf generate fix --profile xccdf_moc.elpmaxe.www_profile_common --fix-type blueprint xccdf-file.xml
|
|
+#
|
|
+# It attempts to fix every selected rule, even if the system is already compliant.
|
|
+#
|
|
+# How to apply this Blueprint:
|
|
+# composer-cli blueprints push blueprint.toml
|
|
+#
|
|
+###############################################################################
|
|
+
|
|
+name = "xccdf_moc.elpmaxe.www_profile_common"
|
|
+description = "Profile title on one line"
|
|
+version = "1.0"
|
|
+distro = rhel-80
|
|
+
|
|
+[[packages]]
|
|
+name = "aide"
|
|
+version = "*"
|
|
+
|
|
+[[customizations.filesystem]]
|
|
+mountpoint = "/home"
|
|
+size = 1
|
|
+
|
|
+[[customizations.filesystem]]
|
|
+mountpoint = "/tmp"
|
|
+size = 2
|
|
+
|
|
+[customizations.kernel]
|
|
+append = "foo=bar audit=1"
|
|
+
|
|
+[customizations.services]
|
|
+enabled = ["sshd","usbguard"]
|
|
+disabled = ["kdump"]
|
|
+
|
|
diff --git a/tests/API/XCCDF/unittests/test_remediation_blueprint.xccdf.xml b/tests/API/XCCDF/unittests/test_remediation_blueprint.xccdf.xml
|
|
new file mode 100644
|
|
index 0000000000..e685620dac
|
|
--- /dev/null
|
|
+++ b/tests/API/XCCDF/unittests/test_remediation_blueprint.xccdf.xml
|
|
@@ -0,0 +1,102 @@
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
+<Benchmark xmlns="http://checklists.nist.gov/xccdf/1.2" id="xccdf_moc.elpmaxe.www_benchmark_test">
|
|
+ <status>accepted</status>
|
|
+ <version>1.0</version>
|
|
+ <Profile id="xccdf_moc.elpmaxe.www_profile_common">
|
|
+ <title>Profile title on one line</title>
|
|
+ <description>Profile description</description>
|
|
+ <select idref="xccdf_moc.elpmaxe.www_rule_1" selected="true"/>
|
|
+ </Profile>
|
|
+ <Rule selected="true" id="xccdf_moc.elpmaxe.www_rule_1">
|
|
+ <title>Install aide</title>
|
|
+ <fix system="urn:redhat:osbuild:blueprint">
|
|
+[[packages]]
|
|
+name = "aide"
|
|
+version = "*"
|
|
+</fix>
|
|
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
|
|
+ <check-content-ref href="test_remediation_simple.oval.xml" name="oval:moc.elpmaxe.www:def:1"/>
|
|
+ </check>
|
|
+ </Rule>
|
|
+ <Rule selected="true" id="xccdf_moc.elpmaxe.www_rule_2">
|
|
+ <title>Define /home</title>
|
|
+ <fix system="urn:redhat:osbuild:blueprint">
|
|
+[[customizations.filesystem]]
|
|
+mountpoint = "/home"
|
|
+size = 1
|
|
+</fix>
|
|
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
|
|
+ <check-content-ref href="test_remediation_simple.oval.xml" name="oval:moc.elpmaxe.www:def:1"/>
|
|
+ </check>
|
|
+ </Rule>
|
|
+ <Rule selected="true" id="xccdf_moc.elpmaxe.www_rule_3">
|
|
+ <title>Add audit=1 kernel option</title>
|
|
+ <fix system="urn:redhat:osbuild:blueprint">
|
|
+[customizations.kernel]
|
|
+append = "audit=1"
|
|
+</fix>
|
|
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
|
|
+ <check-content-ref href="test_remediation_simple.oval.xml" name="oval:moc.elpmaxe.www:def:1"/>
|
|
+ </check>
|
|
+ </Rule>
|
|
+ <Rule selected="true" id="xccdf_moc.elpmaxe.www_rule_4">
|
|
+ <title>Add foo=bar kernel option</title>
|
|
+ <fix system="urn:redhat:osbuild:blueprint">
|
|
+[customizations.kernel]
|
|
+append = "foo=bar"
|
|
+</fix>
|
|
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
|
|
+ <check-content-ref href="test_remediation_simple.oval.xml" name="oval:moc.elpmaxe.www:def:1"/>
|
|
+ </check>
|
|
+ </Rule>
|
|
+ <Rule selected="true" id="xccdf_moc.elpmaxe.www_rule_5">
|
|
+ <title>Define /tmp</title>
|
|
+ <fix system="urn:redhat:osbuild:blueprint">
|
|
+[[customizations.filesystem]]
|
|
+mountpoint = "/tmp"
|
|
+size = 2
|
|
+</fix>
|
|
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
|
|
+ <check-content-ref href="test_remediation_simple.oval.xml" name="oval:moc.elpmaxe.www:def:1"/>
|
|
+ </check>
|
|
+ </Rule>
|
|
+ <Rule selected="true" id="xccdf_moc.elpmaxe.www_rule_6">
|
|
+ <title>Enable usbguard</title>
|
|
+ <fix system="urn:redhat:osbuild:blueprint">
|
|
+[customizations.services]
|
|
+enabled = ["usbguard"]
|
|
+</fix>
|
|
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
|
|
+ <check-content-ref href="test_remediation_simple.oval.xml" name="oval:moc.elpmaxe.www:def:1"/>
|
|
+ </check>
|
|
+ </Rule>
|
|
+ <Rule selected="true" id="xccdf_moc.elpmaxe.www_rule_7">
|
|
+ <title>Disable kdump</title>
|
|
+ <fix system="urn:redhat:osbuild:blueprint">
|
|
+[customizations.services]
|
|
+disabled = ["kdump"]
|
|
+</fix>
|
|
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
|
|
+ <check-content-ref href="test_remediation_simple.oval.xml" name="oval:moc.elpmaxe.www:def:1"/>
|
|
+ </check>
|
|
+ </Rule>
|
|
+ <Rule selected="true" id="xccdf_moc.elpmaxe.www_rule_8">
|
|
+ <title>Set distro (RHEL 8.0)</title>
|
|
+ <fix system="urn:redhat:osbuild:blueprint">
|
|
+distro = rhel-80
|
|
+</fix>
|
|
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
|
|
+ <check-content-ref href="test_remediation_simple.oval.xml" name="oval:moc.elpmaxe.www:def:1"/>
|
|
+ </check>
|
|
+ </Rule>
|
|
+ <Rule selected="true" id="xccdf_moc.elpmaxe.www_rule_9">
|
|
+ <title>Enable sshd</title>
|
|
+ <fix system="urn:redhat:osbuild:blueprint">
|
|
+[customizations.services]
|
|
+enabled = ["sshd"]
|
|
+</fix>
|
|
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
|
|
+ <check-content-ref href="test_remediation_simple.oval.xml" name="oval:moc.elpmaxe.www:def:1"/>
|
|
+ </check>
|
|
+ </Rule>
|
|
+</Benchmark>
|