diff --git a/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/ansible/shared.yml b/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/ansible/shared.yml index e83aeb894e4..f8359f007da 100644 --- a/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/ansible/shared.yml +++ b/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/ansible/shared.yml @@ -5,41 +5,63 @@ # disruption = low {{{ ansible_instantiate_variables("sshd_approved_ciphers") }}} -- name: "{{{ rule_title }}}: Set facts" - set_fact: - path: /etc/crypto-policies/back-ends/opensshserver.config - correct_value: "-oCiphers={{ sshd_approved_ciphers }}" - -- name: "{{{ rule_title }}}: Stat" - stat: - path: "{{ path }}" - follow: yes - register: opensshserver_file - -- name: "{{{ rule_title }}}: Create" - lineinfile: - path: "{{ path }}" - line: "CRYPTO_POLICY='{{ correct_value }}'" - create: yes - when: not opensshserver_file.stat.exists or opensshserver_file.stat.size <= correct_value|length - -- name: "{{{ rule_title }}}" - block: - - name: "Existing value check" - lineinfile: - path: "{{ path }}" - create: false - regexp: "{{ correct_value }}" - state: absent - check_mode: true - changed_when: false - register: opensshserver - - - name: "Update/Correct value" - replace: - path: "{{ path }}" - regexp: (-oCiphers=\S+) - replace: "{{ correct_value }}" - when: opensshserver.found is defined and opensshserver.found != 1 - - when: opensshserver_file.stat.exists and opensshserver_file.stat.size > correct_value|length +- name: "{{{ rule_title }}}: Set relevant paths and correct value" + ansible.builtin.set_fact: + opensshserver_path: /etc/crypto-policies/back-ends/opensshserver.config + local_path: /etc/crypto-policies/local.d/opensshserver-ssg.config + correct_value: "-oCiphers={{ sshd_approved_ciphers }}" + +- name: "{{{ rule_title }}}: Ensure crypto config exists" + ansible.builtin.stat: + path: "{{ opensshserver_path }}" + follow: true + register: opensshserver_file + +- name: "{{{ rule_title }}}: Generate default config if missing or empty" + ansible.builtin.command: update-crypto-policies --no-reload + when: not opensshserver_file.stat.exists or opensshserver_file.stat.size == 0 + +- name: "{{{ rule_title }}}: Read opensshserver.config content" + ansible.builtin.slurp: + src: "{{ opensshserver_path }}" + register: ssh_config_raw + +- name: "{{{ rule_title }}}: Extract last CRYPTO_POLICY line" + ansible.builtin.set_fact: + last_crypto_policy: "{{ (ssh_config_raw.content | b64decode).splitlines() | select('match', \"^\\s*CRYPTO_POLICY='[^']+'\") | list | last | default('') }}" + +- name: "{{{ rule_title }}}: Check if correct_value is present" + ansible.builtin.set_fact: + cipher_is_correct: "{{ correct_value in last_crypto_policy }}" + +- name: "{{{ rule_title }}}: Extract current Ciphers if needed" + ansible.builtin.set_fact: + existing_cipher: "{{ (last_crypto_policy | regex_findall('(-oCiphers=\\S+)', '\\1')) | last | default('') }}" + when: not cipher_is_correct and last_crypto_policy != '' + +- name: "{{{ rule_title }}}: Build full updated CRYPTO_POLICY line" + set_fact: + updated_crypto_policy: >- + {% if last_crypto_policy == '' %} + CRYPTO_POLICY='{{ correct_value }}' + {% elif existing_cipher != '' %} + {{ last_crypto_policy | regex_replace(existing_cipher, correct_value) }} + {% else %} + {{ last_crypto_policy[:-1] ~ " " ~ correct_value ~ "'" }} + {% endif %} + when: not cipher_is_correct + +- name: "{{{ rule_title }}}: Ensure local.d dir exists" + ansible.builtin.file: + path: "{{ local_path | dirname }}" + state: directory + +- name: "{{{ rule_title }}}: Write CRYPTO_POLICY to local config" + ansible.builtin.lineinfile: + path: "{{ local_path }}" + line: "{{ '\n' ~ updated_crypto_policy }}" + create: yes + insertafter: EOF + +- name: "{{{ rule_title }}}: Apply updated crypto policies" + ansible.builtin.command: update-crypto-policies --no-reload diff --git a/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/bash/shared.sh b/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/bash/shared.sh index dec0e22b774..43fed0ef36d 100644 --- a/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/bash/shared.sh +++ b/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/bash/shared.sh @@ -3,27 +3,33 @@ {{{ bash_instantiate_variables("sshd_approved_ciphers") }}} CONF_FILE=/etc/crypto-policies/back-ends/opensshserver.config +LOCAL_CONF_DIR=/etc/crypto-policies/local.d +LOCAL_CONF_FILE=${LOCAL_CONF_DIR}/opensshserver-ssg.config correct_value="-oCiphers=${sshd_approved_ciphers}" -# Test if file exists -test -f ${CONF_FILE} || touch ${CONF_FILE} - -# Ensure CRYPTO_POLICY is not commented out -sed -i 's/#CRYPTO_POLICY=/CRYPTO_POLICY=/' ${CONF_FILE} +# Test if file exists, create default it if not +if [[ ! -s ${CONF_FILE} ]] || ! grep -q "^\s*CRYPTO_POLICY=" ${CONF_FILE} ; then + update-crypto-policies --no-reload # Generate a default configuration +fi -if ! grep -q "\\$correct_value" "$CONF_FILE"; then - # We need to get the existing value, using PCRE to maintain same regex - existing_value=$(grep -Po '(-oCiphers=\S+)' ${CONF_FILE}) +# Get the last occurrence of CRYPTO_POLICY +last_crypto_policy=$(grep -Eo "^\s*CRYPTO_POLICY='[^']+'" ${CONF_FILE} | tail -n 1) - if [[ ! -z ${existing_value} ]]; then - # replace existing_value with correct_value - sed -i "s/${existing_value}/${correct_value}/g" ${CONF_FILE} - else - # ***NOTE*** # - # This probably means this file is not here or it's been modified - # unintentionally. - # ********** # - # echo correct_value to end - echo "CRYPTO_POLICY='${correct_value}'" >> ${CONF_FILE} +# Copy the last CRYPTO_POLICY value to the local configuration file +if [[ -n "$last_crypto_policy" ]]; then + if ! grep -qe "$correct_value" <<< "$last_crypto_policy"; then + # If an existing -oCiphers= is found, replace it + # Else, append correct_value before the closing apostrophe + if [[ "$last_crypto_policy" == *"-oCiphers="* ]]; then + last_crypto_policy=$(echo "$last_crypto_policy" | sed -E "s/-oCiphers=\S+/${correct_value}/") + else + last_crypto_policy=$(echo "$last_crypto_policy" | sed -E "s/'[[:space:]]*$/ ${correct_value}'/") + fi + # Write updated line to LOCAL_CONF_FILE + echo -e "\n$last_crypto_policy" > "$LOCAL_CONF_FILE" fi +else + echo -e "\nCRYPTO_POLICY='${correct_value}'" > ${LOCAL_CONF_FILE} fi + +update-crypto-policies --no-reload diff --git a/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/oval/shared.xml b/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/oval/shared.xml index 41994d946e1..2677b284ede 100644 --- a/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/oval/shared.xml +++ b/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/oval/shared.xml @@ -21,7 +21,7 @@ {{%- else -%}} <ind:pattern operation="pattern match">^(?!#).*Ciphers\s+([^\s']+).*$</ind:pattern> {{%- endif -%}} - <ind:instance operation="equals" datatype="int">1</ind:instance> + <ind:instance operation="greater than or equal" datatype="int">-1</ind:instance> </ind:textfilecontent54_object> <ind:textfilecontent54_state id="ste_{{{ rule_id }}}" version="1"> diff --git a/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/tests/rhel8_stig_multi_crypto_correct.pass.sh b/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/tests/rhel8_stig_multi_crypto_correct.pass.sh new file mode 100644 index 00000000000..fa39137d27d --- /dev/null +++ b/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/tests/rhel8_stig_multi_crypto_correct.pass.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# platform = Not Applicable +# variables = sshd_approved_ciphers=aes256-ctr,aes192-ctr,aes128-ctr,aes256-gcm@openssh.com,aes128-gcm@openssh.com + +sshd_approved_ciphers=aes256-ctr,aes192-ctr,aes128-ctr,aes256-gcm@openssh.com,aes128-gcm@openssh.com + +configfile=/etc/crypto-policies/back-ends/opensshserver.config +correct_value="-oCiphers=${sshd_approved_ciphers}" + +# Ensure directory + file is there +test -d /etc/crypto-policies/back-ends || mkdir -p /etc/crypto-policies/back-ends + +# Get the last CRYPTO_POLICY line +last_crypto_policy=$(grep -E "^CRYPTO_POLICY='[^']+'" "$configfile" | tail -n 1) + +# Generate a corrected version by replacing any -oCiphers= value +if grep -qPo '(-oCiphers=\S+)' <<< "$last_crypto_policy"; then + fixed_crypto_policy=$(sed -E "s/-oCiphers=\S+/${correct_value}/" <<< "$last_crypto_policy") +fi + +echo -e "\n$fixed_crypto_policy" >> "$configfile" diff --git a/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/tests/rhel8_stig_multi_crypto_missing_ciphers.fail.sh b/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/tests/rhel8_stig_multi_crypto_missing_ciphers.fail.sh new file mode 100644 index 00000000000..125daa79b4d --- /dev/null +++ b/linux_os/guide/system/software/integrity/crypto/harden_sshd_ciphers_opensshserver_conf_crypto_policy/tests/rhel8_stig_multi_crypto_missing_ciphers.fail.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# platform = Not Applicable +# variables = sshd_approved_ciphers=aes256-ctr,aes192-ctr,aes128-ctr,aes256-gcm@openssh.com,aes128-gcm@openssh.com + +configfile=/etc/crypto-policies/back-ends/opensshserver.config + +# Ensure directory + file is there +test -d /etc/crypto-policies/back-ends || mkdir -p /etc/crypto-policies/back-ends + +# Get the last CRYPTO_POLICY line +last_crypto_policy=$(grep -E "^CRYPTO_POLICY='[^']+'" "$configfile" | tail -n 1) + +# Generate a corrected version by replacing any -oCiphers= value +if grep -qPo '(-oCiphers=\S+)' <<< "$last_crypto_policy"; then + fixed_crypto_policy=$(sed -E "s/-oCiphers=\S+[[:space:]]*//" <<< "$last_crypto_policy") +fi + +echo -e "\n$fixed_crypto_policy" >> "$configfile" diff --git a/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/ansible/shared.yml b/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/ansible/shared.yml index 6a0e45947f5..687b5ecd3dc 100644 --- a/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/ansible/shared.yml +++ b/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/ansible/shared.yml @@ -5,41 +5,63 @@ # disruption = low {{{ ansible_instantiate_variables("sshd_approved_macs") }}} -- name: "{{{ rule_title }}}: Set facts" - set_fact: - path: /etc/crypto-policies/back-ends/opensshserver.config - correct_value: "-oMACs={{ sshd_approved_macs }}" - -- name: "{{{ rule_title }}}: Stat" - stat: - path: "{{ path }}" - follow: yes - register: opensshserver_file - -- name: "{{{ rule_title }}}: Create" - lineinfile: - path: "{{ path }}" - line: "CRYPTO_POLICY='{{ correct_value }}'" - create: yes - when: not opensshserver_file.stat.exists or opensshserver_file.stat.size <= correct_value|length - -- name: "{{{ rule_title }}}" - block: - - name: "Existing value check" - lineinfile: - path: "{{ path }}" - create: false - regexp: "{{ correct_value }}" - state: absent - check_mode: true - changed_when: false - register: opensshserver - - - name: "Update/Correct value" - replace: - path: "{{ path }}" - regexp: (-oMACs=\S+) - replace: "{{ correct_value }}" - when: opensshserver.found is defined and opensshserver.found != 1 - - when: opensshserver_file.stat.exists and opensshserver_file.stat.size > correct_value|length +- name: "{{{ rule_title }}}: Set relevant paths and correct value" + ansible.builtin.set_fact: + opensshserver_path: /etc/crypto-policies/back-ends/opensshserver.config + local_path: /etc/crypto-policies/local.d/opensshserver-ssg.config + correct_value: "-oMACs={{ sshd_approved_macs }}" + +- name: "{{{ rule_title }}}: Ensure crypto config exists" + ansible.builtin.stat: + path: "{{ opensshserver_path }}" + follow: true + register: opensshserver_file + +- name: "{{{ rule_title }}}: Generate default config if missing or empty" + ansible.builtin.command: update-crypto-policies --no-reload + when: not opensshserver_file.stat.exists or opensshserver_file.stat.size == 0 + +- name: "{{{ rule_title }}}: Read opensshserver.config content" + ansible.builtin.slurp: + src: "{{ opensshserver_path }}" + register: ssh_config_raw + +- name: "{{{ rule_title }}}: Extract last CRYPTO_POLICY line" + ansible.builtin.set_fact: + last_crypto_policy: "{{ (ssh_config_raw.content | b64decode).splitlines() | select('match', \"^\\s*CRYPTO_POLICY='[^']+'\") | list | last | default('') }}" + +- name: "{{{ rule_title }}}: Check if correct_value is present" + ansible.builtin.set_fact: + mac_is_correct: "{{ correct_value in last_crypto_policy }}" + +- name: "{{{ rule_title }}}: Extract current Ciphers if needed" + ansible.builtin.set_fact: + existing_mac: "{{ (last_crypto_policy | regex_findall('(-oMACs=\\S+)', '\\1')) | last | default('') }}" + when: not mac_is_correct and last_crypto_policy != '' + +- name: "{{{ rule_title }}}: Build full updated CRYPTO_POLICY line" + set_fact: + updated_crypto_policy: >- + {% if last_crypto_policy == '' %} + CRYPTO_POLICY='{{ correct_value }}' + {% elif existing_mac != '' %} + {{ last_crypto_policy | regex_replace(existing_mac, correct_value) }} + {% else %} + {{ last_crypto_policy[:-1] ~ " " ~ correct_value ~ "'" }} + {% endif %} + when: not mac_is_correct + +- name: "{{{ rule_title }}}: Ensure local.d dir exists" + ansible.builtin.file: + path: "{{ local_path | dirname }}" + state: directory + +- name: "{{{ rule_title }}}: Write CRYPTO_POLICY to local config" + ansible.builtin.lineinfile: + path: "{{ local_path }}" + line: "{{ '\n' ~ updated_crypto_policy }}" + create: yes + insertafter: EOF + +- name: "{{{ rule_title }}}: Apply updated crypto policies" + ansible.builtin.command: update-crypto-policies --no-reload diff --git a/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/bash/shared.sh b/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/bash/shared.sh index 1ead9584168..0c124e62471 100644 --- a/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/bash/shared.sh +++ b/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/bash/shared.sh @@ -3,27 +3,33 @@ {{{ bash_instantiate_variables("sshd_approved_macs") }}} CONF_FILE=/etc/crypto-policies/back-ends/opensshserver.config +LOCAL_CONF_DIR=/etc/crypto-policies/local.d +LOCAL_CONF_FILE=${LOCAL_CONF_DIR}/opensshserver-ssg.config correct_value="-oMACs=${sshd_approved_macs}" -# Test if file exists -test -f ${CONF_FILE} || touch ${CONF_FILE} - -# Ensure CRYPTO_POLICY is not commented out -sed -i 's/#CRYPTO_POLICY=/CRYPTO_POLICY=/' ${CONF_FILE} +# Test if file exists, create default it if not +if [[ ! -s ${CONF_FILE} ]] || ! grep -q "^\s*CRYPTO_POLICY=" ${CONF_FILE} ; then + update-crypto-policies --no-reload # Generate a default configuration +fi -if ! grep -q "\\$correct_value" "$CONF_FILE"; then - # We need to get the existing value, using PCRE to maintain same regex - existing_value=$(grep -Po '(-oMACs=\S+)' ${CONF_FILE}) +# Get the last occurrence of CRYPTO_POLICY +last_crypto_policy=$(grep -Eo "^\s*CRYPTO_POLICY='[^']+'" ${CONF_FILE} | tail -n 1) - if [[ ! -z ${existing_value} ]]; then - # replace existing_value with correct_value - sed -i "s/${existing_value}/${correct_value}/g" ${CONF_FILE} - else - # ***NOTE*** # - # This probably means this file is not here or it's been modified - # unintentionally. - # ********** # - # echo correct_value to end - echo "CRYPTO_POLICY='${correct_value}'" >> ${CONF_FILE} +# Copy the last CRYPTO_POLICY value to the local configuration file +if [[ -n "$last_crypto_policy" ]]; then + if ! grep -qe "$correct_value" <<< "$last_crypto_policy"; then + # If an existing -oMACs= is found, replace it + # Else, append correct_value before the closing apostrophe + if [[ "$last_crypto_policy" == *"-oMACs="* ]]; then + last_crypto_policy=$(echo "$last_crypto_policy" | sed -E "s/-oMACs=\S+/${correct_value}/") + else + last_crypto_policy=$(echo "$last_crypto_policy" | sed -E "s/'[[:space:]]*$/ ${correct_value}'/") + fi + # Write updated line to LOCAL_CONF_FILE + echo -e "\n$last_crypto_policy" > "$LOCAL_CONF_FILE" fi +else + echo -e "\nCRYPTO_POLICY='${correct_value}'" > ${LOCAL_CONF_FILE} fi + +update-crypto-policies --no-reload diff --git a/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/oval/shared.xml b/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/oval/shared.xml index 18028157032..cb1806a701c 100644 --- a/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/oval/shared.xml +++ b/linux_os/guide/system/software/integrity/crypto/harden_sshd_macs_opensshserver_conf_crypto_policy/oval/shared.xml @@ -17,7 +17,7 @@ <ind:textfilecontent54_object id="obj_{{{ rule_id }}}" version="1"> <ind:filepath>{{{ PATH }}}</ind:filepath> <ind:pattern operation="pattern match">^(?!#).*(-oMACs=\S+).+$</ind:pattern> - <ind:instance operation="equals" datatype="int">1</ind:instance> + <ind:instance operation="greater than or equal" datatype="int">-1</ind:instance> </ind:textfilecontent54_object> <ind:textfilecontent54_state id="ste_{{{ rule_id }}}" version="1">