From 8424b0a6babec4add4fdfd0d17b434ea4128467e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Sj=C3=B6gren?= Date: Mon, 23 Oct 2017 15:38:08 +0200 Subject: [PATCH 01/10] add check and score info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Thomas Sjögren --- docker-bench-security.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docker-bench-security.sh b/docker-bench-security.sh index ce4de2c..c7ef00a 100755 --- a/docker-bench-security.sh +++ b/docker-bench-security.sh @@ -71,6 +71,12 @@ if [ "x$ID" != "x0" ]; then sleep 3 fi +# Total Score +# Warn Scored -1, Pass Scored +1, Not Score -0 + +totalChecks=0 +currentScore=0 + logit "Initializing $(date)\n" beginjson "1.3.4" "$(date +%s)" @@ -94,6 +100,12 @@ main () { . ./"$test" done + printf "\n" + info "Checks: $totalChecks" + info "Score: $currentScore" + integerjson "checks" "$totalChecks" + integerjson "score" "$currentScore" + endjson "$(date +%s)" } From a7600dd539d2af4af39057018ecf39940f2a0a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Sj=C3=B6gren?= Date: Mon, 23 Oct 2017 15:38:31 +0200 Subject: [PATCH 02/10] add integer for json logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Thomas Sjögren --- output_lib.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/output_lib.sh b/output_lib.sh index 5ead4b7..af79f02 100644 --- a/output_lib.sh +++ b/output_lib.sh @@ -40,3 +40,7 @@ endjson (){ logjson (){ printf "\n \"%s\": \"%s\"," "$1" "$2" | tee -a "$logger.json" 2>/dev/null 1>&2 } + +integerjson (){ + printf "\n \"%s\": %s," "$1" "$2" | tee -a "$logger.json" 2>/dev/null 1>&2 +} From 3d532a29ac4f0e8fa77de5168ccfd2bc20f29175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Sj=C3=B6gren?= Date: Mon, 23 Oct 2017 15:39:18 +0200 Subject: [PATCH 03/10] add score and totalChecks to 1_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Thomas Sjögren --- tests/1_host_configuration.sh | 67 ++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/tests/1_host_configuration.sh b/tests/1_host_configuration.sh index ef6ac4c..579b949 100644 --- a/tests/1_host_configuration.sh +++ b/tests/1_host_configuration.sh @@ -6,24 +6,32 @@ auditrules="/etc/audit/audit.rules" # 1.1 check_1_1="1.1 - Ensure a separate partition for containers has been created" +totalChecks=$((totalChecks + 1)) + if grep /var/lib/docker /etc/fstab >/dev/null 2>&1; then pass "$check_1_1" logjson "1.1" "PASS" + currentScore=$((currentScore + 1)) elif mountpoint -q -- /var/lib/docker >/dev/null 2>&1; then pass "$check_1_1" logjson "1.1" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_1" logjson "1.1" "WARN" + currentScore=$((currentScore - 1)) fi # 1.2 check_1_2="1.2 - Ensure the container host has been Hardened" +totalChecks=$((totalChecks + 1)) note "$check_1_2" logjson "1.2" "INFO" +currentScore=$((currentScore - 0)) # 1.3 check_1_3="1.3 - Ensure Docker is up to date" +totalChecks=$((totalChecks + 1)) docker_version=$(docker version | grep -i -A1 '^server' | grep -i 'version:' \ | awk '{print $NF; exit}' | tr -d '[:alpha:]-,') docker_current_version="$(date +%y.%m.0 -d @$(( $(date +%s) - 2592000)))" @@ -33,237 +41,294 @@ if [ $? -eq 11 ]; then 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" logjson "1.3" "INFO" + currentScore=$((currentScore - 0)) else pass "$check_1_3" info " * Using $docker_version which is current" info " * Check with your operating system vendor for support and security maintenance for Docker" logjson "1.3" "PASS" + currentScore=$((currentScore - 0)) fi # 1.4 check_1_4="1.4 - Ensure only trusted users are allowed to control Docker daemon" +totalChecks=$((totalChecks + 1)) docker_users=$(getent group docker) info "$check_1_4" for u in $docker_users; do info " * $u" logjson "1.4" "$u" done +currentScore=$((currentScore - 0)) # 1.5 check_1_5="1.5 - Ensure auditing is configured for the Docker daemon" +totalChecks=$((totalChecks + 1)) file="/usr/bin/docker " if command -v auditctl >/dev/null 2>&1; then if auditctl -l | grep "$file" >/dev/null 2>&1; then pass "$check_1_5" logjson "1.5" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_5" logjson "1.5" "WARN" + currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then pass "$check_1_5" logjson "1.5" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_5" logjson "1.5" "WARN" + currentScore=$((currentScore - 1)) fi # 1.6 check_1_6="1.6 - Ensure auditing is configured for Docker files and directories - /var/lib/docker" +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_1_6" logjson "1.6" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_6" logjson "1.6" "WARN" + currentScore=$((currentScore - 1)) fi elif grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then pass "$check_1_6" logjson "1.6" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_6" logjson "1.6" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_1_6" info " * Directory not found" logjson "1.6" "INFO" + currentScore=$((currentScore + 0)) fi # 1.7 check_1_7="1.7 - Ensure auditing is configured for Docker files and directories - /etc/docker" +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_1_7" logjson "1.7" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_7" logjson "1.7" "WARN" + currentScore=$((currentScore - 1)) fi elif grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then pass "$check_1_7" logjson "1.7" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_7" logjson "1.7" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_1_7" info " * Directory not found" logjson "1.7" "INFO" + currentScore=$((currentScore + 0)) fi # 1.8 check_1_8="1.8 - Ensure auditing is configured for Docker files and directories - docker.service" +totalChecks=$((totalChecks + 1)) file="$(get_systemd_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_1_8" logjson "1.8" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_8" logjson "1.8" "WARN" + currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then pass "$check_1_8" - logjson "1.8" "pass" + logjson "1.8" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_8" logjson "1.8" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_1_8" info " * File not found" logjson "1.8" "INFO" + currentScore=$((currentScore + 0)) fi # 1.9 check_1_9="1.9 - Ensure auditing is configured for Docker files and directories - docker.socket" +totalChecks=$((totalChecks + 1)) file="$(get_systemd_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_1_9" logjson "1.9" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_9" logjson "1.9" "WARN" + currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then pass "$check_1_9" logjson "1.9" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_9" logjson "1.9" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_1_9" info " * File not found" logjson "1.9" "INFO" + currentScore=$((currentScore + 0)) fi # 1.10 check_1_10="1.10 - Ensure auditing is configured for Docker files and directories - /etc/default/docker" +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_1_10" logjson "1.10" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_10" logjson "1.10" "WARN" + currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then pass "$check_1_10" logjson "1.10" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_10" logjson "1.10" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_1_10" info " * File not found" logjson "1.10" "INFO" + currentScore=$((currentScore + 0)) fi # 1.11 check_1_11="1.11 - Ensure auditing is configured for Docker files and directories - /etc/docker/daemon.json" +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_1_11" logjson "1.11" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_11" logjson "1.11" "WARN" + currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then pass "$check_1_11" logjson "1.11" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_11" logjson "1.11" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_1_11" info " * File not found" logjson "1.11" "INFO" + currentScore=$((currentScore + 0)) fi # 1.12 check_1_12="1.12 - Ensure auditing is configured for Docker files and directories - /usr/bin/docker-containerd" +totalChecks=$((totalChecks + 1)) file="/usr/bin/docker-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_1_12" logjson "1.12" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_12" logjson "1.12" "WARN" + currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then pass "$check_1_12" logjson "1.12" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_12" logjson "1.12" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_1_12" info " * File not found" logjson "1.12" "INFO" + currentScore=$((currentScore + 0)) fi # 1.13 check_1_13="1.13 - Ensure auditing is configured for Docker files and directories - /usr/bin/docker-runc" +totalChecks=$((totalChecks + 1)) file="/usr/bin/docker-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_1_13" logjson "1.13" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_13" logjson "1.13" "WARN" + currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then pass "$check_1_13" logjson "1.13" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_1_13" logjson "1.13" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_1_13" info " * File not found" logjson "1.13" "INFO" + currentScore=$((currentScore + 0)) fi From ec4060ea2fdf2270a21110353fa236b863591bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Sj=C3=B6gren?= Date: Mon, 23 Oct 2017 15:39:32 +0200 Subject: [PATCH 04/10] add score and totalChecks to 2_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Thomas Sjögren --- tests/2_docker_daemon_configuration.sh | 77 ++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/tests/2_docker_daemon_configuration.sh b/tests/2_docker_daemon_configuration.sh index 2eafc88..6c459a1 100644 --- a/tests/2_docker_daemon_configuration.sh +++ b/tests/2_docker_daemon_configuration.sh @@ -5,86 +5,110 @@ info "2 - Docker daemon configuration" # 2.1 check_2_1="2.1 - Ensure network traffic is restricted between containers on the default bridge" +totalChecks=$((totalChecks + 1)) if get_docker_effective_command_line_args '--icc' | grep false >/dev/null 2>&1; then pass "$check_2_1" logjson "2.1" "PASS" + currentScore=$((currentScore + 1)) elif get_docker_configuration_file_args 'icc' | grep "false" >/dev/null 2>&1; then pass "$check_2_1" logjson "2.1" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_1" logjson "2.1" "WARN" + currentScore=$((currentScore - 1)) fi # 2.2 check_2_2="2.2 - Ensure the logging level is set to 'info'" +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_2_2" logjson "2.2" "PASS" + currentScore=$((currentScore + 1)) elif [ -z "$(get_docker_configuration_file_args 'log-level')" ]; then pass "$check_2_2" logjson "2.2" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_2" logjson "2.2" "WARN" + currentScore=$((currentScore - 1)) 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_2_2" logjson "2.2" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_2" logjson "2.2" "WARN" + currentScore=$((currentScore - 1)) fi else pass "$check_2_2" logjson "2.2" "PASS" + currentScore=$((currentScore + 1)) fi # 2.3 check_2_3="2.3 - Ensure Docker is allowed to make changes to iptables" +totalChecks=$((totalChecks + 1)) if get_docker_effective_command_line_args '--iptables' | grep "false" >/dev/null 2>&1; then warn "$check_2_3" logjson "2.3" "WARN" + currentScore=$((currentScore - 1)) elif get_docker_configuration_file_args 'iptables' | grep "false" >/dev/null 2>&1; then warn "$check_2_3" logjson "2.3" "WARN" + currentScore=$((currentScore - 1)) else pass "$check_2_3" logjson "2.3" "PASS" + currentScore=$((currentScore + 1)) fi # 2.4 check_2_4="2.4 - Ensure insecure registries are not used" +totalChecks=$((totalChecks + 1)) if get_docker_effective_command_line_args '--insecure-registry' | grep "insecure-registry" >/dev/null 2>&1; then warn "$check_2_4" logjson "2.4" "WARN" + currentScore=$((currentScore - 1)) 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_2_4" logjson "2.4" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_4" logjson "2.4" "WARN" + currentScore=$((currentScore - 1)) fi else pass "$check_2_4" logjson "2.4" "PASS" + currentScore=$((currentScore + 1)) fi # 2.5 check_2_5="2.5 - Ensure aufs storage driver is not used" +totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "^Storage Driver:\s*aufs\s*$" >/dev/null 2>&1; then warn "$check_2_5" logjson "2.5" "WARN" + currentScore=$((currentScore - 1)) else pass "$check_2_5" logjson "2.5" "PASS" + currentScore=$((currentScore + 1)) fi # 2.6 check_2_6="2.6 - Ensure TLS authentication for Docker daemon is configured" +totalChecks=$((totalChecks + 1)) if grep -i 'tcp://' "$CONFIG_FILE" 2>/dev/null 1>&2; then if [ $(get_docker_configuration_file_args '"tls":' | grep 'true') ] || \ [ $(get_docker_configuration_file_args '"tlsverify' | grep 'true') ] ; then @@ -92,190 +116,243 @@ if grep -i 'tcp://' "$CONFIG_FILE" 2>/dev/null 1>&2; then if get_docker_configuration_file_args 'tlsverify' | grep 'true' >/dev/null 2>&1; then pass "$check_2_6" logjson "2.6" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_6" warn " * Docker daemon currently listening on TCP with TLS, but no verification" logjson "2.6" "WARN" + currentScore=$((currentScore - 1)) fi fi else warn "$check_2_6" warn " * Docker daemon currently listening on TCP without TLS" logjson "2.6" "WARN" + currentScore=$((currentScore - 1)) fi elif get_docker_cumulative_command_line_args '-H' | grep -vE '(unix|fd)://' >/dev/null 2>&1; then if get_docker_cumulative_command_line_args '--tlskey' | grep 'tlskey=' >/dev/null 2>&1; then if get_docker_cumulative_command_line_args '--tlsverify' | grep 'tlsverify' >/dev/null 2>&1; then pass "$check_2_6" logjson "2.6" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_6" warn " * Docker daemon currently listening on TCP with TLS, but no verification" logjson "2.6" "WARN" + currentScore=$((currentScore - 1)) fi else warn "$check_2_6" warn " * Docker daemon currently listening on TCP without TLS" logjson "2.6" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_2_6" info " * Docker daemon not listening on TCP" logjson "2.6" "INFO" + currentScore=$((currentScore +0)) fi # 2.7 check_2_7="2.7 - Ensure the default ulimit is configured appropriately" +totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'default-ulimit' | grep -v '{}' >/dev/null 2>&1; then pass "$check_2_7" logjson "2.7" "PASS" + currentScore=$((currentScore + 1)) elif get_docker_effective_command_line_args '--default-ulimit' | grep "default-ulimit" >/dev/null 2>&1; then pass "$check_2_7" logjson "2.7" "PASS" + currentScore=$((currentScore + 1)) else info "$check_2_7" info " * Default ulimit doesn't appear to be set" logjson "2.7" "INFO" + currentScore=$((currentScore + 0)) fi # 2.8 check_2_8="2.8 - Enable user namespace support" +totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'userns-remap' | grep -v '""'; then pass "$check_2_8" logjson "2.8" "PASS" + currentScore=$((currentScore + 1)) elif get_docker_effective_command_line_args '--userns-remap' | grep "userns-remap" >/dev/null 2>&1; then pass "$check_2_8" logjson "2.8" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_8" logjson "2.8" "WARN" + currentScore=$((currentScore - 1)) fi # 2.9 check_2_9="2.9 - Ensure the default cgroup usage has been confirmed" +totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'cgroup-parent' | grep -v '""'; then warn "$check_2_9" info " * Confirm cgroup usage" logjson "2.9" "INFO" + currentScore=$((currentScore + 0)) elif get_docker_effective_command_line_args '--cgroup-parent' | grep "cgroup-parent" >/dev/null 2>&1; then warn "$check_2_9" info " * Confirm cgroup usage" logjson "2.9" "INFO" + currentScore=$((currentScore + 0)) else pass "$check_2_9" logjson "2.9" "PASS" + currentScore=$((currentScore + 1)) fi # 2.10 check_2_10="2.10 - Ensure base device size is not changed until needed" +totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'storage-opts' | grep "dm.basesize" >/dev/null 2>&1; then warn "$check_2_10" logjson "2.10" "WARN" + currentScore=$((currentScore - 1)) elif get_docker_effective_command_line_args '--storage-opt' | grep "dm.basesize" >/dev/null 2>&1; then warn "$check_2_10" logjson "2.10" "WARN" + currentScore=$((currentScore - 1)) else pass "$check_2_10" logjson "2.10" "PASS" + currentScore=$((currentScore + 1)) fi # 2.11 check_2_11="2.11 - Ensure that authorization for Docker client commands is enabled" +totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'authorization-plugins' | grep -v '\[]'; then pass "$check_2_11" logjson "2.11" "PASS" + currentScore=$((currentScore + 1)) elif get_docker_effective_command_line_args '--authorization-plugin' | grep "authorization-plugin" >/dev/null 2>&1; then pass "$check_2_11" logjson "2.11" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_11" logjson "2.11" "WARN" + currentScore=$((currentScore - 1)) fi # 2.12 check_2_12="2.12 - Ensure centralized and remote logging is configured" +totalChecks=$((totalChecks + 1)) if docker info --format '{{ .LoggingDriver }}' | grep 'json-file' >/dev/null 2>&1; then warn "$check_2_12" logjson "2.12" "WARN" + currentScore=$((currentScore - 1)) else pass "$check_2_12" logjson "2.12" "PASS" + currentScore=$((currentScore + 1)) fi # 2.13 check_2_13="2.13 - Ensure operations on legacy registry (v1) are Disabled" +totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'disable-legacy-registry' | grep 'true' >/dev/null 2>&1; then pass "$check_2_13" logjson "2.13" "PASS" + currentScore=$((currentScore + 1)) elif get_docker_effective_command_line_args '--disable-legacy-registry' | grep "disable-legacy-registry" >/dev/null 2>&1; then pass "$check_2_13" logjson "2.13" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_13" logjson "2.13" "WARN" + currentScore=$((currentScore - 1)) fi # 2.14 check_2_14="2.14 - Ensure live restore is Enabled" +totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Live Restore Enabled:\s*true\s*" >/dev/null 2>&1; then pass "$check_2_14" logjson "2.14" "PASS" + currentScore=$((currentScore + 1)) else if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then pass "$check_2_14 (Incompatible with swarm mode)" logjson "2.14" "PASS" + currentScore=$((currentScore + 1)) elif get_docker_effective_command_line_args '--live-restore' | grep "live-restore" >/dev/null 2>&1; then pass "$check_2_14" logjson "2.14" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_14" logjson "2.14" "WARN" + currentScore=$((currentScore - 1)) fi fi # 2.15 check_2_15="2.15 - Ensure Userland Proxy is Disabled" +totalChecks=$((totalChecks + 1)) if get_docker_configuration_file_args 'userland-proxy' | grep false >/dev/null 2>&1; then pass "$check_2_15" logjson "2.15" "PASS" + currentScore=$((currentScore + 1)) elif get_docker_effective_command_line_args '--userland-proxy=false' 2>/dev/null | grep "userland-proxy=false" >/dev/null 2>&1; then pass "$check_2_15" logjson "2.15" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_15" logjson "2.15" "WARN" + currentScore=$((currentScore - 1)) fi # 2.16 check_2_16="2.16 - Ensure daemon-wide custom seccomp profile is applied, if needed" +totalChecks=$((totalChecks + 1)) if docker info --format '{{ .SecurityOptions }}' | grep 'name=seccomp,profile=default' 2>/dev/null 1>&2; then pass "$check_2_16" logjson "2.16" "PASS" + currentScore=$((currentScore + 1)) else info "$check_2_16" logjson "2.16" "INFO" + currentScore=$((currentScore + 0)) fi # 2.17 check_2_17="2.17 - Ensure experimental features are avoided in production" +totalChecks=$((totalChecks + 1)) if docker version -f '{{.Server.Experimental}}' | grep false 2>/dev/null 1>&2; then pass "$check_2_17" logjson "2.17" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_17" logjson "2.17" "WARN" + currentScore=$((currentScore - 1)) fi # 2.18 check_2_18="2.18 - Ensure containers are restricted from acquiring new privileges" +totalChecks=$((totalChecks + 1)) if get_docker_effective_command_line_args '--no-new-privileges' >/dev/null 2>&1; then pass "$check_2_18" logjson "2.18" "PASS" + currentScore=$((currentScore + 1)) elif get_docker_configuration_file_args 'no-new-privileges' >/dev/null 2>&1; then pass "$check_2_18" logjson "2.18" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_2_18" logjson "2.18" "WARN" + currentScore=$((currentScore - 1)) fi From f9be3996f49998824ab2c834acadda8733812364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Sj=C3=B6gren?= Date: Mon, 23 Oct 2017 15:39:52 +0200 Subject: [PATCH 05/10] add score and totalChecks to 3_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Thomas Sjögren --- tests/3_docker_daemon_configuration_files.sh | 80 ++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/tests/3_docker_daemon_configuration_files.sh b/tests/3_docker_daemon_configuration_files.sh index a016d76..bd4bf6a 100644 --- a/tests/3_docker_daemon_configuration_files.sh +++ b/tests/3_docker_daemon_configuration_files.sh @@ -5,114 +5,139 @@ info "3 - Docker daemon configuration files" # 3.1 check_3_1="3.1 - Ensure that docker.service file ownership is set to root:root" +totalChecks=$((totalChecks + 1)) file="$(get_systemd_service_file docker.service)" if [ -f "$file" ]; then if [ "$(stat -c %u%g $file)" -eq 00 ]; then pass "$check_3_1" logjson "3.1" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_1" warn " * Wrong ownership for $file" logjson "3.1" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_1" info " * File not found" logjson "3.1" "INFO" + currentScore=$((currentScore + 0)) fi # 3.2 check_3_2="3.2 - Ensure that docker.service file permissions are set to 644 or more restrictive" +totalChecks=$((totalChecks + 1)) file="$(get_systemd_service_file docker.service)" if [ -f "$file" ]; then if [ "$(stat -c %a $file)" -eq 644 -o "$(stat -c %a $file)" -eq 600 ]; then pass "$check_3_2" logjson "3.2" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_2" warn " * Wrong permissions for $file" logjson "3.2" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_2" info " * File not found" logjson "3.2" "INFO" + currentScore=$((currentScore + 0)) fi # 3.3 check_3_3="3.3 - Ensure that docker.socket file ownership is set to root:root" +totalChecks=$((totalChecks + 1)) file="$(get_systemd_service_file docker.socket)" if [ -f "$file" ]; then if [ "$(stat -c %u%g $file)" -eq 00 ]; then pass "$check_3_3" logjson "3.3" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_3" warn " * Wrong ownership for $file" logjson "3.3" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_3" info " * File not found" logjson "3.3" "INFO" + currentScore=$((currentScore + 0)) fi # 3.4 check_3_4="3.4 - Ensure that docker.socket file permissions are set to 644 or more restrictive" +totalChecks=$((totalChecks + 1)) file="$(get_systemd_service_file docker.socket)" if [ -f "$file" ]; then if [ "$(stat -c %a $file)" -eq 644 -o "$(stat -c %a $file)" -eq 600 ]; then pass "$check_3_4" logjson "3.4" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_4" warn " * Wrong permissions for $file" logjson "3.4" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_4" info " * File not found" logjson "3.4" "INFO" + currentScore=$((currentScore + 0)) fi # 3.5 check_3_5="3.5 - Ensure that /etc/docker directory ownership is set to root:root" +totalChecks=$((totalChecks + 1)) directory="/etc/docker" if [ -d "$directory" ]; then if [ "$(stat -c %u%g $directory)" -eq 00 ]; then pass "$check_3_5" logjson "3.5" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_5" warn " * Wrong ownership for $directory" logjson "3.5" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_5" info " * Directory not found" logjson "3.5" "INFO" + currentScore=$((currentScore + 0)) fi # 3.6 check_3_6="3.6 - Ensure that /etc/docker directory permissions are set to 755 or more restrictive" +totalChecks=$((totalChecks + 1)) directory="/etc/docker" if [ -d "$directory" ]; then if [ "$(stat -c %a $directory)" -eq 755 -o "$(stat -c %a $directory)" -eq 700 ]; then pass "$check_3_6" logjson "3.6" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_6" warn " * Wrong permissions for $directory" logjson "3.6" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_6" info " * Directory not found" logjson "3.6" "INFO" + currentScore=$((currentScore + 0)) fi # 3.7 check_3_7="3.7 - Ensure that registry certificate file ownership is set to root:root" +totalChecks=$((totalChecks + 1)) directory="/etc/docker/certs.d/" if [ -d "$directory" ]; then fail=0 @@ -126,18 +151,22 @@ if [ -d "$directory" ]; then warn "$check_3_7" warn " * Wrong ownership for $directory" logjson "3.7" "WARN" + currentScore=$((currentScore - 1)) else pass "$check_3_7" logjson "3.7" "PASS" + currentScore=$((currentScore + 1)) fi else info "$check_3_7" info " * Directory not found" logjson "3.7" "INFO" + currentScore=$((currentScore + 0)) fi # 3.8 check_3_8="3.8 - Ensure that registry certificate file permissions are set to 444 or more restrictive" +totalChecks=$((totalChecks + 1)) directory="/etc/docker/certs.d/" if [ -d "$directory" ]; then fail=0 @@ -151,18 +180,22 @@ if [ -d "$directory" ]; then warn "$check_3_8" warn " * Wrong permissions for $directory" logjson "3.8" "WARN" + currentScore=$((currentScore - 1)) else pass "$check_3_8" logjson "3.8" "PASS" + currentScore=$((currentScore + 1)) fi else info "$check_3_8" info " * Directory not found" logjson "3.8" "INFO" + currentScore=$((currentScore + 0)) fi # 3.9 check_3_9="3.9 - Ensure that TLS CA certificate file ownership is set to root:root" +totalChecks=$((totalChecks + 1)) if ! [ -z $(get_docker_configuration_file_args 'tlscacert') ]; then tlscacert=$(get_docker_configuration_file_args 'tlscacert') else @@ -172,19 +205,23 @@ if [ -f "$tlscacert" ]; then if [ "$(stat -c %u%g "$tlscacert")" -eq 00 ]; then pass "$check_3_9" logjson "3.9" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_9" warn " * Wrong ownership for $tlscacert" logjson "3.9" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_9" info " * No TLS CA certificate found" logjson "3.9" "INFO" + currentScore=$((currentScore + 0)) fi # 3.10 check_3_10="3.10 - Ensure that TLS CA certificate file permissions are set to 444 or more restrictive" +totalChecks=$((totalChecks + 1)) if ! [ -z $(get_docker_configuration_file_args 'tlscacert') ]; then tlscacert=$(get_docker_configuration_file_args 'tlscacert') else @@ -194,19 +231,23 @@ if [ -f "$tlscacert" ]; then if [ "$(stat -c %a $tlscacert)" -eq 444 -o "$(stat -c %a $tlscacert)" -eq 400 ]; then pass "$check_3_10" logjson "3.10" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_10" warn " * Wrong permissions for $tlscacert" logjson "3.10" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_10" info " * No TLS CA certificate found" logjson "3.10" "INFO" + currentScore=$((currentScore + 0)) fi # 3.11 check_3_11="3.11 - Ensure that Docker server certificate file ownership is set to root:root" +totalChecks=$((totalChecks + 1)) if ! [ -z $(get_docker_configuration_file_args 'tlscert') ]; then tlscert=$(get_docker_configuration_file_args 'tlscert') else @@ -216,19 +257,23 @@ if [ -f "$tlscert" ]; then if [ "$(stat -c %u%g "$tlscert")" -eq 00 ]; then pass "$check_3_11" logjson "3.11" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_11" warn " * Wrong ownership for $tlscert" logjson "3.11" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_11" info " * No TLS Server certificate found" logjson "3.11" "INFO" + currentScore=$((currentScore + 0)) fi # 3.12 check_3_12="3.12 - Ensure that Docker server certificate file permissions are set to 444 or more restrictive" +totalChecks=$((totalChecks + 1)) if ! [ -z $(get_docker_configuration_file_args 'tlscert') ]; then tlscert=$(get_docker_configuration_file_args 'tlscert') else @@ -238,19 +283,23 @@ if [ -f "$tlscert" ]; then if [ "$(stat -c %a $tlscert)" -eq 444 -o "$(stat -c %a $tlscert)" -eq 400 ]; then pass "$check_3_12" logjson "3.12" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_12" warn " * Wrong permissions for $tlscert" logjson "3.12" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_12" info " * No TLS Server certificate found" logjson "3.12" "INFO" + currentScore=$((currentScore + 0)) fi # 3.13 check_3_13="3.13 - Ensure that Docker server certificate key file ownership is set to root:root" +totalChecks=$((totalChecks + 1)) if ! [ -z $(get_docker_configuration_file_args 'tlskey') ]; then tlskey=$(get_docker_configuration_file_args 'tlskey') else @@ -260,19 +309,23 @@ if [ -f "$tlskey" ]; then if [ "$(stat -c %u%g "$tlskey")" -eq 00 ]; then pass "$check_3_13" logjson "3.13" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_13" warn " * Wrong ownership for $tlskey" logjson "3.13" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_13" info " * No TLS Key found" logjson "3.13" "INFO" + currentScore=$((currentScore + 0)) fi # 3.14 check_3_14="3.14 - Ensure that Docker server certificate key file permissions are set to 400" +totalChecks=$((totalChecks + 1)) if ! [ -z $(get_docker_configuration_file_args 'tlskey') ]; then tlskey=$(get_docker_configuration_file_args 'tlskey') else @@ -282,121 +335,148 @@ if [ -f "$tlskey" ]; then if [ "$(stat -c %a $tlskey)" -eq 400 ]; then pass "$check_3_14" logjson "3.14" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_14" warn " * Wrong permissions for $tlskey" logjson "3.14" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_14" info " * No TLS Key found" logjson "3.14" "INFO" + currentScore=$((currentScore + 0)) fi # 3.15 check_3_15="3.15 - Ensure that Docker socket file ownership is set to root:docker" +totalChecks=$((totalChecks + 1)) file="/var/run/docker.sock" if [ -S "$file" ]; then if [ "$(stat -c %U:%G $file)" = 'root:docker' ]; then pass "$check_3_15" logjson "3.15" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_15" warn " * Wrong ownership for $file" logjson "3.15" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_15" info " * File not found" logjson "3.15" "INFO" + currentScore=$((currentScore + 0)) fi # 3.16 check_3_16="3.16 - Ensure that Docker socket file permissions are set to 660 or more restrictive" +totalChecks=$((totalChecks + 1)) file="/var/run/docker.sock" if [ -S "$file" ]; then if [ "$(stat -c %a $file)" -eq 660 -o "$(stat -c %a $file)" -eq 600 ]; then pass "$check_3_16" logjson "3.16" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_16" warn " * Wrong permissions for $file" logjson "3.16" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_16" info " * File not found" logjson "3.16" "INFO" + currentScore=$((currentScore + 0)) fi # 3.17 check_3_17="3.17 - Ensure that daemon.json file ownership is set to root:root" +totalChecks=$((totalChecks + 1)) file="/etc/docker/daemon.json" if [ -f "$file" ]; then if [ "$(stat -c %U:%G $file)" = 'root:root' ]; then pass "$check_3_17" logjson "3.17" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_17" warn " * Wrong ownership for $file" logjson "3.17" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_17" info " * File not found" logjson "3.17" "INFO" + currentScore=$((currentScore + 0)) fi # 3.18 check_3_18="3.18 - Ensure that daemon.json file permissions are set to 644 or more restrictive" +totalChecks=$((totalChecks + 1)) file="/etc/docker/daemon.json" if [ -f "$file" ]; then if [ "$(stat -c %a $file)" -eq 644 -o "$(stat -c %a $file)" -eq 600 ]; then pass "$check_3_18" logjson "3.18" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_18" warn " * Wrong permissions for $file" logjson "3.18" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_18" info " * File not found" logjson "3.18" "INFO" + currentScore=$((currentScore - 0)) fi # 3.19 check_3_19="3.19 - Ensure that /etc/default/docker file ownership is set to root:root" +totalChecks=$((totalChecks + 1)) file="/etc/default/docker" if [ -f "$file" ]; then if [ "$(stat -c %U:%G $file)" = 'root:root' ]; then pass "$check_3_19" logjson "3.19" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_19" warn " * Wrong ownership for $file" logjson "3.19" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_19" info " * File not found" logjson "3.19" "INFO" + currentScore=$((currentScore + 0)) fi # 3.20 check_3_20="3.20 - Ensure that /etc/default/docker file permissions are set to 644 or more restrictive" +totalChecks=$((totalChecks + 1)) file="/etc/default/docker" if [ -f "$file" ]; then if [ "$(stat -c %a $file)" -eq 644 -o "$(stat -c %a $file)" -eq 600 ]; then pass "$check_3_20" logjson "3.20" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_3_20" warn " * Wrong permissions for $file" logjson "3.20" "WARN" + currentScore=$((currentScore - 1)) fi else info "$check_3_20" info " * File not found" logjson "3.20" "INFO" + currentScore=$((currentScore + 0)) fi From de8225027448f5a08a1b60d26a800385242ccf91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Sj=C3=B6gren?= Date: Mon, 23 Oct 2017 15:40:12 +0200 Subject: [PATCH 06/10] add score and totalChecks to 4_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Thomas Sjögren --- tests/4_container_images.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/4_container_images.sh b/tests/4_container_images.sh index 0861bd2..63f6223 100644 --- a/tests/4_container_images.sh +++ b/tests/4_container_images.sh @@ -5,12 +5,14 @@ info "4 - Container Images and Build File" # 4.1 check_4_1="4.1 - Ensure a user for the container has been created" +totalChecks=$((totalChecks + 1)) # If container_users is empty, there are no running containers if [ -z "$containers" ]; then info "$check_4_1" info " * No containers running" logjson "4.1" "INFO" + currentScore=$((currentScore + 0)) else # We have some containers running, set failure flag to 0. Check for Users. fail=0 @@ -37,6 +39,9 @@ else if [ $fail -eq 0 ]; then pass "$check_4_1" logjson "4.1" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi fi # Make the loop separator go back to space @@ -46,31 +51,41 @@ images=$(docker images -q) # 4.2 check_4_2="4.2 - Ensure that containers use trusted base images" +totalChecks=$((totalChecks + 1)) note "$check_4_2" logjson "4.2" "NOTE" +currentScore=$((currentScore + 0)) # 4.3 check_4_3="4.3 - Ensure unnecessary packages are not installed in the container" +totalChecks=$((totalChecks + 1)) note "$check_4_3" logjson "4.3" "NOTE" +currentScore=$((currentScore + 0)) # 4.4 check_4_4="4.4 - Ensure images are scanned and rebuilt to include security patches" +totalChecks=$((totalChecks + 1)) note "$check_4_4" logjson "4.4" "NOTE" +currentScore=$((currentScore + 0)) # 4.5 check_4_5="4.5 - Ensure Content trust for Docker is Enabled" +totalChecks=$((totalChecks + 1)) if [ "x$DOCKER_CONTENT_TRUST" = "x1" ]; then pass "$check_4_5" logjson "4.5" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_4_5" logjson "4.5" "WARN" + currentScore=$((currentScore - 1)) fi # 4.6 check_4_6="4.6 - Ensure HEALTHCHECK instructions have been added to the container image" +totalChecks=$((totalChecks + 1)) fail=0 for img in $images; do if docker inspect --format='{{.Config.Healthcheck}}' "$img" 2>/dev/null | grep -e "" >/dev/null 2>&1; then @@ -89,10 +104,14 @@ done if [ $fail -eq 0 ]; then pass "$check_4_6" logjson "4.6" "PASS" + currentScore=$((currentScore + 1)) +else + currentScore=$((currentScore - 1)) fi # 4.7 check_4_7="4.7 - Ensure update instructions are not use alone in the Dockerfile" +totalChecks=$((totalChecks + 1)) fail=0 for img in $images; do if docker history "$img" 2>/dev/null | grep -e "update" >/dev/null 2>&1; then @@ -110,15 +129,21 @@ done if [ $fail -eq 0 ]; then pass "$check_4_7" logjson "4.7" "PASS" + currentScore=$((currentScore + 1)) +else + currentScore=$((currentScore + 0)) fi # 4.8 check_4_8="4.8 - Ensure setuid and setgid permissions are removed in the images" +totalChecks=$((totalChecks + 1)) note "$check_4_8" logjson "4.8" "NOTE" +currentScore=$((currentScore + 0)) # 4.9 check_4_9="4.9 - Ensure COPY is used instead of ADD in Dockerfile" +totalChecks=$((totalChecks + 1)) fail=0 for img in $images; do docker history "$img" 2> /dev/null | grep 'ADD' >/dev/null 2>&1 @@ -133,19 +158,25 @@ for img in $images; do info " * ADD in image history: $imgName" logjson "4.9" "INFO: $imgName" fi + currentScore=$((currentScore + 0)) fi done if [ $fail -eq 0 ]; then pass "$check_4_9" logjson "4.9" "PASS" + currentScore=$((currentScore + 1)) fi # 4.10 check_4_10="4.10 - Ensure secrets are not stored in Dockerfiles" +totalChecks=$((totalChecks + 1)) note "$check_4_10" logjson "4.10" "NOTE" +currentScore=$((currentScore + 0)) # 4.11 check_4_11="4.11 - Ensure verified packages are only Installed" +totalChecks=$((totalChecks + 1)) note "$check_4_11" logjson "4.11" "NOTE" +currentScore=$((currentScore + 0)) From e32910172f42515c8f104d0a3e0c4abd66a79544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Sj=C3=B6gren?= Date: Mon, 23 Oct 2017 15:40:52 +0200 Subject: [PATCH 07/10] add score and totalChecks to 5_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Thomas Sjögren --- tests/5_container_runtime.sh | 123 ++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 3 deletions(-) diff --git a/tests/5_container_runtime.sh b/tests/5_container_runtime.sh index 61658a7..eb86e57 100644 --- a/tests/5_container_runtime.sh +++ b/tests/5_container_runtime.sh @@ -12,6 +12,7 @@ else ' # 5.1 check_5_1="5.1 - Ensure AppArmor Profile is Enabled" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -34,10 +35,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_1" logjson "5.1" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.2 check_5_2="5.2 - Ensure SELinux security options are set, if applicable" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -60,10 +65,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_2" logjson "5.2" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.3 check_5_3="5.3 - Ensure Linux Kernel Capabilities are restricted within containers" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -89,10 +98,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_3" logjson "5.3" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.4 check_5_4="5.4 - Ensure privileged containers are not used" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -115,10 +128,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_4" logjson "5.4" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.5 check_5_5="5.5 - Ensure sensitive host system directories are not mounted on containers" + 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. @@ -161,10 +178,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_5" logjson "5.5" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.6 check_5_6="5.6 - Ensure ssh is not run within containers" + totalChecks=$((totalChecks + 1)) fail=0 printcheck=0 @@ -178,7 +199,7 @@ else warn " * Container running sshd: $c" logjson "5.6" "WARN: $c" fail=1 - printcheck=1 + printcheck=1 else warn " * Container running sshd: $c" logjson "5.6" "WARN: $c" @@ -190,7 +211,7 @@ else if [ $printcheck -eq 0 ]; then warn "$check_5_6" logjson "5.6" "WARN" - printcheck=1 + printcheck=1 fi warn " * Docker exec fails: $c" logjson "5.6" "WARN: $c" @@ -201,10 +222,14 @@ else # We went through all the containers and found none with sshd if [ $fail -eq 0 ]; then pass "$check_5_6" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.7 check_5_7="5.7 - Ensure privileged ports are not mapped within containers" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -231,15 +256,21 @@ else if [ $fail -eq 0 ]; then pass "$check_5_7" logjson "5.7" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.8 check_5_8="5.8 - Ensure only needed ports are open on the container" + totalChecks=$((totalChecks + 1)) note "$check_5_8" logjson "5.8" "NOTE" + currentScore=$((currentScore + 0)) # 5.9 check_5_9="5.9 - Ensure the host's network namespace is not shared" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -262,10 +293,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_9" logjson "5.9" "PASS" + currentScore=$((currentScore + 0)) + else + currentScore=$((currentScore - 1)) fi # 5.10 check_5_10="5.10 - Ensure memory usage for container is limited" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -292,10 +327,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_10" logjson "5.10" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.11 check_5_11="5.11 - Ensure CPU priority is set appropriately on the container" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -322,10 +361,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_11" logjson "5.11" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.12 check_5_12="5.12 - Ensure the container's root filesystem is mounted as read only" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -348,10 +391,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_12" logjson "5.12" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.13 check_5_13="5.13 - Ensure incoming container traffic is binded to a specific host interface" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -374,10 +421,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_13" logjson "5.13" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.14 check_5_14="5.14 - Ensure 'on-failure' container restart policy is set to '5'" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -400,10 +451,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_14" logjson "5.14" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.15 check_5_15="5.15 - Ensure the host's process namespace is not shared" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -426,10 +481,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_15" logjson "5.15" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.16 check_5_16="5.16 - Ensure the host's IPC namespace is not shared" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -452,10 +511,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_16" logjson "5.16" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.17 check_5_17="5.17 - Ensure host devices are not directly exposed to containers" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -478,10 +541,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_17" logjson "5.17" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore + 0)) fi # 5.18 check_5_18="5.18 - Ensure the default ulimit is overwritten at runtime, only if needed" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -504,10 +571,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_18" logjson "5.18" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore + 0)) fi # 5.19 check_5_19="5.19 - Ensure mount propagation mode is not set to shared" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -526,13 +597,17 @@ else fi done # We went through all the containers and found none with shared propagation mode - if [ $fail -eq 0 ]; then + if [ $fail -eq 0 ]; then pass "$check_5_19" logjson "5.19" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.20 check_5_20="5.20 - Ensure the host's UTS namespace is not shared" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -555,10 +630,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_20" logjson "5.20" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.21 check_5_21="5.21 - Ensure the default seccomp profile is not Disabled" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -579,20 +658,28 @@ else if [ $fail -eq 0 ]; then pass "$check_5_21" logjson "5.21" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.22 check_5_22="5.22 - Ensure docker exec commands are not used with privileged option" + totalChecks=$((totalChecks + 1)) note "$check_5_22" logjson "5.22" "NOTE" + currentScore=$((currentScore + 0)) # 5.23 check_5_23="5.23 - Ensure docker exec commands are not used with user option" + totalChecks=$((totalChecks + 1)) note "$check_5_23" logjson "5.23" "NOTE" + currentScore=$((currentScore + 0)) # 5.24 check_5_24="5.24 - Ensure cgroup usage is confirmed" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -615,10 +702,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_24" logjson "5.24" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.25 check_5_25="5.25 - Ensure the container is restricted from acquiring additional privileges" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -639,10 +730,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_25" logjson "5.25" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.26 check_5_26="5.26 - Ensure container health is checked at runtime" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -661,15 +756,21 @@ else if [ $fail -eq 0 ]; then pass "$check_5_26" logjson "5.26" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.27 check_5_27="5.27 - Ensure docker commands always get the latest version of the image" + totalChecks=$((totalChecks + 1)) info "$check_5_27" logjson "5.27" "INFO" + currentScore=$((currentScore + 0)) # 5.28 check_5_28="5.28 - Ensure PIDs cgroup limit is used" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -692,10 +793,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_28" logjson "5.28" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.29 check_5_29="5.29 - Ensure Docker's default bridge docker0 is not used" + totalChecks=$((totalChecks + 1)) fail=0 networks=$(docker network ls -q 2>/dev/null) @@ -715,16 +820,21 @@ else logjson "5.29" "INFO: $c" 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_5_29" logjson "5.29" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.30 check_5_30="5.30 - Ensure the host's user namespaces is not shared" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -745,10 +855,14 @@ else if [ $fail -eq 0 ]; then pass "$check_5_30" logjson "5.30" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi # 5.31 check_5_31="5.31 - Ensure the Docker socket is not mounted inside any containers" + totalChecks=$((totalChecks + 1)) fail=0 for c in $containers; do @@ -769,5 +883,8 @@ else if [ $fail -eq 0 ]; then pass "$check_5_31" logjson "5.31" "PASS" + currentScore=$((currentScore + 1)) + else + currentScore=$((currentScore - 1)) fi fi From 7ebe21823d971e29886c124a1a859a78e885b1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Sj=C3=B6gren?= Date: Mon, 23 Oct 2017 15:41:03 +0200 Subject: [PATCH 08/10] add score and totalChecks to 6_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Thomas Sjögren --- tests/6_docker_security_operations.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/6_docker_security_operations.sh b/tests/6_docker_security_operations.sh index 52979e7..c09a833 100644 --- a/tests/6_docker_security_operations.sh +++ b/tests/6_docker_security_operations.sh @@ -5,6 +5,7 @@ info "6 - Docker Security Operations" # 6.1 check_6_1="6.1 - Avoid image sprawl" +totalChecks=$((totalChecks + 1)) images=$(docker images -q | sort -u | wc -l | awk '{print $1}') active_images=0 @@ -21,9 +22,11 @@ if [ "$active_images" -lt "$((images / 2))" ]; then info " * Only $active_images out of $images are in use" logjson "6.1" "INFO: $active_images" fi +currentScore=$((currentScore + 0)) # 6.2 check_6_2="6.2 - Avoid container sprawl" +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))" @@ -36,3 +39,4 @@ else info " * There are currently a total of $total_containers containers, with $running_containers of them currently running" logjson "6.2" "INFO: $running_containers" fi +currentScore=$((currentScore + 0)) From 976463a87bffc47d8fa4cd9ea6a1de813d351881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Sj=C3=B6gren?= Date: Mon, 23 Oct 2017 15:41:15 +0200 Subject: [PATCH 09/10] add score and totalChecks to 7_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Thomas Sjögren --- tests/7_docker_swarm_configuration.sh | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/7_docker_swarm_configuration.sh b/tests/7_docker_swarm_configuration.sh index a3a80c7..62ff109 100644 --- a/tests/7_docker_swarm_configuration.sh +++ b/tests/7_docker_swarm_configuration.sh @@ -5,52 +5,65 @@ info "7 - Docker Swarm Configuration" # 7.1 check_7_1="7.1 - Ensure swarm mode is not Enabled, if not needed" +totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:*\sinactive\s*" >/dev/null 2>&1; then pass "$check_7_1" logjson "7.1" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_7_1" logjson "7.1" "WARN" + currentScore=$((currentScore - 1)) fi # 7.2 check_7_2="7.2 - Ensure the minimum number of manager nodes have been created in a swarm" +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" -le 1 ]; then pass "$check_7_2" logjson "7.2" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_7_2" logjson "7.2" "WARN" + currentScore=$((currentScore - 1)) fi else pass "$check_7_2 (Swarm mode not enabled)" logjson "7.2" "PASS" + currentScore=$((currentScore + 1)) fi # 7.3 check_7_3="7.3 - Ensure swarm services are binded to a specific host interface" +totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then netstat -lnt | grep -e '\[::]:2377 ' -e ':::2377' -e '*:2377 ' -e ' 0\.0\.0\.0:2377 ' >/dev/null 2>&1 if [ $? -eq 1 ]; then pass "$check_7_3" logjson "7.3" "PASS" + currentScore=$((currentScore + 1)) else warn "$check_7_3" logjson "7.3" "WARN" + currentScore=$((currentScore - 1)) fi else pass "$check_7_3 (Swarm mode not enabled)" logjson "7.3" "PASS" + currentScore=$((currentScore + 1)) fi # 7.4 check_7_4="7.4 - Ensure data exchanged between containers are encrypted on different nodes on the overlay network" +totalChecks=$((totalChecks + 1)) if docker network ls --filter driver=overlay --quiet | \ xargs docker network inspect --format '{{.Name}} {{ .Options }}' 2>/dev/null | \ grep -v 'encrypted:' 2>/dev/null 1>&2; then warn "$check_7_4" + currentScore=$((currentScore - 1)) for encnet in $(docker network ls --filter driver=overlay --quiet); do if docker network inspect --format '{{.Name}} {{ .Options }}' "$encnet" | \ grep -v 'encrypted:' 2>/dev/null 1>&2; then @@ -61,79 +74,101 @@ if docker network ls --filter driver=overlay --quiet | \ else pass "$check_7_4" logjson "7.4" "PASS" + currentScore=$((currentScore + 1)) fi # 7.5 check_7_5="7.5 - Ensure Docker's secret management commands are used for managing secrets in a Swarm cluster" +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_7_5" logjson "7.5" "PASS" + currentScore=$((currentScore + 1)) else info "$check_7_5" logjson "7.5" "INFO" + currentScore=$((currentScore + 0)) fi else pass "$check_7_5 (Swarm mode not enabled)" logjson "7.5" "PASS" + currentScore=$((currentScore + 1)) fi # 7.6 check_7_6="7.6 - Ensure swarm manager is run in auto-lock mode" +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_7_6" logjson "7.6" "WARN" + currentScore=$((currentScore - 1)) else pass "$check_7_6" logjson "7.6" "PASS" + currentScore=$((currentScore + 1)) fi else pass "$check_7_6 (Swarm mode not enabled)" logjson "7.6" "PASS" + currentScore=$((currentScore + 1)) fi # 7.7 check_7_7="7.7 - Ensure swarm manager auto-lock key is rotated periodically" +totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then note "$check_7_7" logjson "7.7" "NOTE" + currentScore=$((currentScore + 0)) else pass "$check_7_7 (Swarm mode not enabled)" logjson "7.7" "PASS" + currentScore=$((currentScore + 1)) fi # 7.8 check_7_8="7.8 - Ensure node certificates are rotated as appropriate" +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_7_8" logjson "7.8" "PASS" + currentScore=$((currentScore + 1)) else info "$check_7_8" logjson "7.8" "INFO" + currentScore=$((currentScore + 0)) fi else pass "$check_7_8 (Swarm mode not enabled)" logjson "7.8" "PASS" + currentScore=$((currentScore + 1)) fi # 7.9 check_7_9="7.9 - Ensure CA certificates are rotated as appropriate" +totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then info "$check_7_9" logjson "7.9" "INFO" + currentScore=$((currentScore + 0)) else pass "$check_7_9 (Swarm mode not enabled)" logjson "7.9" "PASS" + currentScore=$((currentScore + 1)) fi # 7.10 check_7_10="7.10 - Ensure management plane traffic has been separated from data plane traffic" +totalChecks=$((totalChecks + 1)) if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then info "$check_7_10" logjson "7.10" "INFO" + currentScore=$((currentScore + 0)) else pass "$check_7_10 (Swarm mode not enabled)" logjson "7.10" "PASS" + currentScore=$((currentScore + 1)) fi From ce5ab6b06367560a49eac6f51cac8574faf783b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Sj=C3=B6gren?= Date: Fri, 12 Jan 2018 11:42:52 +0100 Subject: [PATCH 10/10] update version check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Thomas Sjögren --- tests/1_host_configuration.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/1_host_configuration.sh b/tests/1_host_configuration.sh index 579b949..cf45ab0 100644 --- a/tests/1_host_configuration.sh +++ b/tests/1_host_configuration.sh @@ -32,7 +32,7 @@ currentScore=$((currentScore - 0)) # 1.3 check_1_3="1.3 - Ensure Docker is up to date" totalChecks=$((totalChecks + 1)) -docker_version=$(docker version | grep -i -A1 '^server' | grep -i 'version:' \ +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"