Skip to content

Commit

Permalink
Add --raw switch to xccdf generate fix module
Browse files Browse the repository at this point in the history
The option would allow the user to generate fix scripts
without headers and boilerplate. Currently implemented
for Kickstart remediation type.
  • Loading branch information
evgenyz committed Aug 12, 2024
1 parent fbf3e3c commit 23f655a
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/XCCDF_POLICY/public/xccdf_policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ OSCAP_API bool xccdf_policy_resolve(struct xccdf_policy * policy);
* @param output_fd write prescription to this file descriptor
* @returns zero on success, non-zero indicate partial (incomplete) output.
*/
OSCAP_API int xccdf_policy_generate_fix(struct xccdf_policy *policy, struct xccdf_result *result, const char *sys, const char *input_file_name, struct oscap_source *tailoring, int output_fd);
OSCAP_API int xccdf_policy_generate_fix(struct xccdf_policy *policy, struct xccdf_result *result, const char *sys, const char *input_file_name, struct oscap_source *tailoring, int output_fd, int raw);

/**
* xccdf_policy_model_get_files and xccdf_item_get_files each return oscap_file_entries instead of raw strings
Expand Down
43 changes: 24 additions & 19 deletions src/XCCDF_POLICY/xccdf_policy_remediate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1749,7 +1749,7 @@ static void logvol_cmd_free(void *ptr)
free(cmd);
}

static int _xccdf_policy_generate_fix_kickstart(struct oscap_list *rules_to_fix, struct xccdf_policy *policy, const char *sys, const char *input_file_name, struct oscap_source *tailoring, int output_fd)
static int _xccdf_policy_generate_fix_kickstart(struct oscap_list *rules_to_fix, struct xccdf_policy *policy, const char *sys, const char *input_file_name, struct oscap_source *tailoring, int raw, int output_fd)
{
int ret = 0;
struct kickstart_commands cmds = {
Expand All @@ -1775,9 +1775,8 @@ static int _xccdf_policy_generate_fix_kickstart(struct oscap_list *rules_to_fix,
}
oscap_iterator_free(rules_to_fix_it);

_write_text_to_fd(output_fd, "\n");
const char *common_template = (
"# Default values for automated installation\n"
"\n# Default values for automated installation\n"
"lang en_US.UTF-8\n"
"keyboard --vckeymap us\n"
"timezone --utc America/New_York\n"
Expand All @@ -1786,11 +1785,13 @@ static int _xccdf_policy_generate_fix_kickstart(struct oscap_list *rules_to_fix,
"rootpw %s\n"
"\n"
);
char *password = oscap_generate_random_string(24, NULL);
char *common = oscap_sprintf(common_template, password);
_write_text_to_fd(output_fd, common);
free(password);
free(common);
if (raw == 0) {
char *password = oscap_generate_random_string(24, NULL);
char *common = oscap_sprintf(common_template, password);
_write_text_to_fd(output_fd, common);
free(password);
free(common);
}

_generate_kickstart_pre(&cmds, output_fd);

Expand All @@ -1811,7 +1812,8 @@ static int _xccdf_policy_generate_fix_kickstart(struct oscap_list *rules_to_fix,

_generate_kickstart_post(&cmds, output_fd);

_write_text_to_fd(output_fd, "# Reboot after the installation is complete\nreboot\n");
if (raw == 0)
_write_text_to_fd(output_fd, "# Reboot after the installation is complete\nreboot\n");

oscap_list_free(cmds.package_install, free);
oscap_list_free(cmds.package_remove, free);
Expand All @@ -1826,7 +1828,7 @@ static int _xccdf_policy_generate_fix_kickstart(struct oscap_list *rules_to_fix,
return ret;
}

int xccdf_policy_generate_fix(struct xccdf_policy *policy, struct xccdf_result *result, const char *sys, const char *input_file_name, struct oscap_source *tailoring, int output_fd)
int xccdf_policy_generate_fix(struct xccdf_policy *policy, struct xccdf_result *result, const char *sys, const char *input_file_name, struct oscap_source *tailoring, int output_fd, int raw)
{
__attribute__nonnull__(policy);
int ret = 0;
Expand All @@ -1844,10 +1846,11 @@ int xccdf_policy_generate_fix(struct xccdf_policy *policy, struct xccdf_result *
return 1;
}

if (_write_script_header_to_fd(policy, result, sys, input_file_name, tailoring_file_name, output_fd) != 0) {
oscap_list_free(rules_to_fix, NULL);
return 1;
}
if (raw == 0)
if (_write_script_header_to_fd(policy, result, sys, input_file_name, tailoring_file_name, output_fd) != 0) {
oscap_list_free(rules_to_fix, NULL);
return 1;
}

struct xccdf_item_iterator *item_it = xccdf_benchmark_get_content(benchmark);
while (xccdf_item_iterator_has_more(item_it)) {
Expand All @@ -1861,10 +1864,11 @@ int xccdf_policy_generate_fix(struct xccdf_policy *policy, struct xccdf_result *
else {
dI("Generating result-oriented fixes for policy(result/@id=%s)", xccdf_result_get_id(result));

if (_write_script_header_to_fd(policy, result, sys, input_file_name, tailoring_file_name, output_fd) != 0) {
oscap_list_free(rules_to_fix, NULL);
return 1;
}
if (raw == 0)
if (_write_script_header_to_fd(policy, result, sys, input_file_name, tailoring_file_name, output_fd) != 0) {
oscap_list_free(rules_to_fix, NULL);
return 1;
}

struct xccdf_rule_result_iterator *rr_it = xccdf_result_get_rule_results(result);
while (xccdf_rule_result_iterator_has_more(rr_it)) {
Expand All @@ -1884,7 +1888,7 @@ int xccdf_policy_generate_fix(struct xccdf_policy *policy, struct xccdf_result *
} else if (strcmp(sys, "urn:redhat:osbuild:blueprint") == 0) {
ret = _xccdf_policy_generate_fix_blueprint(rules_to_fix, policy, sys, output_fd);
} else if (strcmp(sys, "urn:xccdf:fix:script:kickstart") == 0) {
ret = _xccdf_policy_generate_fix_kickstart(rules_to_fix, policy, sys, input_file_name, tailoring, output_fd);
ret = _xccdf_policy_generate_fix_kickstart(rules_to_fix, policy, sys, input_file_name, tailoring, raw, output_fd);
} else {
ret = _xccdf_policy_generate_fix_other(rules_to_fix, policy, sys, output_fd);
}
Expand All @@ -1893,3 +1897,4 @@ int xccdf_policy_generate_fix(struct xccdf_policy *policy, struct xccdf_result *

return ret;
}

1 change: 1 addition & 0 deletions tests/API/XCCDF/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,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_kickstart.sh")
add_oscap_test("test_remediation_kickstart_raw.sh")
add_oscap_test("test_remediation_metadata.sh")
add_oscap_test("test_remediation_blueprint.sh")
add_oscap_test("test_remediation_bad_fix.sh")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Create partition layout scheme (required for security compliance)
zerombr
clearpart --all --initlabel
reqpart --add-boot
part pv.01 --grow --size=1
volgroup system pv.01
logvol / --name=root --vgname=system --size=2000 --grow
logvol swap --name=swap --vgname=system --size=1000
logvol /var/tmp --name=vartmp --vgname=system --size=1024

# Configure boot loader options (required for security compliance)
bootloader --append="quick audit=1"

# Disable the kdump kernel crash dumping mechanism (required for security compliance)
%addon com_redhat_kdump --disable
%end

# Disable and enable services in firewall (required for security compliance)
firewall --remove-service=httpd --service=sshd

# Disable and enable systemd services (required for security compliance)
services --disabled=telnet,httpd --enabled=auditd,rsyslog,sshd

# Packages selection (required for security compliance)
%packages
openscap-scanner
scap-security-guide
rsyslog
openssh-server
podman
-usbguard
%end

# Perform OpenSCAP hardening (required for security compliance)
%post --erroronfail
oscap xccdf eval --remediate --results-arf /root/oscap_arf.xml --report /root/oscap_report.html --profile 'xccdf_org.openscap.www_profile_common' /usr/share/xml/scap/ssg/content/test_remediation_kickstart.ds.xml
[ $? -eq 0 -o $? -eq 2 ] || exit 1
%end

# Additional %post section (required for security compliance)
%post --nochroot
mkdir -p /etc/ddfds
%end

# Additional %post section (required for security compliance)
%post --nochroot
mkdir -p /etc/abcd
%end

# Additional %post section (required for security compliance)
%post
rm -rf /etc/xyz
# create a new path
feel /etc/xyz
%end

23 changes: 23 additions & 0 deletions tests/API/XCCDF/unittests/test_remediation_kickstart_raw.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
. $builddir/tests/test_common.sh

set -e -o pipefail

function test_raw {
kickstart=$(mktemp)
stderr=$(mktemp)
expected_modified=$(mktemp)

sed "s;TEST_DATA_STREAM_PATH;$srcdir/test_remediation_kickstart.ds.xml;" "$srcdir/test_remediation_kickstart_expected_raw.cfg" > "$expected_modified"

$OSCAP xccdf generate fix --fix-type kickstart --raw --output "$kickstart" --profile common "$srcdir/test_remediation_kickstart.ds.xml"

diff -u "$expected_modified" "$kickstart"

rm -rf "$kickstart"
rm -rf "$stderr"
rm -rf "$expected_modified"
rm -rf "$kickstart_modified"
}

test_raw
1 change: 1 addition & 0 deletions utils/oscap-tool.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ struct oscap_action {
char *local_files;
char *reference;
int references;
int raw;
};

int app_xslt(const char *infile, const char *xsltfile, const char *outfile, const char **params);
Expand Down
8 changes: 5 additions & 3 deletions utils/oscap-xccdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ static struct oscap_module XCCDF_GEN_FIX = {
" --fix-type <type> - Fix type. Should be one of: bash, ansible, puppet, anaconda, ignition, kubernetes,\n"
" blueprint, kickstart (default: bash).\n"
" --output <file> - Write the script into file.\n"
" --raw - Don't write extra headers or boilerplate instructions, only compose the content snippets.\n"
" --result-id <id> - Fixes will be generated for failed rule-results of the specified TestResult.\n"
" --benchmark-id <id> - ID of XCCDF Benchmark in some component in the data stream that should be used.\n"
" (only applicable for source data streams)\n"
Expand Down Expand Up @@ -1041,7 +1042,7 @@ int app_generate_fix(const struct oscap_action *action)

struct xccdf_policy *policy = xccdf_session_get_xccdf_policy(session);
struct xccdf_result *result = xccdf_policy_get_result_by_id(policy, xccdf_session_get_result_id(session));
if (xccdf_policy_generate_fix(policy, result, remediation_system, action->f_xccdf, tailoring, output_fd) == 0)
if (xccdf_policy_generate_fix(policy, result, remediation_system, action->f_xccdf, tailoring, output_fd, action->raw) == 0)
ret = OSCAP_OK;
} else { // Fallback to profile if result id is missing
/* Profile-oriented fixes */
Expand All @@ -1055,7 +1056,7 @@ int app_generate_fix(const struct oscap_action *action)
}
}
struct xccdf_policy *policy = xccdf_session_get_xccdf_policy(session);
if (xccdf_policy_generate_fix(policy, NULL, remediation_system, action->f_xccdf, tailoring, output_fd) == 0)
if (xccdf_policy_generate_fix(policy, NULL, remediation_system, action->f_xccdf, tailoring, output_fd, action->raw) == 0)
ret = OSCAP_OK;
}
cleanup2:
Expand Down Expand Up @@ -1243,8 +1244,9 @@ bool getopt_xccdf(int argc, char **argv, struct oscap_action *action)
{"hide-profile-info", no_argument, &action->hide_profile_info, 1},
{"export-variables", no_argument, &action->export_variables, 1},
{"skip-schematron", no_argument, &action->schematron, 0},
{"without-syschar", no_argument, &action->without_sys_chars, 1},
{"without-syschar", no_argument, &action->without_sys_chars, 1},
{"thin-results", no_argument, &action->thin_results, 1},
{"raw", no_argument, &action->raw, 1},
// end
{0, 0, 0, 0}
};
Expand Down

0 comments on commit 23f655a

Please sign in to comment.