From 7144b947de7e94fa84db9c7c61ba04d7f6a9aea0 Mon Sep 17 00:00:00 2001 From: Razvan Stoica Date: Tue, 16 Mar 2021 10:05:49 +0200 Subject: [PATCH] Tests update --- tests/1_host_configuration.sh | 427 ++++++--------- tests/2_docker_daemon_configuration.sh | 306 ++++------- tests/3_docker_daemon_configuration_files.sh | 374 +++++-------- tests/4_container_images.sh | 111 ++-- tests/5_container_runtime.sh | 520 +++++++------------ tests/6_docker_security_operations.sh | 18 +- tests/7_docker_swarm_configuration.sh | 145 ++---- tests/8_docker_enterprise_configuration.sh | 55 +- tests/99_community_checks.sh | 58 ++- tests/TESTS.md | 266 ++++++++++ 10 files changed, 1007 insertions(+), 1273 deletions(-) create mode 100644 tests/TESTS.md diff --git a/tests/1_host_configuration.sh b/tests/1_host_configuration.sh index 709a01e..65954c4 100644 --- a/tests/1_host_configuration.sh +++ b/tests/1_host_configuration.sh @@ -16,43 +16,36 @@ check_1_1() { info "$check" } -# 1.1.1 check_1_1_1() { local id="1.1.1" local desc="Ensure the container host has been Hardened (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "INFO" } -# 1.1.2 check_1_1_2() { local id="1.1.2" local desc="Ensure that the version of Docker is up to date (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \ | awk '{print $NF; exit}' | tr -d '[:alpha:]-,') docker_current_version="$(date +%y.%m.0 -d @$(( $(date +%s) - 2592000)))" do_version_check "$docker_current_version" "$docker_version" if [ $? -eq 11 ]; then - info "$check" + info -c "$check" info " * Using $docker_version, verify is it up to date as deemed necessary" info " * Your operating system vendor may provide support and security maintenance for Docker" - resulttestjson "INFO" "Using $docker_version" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Using $docker_version" else - pass "$check" + pass -c "$check" info " * Using $docker_version which is current" info " * Check with your operating system vendor for support and security maintenance for Docker" - resulttestjson "PASS" "Using $docker_version" - currentScore=$((currentScore + 0)) + logcheckresult "PASS" "Using $docker_version" fi } @@ -63,462 +56,384 @@ check_1_2() { info "$check" } -# 1.2.1 check_1_2_1() { local id="1.2.1" local desc="Ensure a separate partition for containers has been created (Scored)" - local remediation="For new installations, you should create a separate partition for the \'/var/lib/docker\' mount point. For systems that have already been installed, you should use the Logical Volume Manager (LVM) within Linux to create a new partition." + local remediation="For new installations, you should create a separate partition for the /var/lib/docker mount point. For systems that have already been installed, you should use the Logical Volume Manager (LVM) within Linux to create a new partition." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) docker_root_dir=$(docker info -f '{{ .DockerRootDir }}') if docker info | grep -q userns ; then docker_root_dir=$(readlink -f "$docker_root_dir/..") fi if mountpoint -q -- "$docker_root_dir" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi } -# 1.2.2 -check_1_2_2() { +check_1_2_2() { local id="1.2.2" local desc="Ensure only trusted users are allowed to control Docker daemon (Scored)" - local check="$id - $desc" + local remediation="You should remove any untrusted users from the docker group using command sudo gpasswd -d docker or add trusted users to the docker group using command sudo usermod -aG docker . You should not create a mapping of sensitive directories from the host to container volumes." + local remediationImpact="Only trust user are allow to build and execute containers as normal user." + local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if command -v getent >/dev/null 2>&1; then docker_users=$(getent group docker) else docker_users=$(grep 'docker' /etc/group) fi - info "$check" - for u in $docker_users; do - info " * $u" - done - resulttestjson "INFO" "users" "$docker_users" - currentScore=$((currentScore + 0)) -} + docker_users=$(printf "%s" "$docker_users" | awk -F: '{print $4}') -# 1.2.3 -check_1_2_3() { - local id="1.2.3" - local desc="Ensure auditing is configured for the Docker daemon (Scored)" - local remediation="Install and configure auditd using command \'sudo apt-get install auditd\'. Add \'-w /usr/bin/dockerd -k docker\' to the \'/etc/audit/rules.d/audit.rules\' file. Then restart the audit daemon using command \'service auditd restart\'." - local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions." - local check="$id - $desc" - starttestjson "$id" "$desc" - - totalChecks=$((totalChecks + 1)) - file="/usr/bin/dockerd" - if command -v auditctl >/dev/null 2>&1; then - if auditctl -l | grep "$file" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) - else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) - fi - elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + local doubtfulusers="" + if [ -n "$dockertrustusers" ]; then + for u in $(printf "%s" "$docker_users" | sed "s/,/ /g"); do + if ! printf "%s" "$dockertrustusers" | grep -q "$u" ; then + if [ -n "${doubtfulusers}" ]; then + doubtfulusers="${doubtfulusers},$u" + else + doubtfulusers="$u" + fi + fi + done else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + info -c "$check" + info " * Users: $docker_users" + logcheckresult "INFO" "doubtfulusers" "$docker_users" + fi + + if [ -n "${doubtfulusers}" ]; then + warn -s "$check" + warn " * Doubtful users: $doubtfulusers" + logcheckresult "WARN" "doubtfulusers" "$doubtfulusers" + fi + + if [ -z "${doubtfulusers}" ] && [ -n "${dockertrustusers}" ]; then + pass -s "$check" + logcheckresult "PASS" fi } -# 1.2.4 -check_1_2_4() { - local id="1.2.4" - local desc="Ensure auditing is configured for Docker files and directories - /var/lib/docker (Scored)" - local remediation="Install and configure auditd using command \'sudo apt-get install auditd\'. Add \'-w /var/lib/docker -k docker\' to the \'/etc/audit/rules.d/audit.rules\' file. Then restart the audit daemon using command \'service auditd restart\'." +check_1_2_3() { + local id="1.2.3" + local desc="Ensure auditing is configured for the Docker daemon (Scored)" + local remediation="Install and configure auditd using command sudo apt-get install auditd. Add -w /usr/bin/dockerd -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart." + local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions." + local check="$id - $desc" + starttestjson "$id" "$desc" + + file="/usr/bin/dockerd" + if command -v auditctl >/dev/null 2>&1; then + if auditctl -l | grep "$file" >/dev/null 2>&1; then + pass -s "$check" + logcheckresult "PASS" + else + warn -s "$check" + logcheckresult "WARN" + fi + elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then + pass -s "$check" + logcheckresult "PASS" + else + warn -s "$check" + logcheckresult "WARN" + fi +} + +check_1_2_4() { + local id="1.2.4" + local desc="Ensure auditing is configured for Docker files and directories - /var/lib/docker (Scored)" + local remediation="Install and configure auditd using command sudo apt-get install auditd. Add -w /var/lib/docker -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart." local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) directory="/var/lib/docker" if [ -d "$directory" ]; then if command -v auditctl >/dev/null 2>&1; then if auditctl -l | grep $directory >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi elif grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - info "$check" + info -c "$check" info " * Directory not found" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "INFO" "Directory not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Directory not found" fi } -# 1.2.5 check_1_2_5() { local id="1.2.5" local desc="Ensure auditing is configured for Docker files and directories - /etc/docker (Scored)" - local remediation="Install and configure auditd using command \'sudo apt-get install auditd\'. Add \'-w /etc/docker -k docker\' to the \'/etc/audit/rules.d/audit.rules\' file. Then restart the audit daemon using command \'service auditd restart\'." + local remediation="Install and configure auditd using command sudo apt-get install auditd. Add -w /etc/docker -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart." local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) directory="/etc/docker" if [ -d "$directory" ]; then if command -v auditctl >/dev/null 2>&1; then if auditctl -l | grep $directory >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi elif grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - info "$check" + info -c "$check" info " * Directory not found" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "INFO" "Directory not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Directory not found" fi } -# 1.2.6 check_1_2_6() { local id="1.2.6" local desc="Ensure auditing is configured for Docker files and directories - docker.service (Scored)" - local remediation="Install and configure auditd using command \'sudo apt-get install auditd\'. Add \'-w $(systemctl show -p FragmentPath docker.service | sed 's/.*=//') -k docker\' to the \'/etc/audit/rules.d/audit.rules\' file. Then restart the audit daemon using command \'service auditd restart\'." + local remediation + remediation="Install and configure auditd using command sudo apt-get install auditd. Add -w $(systemctl show -p FragmentPath docker.service | sed 's/.*=//') -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart." local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="$(get_service_file docker.service)" if [ -f "$file" ]; then if command -v auditctl >/dev/null 2>&1; then if auditctl -l | grep "$file" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - info "$check" + info -c "$check" info " * File not found" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 1.2.7 check_1_2_7() { local id="1.2.7" local desc="Ensure auditing is configured for Docker files and directories - docker.socket (Scored)" - local remediation="Install and configure auditd using command \'sudo apt-get install auditd\'. Add \'-w $(systemctl show -p FragmentPath docker.socket | sed 's/.*=//') -k docker\' to the \'/etc/audit/rules.d/audit.rules\' file. Then restart the audit daemon using command \'service auditd restart\'." + local remediation + remediation="Install and configure auditd using command sudo apt-get install auditd. Add -w $(systemctl show -p FragmentPath docker.socket | sed 's/.*=//') -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart." local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="$(get_service_file docker.socket)" if [ -e "$file" ]; then if command -v auditctl >/dev/null 2>&1; then if auditctl -l | grep "$file" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - info "$check" + info -c "$check" info " * File not found" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 1.2.8 check_1_2_8() { local id="1.2.8" local desc="Ensure auditing is configured for Docker files and directories - /etc/default/docker (Scored)" - local remediation="Install and configure auditd using command \'sudo apt-get install auditd\'. Add \'-w /etc/default/docker -k docker\' to the \'/etc/audit/rules.d/audit.rules\' file. Then restart the audit daemon using command \'service auditd restart\'." + local remediation="Install and configure auditd using command sudo apt-get install auditd. Add -w /etc/default/docker -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart." local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/etc/default/docker" if [ -f "$file" ]; then if command -v auditctl >/dev/null 2>&1; then if auditctl -l | grep $file >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - info "$check" + info -c "$check" info " * File not found" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 1.2.9 check_1_2_9() { local id="1.2.9" local desc="Ensure auditing is configured for Docker files and directories - /etc/sysconfig/docker (Scored)" - local remediation="Install and configure auditd using command \'sudo apt-get install auditd\'. Add \'-w /etc/sysconfig/docker -k docker\' to the \'/etc/audit/rules.d/audit.rules\' file. Then restart the audit daemon using command \'service auditd restart\'." + local remediation="Install and configure auditd using command sudo apt-get install auditd. Add -w /etc/sysconfig/docker -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart." local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/etc/sysconfig/docker" if [ -f "$file" ]; then if command -v auditctl >/dev/null 2>&1; then if auditctl -l | grep $file >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - info "$check" + info -c "$check" info " * File not found" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 1.2.10 check_1_2_10() { local id="1.2.10" local desc="Ensure auditing is configured for Docker files and directories - /etc/docker/daemon.json (Scored)" - local remediation="Install and configure auditd using command \'sudo apt-get install auditd\'. Add \'-w /etc/docker/daemon.json -k docker\' to the \'/etc/audit/rules.d/audit.rules\' file. Then restart the audit daemon using command \'service auditd restart\'." + local remediation="Install and configure auditd using command sudo apt-get install auditd. Add -w /etc/docker/daemon.json -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart." local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/etc/docker/daemon.json" if [ -f "$file" ]; then if command -v auditctl >/dev/null 2>&1; then if auditctl -l | grep $file >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - info "$check" + info -c "$check" info " * File not found" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 1.2.11 check_1_2_11() { local id="1.2.11" local desc="Ensure auditing is configured for Docker files and directories - /usr/bin/containerd (Scored)" - local remediation="Install and configure auditd using command \'sudo apt-get install auditd\'. Add \'-w /usr/bin/containerd -k docker\' to the \'/etc/audit/rules.d/audit.rules\' file. Then restart the audit daemon using command \'service auditd restart\'." + local remediation="Install and configure auditd using command sudo apt-get install auditd. Add -w /usr/bin/containerd -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart." local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/usr/bin/containerd" if [ -f "$file" ]; then if command -v auditctl >/dev/null 2>&1; then if auditctl -l | grep $file >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - info "$check" + info -c "$check" info " * File not found" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 1.2.12 check_1_2_12() { local id="1.2.12" local desc="Ensure auditing is configured for Docker files and directories - /usr/sbin/runc (Scored)" - local remediation="Install and configure auditd using command \'sudo apt-get install auditd\'. Add \'-w /usr/sbin/runc -k docker\' to the \'/etc/audit/rules.d/audit.rules\' file. Then restart the audit daemon using command \'service auditd restart\'." + local remediation="Install and configure auditd using command sudo apt-get install auditd. Add -w /usr/sbin/runc -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart." local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/usr/sbin/runc" if [ -f "$file" ]; then if command -v auditctl >/dev/null 2>&1; then if auditctl -l | grep $file >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - info "$check" + info -c "$check" info " * File not found" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } diff --git a/tests/2_docker_daemon_configuration.sh b/tests/2_docker_daemon_configuration.sh index 00f87c1..5d56d4f 100644 --- a/tests/2_docker_daemon_configuration.sh +++ b/tests/2_docker_daemon_configuration.sh @@ -9,386 +9,306 @@ check_2() { startsectionjson "$id" "$desc" } -# 2.1 check_2_1() { local id="2.1" local desc="Ensure network traffic is restricted between containers on the default bridge (Scored)" - local remediation="Edit the Docker daemon configuration file to ensure that inter-container communication is disabled: \'icc\': false." + local remediation="Edit the Docker daemon configuration file to ensure that inter-container communication is disabled: icc: false." local remediationImpact="Inter-container communication is disabled on the default network bridge. If any communication between containers on the same host is desired, it needs to be explicitly defined using container linking or custom networks." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if get_docker_effective_command_line_args '--icc' | grep false >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" elif get_docker_configuration_file_args 'icc' | grep "false" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi } -# 2.2 check_2_2() { local id="2.2" local desc="Ensure the logging level is set to 'info' (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'log-level' >/dev/null 2>&1; then if get_docker_configuration_file_args 'log-level' | grep info >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" elif [ -z "$(get_docker_configuration_file_args 'log-level')" ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi elif get_docker_effective_command_line_args '-l'; then if get_docker_effective_command_line_args '-l' | grep "info" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" fi } -# 2.3 check_2_3() { local id="2.3" local desc="Ensure Docker is allowed to make changes to iptables (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if get_docker_effective_command_line_args '--iptables' | grep "false" >/dev/null 2>&1; then - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" elif get_docker_configuration_file_args 'iptables' | grep "false" >/dev/null 2>&1; then - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" else - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" fi } -# 2.4 check_2_4() { local id="2.4" local desc="Ensure insecure registries are not used (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if get_docker_effective_command_line_args '--insecure-registry' | grep "insecure-registry" >/dev/null 2>&1; then - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" elif ! [ -z "$(get_docker_configuration_file_args 'insecure-registries')" ]; then if get_docker_configuration_file_args 'insecure-registries' | grep '\[]' >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" fi } -# 2.5 check_2_5() { local id="2.5" local desc="Ensure aufs storage driver is not used (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "^\sStorage Driver:\s*aufs\s*$" >/dev/null 2>&1; then - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" else - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" fi } -# 2.6 check_2_6() { local id="2.6" local desc="Ensure TLS authentication for Docker daemon is configured (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if [ $(get_docker_configuration_file_args 'tcp://') ] || \ [ $(get_docker_cumulative_command_line_args '-H' | grep -vE '(unix|fd)://') >/dev/null 2>&1 ]; then if [ $(get_docker_configuration_file_args '"tlsverify":' | grep 'true') ] || \ [ $(get_docker_cumulative_command_line_args '--tlsverify' | grep 'tlsverify') >/dev/null 2>&1 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" elif [ $(get_docker_configuration_file_args '"tls":' | grep 'true') ] || \ [ $(get_docker_cumulative_command_line_args '--tls' | grep 'tls$') >/dev/null 2>&1 ]; then - warn "$check" + warn -s "$check" warn " * Docker daemon currently listening on TCP with TLS, but no verification" - resulttestjson "WARN" "Docker daemon currently listening on TCP with TLS, but no verification" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Docker daemon currently listening on TCP with TLS, but no verification" else - warn "$check" + warn -s "$check" warn " * Docker daemon currently listening on TCP without TLS" - resulttestjson "WARN" "Docker daemon currently listening on TCP without TLS" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Docker daemon currently listening on TCP without TLS" fi else - info "$check" + info -c "$check" info " * Docker daemon not listening on TCP" - resulttestjson "INFO" "Docker daemon not listening on TCP" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Docker daemon not listening on TCP" fi } -# 2.7 check_2_7() { local id="2.7" local desc="Ensure the default ulimit is configured appropriately (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'default-ulimit' | grep -v '{}' >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check" + logcheckresult "PASS" elif get_docker_effective_command_line_args '--default-ulimit' | grep "default-ulimit" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check" + logcheckresult "PASS" else - info "$check" + info -c "$check" info " * Default ulimit doesn't appear to be set" - resulttestjson "INFO" "Default ulimit doesn't appear to be set" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Default ulimit doesn't appear to be set" fi } -# 2.8 check_2_8() { local id="2.8" local desc="Enable user namespace support (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'userns-remap' | grep -v '""'; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" elif get_docker_effective_command_line_args '--userns-remap' | grep "userns-remap" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi } -# 2.9 check_2_9() { local id="2.9" local desc="Ensure the default cgroup usage has been confirmed (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'cgroup-parent' | grep -v ''; then - warn "$check" + warn -s "$check" info " * Confirm cgroup usage" - resulttestjson "WARN" "Confirm cgroup usage" - currentScore=$((currentScore + 0)) + logcheckresult "WARN" "Confirm cgroup usage" elif get_docker_effective_command_line_args '--cgroup-parent' | grep "cgroup-parent" >/dev/null 2>&1; then - warn "$check" + warn -s "$check" info " * Confirm cgroup usage" - resulttestjson "WARN" "Confirm cgroup usage" - currentScore=$((currentScore + 0)) + logcheckresult "WARN" "Confirm cgroup usage" else - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" fi } -# 2.10 check_2_10() { local id="2.10" local desc="Ensure base device size is not changed until needed (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'storage-opts' | grep "dm.basesize" >/dev/null 2>&1; then - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" elif get_docker_effective_command_line_args '--storage-opt' | grep "dm.basesize" >/dev/null 2>&1; then - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" else - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" fi } -# 2.11 check_2_11() { local id="2.11" local desc="Ensure that authorization for Docker client commands is enabled (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'authorization-plugins' | grep -v '\[]'; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" elif get_docker_effective_command_line_args '--authorization-plugin' | grep "authorization-plugin" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi } -# 2.12 check_2_12() { local id="2.12" local desc="Ensure centralized and remote logging is configured (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info --format '{{ .LoggingDriver }}' | grep 'json-file' >/dev/null 2>&1; then - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" else - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" fi } -# 2.13 check_2_13() { local id="2.13" local desc="Ensure live restore is enabled (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Live Restore Enabled:\s*true\s*" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then - pass "$check (Incompatible with swarm mode)" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check (Incompatible with swarm mode)" + logcheckresult "PASS" elif get_docker_effective_command_line_args '--live-restore' | grep "live-restore" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi fi } -# 2.14 check_2_14() { local id="2.14" local desc="Ensure Userland Proxy is Disabled (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'userland-proxy' | grep false >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" elif get_docker_effective_command_line_args '--userland-proxy=false' 2>/dev/null | grep "userland-proxy=false" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi } -# 2.15 check_2_15() { local id="2.15" local desc="Ensure that a daemon-wide custom seccomp profile is applied if appropriate (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info --format '{{ .SecurityOptions }}' | grep 'name=seccomp,profile=default' 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check" + logcheckresult "PASS" else - info "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + info -c "$check" + logcheckresult "INFO" fi } -# 2.16 check_2_16() { docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \ | awk '{print $NF; exit}' | tr -d '[:alpha:]-,.' | cut -c 1-4) @@ -398,45 +318,37 @@ check_2_16() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if [ "$docker_version" -le 1903 ]; then if docker version -f '{{.Server.Experimental}}' | grep false 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else local desc="$desc (Deprecated)" local check="$id - $desc" - info "$desc" - resulttestjson "INFO" + info -c "$desc" + logcheckresult "INFO" fi } -# 2.17 check_2_17() { local id="2.17" local desc="Ensure containers are restricted from acquiring new privileges (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if get_docker_effective_command_line_args '--no-new-privileges' | grep "no-new-privileges" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" elif get_docker_configuration_file_args 'no-new-privileges' | grep true >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi } diff --git a/tests/3_docker_daemon_configuration_files.sh b/tests/3_docker_daemon_configuration_files.sh index f5ea624..f443b99 100644 --- a/tests/3_docker_daemon_configuration_files.sh +++ b/tests/3_docker_daemon_configuration_files.sh @@ -9,182 +9,150 @@ check_3() { startsectionjson "$id" "$desc" } -# 3.1 check_3_1() { local id="3.1" local desc="Ensure that the docker.service file ownership is set to root:root (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="$(get_service_file docker.service)" if [ -f "$file" ]; then if [ "$(stat -c %u%g $file)" -eq 00 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong ownership for $file" - resulttestjson "WARN" "Wrong ownership for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong ownership for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 3.2 check_3_2() { local id="3.2" local desc="Ensure that docker.service file permissions are appropriately set (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="$(get_service_file docker.service)" if [ -f "$file" ]; then if [ "$(stat -c %a $file)" -le 644 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong permissions for $file" - resulttestjson "WARN" "Wrong permissions for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong permissions for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 3.3 check_3_3() { local id="3.3" local desc="Ensure that docker.socket file ownership is set to root:root (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="$(get_service_file docker.socket)" if [ -f "$file" ]; then if [ "$(stat -c %u%g $file)" -eq 00 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong ownership for $file" - resulttestjson "WARN" "Wrong ownership for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong ownership for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 3.4 check_3_4() { local id="3.4" local desc="Ensure that docker.socket file permissions are set to 644 or more restrictive (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="$(get_service_file docker.socket)" if [ -f "$file" ]; then if [ "$(stat -c %a $file)" -le 644 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong permissions for $file" - resulttestjson "WARN" "Wrong permissions for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong permissions for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 3.5 check_3_5() { local id="3.5" local desc="Ensure that the /etc/docker directory ownership is set to root:root (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) directory="/etc/docker" if [ -d "$directory" ]; then if [ "$(stat -c %u%g $directory)" -eq 00 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong ownership for $directory" - resulttestjson "WARN" "Wrong ownership for $directory" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong ownership for $directory" fi else - info "$check" + info -c "$check" info " * Directory not found" - resulttestjson "INFO" "Directory not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Directory not found" fi } -# 3.6 check_3_6() { local id="3.6" local desc="Ensure that /etc/docker directory permissions are set to 755 or more restrictively (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) directory="/etc/docker" if [ -d "$directory" ]; then if [ "$(stat -c %a $directory)" -le 755 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong permissions for $directory" - resulttestjson "WARN" "Wrong permissions for $directory" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong permissions for $directory" fi else - info "$check" + info -c "$check" info " * Directory not found" - resulttestjson "INFO" "Directory not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Directory not found" fi } -# 3.7 check_3_7() { local id="3.7" local desc="Ensure that registry certificate file ownership is set to root:root (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) directory="/etc/docker/certs.d/" if [ -d "$directory" ]; then fail=0 @@ -195,31 +163,26 @@ check_3_7() { fi done if [ $fail -eq 1 ]; then - warn "$check" + warn -s "$check" warn " * Wrong ownership for $directory" - resulttestjson "WARN" "Wrong ownership for $directory" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong ownership for $directory" else - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" fi else - info "$check" + info -c "$check" info " * Directory not found" - resulttestjson "INFO" "Directory not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Directory not found" fi } -# 3.8 check_3_8() { local id="3.8" local desc="Ensure that registry certificate file permissions are set to 444 or more restrictively (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) directory="/etc/docker/certs.d/" if [ -d "$directory" ]; then fail=0 @@ -230,31 +193,26 @@ check_3_8() { fi done if [ $fail -eq 1 ]; then - warn "$check" + warn -s "$check" warn " * Wrong permissions for $directory" - resulttestjson "WARN" "Wrong permissions for $directory" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong permissions for $directory" else - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" fi else - info "$check" + info -c "$check" info " * Directory not found" - resulttestjson "INFO" "Directory not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Directory not found" fi } -# 3.9 check_3_9() { local id="3.9" local desc="Ensure that TLS CA certificate file ownership is set to root:root (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if [ -n "$(get_docker_configuration_file_args 'tlscacert')" ]; then tlscacert=$(get_docker_configuration_file_args 'tlscacert') else @@ -262,31 +220,26 @@ check_3_9() { fi if [ -f "$tlscacert" ]; then if [ "$(stat -c %u%g "$tlscacert")" -eq 00 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong ownership for $tlscacert" - resulttestjson "WARN" "Wrong ownership for $tlscacert" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong ownership for $tlscacert" fi else - info "$check" + info -c "$check" info " * No TLS CA certificate found" - resulttestjson "INFO" "No TLS CA certificate found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "No TLS CA certificate found" fi } -# 3.10 check_3_10() { local id="3.10" local desc="Ensure that TLS CA certificate file permissions are set to 444 or more restrictively (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if [ -n "$(get_docker_configuration_file_args 'tlscacert')" ]; then tlscacert=$(get_docker_configuration_file_args 'tlscacert') else @@ -294,31 +247,26 @@ check_3_10() { fi if [ -f "$tlscacert" ]; then if [ "$(stat -c %a $tlscacert)" -le 444 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong permissions for $tlscacert" - resulttestjson "WARN" "Wrong permissions for $tlscacert" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong permissions for $tlscacert" fi else - info "$check" + info -c "$check" info " * No TLS CA certificate found" - resulttestjson "INFO" "No TLS CA certificate found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "No TLS CA certificate found" fi } -# 3.11 check_3_11() { local id="3.11" local desc="Ensure that Docker server certificate file ownership is set to root:root (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if [ -n "$(get_docker_configuration_file_args 'tlscert')" ]; then tlscert=$(get_docker_configuration_file_args 'tlscert') else @@ -326,31 +274,26 @@ check_3_11() { fi if [ -f "$tlscert" ]; then if [ "$(stat -c %u%g "$tlscert")" -eq 00 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong ownership for $tlscert" - resulttestjson "WARN" "Wrong ownership for $tlscert" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong ownership for $tlscert" fi else - info "$check" + info -c "$check" info " * No TLS Server certificate found" - resulttestjson "INFO" "No TLS Server certificate found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "No TLS Server certificate found" fi } -# 3.12 check_3_12() { local id="3.12" local desc="Ensure that the Docker server certificate file permissions are set to 444 or more restrictively (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if [ -n "$(get_docker_configuration_file_args 'tlscert')" ]; then tlscert=$(get_docker_configuration_file_args 'tlscert') else @@ -358,31 +301,26 @@ check_3_12() { fi if [ -f "$tlscert" ]; then if [ "$(stat -c %a $tlscert)" -le 444 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong permissions for $tlscert" - resulttestjson "WARN" "Wrong permissions for $tlscert" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong permissions for $tlscert" fi else - info "$check" + info -c "$check" info " * No TLS Server certificate found" - resulttestjson "INFO" "No TLS Server certificate found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "No TLS Server certificate found" fi } -# 3.13 check_3_13() { local id="3.13" local desc="Ensure that the Docker server certificate key file ownership is set to root:root (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if [ -n "$(get_docker_configuration_file_args 'tlskey')" ]; then tlskey=$(get_docker_configuration_file_args 'tlskey') else @@ -390,31 +328,26 @@ check_3_13() { fi if [ -f "$tlskey" ]; then if [ "$(stat -c %u%g "$tlskey")" -eq 00 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong ownership for $tlskey" - resulttestjson "WARN" "Wrong ownership for $tlskey" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong ownership for $tlskey" fi else - info "$check" + info -c "$check" info " * No TLS Key found" - resulttestjson "INFO" "No TLS Key found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "No TLS Key found" fi } -# 3.14 check_3_14() { local id="3.14" local desc="Ensure that the Docker server certificate key file permissions are set to 400 (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if [ -n "$(get_docker_configuration_file_args 'tlskey')" ]; then tlskey=$(get_docker_configuration_file_args 'tlskey') else @@ -422,244 +355,201 @@ check_3_14() { fi if [ -f "$tlskey" ]; then if [ "$(stat -c %a $tlskey)" -eq 400 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong permissions for $tlskey" - resulttestjson "WARN" "Wrong permissions for $tlskey" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong permissions for $tlskey" fi else - info "$check" + info -c "$check" info " * No TLS Key found" - resulttestjson "INFO" "No TLS Key found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "No TLS Key found" fi } -# 3.15 check_3_15() { local id="3.15" local desc="Ensure that the Docker socket file ownership is set to root:docker (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/var/run/docker.sock" if [ -S "$file" ]; then if [ "$(stat -c %U:%G $file)" = 'root:docker' ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong ownership for $file" - resulttestjson "WARN" "Wrong ownership for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong ownership for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 3.16 check_3_16() { local id="3.16" local desc="Ensure that the Docker socket file permissions are set to 660 or more restrictively (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/var/run/docker.sock" if [ -S "$file" ]; then if [ "$(stat -c %a $file)" -le 660 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong permissions for $file" - resulttestjson "WARN" "Wrong permissions for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong permissions for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 3.17 check_3_17() { local id="3.17" local desc="Ensure that the daemon.json file ownership is set to root:root (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/etc/docker/daemon.json" if [ -f "$file" ]; then if [ "$(stat -c %U:%G $file)" = 'root:root' ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong ownership for $file" - resulttestjson "WARN" "Wrong ownership for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong ownership for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 3.18 check_3_18() { local id="3.18" local desc="Ensure that daemon.json file permissions are set to 644 or more restrictive (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/etc/docker/daemon.json" if [ -f "$file" ]; then if [ "$(stat -c %a $file)" -le 644 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong permissions for $file" - resulttestjson "WARN" "Wrong permissions for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong permissions for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 3.19 check_3_19() { local id="3.19" local desc="Ensure that the /etc/default/docker file ownership is set to root:root (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/etc/default/docker" if [ -f "$file" ]; then if [ "$(stat -c %U:%G $file)" = 'root:root' ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong ownership for $file" - resulttestjson "WARN" "Wrong ownership for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong ownership for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 3.20 check_3_20() { local id="3.20" local desc="Ensure that the /etc/sysconfig/docker file ownership is set to root:root (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/etc/sysconfig/docker" if [ -f "$file" ]; then if [ "$(stat -c %U:%G $file)" = 'root:root' ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong ownership for $file" - resulttestjson "WARN" "Wrong ownership for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong ownership for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 3.21 check_3_21() { local id="3.21" local desc="Ensure that the /etc/sysconfig/docker file permissions are set to 644 or more restrictively (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/etc/sysconfig/docker" if [ -f "$file" ]; then if [ "$(stat -c %a $file)" -le 644 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong permissions for $file" - resulttestjson "WARN" "Wrong permissions for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong permissions for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } -# 3.22 check_3_22() { local id="3.22" local desc="Ensure that the /etc/default/docker file permissions are set to 644 or more restrictively (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) file="/etc/default/docker" if [ -f "$file" ]; then if [ "$(stat -c %a $file)" -le 644 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" + warn -s "$check" warn " * Wrong permissions for $file" - resulttestjson "WARN" "Wrong permissions for $file" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Wrong permissions for $file" fi else - info "$check" + info -c "$check" info " * File not found" - resulttestjson "INFO" "File not found" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "File not found" fi } diff --git a/tests/4_container_images.sh b/tests/4_container_images.sh index fcd4e42..72a3215 100644 --- a/tests/4_container_images.sh +++ b/tests/4_container_images.sh @@ -9,21 +9,17 @@ check_4() { startsectionjson "$id" "$desc" } -# 4.1 check_4_1() { local id="4.1" local desc="Ensure that a user for the container has been created (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - # If container_users is empty, there are no running containers if [ -z "$containers" ]; then - info "$check" + info -c "$check" info " * No containers running" - resulttestjson "INFO" "No containers running" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "No containers running" else # We have some containers running, set failure flag to 0. Check for Users. fail=0 @@ -37,7 +33,7 @@ check_4_1() { if [ "$user" = "User=0" ] || [ "$user" = "User=root" ] || [ "$user" = "User=" ] || [ "$user" = "User=[]" ] || [ "$user" = "User=" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" + warn -s "$check" warn " * Running as root: $c" root_containers="$root_containers $c" fail=1 @@ -49,94 +45,76 @@ check_4_1() { done # We went through all the containers and found none running as root if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "running as root" "$root_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "running as root" "$root_containers" fi fi # Make the loop separator go back to space set +f; unset IFS } -# 4.2 check_4_2() { local id="4.2" local desc="Ensure that containers use only trusted base images (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "NOTE" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "NOTE" } -# 4.3 check_4_3() { local id="4.3" local desc="Ensure that unnecessary packages are not installed in the container (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "NOTE" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "NOTE" } -# 4.4 check_4_4() { local id="4.4" local desc="Ensure images are scanned and rebuilt to include security patches (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "NOTE" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "NOTE" } -# 4.5 check_4_5() { local id="4.5" local desc="Ensure Content trust for Docker is Enabled (Scored)" - local remediation="Add DOCKER_CONTENT_TRUST variable to the /etc/environment file using command echo \'DOCKER_CONTENT_TRUST=1\' | sudo tee -a /etc/environment." + local remediation="Add DOCKER_CONTENT_TRUST variable to the /etc/environment file using command echo DOCKER_CONTENT_TRUST=1 | sudo tee -a /etc/environment." local remediationImpact="This prevents users from working with tagged images unless they contain a signature." local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if [ "x$DOCKER_CONTENT_TRUST" = "x1" ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - saveRemediation --id "${id}" --rem "${remediation}" --imp "${remediationImpact}" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi } -# 4.6 check_4_6() { local id="4.6" local desc="Ensure that HEALTHCHECK instructions have been added to container images (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) fail=0 no_health_images="" for img in $images; do if docker inspect --format='{{.Config.Healthcheck}}' "$img" 2>/dev/null | grep -e "" >/dev/null 2>&1; then if [ $fail -eq 0 ]; then fail=1 - warn "$check" + warn -s "$check" fi imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null) if ! [ "$imgName" = '[]' ]; then @@ -149,30 +127,26 @@ check_4_6() { fi done if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Images w/o HEALTHCHECK" "$no_health_images" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Images w/o HEALTHCHECK" "$no_health_images" fi } -# 4.7 check_4_7() { local id="4.7" local desc="Ensure update instructions are not used alone in the Dockerfile (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) fail=0 update_images="" for img in $images; do if docker history "$img" 2>/dev/null | grep -e "update" >/dev/null 2>&1; then if [ $fail -eq 0 ]; then fail=1 - info "$check" + info -c "$check" fi imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null) if ! [ "$imgName" = '[]' ]; then @@ -182,36 +156,29 @@ check_4_7() { fi done if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 0)) + pass -c "$check" + logcheckresult "PASS" else - resulttestjson "INFO" "Update instructions found" "$update_images" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Update instructions found" "$update_images" fi } -# 4.8 check_4_8() { local id="4.8" local desc="Ensure setuid and setgid permissions are removed (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "NOTE" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "NOTE" } -# 4.9 check_4_9() { local id="4.9" local desc="Ensure that COPY is used instead of ADD in Dockerfiles (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) fail=0 add_images="" for img in $images; do @@ -219,49 +186,41 @@ check_4_9() { sed '$d' | grep -q 'ADD'; then if [ $fail -eq 0 ]; then fail=1 - info "$check" + info -c "$check" fi imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null) if ! [ "$imgName" = '[]' ]; then info " * ADD in image history: $imgName" add_images="$add_images $imgName" fi - currentScore=$((currentScore + 0)) fi done if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 0)) + pass -c "$check" + logcheckresult "PASS" else - resulttestjson "INFO" "Images using ADD" "$add_images" + logcheckresult "INFO" "Images using ADD" "$add_images" fi } -# 4.10 check_4_10() { local id="4.10" local desc="Ensure secrets are not stored in Dockerfiles (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "NOTE" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "NOTE" } -# 4.11 check_4_11() { local id="4.11" local desc="Ensure only verified packages are are installed (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "NOTE" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "NOTE" } check_4_end() { diff --git a/tests/5_container_runtime.sh b/tests/5_container_runtime.sh index 6b7955d..76c4d6f 100644 --- a/tests/5_container_runtime.sh +++ b/tests/5_container_runtime.sh @@ -13,18 +13,15 @@ check_running_containers() { # If containers is empty, there are no running containers if [ -z "$containers" ]; then info " * No containers running, skipping Section 5" - running_containers=0 else - running_containers=1 # Make the loop separator be a new-line in POSIX compliant fashion set -f; IFS=$' ' fi } -# 5.1 check_5_1() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -33,8 +30,6 @@ check_5_1() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 no_apparmor_containers="" for c in $containers; do @@ -43,7 +38,7 @@ check_5_1() { if [ "$policy" = "AppArmorProfile=" ] || [ "$policy" = "AppArmorProfile=[]" ] || [ "$policy" = "AppArmorProfile=" ] || [ "$policy" = "AppArmorProfile=unconfined" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" + warn -s "$check" warn " * No AppArmorProfile Found: $c" no_apparmor_containers="$no_apparmor_containers $c" fail=1 @@ -55,18 +50,15 @@ check_5_1() { done # We went through all the containers and found none without AppArmor if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers with no AppArmorProfile" "$no_apparmor_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers with no AppArmorProfile" "$no_apparmor_containers" fi } -# 5.2 check_5_2() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -75,8 +67,6 @@ check_5_2() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 no_securityoptions_containers="" for c in $containers; do @@ -85,7 +75,7 @@ check_5_2() { if [ "$policy" = "SecurityOpt=" ] || [ "$policy" = "SecurityOpt=[]" ] || [ "$policy" = "SecurityOpt=" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" + warn -s "$check" warn " * No SecurityOptions Found: $c" no_securityoptions_containers="$no_securityoptions_containers $c" fail=1 @@ -97,18 +87,15 @@ check_5_2() { done # We went through all the containers and found none without SELinux if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers with no SecurityOptions" "$no_securityoptions_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers with no SecurityOptions" "$no_securityoptions_containers" fi } -# 5.3 check_5_3() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -117,8 +104,6 @@ check_5_3() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 caps_containers="" for c in $containers; do @@ -130,7 +115,7 @@ check_5_3() { if [ "$caps" != 'CapAdd=' ] && [ "$caps" != 'CapAdd=[]' ] && [ "$caps" != 'CapAdd=' ] && [ "$caps" != 'CapAdd=' ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" + warn -s "$check" warn " * Capabilities added: $caps to $c" caps_containers="$caps_containers $c" fail=1 @@ -142,18 +127,15 @@ check_5_3() { done # We went through all the containers and found none with extra capabilities if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Capabilities added for containers" "$caps_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Capabilities added for containers" "$caps_containers" fi } -# 5.4 check_5_4() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -162,8 +144,6 @@ check_5_4() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 privileged_containers="" for c in $containers; do @@ -172,7 +152,7 @@ check_5_4() { if [ "$privileged" = "true" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" + warn -s "$check" warn " * Container running in Privileged mode: $c" privileged_containers="$privileged_containers $c" fail=1 @@ -184,18 +164,15 @@ check_5_4() { done # We went through all the containers and found no privileged containers if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers running in privileged mode" "$privileged_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers running in privileged mode" "$privileged_containers" fi } -# 5.5 check_5_5() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -204,8 +181,6 @@ check_5_5() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - # List of sensitive directories to test for. Script uses new-lines as a separator. # Note the lack of identation. It needs it for the substring comparison. sensitive_dirs='/ @@ -233,7 +208,7 @@ check_5_5() { if [ $sensitive -eq 1 ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" + warn -s "$check" warn " * Sensitive directory $v mounted in: $c" sensitive_mount_containers="$sensitive_mount_containers $c:$v" fail=1 @@ -246,18 +221,15 @@ check_5_5() { done # We went through all the containers and found none with sensitive mounts if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers with sensitive directories mounted" "$sensitive_mount_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers with sensitive directories mounted" "$sensitive_mount_containers" fi } -# 5.6 check_5_6() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -266,8 +238,6 @@ check_5_6() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 ssh_exec_containers="" printcheck=0 @@ -277,7 +247,7 @@ check_5_6() { if [ "$processes" -ge 1 ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" + warn -s "$check" warn " * Container running sshd: $c" ssh_exec_containers="$ssh_exec_containers $c" fail=1 @@ -291,7 +261,7 @@ check_5_6() { exec_check=$(docker exec "$c" ps -el 2>/dev/null) if [ $? -eq 255 ]; then if [ $printcheck -eq 0 ]; then - warn "$check" + warn -s "$check" printcheck=1 fi warn " * Docker exec fails: $c" @@ -302,18 +272,15 @@ check_5_6() { done # We went through all the containers and found none with sshd if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers with sshd/docker exec failures" "$ssh_exec_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers with sshd/docker exec failures" "$ssh_exec_containers" fi } -# 5.7 check_5_7() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -322,8 +289,6 @@ check_5_7() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 privileged_port_containers="" for c in $containers; do @@ -335,7 +300,7 @@ check_5_7() { if [ -n "$port" ] && [ "$port" -lt 1024 ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" + warn -s "$check" warn " * Privileged Port in use: $port in $c" privileged_port_containers="$privileged_port_containers $c:$port" fail=1 @@ -348,18 +313,15 @@ check_5_7() { done # We went through all the containers and found no privileged ports if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers using privileged ports" "$privileged_port_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers using privileged ports" "$privileged_port_containers" fi } -# 5.8 check_5_8() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -368,15 +330,12 @@ check_5_8() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "NOTE" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "NOTE" } -# 5.9 check_5_9() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -385,8 +344,6 @@ check_5_9() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 net_host_containers="" for c in $containers; do @@ -395,7 +352,7 @@ check_5_9() { if [ "$mode" = "NetworkMode=host" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" + warn -s "$check" warn " * Container running with networking mode 'host': $c" net_host_containers="$net_host_containers $c" fail=1 @@ -407,18 +364,15 @@ check_5_9() { done # We went through all the containers and found no Network Mode host if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 0)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers running with networking mode 'host'" "$net_host_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers running with networking mode 'host'" "$net_host_containers" fi } -# 5.10 check_5_10() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -427,8 +381,6 @@ check_5_10() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 mem_unlimited_containers="" for c in $containers; do @@ -441,30 +393,27 @@ check_5_10() { if [ "$memory" = "0" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Container running without memory restrictions: $c" + warn -s "$check" + warn " * Container running without memory restrictions: $c" mem_unlimited_containers="$mem_unlimited_containers $c" fail=1 else - warn " * Container running without memory restrictions: $c" + warn " * Container running without memory restrictions: $c" mem_unlimited_containers="$mem_unlimited_containers $c" fi fi done # We went through all the containers and found no lack of Memory restrictions if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Container running without memory restrictions" "$mem_unlimited_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Container running without memory restrictions" "$mem_unlimited_containers" fi } -# 5.11 check_5_11() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -473,8 +422,6 @@ check_5_11() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 cpu_unlimited_containers="" for c in $containers; do @@ -487,30 +434,27 @@ check_5_11() { if [ "$shares" = "0" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Container running without CPU restrictions: $c" + warn -s "$check" + warn " * Container running without CPU restrictions: $c" cpu_unlimited_containers="$cpu_unlimited_containers $c" fail=1 else - warn " * Container running without CPU restrictions: $c" + warn " * Container running without CPU restrictions: $c" cpu_unlimited_containers="$cpu_unlimited_containers $c" fi fi done # We went through all the containers and found no lack of CPUShare restrictions if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers running without CPU restrictions" "$cpu_unlimited_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers running without CPU restrictions" "$cpu_unlimited_containers" fi } -# 5.12 check_5_12() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -519,8 +463,6 @@ check_5_12() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 fsroot_mount_containers="" for c in $containers; do @@ -529,30 +471,27 @@ check_5_12() { if [ "$read_status" = "false" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Container running with root FS mounted R/W: $c" + warn -s "$check" + warn " * Container running with root FS mounted R/W: $c" fsroot_mount_containers="$fsroot_mount_containers $c" fail=1 else - warn " * Container running with root FS mounted R/W: $c" + warn " * Container running with root FS mounted R/W: $c" fsroot_mount_containers="$fsroot_mount_containers $c" fi fi done # We went through all the containers and found no R/W FS mounts if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers running with root FS mounted R/W" "$fsroot_mount_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers running with root FS mounted R/W" "$fsroot_mount_containers" fi } -# 5.13 check_5_13() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -561,8 +500,6 @@ check_5_13() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 incoming_unbound_containers="" for c in $containers; do @@ -570,12 +507,12 @@ check_5_13() { if [ "$ip" = "0.0.0.0" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Port being bound to wildcard IP: $ip in $c" + warn -s "$check" + warn " * Port being bound to wildcard IP: $ip in $c" incoming_unbound_containers="$incoming_unbound_containers $c:$ip" fail=1 else - warn " * Port being bound to wildcard IP: $ip in $c" + warn " * Port being bound to wildcard IP: $ip in $c" incoming_unbound_containers="$incoming_unbound_containers $c:$ip" fi fi @@ -583,18 +520,15 @@ check_5_13() { done # We went through all the containers and found no ports bound to 0.0.0.0 if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers with port bound to wildcard IP" "$incoming_unbound_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers with port bound to wildcard IP" "$incoming_unbound_containers" fi } -# 5.14 check_5_14() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -603,8 +537,6 @@ check_5_14() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 maxretry_unset_containers="" for c in $containers; do @@ -613,30 +545,27 @@ check_5_14() { if [ "$policy" != "MaximumRetryCount=5" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * MaximumRetryCount is not set to 5: $c" + warn -s "$check" + warn " * MaximumRetryCount is not set to 5: $c" maxretry_unset_containers="$maxretry_unset_containers $c" fail=1 else - warn " * MaximumRetryCount is not set to 5: $c" + warn " * MaximumRetryCount is not set to 5: $c" maxretry_unset_containers="$maxretry_unset_containers $c" fi fi done # We went through all the containers and they all had MaximumRetryCount=5 if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers with MaximumRetryCount not set to 5" "$maxretry_unset_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers with MaximumRetryCount not set to 5" "$maxretry_unset_containers" fi } -# 5.15 check_5_15() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -645,8 +574,6 @@ check_5_15() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 pidns_shared_containers="" for c in $containers; do @@ -655,30 +582,27 @@ check_5_15() { if [ "$mode" = "PidMode=host" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Host PID namespace being shared with: $c" + warn -s "$check" + warn " * Host PID namespace being shared with: $c" pidns_shared_containers="$pidns_shared_containers $c" fail=1 else - warn " * Host PID namespace being shared with: $c" + warn " * Host PID namespace being shared with: $c" pidns_shared_containers="$pidns_shared_containers $c" fi fi done # We went through all the containers and found none with PidMode as host if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers sharing host PID namespace" "$pidns_shared_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers sharing host PID namespace" "$pidns_shared_containers" fi } -# 5.16 check_5_16() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -687,8 +611,6 @@ check_5_16() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 ipcns_shared_containers="" for c in $containers; do @@ -697,30 +619,27 @@ check_5_16() { if [ "$mode" = "IpcMode=host" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Host IPC namespace being shared with: $c" + warn -s "$check" + warn " * Host IPC namespace being shared with: $c" ipcns_shared_containers="$ipcns_shared_containers $c" fail=1 else - warn " * Host IPC namespace being shared with: $c" + warn " * Host IPC namespace being shared with: $c" ipcns_shared_containers="$ipcns_shared_containers $c" fi fi done # We went through all the containers and found none with IPCMode as host if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers sharing host IPC namespace" "$ipcns_shared_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers sharing host IPC namespace" "$ipcns_shared_containers" fi } -# 5.17 check_5_17() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -729,8 +648,6 @@ check_5_17() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 hostdev_exposed_containers="" for c in $containers; do @@ -739,30 +656,27 @@ check_5_17() { if [ "$devices" != "Devices=" ] && [ "$devices" != "Devices=[]" ] && [ "$devices" != "Devices=" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - info "$check" - info " * Container has devices exposed directly: $c" + info -c "$check" + info " * Container has devices exposed directly: $c" hostdev_exposed_containers="$hostdev_exposed_containers $c" fail=1 else - info " * Container has devices exposed directly: $c" + info " * Container has devices exposed directly: $c" hostdev_exposed_containers="$hostdev_exposed_containers $c" fi fi done # We went through all the containers and found none with devices if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check" + logcheckresult "PASS" else - resulttestjson "INFO" "Containers with host devices exposed directly" "$hostdev_exposed_containers" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Containers with host devices exposed directly" "$hostdev_exposed_containers" fi } -# 5.18 check_5_18() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -771,8 +685,6 @@ check_5_18() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 no_ulimit_containers="" for c in $containers; do @@ -781,30 +693,27 @@ check_5_18() { if [ "$ulimits" = "Ulimits=" ] || [ "$ulimits" = "Ulimits=[]" ] || [ "$ulimits" = "Ulimits=" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - info "$check" - info " * Container no default ulimit override: $c" + info -c "$check" + info " * Container no default ulimit override: $c" no_ulimit_containers="$no_ulimit_containers $c" fail=1 else - info " * Container no default ulimit override: $c" + info " * Container no default ulimit override: $c" no_ulimit_containers="$no_ulimit_containers $c" fi fi done # We went through all the containers and found none without Ulimits if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check" + logcheckresult "PASS" else - resulttestjson "INFO" "Containers with no default ulimit override" "$no_ulimit_containers" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Containers with no default ulimit override" "$no_ulimit_containers" fi } -# 5.19 check_5_19() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -813,8 +722,6 @@ check_5_19() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 mountprop_shared_containers="" for c in $containers; do @@ -822,30 +729,27 @@ check_5_19() { grep shared 2>/dev/null 1>&2; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Mount propagation mode is shared: $c" + warn -s "$check" + warn " * Mount propagation mode is shared: $c" mountprop_shared_containers="$mountprop_shared_containers $c" fail=1 else - warn " * Mount propagation mode is shared: $c" + warn " * Mount propagation mode is shared: $c" mountprop_shared_containers="$mountprop_shared_containers $c" fi fi done # We went through all the containers and found none with shared propagation mode if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers with shared mount propagation" "$mountprop_shared_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers with shared mount propagation" "$mountprop_shared_containers" fi } -# 5.20 check_5_20() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -854,8 +758,6 @@ check_5_20() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 utcns_shared_containers="" for c in $containers; do @@ -864,30 +766,27 @@ check_5_20() { if [ "$mode" = "UTSMode=host" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Host UTS namespace being shared with: $c" + warn -s "$check" + warn " * Host UTS namespace being shared with: $c" utcns_shared_containers="$utcns_shared_containers $c" fail=1 else - warn " * Host UTS namespace being shared with: $c" + warn " * Host UTS namespace being shared with: $c" utcns_shared_containers="$utcns_shared_containers $c" fi fi done # We went through all the containers and found none with UTSMode as host if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers sharing host UTS namespace" "$utcns_shared_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers sharing host UTS namespace" "$utcns_shared_containers" fi } -# 5.21 check_5_21() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -896,8 +795,6 @@ check_5_21() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 seccomp_disabled_containers="" for c in $containers; do @@ -905,30 +802,27 @@ check_5_21() { grep -E 'seccomp:unconfined|seccomp=unconfined' 2>/dev/null 1>&2; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Default seccomp profile disabled: $c" + warn -s "$check" + warn " * Default seccomp profile disabled: $c" seccomp_disabled_containers="$seccomp_disabled_containers $c" fail=1 else - warn " * Default seccomp profile disabled: $c" + warn " * Default seccomp profile disabled: $c" seccomp_disabled_containers="$seccomp_disabled_containers $c" fi fi done # We went through all the containers and found none with default secomp profile disabled if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers with default seccomp profile disabled" "$seccomp_disabled_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers with default seccomp profile disabled" "$seccomp_disabled_containers" fi } -# 5.22 check_5_22() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -937,15 +831,12 @@ check_5_22() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "NOTE" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "NOTE" } -# 5.23 check_5_23() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -954,15 +845,12 @@ check_5_23() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "NOTE" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "NOTE" } -# 5.24 check_5_24() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -971,8 +859,6 @@ check_5_24() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 unexpected_cgroup_containers="" for c in $containers; do @@ -981,30 +867,27 @@ check_5_24() { if [ "$mode" != "CgroupParent=x" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Confirm cgroup usage: $c" + warn -s "$check" + warn " * Confirm cgroup usage: $c" unexpected_cgroup_containers="$unexpected_cgroup_containers $c" fail=1 else - warn " * Confirm cgroup usage: $c" + warn " * Confirm cgroup usage: $c" unexpected_cgroup_containers="$unexpected_cgroup_containers $c" fi fi done # We went through all the containers and found none with UTSMode as host if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers using unexpected cgroup" "$unexpected_cgroup_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers using unexpected cgroup" "$unexpected_cgroup_containers" fi } -# 5.25 check_5_25() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi local id="5.25" @@ -1012,38 +895,33 @@ check_5_25() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 addprivs_containers="" for c in $containers; do if ! docker inspect --format 'SecurityOpt={{.HostConfig.SecurityOpt }}' "$c" | grep 'no-new-privileges' 2>/dev/null 1>&2; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Privileges not restricted: $c" + warn -s "$check" + warn " * Privileges not restricted: $c" addprivs_containers="$addprivs_containers $c" fail=1 else - warn " * Privileges not restricted: $c" + warn " * Privileges not restricted: $c" addprivs_containers="$addprivs_containers $c" fi fi done # We went through all the containers and found none with capability to acquire additional privileges if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers without restricted privileges" "$addprivs_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers without restricted privileges" "$addprivs_containers" fi } -# 5.26 check_5_26() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -1052,36 +930,31 @@ check_5_26() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 nohealthcheck_containers="" for c in $containers; do if ! docker inspect --format '{{ .Id }}: Health={{ .State.Health.Status }}' "$c" 2>/dev/null 1>&2; then if [ $fail -eq 0 ]; then - warn "$check" - warn " * Health check not set: $c" + warn -s "$check" + warn " * Health check not set: $c" nohealthcheck_containers="$nohealthcheck_containers $c" fail=1 else - warn " * Health check not set: $c" + warn " * Health check not set: $c" nohealthcheck_containers="$nohealthcheck_containers $c" fi fi done if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers without health check" "$nohealthcheck_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers without health check" "$nohealthcheck_containers" fi } -# 5.27 check_5_27() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -1090,15 +963,12 @@ check_5_27() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - info "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + info -c "$check" + logcheckresult "INFO" } -# 5.28 check_5_28() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -1107,8 +977,6 @@ check_5_28() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 nopids_limit_containers="" for c in $containers; do @@ -1117,30 +985,27 @@ check_5_28() { if [ "$pidslimit" = "0" ] || [ "$pidslimit" = "" ] || [ "$pidslimit" = "-1" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * PIDs limit not set: $c" + warn -s "$check" + warn " * PIDs limit not set: $c" nopids_limit_containers="$nopids_limit_containers $c" fail=1 else - warn " * PIDs limit not set: $c" + warn " * PIDs limit not set: $c" nopids_limit_containers="$nopids_limit_containers $c" fi fi done # We went through all the containers and found all with PIDs limit if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers without PIDs cgroup limit" "$nopids_limit_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers without PIDs cgroup limit" "$nopids_limit_containers" fi } -# 5.29 check_5_29() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -1149,8 +1014,6 @@ check_5_29() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 docker_network_containers="" networks=$(docker network ls -q 2>/dev/null) @@ -1161,7 +1024,7 @@ check_5_29() { if [ -n "$docker0Containers" ]; then if [ $fail -eq 0 ]; then - info "$check" + info -c "$check" fail=1 fi for c in $docker0Containers; do @@ -1172,28 +1035,24 @@ check_5_29() { cName=$(docker inspect --format '{{.Name}}' "$c" 2>/dev/null | sed 's/\///g' | grep -Ev "$pattern" ) fi if [ -n "$cName" ]; then - info " * Container in docker0 network: $cName" + info " * Container in docker0 network: $cName" docker_network_containers="$docker_network_containers $c:$cName" fi done fi - currentScore=$((currentScore + 0)) fi done # We went through all the containers and found none in docker0 network if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check" + logcheckresult "PASS" else - resulttestjson "INFO" "Containers using docker0 network" "$docker_network_containers" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "Containers using docker0 network" "$docker_network_containers" fi } -# 5.30 check_5_30() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -1202,38 +1061,33 @@ check_5_30() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 hostns_shared_containers="" for c in $containers; do if docker inspect --format '{{ .HostConfig.UsernsMode }}' "$c" 2>/dev/null | grep -i 'host' >/dev/null 2>&1; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Namespace shared: $c" + warn -s "$check" + warn " * Namespace shared: $c" hostns_shared_containers="$hostns_shared_containers $c" fail=1 else - warn " * Namespace shared: $c" + warn " * Namespace shared: $c" hostns_shared_containers="$hostns_shared_containers $c" fi fi done # We went through all the containers and found none with host's user namespace shared if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers sharing host user namespace" "$hostns_shared_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers sharing host user namespace" "$hostns_shared_containers" fi } -# 5.31 check_5_31() { - if [ "$running_containers" -ne 1 ]; then + if [ -z "$containers" ]; then return fi @@ -1242,32 +1096,28 @@ check_5_31() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - fail=0 docker_sock_containers="" for c in $containers; do if docker inspect --format '{{ .Mounts }}' "$c" 2>/dev/null | grep 'docker.sock' >/dev/null 2>&1; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" - warn " * Docker socket shared: $c" + warn -s "$check" + warn " * Docker socket shared: $c" docker_sock_containers="$docker_sock_containers $c" fail=1 else - warn " * Docker socket shared: $c" + warn " * Docker socket shared: $c" docker_sock_containers="$docker_sock_containers $c" fi fi done # We went through all the containers and found none with docker.sock shared if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Containers sharing docker socket" "$docker_sock_containers" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Containers sharing docker socket" "$docker_sock_containers" fi } diff --git a/tests/6_docker_security_operations.sh b/tests/6_docker_security_operations.sh index 35f4f03..1a97be6 100644 --- a/tests/6_docker_security_operations.sh +++ b/tests/6_docker_security_operations.sh @@ -9,14 +9,12 @@ check_6() { startsectionjson "$id" "$desc" } -# 6.1 check_6_1() { local id="6.1" local desc="Ensure that image sprawl is avoided (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) images=$(docker images -q | sort -u | wc -l | awk '{print $1}') active_images=0 @@ -26,37 +24,31 @@ check_6_1() { fi done - info "$check" - info " * There are currently: $images images" + info -c "$check" + info " * There are currently: $images images" if [ "$active_images" -lt "$((images / 2))" ]; then info " * Only $active_images out of $images are in use" fi - resulttestjson "INFO" "$active_images active/$images in use" - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "$active_images active/$images in use" } -# 6.2 check_6_2() { local id="6.2" local desc="Ensure that container sprawl is avoided (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) total_containers=$(docker info 2>/dev/null | grep "Containers" | awk '{print $2}') running_containers=$(docker ps -q | wc -l | awk '{print $1}') diff="$((total_containers - running_containers))" + info -c "$check" if [ "$diff" -gt 25 ]; then - info "$check" info " * There are currently a total of $total_containers containers, with only $running_containers of them currently running" - resulttestjson "INFO" "$total_containers total/$running_containers running" else - info "$check" info " * There are currently a total of $total_containers containers, with $running_containers of them currently running" - resulttestjson "INFO" "$total_containers total/$running_containers running" fi - currentScore=$((currentScore + 0)) + logcheckresult "INFO" "$total_containers total/$running_containers running" } check_6_end() { diff --git a/tests/7_docker_swarm_configuration.sh b/tests/7_docker_swarm_configuration.sh index 63b65ab..057d693 100644 --- a/tests/7_docker_swarm_configuration.sh +++ b/tests/7_docker_swarm_configuration.sh @@ -9,85 +9,69 @@ check_7() { startsectionjson "$id" "$desc" } -# 7.1 check_7_1() { local id="7.1" local desc="Ensure swarm mode is not Enabled, if not needed (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:*\sinactive\s*" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi } -# 7.2 check_7_2() { local id="7.2" local desc="Ensure that the minimum number of manager nodes have been created in a swarm (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then managernodes=$(docker node ls | grep -c "Leader") if [ "$managernodes" -eq 1 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - pass "$check (Swarm mode not enabled)" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check (Swarm mode not enabled)" + logcheckresult "PASS" fi } -# 7.3 check_7_3() { local id="7.3" local desc="Ensure that swarm services are bound to a specific host interface (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then $netbin -lnt | grep -e '\[::]:2377 ' -e ':::2377' -e '*:2377 ' -e ' 0\.0\.0\.0:2377 ' >/dev/null 2>&1 if [ $? -eq 1 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else - pass "$check (Swarm mode not enabled)" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check (Swarm mode not enabled)" + logcheckresult "PASS" fi } -# 7.4 check_7_4() { local id="7.4" local desc="Ensure that all Docker swarm overlay networks are encrypted (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) fail=0 unencrypted_networks="" for encnet in $(docker network ls --filter driver=overlay --quiet); do @@ -95,7 +79,7 @@ check_7_4() { grep -v 'encrypted:' 2>/dev/null 1>&2; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then - warn "$check" + warn -s "$check" fail=1 fi warn " * Unencrypted overlay network: $(docker network inspect --format '{{ .Name }} ({{ .Scope }})' "$encnet")" @@ -104,144 +88,115 @@ check_7_4() { done # We went through all the networks and found none that are unencrypted if [ $fail -eq 0 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - resulttestjson "WARN" "Unencrypted overlay networks:" "$unencrypted_networks" - currentScore=$((currentScore - 1)) + logcheckresult "WARN" "Unencrypted overlay networks:" "$unencrypted_networks" fi } -# 7.5 check_7_5() { local id="7.5" local desc="Ensure that Docker's secret management commands are used for managing secrets in a swarm cluster (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then if [ "$(docker secret ls -q | wc -l)" -ge 1 ]; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check" + logcheckresult "PASS" else - info "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + info -c "$check" + logcheckresult "INFO" fi else - pass "$check (Swarm mode not enabled)" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check (Swarm mode not enabled)" + logcheckresult "PASS" fi } -# 7.6 check_7_6() { local id="7.6" local desc="Ensure that swarm manager is run in auto-lock mode (Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then if ! docker swarm unlock-key 2>/dev/null | grep 'SWMKEY' 2>/dev/null 1>&2; then - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" else - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" fi else - pass "$check (Swarm mode not enabled)" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check (Swarm mode not enabled)" + logcheckresult "PASS" fi } -# 7.7 check_7_7() { local id="7.7" local desc="Ensure that the swarm manager auto-lock key is rotated periodically (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then - note "$check" - resulttestjson "NOTE" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "NOTE" else - pass "$check (Swarm mode not enabled)" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check (Swarm mode not enabled)" + logcheckresult "PASS" fi } -# 7.8 check_7_8() { local id="7.8" local desc="Ensure that node certificates are rotated as appropriate (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then if docker info 2>/dev/null | grep "Expiry Duration: 2 days"; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check" + logcheckresult "PASS" else - info "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + info -c "$check" + logcheckresult "INFO" fi else - pass "$check (Swarm mode not enabled)" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check (Swarm mode not enabled)" + logcheckresult "PASS" fi } -# 7.9 check_7_9() { local id="7.9" local desc="Ensure that CA certificates are rotated as appropriate (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then - info "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + info -c "$check" + logcheckresult "INFO" else - pass "$check (Swarm mode not enabled)" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check (Swarm mode not enabled)" + logcheckresult "PASS" fi } -# 7.10 check_7_10() { local id="7.10" local desc="Ensure that management plane traffic is separated from data plane traffic (Not Scored)" local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then - info "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + info -c "$check" + logcheckresult "INFO" else - pass "$check (Swarm mode not enabled)" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -c "$check (Swarm mode not enabled)" + logcheckresult "PASS" fi } diff --git a/tests/8_docker_enterprise_configuration.sh b/tests/8_docker_enterprise_configuration.sh index a1d2e65..7111c21 100644 --- a/tests/8_docker_enterprise_configuration.sh +++ b/tests/8_docker_enterprise_configuration.sh @@ -29,7 +29,6 @@ check_8_1() { info "$check" } -# 8.1.1 check_8_1_1() { if [ "$enterprise_license" -ne 1 ]; then return @@ -40,13 +39,10 @@ check_8_1_1() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "INFO" } -# 8.1.2 check_8_1_2() { if [ "$enterprise_license" -ne 1 ]; then return @@ -57,13 +53,10 @@ check_8_1_2() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "INFO" } -# 8.1.3 check_8_1_3() { if [ "$enterprise_license" -ne 1 ]; then return @@ -74,13 +67,10 @@ check_8_1_3() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "INFO" } -# 8.1.4 check_8_1_4() { if [ "$enterprise_license" -ne 1 ]; then return @@ -91,13 +81,10 @@ check_8_1_4() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "INFO" } -# 8.1.5 check_8_1_5() { if [ "$enterprise_license" -ne 1 ]; then return @@ -108,13 +95,10 @@ check_8_1_5() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "INFO" } -# 8.1.6 check_8_1_6() { if [ "$enterprise_license" -ne 1 ]; then return @@ -125,13 +109,10 @@ check_8_1_6() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "INFO" } -# 8.1.7 check_8_1_7() { if [ "$enterprise_license" -ne 1 ]; then return @@ -142,10 +123,8 @@ check_8_1_7() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "INFO" } check_8_2() { @@ -169,10 +148,8 @@ check_8_2_1() { local check="$id - $desc" starttestjson "$id" "$desc" - totalChecks=$((totalChecks + 1)) - note "$check" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + note -c "$check" + logcheckresult "INFO" } check_8_end() { diff --git a/tests/99_community_checks.sh b/tests/99_community_checks.sh index 3a14619..035a541 100644 --- a/tests/99_community_checks.sh +++ b/tests/99_community_checks.sh @@ -8,24 +8,45 @@ check_c() { startsectionjson "$id" "$desc" } -# check_c_1 check_c_1() { - local check="C.1 - This is a example check" - totalChecks=$((totalChecks + 1)) + local id="C.1" + local desc="This is a example check for a Scored check" + local check="$id - $desc" + starttestjson "$id" "$desc" + if docker info --format='{{ .Architecture }}' | grep 'x86_64' 2>/dev/null 1>&2; then - pass "$check" - resulttestjson "PASS" + pass -s "$check" + logcheckresult "PASS" + elif docker info --format='{{ .Architecture }}' | grep 'aarch64' 2>/dev/null 1>&2; then + info -c "$check" + logcheckresult "INFO" else - warn "$check" - resulttestjson "WARN" + warn -s "$check" + logcheckresult "WARN" + fi +} + +check_c_1_1() { + local id="C.1.1" + local desc="This is a example check for a Not Scored check" + local check="$id - $desc" + starttestjson "$id" "$desc" + + if docker info --format='{{ .Architecture }}' | grep 'x86_64' 2>/dev/null 1>&2; then + pass -c "$check" + logcheckresult "PASS" + elif docker info --format='{{ .Architecture }}' | grep 'aarch64' 2>/dev/null 1>&2; then + info -c "$check" + logcheckresult "INFO" + else + warn -c "$check" + logcheckresult "WARN" fi } -# check_c_2 check_c_2() { docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \ | awk '{print $NF; exit}' | tr -d '[:alpha:]-,.' | cut -c 1-4) - totalChecks=$((totalChecks + 1)) local id="C.2" local desc="Ensure operations on legacy registry (v1) are Disabled" @@ -34,23 +55,20 @@ check_c_2() { if [ "$docker_version" -lt 1712 ]; then if get_docker_configuration_file_args 'disable-legacy-registry' | grep 'true' >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" elif get_docker_effective_command_line_args '--disable-legacy-registry' | grep "disable-legacy-registry" >/dev/null 2>&1; then - pass "$check" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) + pass -s "$check" + logcheckresult "PASS" else - warn "$check" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + warn -s "$check" + logcheckresult "WARN" fi else local desc="$desc (Deprecated)" local check="$id - $desc" - info "$check" - resulttestjson "INFO" + info -c "$check" + logcheckresult "INFO" fi } diff --git a/tests/TESTS.md b/tests/TESTS.md new file mode 100644 index 0000000..fe2d799 --- /dev/null +++ b/tests/TESTS.md @@ -0,0 +1,266 @@ +# Available Checks +Check ID | Category | Subcategory | Check Name +------------ | ------------ | ------------ | ------------ +`host_configuration` | Host Configuration +`host_general_configuration` | | General Configuration +`check_1_1_1` | | | Ensure the container host has been Hardened (Not Scored) +`check_1_1_2` | | | Ensure that the version of Docker is up to date (Not Scored) +`linux_hosts_specific_configuration` | | Linux Hosts Specific Configuration +`check_1_2_1` | | | Ensure a separate partition for containers has been created (Scored) +`check_1_2_2` | | | Ensure only trusted users are allowed to control Docker daemon (Scored) +`check_1_2_3` | | | Ensure auditing is configured for the Docker daemon (Scored) +`check_1_2_4` | | | Ensure auditing is configured for Docker files and directories - /var/lib/docker (Scored) +`check_1_2_5` | | | Ensure auditing is configured for Docker files and directories - /etc/docker (Scored) +`check_1_2_6` | | | Ensure auditing is configured for Docker files and directories - docker.service (Scored) +`check_1_2_7` | | | Ensure auditing is configured for Docker files and directories - docker.socket (Scored) +`check_1_2_8` | | | Ensure auditing is configured for Docker files and directories - /etc/default/docker (Scored) +`check_1_2_9` | | | Ensure auditing is configured for Docker files and directories - /etc/sysconfig/docker (Scored) +`check_1_2_10` | | | Ensure auditing is configured for Docker files and directories - /etc/docker/daemon.json (Scored) +`check_1_2_11` | | | Ensure auditing is configured for Docker files and directories - /usr/bin/containerd (Scored) +`check_1_2_12` | | | Ensure auditing is configured for Docker files and directories - /usr/sbin/runc (Scored) +`docker_daemon_configuration` | Docker daemon configuration +`check_2_1` | | Ensure network traffic is restricted between containers on the default bridge (Scored) +`check_2_2` | | Ensure the logging level is set to 'info' (Scored) +`check_2_3` | | Ensure Docker is allowed to make changes to iptables (Scored) +`check_2_4` | | Ensure insecure registries are not used (Scored) +`check_2_5` | | Ensure aufs storage driver is not used (Scored) +`check_2_6` | | Ensure TLS authentication for Docker daemon is configured (Scored) +`check_2_7` | | Ensure the default ulimit is configured appropriately (Not Scored) +`check_2_8` | | Enable user namespace support (Scored) +`check_2_9` | | Ensure the default cgroup usage has been confirmed (Scored) +`check_2_10` | | Ensure base device size is not changed until needed (Scored) +`check_2_11` | | Ensure that authorization for Docker client commands is enabled (Scored) +`check_2_12` | | Ensure centralized and remote logging is configured (Scored) +`check_2_13` | | Ensure live restore is enabled (Scored) +`check_2_14` | | Ensure Userland Proxy is Disabled (Scored) +`check_2_15` | | Ensure that a daemon-wide custom seccomp profile is applied if appropriate (Not Scored) +`check_2_16` | | Ensure that experimental features are not implemented in production (Scored) +`check_2_17` | | Ensure containers are restricted from acquiring new privileges (Scored) +`docker_daemon_files` | Docker daemon configuration files +`check_3_1` | | Ensure that the docker.service file ownership is set to root:root (Scored) +`check_3_2` | | Ensure that docker.service file permissions are appropriately set (Scored) +`check_3_3` | | Ensure that docker.socket file ownership is set to root:root (Scored) +`check_3_4` | | Ensure that docker.socket file permissions are set to 644 or more restrictive (Scored) +`check_3_5` | | Ensure that the /etc/docker directory ownership is set to root:root (Scored) +`check_3_6` | | Ensure that /etc/docker directory permissions are set to 755 or more restrictively (Scored) +`check_3_7` | | Ensure that registry certificate file ownership is set to root:root (Scored) +`check_3_8` | | Ensure that registry certificate file permissions are set to 444 or more restrictively (Scored) +`check_3_9` | | Ensure that TLS CA certificate file ownership is set to root:root (Scored) +`check_3_10` | | Ensure that TLS CA certificate file permissions are set to 444 or more restrictively (Scored) +`check_3_11` | | Ensure that Docker server certificate file ownership is set to root:root (Scored) +`check_3_12` | | Ensure that the Docker server certificate file permissions are set to 444 or more restrictively (Scored) +`check_3_13` | | Ensure that the Docker server certificate key file ownership is set to root:root (Scored) +`check_3_14` | | Ensure that the Docker server certificate key file permissions are set to 400 (Scored) +`check_3_15` | | Ensure that the Docker socket file ownership is set to root:docker (Scored) +`check_3_16` | | Ensure that the Docker socket file permissions are set to 660 or more restrictively (Scored) +`check_3_17` | | Ensure that the daemon.json file ownership is set to root:root (Scored) +`check_3_18` | | Ensure that daemon.json file permissions are set to 644 or more restrictive (Scored) +`check_3_19` | | Ensure that the /etc/default/docker file ownership is set to root:root (Scored) +`check_3_20` | | Ensure that the /etc/sysconfig/docker file ownership is set to root:root (Scored) +`check_3_21` | | Ensure that the /etc/sysconfig/docker file permissions are set to 644 or more restrictively (Scored) +`check_3_22` | | Ensure that the /etc/default/docker file permissions are set to 644 or more restrictively (Scored) +`container_images` | Container Images and Build File +`check_4.1` | | Ensure that a user for the container has been created (Scored) +`check_4.2` | | Ensure that containers use only trusted base images (Not Scored) +`check_4.3` | | Ensure that unnecessary packages are not installed in the container (Not Scored) +`check_4.4` | | Ensure images are scanned and rebuilt to include security patches (Not Scored) +`check_4.5` | | Ensure Content trust for Docker is Enabled (Scored) +`check_4.6` | | Ensure that HEALTHCHECK instructions have been added to container images (Scored) +`check_4.7` | | Ensure update instructions are not used alone in the Dockerfile (Not Scored) +`check_4.8` | | Ensure setuid and setgid permissions are removed (Not Scored) +`check_4.9` | | Ensure that COPY is used instead of ADD in Dockerfiles (Not Scored) +`check_4.10` | | Ensure secrets are not stored in Dockerfiles (Not Scored) +`check_4.11` | | Ensure only verified packages are are installed (Not Scored) +`container_runtime` | Container Runtime +`check_running_containers` | | Check if exists running containers +`check_5_1` | | Ensure that, if applicable, an AppArmor Profile is enabled (Scored) +`check_5_2` | | Ensure that, if applicable, SELinux security options are set (Scored) +`check_5_3` | | Ensure that Linux kernel capabilities are restricted within containers (Scored) +`check_5_4` | | Ensure that privileged containers are not used (Scored) +`check_5_5` | | Ensure sensitive host system directories are not mounted on containers (Scored) +`check_5_6` | | Ensure sshd is not run within containers (Scored) +`check_5_7` | | Ensure privileged ports are not mapped within containers (Scored) +`check_5_8` | | Ensure that only needed ports are open on the container (Not Scored) +`check_5_9` | | Ensure that the host's network namespace is not shared (Scored) +`check_5_10` | | Ensure that the memory usage for containers is limited (Scored) +`check_5_11` | | Ensure that CPU priority is set appropriately on containers (Scored) +`check_5_12` | | Ensure that the container's root filesystem is mounted as read only (Scored) +`check_5_13` | | Ensure that incoming container traffic is bound to a specific host interface (Scored) +`check_5_14` | | Ensure that the 'on-failure' container restart policy is set to '5' (Scored) +`check_5_15` | | Ensure that the host's process namespace is not shared (Scored) +`check_5_16` | | Ensure that the host's IPC namespace is not shared (Scored) +`check_5_17` | | Ensure that host devices are not directly exposed to containers (Not Scored) +`check_5_18` | | Ensure that the default ulimit is overwritten at runtime if needed (Not Scored) +`check_5_19` | | Ensure mount propagation mode is not set to shared (Scored) +`check_5_20` | | Ensure that the host's UTS namespace is not shared (Scored) +`check_5_21` | | Ensurethe default seccomp profile is not Disabled (Scored) +`check_5_22` | | Ensure that docker exec commands are not used with the privileged option (Scored) +`check_5_23` | | Ensure that docker exec commands are not used with the user=root option (Not Scored) +`check_5_24` | | Ensure that cgroup usage is confirmed (Scored) +`check_5_25` | | Ensure that the container is restricted from acquiring additional privileges (Scored) +`check_5_26` | | Ensure that container health is checked at runtime (Scored) +`check_5_27` | | Ensure that Docker commands always make use of the latest version of their image (Not Scored) +`check_5_28` | | Ensure that the PIDs cgroup limit is used (Scored) +`check_5_29` | | Ensure that Docker's default bridge docker0 is not used (Not Scored) +`check_5_30` | | Ensure that the host's user namespaces are not shared (Scored) +`check_5_31` | | Ensure that the Docker socket is not mounted inside any containers (Scored) +`docker_security_operations` | Docker Security Operations +`check_6.1` | | Ensure that image sprawl is avoided (Not Scored) +`check_6.2` | | Ensure that container sprawl is avoided (Not Scored) +`docker_swarm_configuration` | Docker Swarm Configuration +`check_7.1` | | Ensure swarm mode is not Enabled, if not needed (Scored) +`check_7.2` | | Ensure that the minimum number of manager nodes have been created in a swarm (Scored) (Swarm mode not enabled) +`check_7.3` | | Ensure that swarm services are bound to a specific host interface (Scored) (Swarm mode not enabled) +`check_7.4` | | Ensure that all Docker swarm overlay networks are encrypted (Scored) +`check_7.5` | | Ensure that Docker's secret management commands are used for managing secrets in a swarm cluster (Not Scored) (Swarm mode not enabled) +`check_7.6` | | Ensure that swarm manager is run in auto-lock mode (Scored) (Swarm mode not enabled) +`check_7.7` | | Ensure that the swarm manager auto-lock key is rotated periodically (Not Scored) (Swarm mode not enabled) +`check_7.8` | | Ensure that node certificates are rotated as appropriate (Not Scored) (Swarm mode not enabled) +`check_7.9` | | Ensure that CA certificates are rotated as appropriate (Not Scored) (Swarm mode not enabled) +`check_7.10` | | Ensure that management plane traffic is separated from data plane traffic (Not Scored) (Swarm mode not enabled) +`docker_enterprise_configuration` | Docker Enterprise Configuration +`check_product_license` | | Check Docker license +`universal_control_plane_configuration` | | Universal Control Plane Configuration +`check_8.1.1` | | | Configure the LDAP authentication service (Scored) +`check_8.1.2` | | | Use external certificates (Scored) +`check_8.1.3` | | | Enforce the use of client certificate bundles for unprivileged users (Not Scored) +`check_8.1.4` | | | Configure applicable cluster role-based access control policies (Not Scored) +`check_8.1.5` | | | Enable signed image enforcement (Scored) +`check_8.1.6` | | | Set the Per-User Session Limit to a value of '3' or lower (Scored) +`check_8.1.7` | | | Set the 'Lifetime Minutes' and 'Renewal Threshold Minutes' values to '15' or lower and '0' respectively (Scored) +`docker_trusted_registry_configuration` | | Docker Trusted Registry Configuration +`check_8.2.1` | | | Enable image vulnerability scanning (Scored) +`community_checks` | Community contributed checks +`check_c_1` | | This is a example check +`check_c_2` | | Ensure operations on legacy registry (v1) are Disabled (Deprecated) + +## Another Check ID are: +- `community_checks` -> Run all community checks +- `community` -> Is an alias for `community_checks` +- `cis` -> Run all bellow checks category: + - `host_configuration` + - `docker_daemon_configuration` + - `docker_daemon_files` + - `container_images` + - `container_runtime` + - `docker_security_operations` + - `docker_swarm_configuration` + - `docker_enterprise_configuration` +- `all` -> Run all bellow checks category: + - `cis` + - `community` +- `cis_level1` -> Run all bellow checks: + - `host_configuration_level1` + - `docker_daemon_configuration_level1` + - `docker_daemon_files_level1` + - `container_images_level1` + - `container_runtime_level1` + - `docker_security_operations_level1` + - `docker_swarm_configuration_level1` + - `docker_enterprise_configuration_level1` +- `host_configuration_level1` -> Run all bellow checks: + - `check_1_1_1` + - `check_1_1_2` + - `check_1_2_1` + - `check_1_2_2` + - `check_1_2_3` + - `check_1_2_5` + - `check_1_2_6` + - `check_1_2_7` + - `check_1_2_8` + - `check_1_2_9` + - `check_1_2_10` + - `check_1_2_11` + - `check_1_2_12` +- `docker_daemon_configuration_level1` -> Run all bellow checks: + - `check_2_1` + - `check_2_2` + - `check_2_3` + - `check_2_4` + - `check_2_5` + - `check_2_6` + - `check_2_7` + - `check_2_13` + - `check_2_14` + - `check_2_16` + - `check_2_17` +- `docker_daemon_files_level1` -> Run all bellow checks: + - `check_3_1` + - `check_3_2` + - `check_3_3` + - `check_3_4` + - `check_3_5` + - `check_3_6` + - `check_3_7` + - `check_3_8` + - `check_3_9` + - `check_3_10` + - `check_3_11` + - `check_3_12` + - `check_3_13` + - `check_3_14` + - `check_3_15` + - `check_3_16` + - `check_3_17` + - `check_3_18` + - `check_3_19` + - `check_3_20` + - `check_3_21` + - `check_3_22` +- `container_images_level1` -> Run all bellow checks: + - `check_4_1` + - `check_4_2` + - `check_4_3` + - `check_4_4` + - `check_4_6` + - `check_4_7` + - `check_4_9` + - `check_4_10` +- `container_runtime_level1` -> Run all bellow checks: + - `check_running_containers` + - `check_5_1` + - `check_5_3` + - `check_5_4` + - `check_5_5` + - `check_5_6` + - `check_5_7` + - `check_5_8` + - `check_5_9` + - `check_5_10` + - `check_5_11` + - `check_5_12` + - `check_5_13` + - `check_5_14` + - `check_5_15` + - `check_5_16` + - `check_5_17` + - `check_5_18` + - `check_5_19` + - `check_5_20` + - `check_5_21` + - `check_5_24` + - `check_5_25` + - `check_5_26` + - `check_5_27` + - `check_5_28` + - `check_5_30` + - `check_5_31` +- `docker_security_operations_level1` -> Run all bellow checks: + - `check_6_1` + - `check_6_2` +- `docker_swarm_configuration_level1` -> Run all bellow checks: + - `check_7_1` + - `check_7_2` + - `check_7_3` + - `check_7_4` + - `check_7_7` +- `docker_enterprise_configuration_level1` -> Run all bellow checks: + - `check_product_license` + - `check_8_1_1` + - `check_8_1_2` + - `check_8_1_3` + - `check_8_1_4` + - `check_8_1_5` + - `check_8_1_6` + - `check_8_1_7` + - `check_8_2_1`