diff --git a/shared/macros/10-bash.jinja b/shared/macros/10-bash.jinja index 44642ab1ea8..f52ae185b41 100644 --- a/shared/macros/10-bash.jinja +++ b/shared/macros/10-bash.jinja @@ -1465,6 +1465,22 @@ cce="{{{ cce_identifiers['cce'] }}}" {{%- endmacro -%}} +{{# + Ensure file ends with newline + + Do not modify file at all if there already is newline. Always follows + symlinks. + + :param file: file to check +#}} +{{%- macro bash_ensure_nl_at_eof(file) -%}} +{{#- Plain sed '$a\' updates stat even if it dones not change the file. -#}} +if [[ -s "{{{ file }}}" ]] && [[ -n "$(tail -c 1 -- "{{{ file }}}" || true)" ]]; then + LC_ALL=C sed -i --follow-symlinks '$a'\\ "{{{ file }}}" +fi +{{%- endmacro -%}} + + {{# Macro to replace configuration setting in config file or add the configuration setting if it does not exist. @@ -1491,14 +1507,6 @@ cce="{{{ cce_identifiers['cce'] }}}" #}} {{%- macro bash_replace_or_append(config_file, key, value, format='%s = %s') -%}} - -# Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed. -# Otherwise, regular sed command will do. -sed_command=('sed' '-i') -if test -L "{{{ config_file }}}"; then - sed_command+=('--follow-symlinks') -fi - # Strip any search characters in the key arg so that the key can be replaced without # adding any search characters to the config file. stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "{{{ key }}}") @@ -1511,12 +1519,12 @@ printf -v formatted_output "{{{ format }}}" "$stripped_key" "{{{ value }}}" # so if we search for 'setting', 'setting2' won't match. if LC_ALL=C grep -q -m 1 -i -e "{{{ key }}}\\>" "{{{ config_file }}}"; then escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output") - "${sed_command[@]}" "s/{{{ key }}}\\>.*/$escaped_formatted_output/gi" "{{{ config_file }}}" + LC_ALL=C sed -i --follow-symlinks "s/{{{ key }}}\\>.*/$escaped_formatted_output/gi" "{{{ config_file }}}" else - # \n is precaution for case where file ends without trailing newline - {{% if cce_identifiers and 'cce' in cce_identifiers -%}} + {{{ bash_ensure_nl_at_eof(config_file) | indent }}} + {{%- if cce_identifiers and 'cce' in cce_identifiers %}} {{{ set_cce_value() }}} - printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "{{{ config_file }}}" >> "{{{ config_file }}}" + printf '# Per %s: Set %s in %s\n' "${cce}" "${formatted_output}" "{{{ config_file }}}" >> "{{{ config_file }}}" {{%- endif %}} printf '%s\n' "$formatted_output" >> "{{{ config_file }}}" fi diff --git a/tests/unit/bash/bash_os_linux_conditional.bats.jinja b/tests/unit/bash/bash_os_linux_conditional.bats.jinja index c7d7c7a53ba..c25a4500627 100644 --- a/tests/unit/bash/bash_os_linux_conditional.bats.jinja +++ b/tests/unit/bash/bash_os_linux_conditional.bats.jinja @@ -1,8 +1,46 @@ #!/bin/bash -@test "bash_os_linux_conditional - test OS release - RHEL" { - os_release_path="$(mktemp)" +set -pu + +is_old_bats=0 + +setup() { + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + BATS_TEST_TMPDIR="$(mktemp -d)" # 1.4.0 + # shellcheck disable=SC2034 + BATS_TEARDOWN_STARTED= # 1.3.0 + is_old_bats=1 + else + is_old_bats=0 + fi + pushd "${BATS_TEST_TMPDIR}" || exit 1 + os_release_path="os-release" +} + +teardown() { + if (( is_old_bats )); then + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + local tmppath xpwd + tmppath="$(readlink -f -- "${BATS_TEST_TMPDIR}")" + if [[ ! "${tmppath}" =~ ^/tmp/ ]] || [[ ! -d "${tmppath}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + xpwd="$(readlink -f -- .)" + if [[ "${tmppath}" != "${xpwd}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + popd || exit 1 + rm -rf -- "${tmppath}" + BATS_TEST_TMPDIR="" + fi +} +@test "bash_os_linux_conditional - test OS release - RHEL" { cat << EOF > "$os_release_path" NAME="Red Hat Enterprise Linux" VERSION="9.2 (Plow)" @@ -42,13 +80,9 @@ EOF ! ( {{{ bash_os_linux_conditional("fedora", "38", "==", "$os_release_path") }}} ) ! ( {{{ bash_os_linux_conditional("fedora", "9.2", "==", "$os_release_path") }}} ) ! ( {{{ bash_os_linux_conditional("fedora", "9.4", "<", "$os_release_path") }}} ) - - rm -rf "$os_release_path" } @test "bash_os_linux_conditional - test OS release - Ubuntu" { - os_release_path="$(mktemp)" - cat << EOF > "$os_release_path" PRETTY_NAME="Ubuntu 22.04.1 LTS" NAME="Ubuntu" @@ -82,6 +116,4 @@ EOF ! ( {{{ bash_os_linux_conditional("fedora", "38", "==", "$os_release_path") }}} ) ! ( {{{ bash_os_linux_conditional("fedora", "22.10", "<", "$os_release_path") }}} ) - - rm -rf "$os_release_path" } diff --git a/tests/unit/bash/bash_pkg_conditional_rpm.bats.jinja b/tests/unit/bash/bash_pkg_conditional_rpm.bats.jinja index b7037be0f31..71557ddbc75 100644 --- a/tests/unit/bash/bash_pkg_conditional_rpm.bats.jinja +++ b/tests/unit/bash/bash_pkg_conditional_rpm.bats.jinja @@ -1,5 +1,7 @@ #!/bin/bash +set -pu + # Mock the "rpm" command # mocked package: coconut-4.5.17 # The mock is used to avoid the need to have a specific RPM package in a diff --git a/tests/unit/bash/execute_tests.sh b/tests/unit/bash/execute_tests.sh index adb14638428..1766ddaebb4 100755 --- a/tests/unit/bash/execute_tests.sh +++ b/tests/unit/bash/execute_tests.sh @@ -1,10 +1,90 @@ #!/bin/bash -PYTHON_EXECUTABLE="$1" -TESTS_ROOT="$2" -TESTDIR="$3" -OUTDIR="$4" +set -epu -mkdir -p "$OUTDIR" +usage() { + printf "Usage: %s [OPTIONS] PYTHON_EXECUTABLE TESTS_ROOT TESTDIR OUTDIR [bats opts]" "${0##/}" + printf " %s [--help]" "${0##/}" + printf "\nOPTIONS\n" + printf " --verbose\n" + printf " --quiet\n" + printf " --debug\n" + printf " --parallel | --no-parallel\n" + printf " --\n" +} -PYTHONPATH="$TESTS_ROOT/.." ${PYTHON_EXECUTABLE} "$TESTS_ROOT/../build-scripts/expand_jinja.py" --outdir "$OUTDIR" $TESTDIR/*.jinja && bats "$OUTDIR" +OPT_debug=0 +OPT_parallel=0 +if [[ -x /usr/bin/parallel ]]; then + OPT_parallel=1 +fi + +OPT_verbose=1 +while (( $# )); do + case "$1" in + --verbose) (( OPT_verbose++, 1 )); shift ;; + --quiet) OPT_verbose=0; shift ;; + --debug) set -x; OPT_debug=1; shift ;; + + --parallel) OPT_parallel=1; shift ;; + --no[_-]parallel) OPT_parallel=0; shift ;; + + --help) usage; exit 2 ;; + --) shift; break ;; + + *) break ;; + esac +done + +bats_version="$(bats -v)" || : +case "${bats_version##* }" in + # Debian 10 v0.4.0 + # Usage: bats [-c] [-p | -t] + ""|"0."*|"1.0."*|"1.1."*) + OPT_parallel=0 + OPT_verbose=0 + OPT_debug=0 + ;; + # Ubuntu 22.04 + # Error: Bad command line option '--print-output-on-failure' + "1.2."*|"1.3."*|"1.4."*) + OPT_verbose=0 + OPT_debug=0 + ;; +esac + +PYTHON_EXECUTABLE="$1"; shift +TESTS_ROOT="$1"; shift +TESTDIR="$1"; shift +OUTDIR="$1"; shift + +mkdir -p "${OUTDIR}" + +bats_opts=() + +if (( OPT_parallel )); then + bats_opts+=(--jobs "$(nproc)") # 1.2.0 +fi + +if (( OPT_verbose > 1 )); then + bats_opts+=(--verbose-run) # 1.5.0 +elif (( OPT_verbose == 1 )); then + bats_opts+=(--print-output-on-failure) # 1.5.0 +fi + +if (( OPT_debug )); then + bats_opts+=( + --no-tempdir-cleanup # 1.4.0 + --trace # 1.5.0 + ) +fi + +rc=0 +PYTHONPATH="${TESTS_ROOT}/.." ${PYTHON_EXECUTABLE} \ +"${TESTS_ROOT}/../build-scripts/expand_jinja.py" --outdir "${OUTDIR}" \ + "${TESTDIR}"/*.jinja || rc=$? +if (( rc )); then + >&2 echo "ERROR: expand_jinja.py could not create bats files" + exit "${rc}" +fi +bats "${bats_opts[@]}" "$@" "${OUTDIR}" diff --git a/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja b/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja index 227411ba71d..b680fc939c0 100644 --- a/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja +++ b/tests/unit/bash/test_bash_ensure_ini_config.bats.jinja @@ -1,12 +1,50 @@ #!/bin/bash +set -pu function call_bash_ensure_ini_config { {{{ bash_ensure_ini_config("$1", "$2", "$3", "$4") | indent(4) }}} } +is_old_bats=0 + +setup() { + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + BATS_TEST_TMPDIR="$(mktemp -d)" # 1.4.0 + # shellcheck disable=SC2034 + BATS_TEARDOWN_STARTED= # 1.3.0 + is_old_bats=1 + else + is_old_bats=0 + fi + pushd "${BATS_TEST_TMPDIR}" || exit 1 + mkdir -p sssd_test +} + +teardown() { + if (( is_old_bats )); then + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + local tmppath xpwd + tmppath="$(readlink -f -- "${BATS_TEST_TMPDIR}")" + if [[ ! "${tmppath}" =~ ^/tmp/ ]] || [[ ! -d "${tmppath}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + xpwd="$(readlink -f -- .)" + if [[ "${tmppath}" != "${xpwd}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + popd || exit 1 + rm -rf -- "${tmppath}" + BATS_TEST_TMPDIR="" + fi +} + @test "bash_ensure_ini_config - Basic value remediation" { - mkdir sssd_test printf "[pam]\npam_cert_auth = false\n" > sssd_test/sssd.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -14,12 +52,9 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } @test "bash_ensure_ini_config - Value remediation in multiple files" { - mkdir sssd_test printf "[pam]\npam_cert_auth = false\n" > sssd_test/sssd.conf printf "[pam]\npam_cert_auth = false\n" > pam_cert_auth.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -31,13 +66,9 @@ function call_bash_ensure_ini_config { run diff "pam_cert_auth.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm pam_cert_auth.conf - rm -rf sssd_test } @test "bash_ensure_ini_config - No remediation happened" { - mkdir sssd_test printf "[pam]\npam_cert_auth = true\n" > sssd_test/sssd.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -45,12 +76,9 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } @test "bash_ensure_ini_config - Append section with option to empty file" { - mkdir sssd_test printf "" > sssd_test/sssd.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -58,8 +86,6 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } @test "bash_ensure_ini_config - Create file with section and option" { @@ -69,12 +95,9 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } @test "bash_ensure_ini_config - Append option to section" { - mkdir sssd_test printf "[pam]\n" > sssd_test/sssd.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -82,12 +105,9 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } @test "bash_ensure_ini_config - Append option to section when section is substring of option" { - mkdir sssd_test printf "[pam]\n" > sssd_test/sssd.conf expected_output="[pam]\npam_verbosity = 1\npam_cert_auth = true\n" @@ -95,14 +115,10 @@ function call_bash_ensure_ini_config { call_bash_ensure_ini_config "sssd_test/sssd.conf" "pam" "pam_verbosity" "1" run diff "sssd_test/sssd.conf" <(printf "$expected_output") - - rm -rf sssd_test - [ "$status" -eq 0 ] } @test "bash_ensure_ini_config - Append option to section in multiple files" { - mkdir sssd_test printf "[pam]\n" > sssd_test/sssd.conf printf "[pam]\n" > pam_cert_auth.conf expected_output="[pam]\npam_cert_auth = true\n" @@ -111,16 +127,12 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - + run diff "pam_cert_auth.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm pam_cert_auth.conf - rm -rf sssd_test } @test "bash_ensure_ini_config - Append section with option to non-empty file" { - mkdir sssd_test printf "[section]\nkey = value\n" > sssd_test/sssd.conf expected_output="[section]\nkey = value\n[pam]\npam_cert_auth = true\n" @@ -128,6 +140,4 @@ function call_bash_ensure_ini_config { run diff "sssd_test/sssd.conf" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm -rf sssd_test } diff --git a/tests/unit/bash/test_bash_replace_or_append.bats.jinja b/tests/unit/bash/test_bash_replace_or_append.bats.jinja index 138ae4c0f2b..9df981d4e9b 100644 --- a/tests/unit/bash/test_bash_replace_or_append.bats.jinja +++ b/tests/unit/bash/test_bash_replace_or_append.bats.jinja @@ -1,5 +1,6 @@ #!/bin/bash +set -pu function call_bash_replace_or_append { {{{ bash_replace_or_append("$1", "$2", "$3") | indent(4) }}} @@ -9,8 +10,46 @@ function call_bash_replace_or_append_w_format { {{{ bash_replace_or_append("$1", "$2", "$3", "$4") | indent(4) }}} } +is_old_bats=0 + +setup() { + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + BATS_TEST_TMPDIR="$(mktemp -d)" # 1.4.0 + # shellcheck disable=SC2034 + BATS_TEARDOWN_STARTED= # 1.3.0 + is_old_bats=1 + else + is_old_bats=0 + fi + pushd "${BATS_TEST_TMPDIR}" || exit 1 + tmp_file=test.sh + touch "$tmp_file" +} + +teardown() { + if (( is_old_bats )); then + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + local tmppath xpwd + tmppath="$(readlink -f -- "${BATS_TEST_TMPDIR}")" + if [[ ! "${tmppath}" =~ ^/tmp/ ]] || [[ ! -d "${tmppath}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + xpwd="$(readlink -f -- .)" + if [[ "${tmppath}" != "${xpwd}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + popd || exit 1 + rm -rf -- "${tmppath}" + BATS_TEST_TMPDIR="" + fi +} + @test "bash_replace_or_append - Basic value remediation" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_space = 5" > "$tmp_file" expected_output="kernel.randomize_va_space = 2\n" @@ -18,12 +57,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - No remediation happened" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_space = 2" > "$tmp_file" expected_output="kernel.randomize_va_space = 2\n" @@ -31,12 +67,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Append key to empty file" { - tmp_file="$(mktemp)" printf "" > "$tmp_file" expected_output="kernel.randomize_va_space = 2\n" @@ -44,12 +77,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Append key to non-empty file" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_fake = 5" > "$tmp_file" expected_output="kernel.randomize_va_fake = 5\nkernel.randomize_va_space = 2\n" @@ -57,12 +87,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Remediation with format" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_space=5" > "$tmp_file" expected_output="kernel.randomize_va_space=2\n" @@ -70,12 +97,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - No remediation with format" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_space=2" > "$tmp_file" expected_output="kernel.randomize_va_space=2\n" @@ -83,12 +107,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Append key with format to empty file" { - tmp_file="$(mktemp)" printf "" > "$tmp_file" expected_output="kernel.randomize_va_space=2\n" @@ -96,12 +117,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Append key with format to non-empty file" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.randomize_va_fake=5" > "$tmp_file" expected_output="kernel.randomize_va_fake=5\nkernel.randomize_va_space=2\n" @@ -109,12 +127,9 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "bash_replace_or_append - Remediate value containing forward slash" { - tmp_file="$(mktemp)" printf "%s\n" "kernel.core_pattern=|/bin/true" > "$tmp_file" expected_output="kernel.core_pattern=|/bin/false\n" @@ -122,6 +137,873 @@ function call_bash_replace_or_append_w_format { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] +} + +@test "bash_replace_or_append - Key prefix remediation" { + printf "kernel.randomize_va_space = 5\nakernel.randomize_va_space = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\nakernel.randomize_va_space = 5\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Key suffix remediation" { + printf "kernel.randomize_va_space = 5\nkernel.randomize_va_space2 = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\nkernel.randomize_va_space2 = 5\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Key ending with . remediation" { + skip "Implementation needs to have word_boundary" + printf "kernel.randomize_va_space. = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space. = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space.' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Key contains * with remediation" { + skip "Implementation does not quote regexps properly despite skipped_key functionality" + printf "kernel.randomize_va_space. = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space. = 5\nkernel.* = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.*' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Commented remediation" { + printf "kernel.randomize_va_space = 5\n# kernel.randomize_va_space = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n# kernel.randomize_va_space = 5\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Case insensitive key remediation" { + printf "KERNEL.RANDOMIZE_VA_SPACE = 5\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Case sensitive value remediation" { + printf "kernel.randomize_va_space = FOO\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = foo\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' 'foo' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Case insensitive key, remediation happened 3 times" { + printf "kernel.randomize_va_space = foo\nKERNEL.RANDOMIZE_VA_SPACE = 2\nkernel.randomize_va_space = foo\n" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\nkernel.randomize_va_space = 2\nkernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - No file before" { + rm "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Fail if not file" { + skip "bash_replace_or_append does not handle situation where final target is not creatable/readable/writable file" + rm "${tmp_file}" + mkdir -p "${tmp_file}" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Is symlink missing" { + ln -s "${tmp_file}" symlink.sh + rm "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "symlink.sh" '^kernel.randomize_va_space' '2' + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] + [ -L symlink.sh ] + [ -f "${tmp_file}" ] +} + +@test "bash_replace_or_append - Is symlink empty" { + ln -s "${tmp_file}" symlink.sh + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "symlink.sh" '^kernel.randomize_va_space' '2' + [ -L symlink.sh ] + [ -f "${tmp_file}" ] + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Is symlink remediation" { + printf "foo\n%s\nbar\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + ln -s "${tmp_file}" symlink.sh + expected_output="foo\nkernel.randomize_va_space = 2\nbar\n" + + call_bash_replace_or_append "symlink.sh" '^kernel.randomize_va_space' '2' + [ -L symlink.sh ] + [ -f "${tmp_file}" ] + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Filename contains space" { + tmp_file="${tmp_file} " + printf "%s\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Filename contains tab" { + tmp_file="$(printf "\t%s" "${tmp_file}")" + printf "%s\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Filename contains newline" { + tmp_file="$(printf "%s\n" "${tmp_file}")" + printf "%s\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test 'bash_replace_or_append - Filename contains \$(touch foo)' { + tmp_file+=$'$(touch foo)' + printf "%s\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [[ ${tmp_file} =~ foo ]] + [ "${status}" -eq 0 ] + [ ! -f foo ] +} + +@test 'bash_replace_or_append - Filename contains \`touch foo\`' { + tmp_file+=$'`touch foo`' + printf "%s\n" "kernel.randomize_va_space = 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space = 2\n" + + call_bash_replace_or_append "${tmp_file}" '^kernel.randomize_va_space' '2' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [[ ${tmp_file} =~ foo ]] + [ "${status}" -eq 0 ] + [ ! -f foo ] +} + +@test "bash_replace_or_append - Remediate value emtpy" { + printf "%s\n" "kernel.core_pattern=|/bin/true" > "${tmp_file}" + expected_output="kernel.core_pattern=\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.core_pattern' '' '%s=%s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediation with format space" { + printf "%s\n" "kernel.randomize_va_space 5" > "${tmp_file}" + expected_output="kernel.randomize_va_space 2\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.randomize_va_space' '2' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - No remediation with format space" { + printf "%s\n" "kernel.randomize_va_space 2" > "${tmp_file}" + expected_output="kernel.randomize_va_space 2\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.randomize_va_space' '2' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Append key with format to empty file format space" { + printf "" > "${tmp_file}" + expected_output="kernel.randomize_va_space 2\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.randomize_va_space' '2' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Append key with format to non-empty file format space" { + printf "%s\n" "kernel.randomize_va_fake 5" > "${tmp_file}" + expected_output="kernel.randomize_va_fake 5\nkernel.randomize_va_space 2\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.randomize_va_space' '2' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing forward slash format space" { + printf "%s\n" "kernel.core_pattern |/bin/true" > "${tmp_file}" + expected_output="kernel.core_pattern |/bin/false\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.core_pattern' '|/bin/false' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value emtpy format space" { + printf "%s\n" "kernel.core_pattern |/bin/true" > "${tmp_file}" + expected_output="kernel.core_pattern \n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.core_pattern' '' '%s %s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value emtpy format tab" { + printf "kernel.core_pattern\t|/bin/true\n" > "${tmp_file}" + expected_output="kernel.core_pattern\t\n" + + call_bash_replace_or_append_w_format "${tmp_file}" '^kernel.core_pattern' '' '%s\t%s' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate file previously not ending with newline" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}=${value}\n" + + # This way variable value is not trimmed at end and we can test \n etc + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate file previously ending with space" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s " + key_fmt="^%s" + value_fmt="%s" + expected_output="${before} \n${key}=${value}\n" + + # This way variable value is not trimmed at end and we can test \n etc + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate file previously ending with tab" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\t" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\t\n${key}=${value}\n" + + # This way variable value is not trimmed at end and we can test \n etc + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing newline prefix" { + skip "Value newline trim not implemented." + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="\n%s" + expected_output="${before}\n${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing newline suffix" { + skip "Value newline trim not implemented." + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s\n" + expected_output="${before}\n${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing multiple newlines prefix and suffix" { + skip "Value newline trim not implemented." + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="\n\n%s\n\n" + expected_output="${before}\n${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing space prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt=" %s" + expected_output="${before}\n${key}= ${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing space suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s " + expected_output="${before}\n${key}=${value} \n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing multiple spaces prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt=" %s " + expected_output="${before}\n${key}= ${value} \n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing tab prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="\t%s" + expected_output="${before}\n${key}=\t${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing tab suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s\t" + expected_output="${before}\n${key}=${value}\t\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate value containing multiple tab prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="\t\t%s\t\t" + expected_output="${before}\n${key}=\t\t${value}\t\t\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing space prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^ %s" + value_fmt="%s" + expected_output="${before}\n ${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing space suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s " + value_fmt="%s" + expected_output="${before}\n${key} =${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing multiple spaces prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^ %s " + value_fmt="%s" + expected_output="${before}\n ${key} =${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing tab prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^\t%s" + value_fmt="%s" + expected_output="${before}\n\t${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing tab suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^%s\t" + value_fmt="%s" + expected_output="${before}\n${key}\t=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate key containing multiple tab prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s' + before_fmt="%s\n" + key_fmt="^\t\t%s\t\t" + value_fmt="%s" + expected_output="${before}\n\t\t${key}\t\t=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format key containing space prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format=' %s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n ${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format key containing space suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s =%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key} =${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format value containing space prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s= %s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}= ${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format value containing space suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s ' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}=${value} \n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format containing multiple spaces prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format=' %s = %s ' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n ${key} = ${value} \n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" ' %s = %s ' + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format key containing tab prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='\t%s=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n\t${key}=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format key containing tab suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s\t=%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}\t=${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format value containing tab prefix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=\t%s' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}=\t${value}\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format value containing tab suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='%s=%s\t' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n${key}=${value}\t\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" + + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] +} + +@test "bash_replace_or_append - Remediate format containing multiple tab prefix and suffix" { + before="foo" + key="kernel.randomize_va_fake" + value="6" + + format='\t\t%s\t\t=\t\t%s\t\t' + before_fmt="%s\n" + key_fmt="^%s" + value_fmt="%s" + expected_output="${before}\n\t\t${key}\t\t=\t\t${value}\t\t\n" + + IFS='' read -d '' -r key_param < <(printf "${key_fmt}" "${key}") || : + IFS='' read -d '' -r value_param < <(printf "${value_fmt}" "${value}") || : + printf "${before_fmt}" "${before}" > "${tmp_file}" + + call_bash_replace_or_append_w_format "${tmp_file}" "${key_param}" "${value_param}" "${format}" - rm "$tmp_file" + run diff -u "${tmp_file}" <(printf "${expected_output}") + [ "${status}" -eq 0 ] } diff --git a/tests/unit/bash/test_set_config_file.bats.jinja b/tests/unit/bash/test_set_config_file.bats.jinja index d45249b188e..f989eb5ecb4 100644 --- a/tests/unit/bash/test_set_config_file.bats.jinja +++ b/tests/unit/bash/test_set_config_file.bats.jinja @@ -1,5 +1,6 @@ #!/bin/bash +set -pu function call_set_config_file_create_false { {{{ set_config_file("$1", "Compression", "no", False) | indent(4) }}} @@ -11,12 +12,51 @@ function call_set_config_file { } function call_set_config_file_rsyslog { - {{{ set_config_file(path="$1", - parameter="\$DefaultNetstreamDriver", value="gtls", create=true, separator=" ", separator_regex=" ") }}} -} - -@test "Basic value remediation" { - tmp_file="$(mktemp)" + {{{ set_config_file(path="$1", + parameter="\$DefaultNetstreamDriver", value="gtls", + create=true, separator=" ", separator_regex=" ") }}} +} + +is_old_bats=0 + +setup() { + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + BATS_TEST_TMPDIR="$(mktemp -d)" # 1.4.0 + # shellcheck disable=SC2034 + BATS_TEARDOWN_STARTED= # 1.3.0 + is_old_bats=1 + else + is_old_bats=0 + fi + pushd "${BATS_TEST_TMPDIR}" || exit 1 + tmp_file=test.conf + touch "$tmp_file" +} + +teardown() { + if (( is_old_bats )); then + if [[ -z "${BATS_TEST_TMPDIR:-}" ]] || [[ ! -d "${BATS_TEST_TMPDIR}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + local tmppath xpwd + tmppath="$(readlink -f -- "${BATS_TEST_TMPDIR}")" + if [[ ! "${tmppath}" =~ ^/tmp/ ]] || [[ ! -d "${tmppath}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + xpwd="$(readlink -f -- .)" + if [[ "${tmppath}" != "${xpwd}" ]]; then + >&2 echo "INTERNAL ERROR" + exit 3 + fi + popd || exit 1 + rm -rf -- "${tmppath}" + BATS_TEST_TMPDIR="" + fi +} + +@test "set_config_file - Basic value remediation" { printf "%s\n" "Compression yes" > "$tmp_file" expected_output="Compression no\n" @@ -24,12 +64,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } -@test "No remediation happened" { - tmp_file="$(mktemp)" +@test "set_config_file - No remediation happened" { printf "%s\n" "Compression no" > "$tmp_file" expected_output="Compression no\n" @@ -37,12 +74,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } -@test "Multiline file remediation" { - tmp_file="$(mktemp)" +@test "set_config_file - Multiline file remediation" { printf "%s\n" "Protocol 2" "Compression yes" "Port 22" > "$tmp_file" expected_output="Protocol 2\nPort 22\nCompression no\n" @@ -50,12 +84,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } -@test "No remediation on commented line" { - tmp_file="$(mktemp)" +@test "set_config_file - No remediation on commented line" { printf "%s\n" "Protocol 2" "# Compression yes" "Port 22" > "$tmp_file" expected_output="Protocol 2\n# Compression yes\nPort 22\nCompression no\n" @@ -63,12 +94,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } -@test "Create if missing" { - tmp_file="$(mktemp)" +@test "set_config_file - Create if missing" { printf "%s\n" "Protocol 2" "Port 22" > "$tmp_file" expected_output="Protocol 2\nPort 22\nCompression no\n" @@ -76,12 +104,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } -@test "Create file if doesn't exist" { - tmp_file="$(mktemp)" +@test "set_config_file - Create file if doesn't exist" { rm "$tmp_file" expected_output="Compression no\n" @@ -89,12 +114,9 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } -@test "Do not create if missing" { - tmp_file="$(mktemp)" +@test "set_config_file - Do not create if missing" { rm "$tmp_file" run call_set_config_file_create_false "$tmp_file" @@ -104,8 +126,7 @@ function call_set_config_file_rsyslog { } -@test "Case insensitive remediation" { - tmp_file="$(mktemp)" +@test "set_config_file - Case insensitive remediation" { printf "%s\n" "Protocol 2" "COMPRESSION YES" "Port 22" > "$tmp_file" expected_output="Protocol 2\nPort 22\nCompression no\n" @@ -113,90 +134,64 @@ function call_set_config_file_rsyslog { run diff "$tmp_file" <(printf "$expected_output") [ "$status" -eq 0 ] - - rm "$tmp_file" } -@test "Case sensitive remediation" { - tmp_file="$(mktemp)" +@test "set_config_file - Case sensitive remediation" { printf "%s\n" "Protocol 2" "COMPRESSION YES" "Port 22" > "$tmp_file" expected_output="Protocol 2\nCOMPRESSION YES\nPort 22\nCompression no\n" {{{ set_config_file("$tmp_file", "Compression", "no", True, "", "", False) | indent(4) }}} run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" } -@test "Basic Bash remediation" { - tmp_file="$(mktemp)" +@test "set_config_file - Basic Bash remediation" { printf "%s\n" "something=foo" > "$tmp_file" expected_output="something='va lue'\n" {{{ bash_shell_file_set("$tmp_file", "something", "va lue") | indent(4) }}} run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" } -@test "Variable remediation - preserve dollar and use double quotes" { - tmp_file="$(mktemp)" +@test "set_config_file - Variable remediation - preserve dollar and use double quotes" { printf "%s\n" "something=bar" > "$tmp_file" expected_output='something="$value"'"\n" {{{ bash_shell_file_set("$tmp_file", "something", '$value') | indent(4) }}} run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" } -@test "Basic Bash remediation - don't quote" { - tmp_file="$(mktemp)" +@test "set_config_file - Basic Bash remediation - don't quote" { printf "%s\n" "something=foo" > "$tmp_file" expected_output="something=va lue\n" {{{ bash_shell_file_set("$tmp_file", "something", "va lue", no_quotes=true) | indent(4) }}} run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" } -@test "Variable remediation - don't quote" { - tmp_file="$(mktemp)" +@test "set_config_file - Variable remediation - don't quote" { printf "%s\n" "something=bar" > "$tmp_file" expected_output='something=$value'"\n" {{{ bash_shell_file_set("$tmp_file", "something", '$value', no_quotes=true) | indent(4) }}} run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" } @test "set_config_file - handle escaped dollar" { - tmp_file="$(mktemp)" printf "%s\n" '$DefaultNetstreamDriver bad' > "$tmp_file" expected_output='$DefaultNetstreamDriver gtls'"\n" call_set_config_file_rsyslog "$tmp_file" run diff -U2 "$tmp_file" <(printf "$expected_output") - echo "$output" [ "$status" -eq 0 ] - - rm "$tmp_file" }