diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bae896e..c1e3d98 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,7 +47,9 @@ tests/ ├── 4_container_images.sh ├── 5_container_runtime.sh ├── 6_docker_security_operations.sh -└── 7_docker_swarm_configuration.sh +├── 7_docker_swarm_configuration.sh +├── 8_docker_enterprise_configuration.sh +└── 99_community_checks.sh ``` To modify the Docker Bench for Security you should first clone the repository, @@ -55,7 +57,7 @@ make your changes, check your code with `shellcheck`, `checkbashisms` or similar tools, and then sign off on your commits. After that feel free to send us a pull request with the changes. -While this tool was inspired by the [CIS Docker 1.11.0 benchmark](https://benchmarks.cisecurity.org/downloads/show-single/index.cfm?file=docker16.110) +While this tool was inspired by the [CIS Docker 1.11.0 benchmark](https://www.cisecurity.org/benchmark/docker/) and its successors, feel free to add new tests. We will try to turn [dockerbench.com](https://dockerbench.com) into a list of good community benchmarks for both security and performance, and we would love community diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index a61d89b..ffd95d7 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -14,6 +14,7 @@ The following people, listed in alphabetical order, have contributed to docker-b * Ernst de Haan * HuKeping * Ivan Angelov +* J0WI * Jessica Frazelle * Joachim Lusiardi * Joachim Lusiardi @@ -52,4 +53,4 @@ The following people, listed in alphabetical order, have contributed to docker-b * will Farrell * Zvi "Viz" Effron -This list was generated Sun May 5 20:30:13 UTC 2019. +This list was generated Wed Aug 28 10:19:31 UTC 2019. diff --git a/README.md b/README.md index d5e97c1..9109302 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,7 @@ The Docker Bench for Security is a script that checks for dozens of common best-practices around deploying Docker containers in production. The tests are -all automated, and are inspired by the [CIS Docker Community Edition Benchmark v1.1.0](https://benchmarks.cisecurity.org/tools2/docker/CIS_Docker_Community_Edition_Benchmark_v1.1.0.pdf). -We are releasing this as a follow-up to our [Understanding Docker Security and Best Practices](https://blog.docker.com/2015/05/understanding-docker-security-and-best-practices/) -blog post. +all automated, and are inspired by the [CIS Docker Benchmark v1.2.0](https://www.cisecurity.org/benchmark/docker/). We are making this available as an open-source utility so the Docker community can have an easy way to self-assess their hosts and docker containers against diff --git a/distros/Dockerfile.alpine b/distros/Dockerfile.alpine index a724dad..2bbaad3 100644 --- a/distros/Dockerfile.alpine +++ b/distros/Dockerfile.alpine @@ -1,4 +1,4 @@ -FROM alpine:3.9 +FROM alpine:3.10 LABEL \ org.label-schema.name="docker-bench-security" \ diff --git a/docker-bench-security.sh b/docker-bench-security.sh index 2e7d0e6..35e23b9 100755 --- a/docker-bench-security.sh +++ b/docker-bench-security.sh @@ -7,7 +7,7 @@ # Checks for dozens of common best-practices around deploying Docker containers in production. # ------------------------------------------------------------------------------ -version='1.3.4' +version='1.3.5' # Load dependencies . ./functions_lib.sh diff --git a/functions_lib.sh b/functions_lib.sh index f7c32ba..3e07147 100644 --- a/functions_lib.sh +++ b/functions_lib.sh @@ -3,18 +3,21 @@ host_configuration() { check_1 check_1_1 + check_1_1_1 + check_1_1_2 check_1_2 - check_1_3 - check_1_4 - check_1_5 - check_1_6 - check_1_7 - check_1_8 - check_1_9 - check_1_10 - check_1_11 - check_1_12 - check_1_13 + check_1_2_1 + check_1_2_2 + check_1_2_3 + check_1_2_4 + 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 check_1_end } @@ -37,7 +40,6 @@ docker_daemon_configuration() { check_2_15 check_2_16 check_2_17 - check_2_18 check_2_end } @@ -63,6 +65,8 @@ docker_daemon_files() { check_3_18 check_3_19 check_3_20 + check_3_21 + check_3_22 check_3_end } @@ -141,9 +145,26 @@ docker_swarm_configuration() { check_7_end } +docker_enterprise_configuration() { + check_8 + check_product_license + check_8_1 + 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 + check_8_2_1 + check_8_end +} + community_checks() { check_c check_c_1 + check_c_2 check_c_end } @@ -156,6 +177,7 @@ cis() { container_runtime docker_security_operations docker_swarm_configuration + docker_enterprise_configuration } # Community contributed diff --git a/helper_lib.sh b/helper_lib.sh index 3756861..a38d653 100644 --- a/helper_lib.sh +++ b/helper_lib.sh @@ -117,6 +117,6 @@ yell "# ------------------------------------------------------------------------ # Docker, Inc. (c) 2015- # # Checks for dozens of common best-practices around deploying Docker containers in production. -# Inspired by the CIS Docker Community Edition Benchmark v1.1.0. +# Inspired by the CIS Docker Benchmark v1.2.0. # ------------------------------------------------------------------------------" } diff --git a/tests/1_host_configuration.sh b/tests/1_host_configuration.sh index 3ecb844..a9374a1 100644 --- a/tests/1_host_configuration.sh +++ b/tests/1_host_configuration.sh @@ -9,45 +9,33 @@ check_1() { startsectionjson "$id_1" "$desc_1" } -# 1.1 check_1_1() { + logit "" id_1_1="1.1" - desc_1_1="Ensure a separate partition for containers has been created" - check_1_1="$id_1_1 - $desc_1_1" - starttestjson "$id_1_1" "$desc_1_1" - - totalChecks=$((totalChecks + 1)) - - if mountpoint -q -- "$(docker info -f '{{ .DockerRootDir }}')" >/dev/null 2>&1; then - pass "$check_1_1" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) - else - warn "$check_1_1" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) - fi + desc_1_1="General Configuration" + check_1_1="$id_1_1 - $desc_1_1" + info "$check_1_1" } -# 1.2 -check_1_2() { - id_1_2="1.2" - desc_1_2="Ensure the container host has been Hardened" - check_1_2="$id_1_2 - $desc_1_2" - starttestjson "$id_1_2" "$desc_1_2" +# 1.1.1 +check_1_1_1() { + id_1_1_1="1.1.1" + desc_1_1_1="Ensure the container host has been Hardened" + check_1_1_1="$id_1_1_1 - $desc_1_1_1" + starttestjson "$id_1_1_1" "$desc_1_1_1" totalChecks=$((totalChecks + 1)) - note "$check_1_2" + note "$check_1_1_1" resulttestjson "INFO" currentScore=$((currentScore + 0)) } -# 1.3 -check_1_3() { - id_1_3="1.3" - desc_1_3="Ensure Docker is up to date" - check_1_3="$id_1_3 - $desc_1_3" - starttestjson "$id_1_3" "$desc_1_3" +# 1.1.2 +check_1_1_2() { + id_1_1_2="1.1.2" + desc_1_1_2="Ensure Docker is up to date" + check_1_1_2="$id_1_1_2 - $desc_1_1_2" + starttestjson "$id_1_1_2" "$desc_1_1_2" totalChecks=$((totalChecks + 1)) docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \ @@ -55,358 +43,423 @@ check_1_3() { 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_1_3" - 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" + info "$check_1_1_2" + 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)) 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" + pass "$check_1_1_2" + 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)) fi } -# 1.4 -check_1_4() { - id_1_4="1.4" - desc_1_4="Ensure only trusted users are allowed to control Docker daemon" - check_1_4="$id_1_4 - $desc_1_4" - starttestjson "$id_1_4" "$desc_1_4" - - totalChecks=$((totalChecks + 1)) - docker_users=$(getent group docker) - info "$check_1_4" - for u in $docker_users; do - info " * $u" - done - resulttestjson "INFO" "users" "$docker_users" - currentScore=$((currentScore + 0)) +check_1_2() { + logit "" + id_1_2="1.2" + desc_1_2="Linux Hosts Specific Configuration" + check_1_2="$id_1_2 - $desc_1_2" + info "$check_1_2" } -# 1.5 -check_1_5() { - id_1_5="1.5" - desc_1_5="Ensure auditing is configured for the Docker daemon" - check_1_5="$id_1_5 - $desc_1_5" - starttestjson "$id_1_5" "$desc_1_5" +# 1.2.1 +check_1_2_1() { + id_1_2_1="1.2.1" + desc_1_2_1="Ensure a separate partition for containers has been created" + check_1_2_1="$id_1_2_1 - $desc_1_2_1" + starttestjson "$id_1_2_1" "$desc_1_2_1" 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" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) - else - warn "$check_1_5" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) - fi - elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check_1_5" + + if mountpoint -q -- "$(docker info -f '{{ .DockerRootDir }}')" >/dev/null 2>&1; then + pass "$check_1_2_1" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_5" + warn "$check_1_2_1" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi } -# 1.6 -check_1_6() { - id_1_6="1.6" - desc_1_6="Ensure auditing is configured for Docker files and directories - /var/lib/docker" - check_1_6="$id_1_6 - $desc_1_6" - starttestjson "$id_1_6" "$desc_1_6" +# 1.2.2 +check_1_2_2() { + id_1_2_2="1.2.2" + desc_1_2_2="Ensure only trusted users are allowed to control Docker daemon" + check_1_2_2="$id_1_2_2 - $desc_1_2_2" + starttestjson "$id_1_2_2" "$desc_1_2_2" + + totalChecks=$((totalChecks + 1)) + docker_users=$(getent group docker) + info "$check_1_2_2" + for u in $docker_users; do + info " * $u" + done + resulttestjson "INFO" "users" "$docker_users" + currentScore=$((currentScore + 0)) +} + +# 1.2.3 +check_1_2_3() { + id_1_2_3="1.2.3" + desc_1_2_3="Ensure auditing is configured for the Docker daemon" + check_1_2_3="$id_1_2_3 - $desc_1_2_3" + starttestjson "$id_1_2_3" "$desc_1_2_3" + + 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_1_2_3" + resulttestjson "PASS" + currentScore=$((currentScore + 1)) + else + warn "$check_1_2_3" + resulttestjson "WARN" + currentScore=$((currentScore - 1)) + fi + elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then + pass "$check_1_2_3" + resulttestjson "PASS" + currentScore=$((currentScore + 1)) + else + warn "$check_1_2_3" + resulttestjson "WARN" + currentScore=$((currentScore - 1)) + fi +} + +# 1.2.4 +check_1_2_4() { + id_1_2_4="1.2.4" + desc_1_2_4="Ensure auditing is configured for Docker files and directories - /var/lib/docker" + check_1_2_4="$id_1_2_4 - $desc_1_2_4" + starttestjson "$id_1_2_4" "$desc_1_2_4" 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" + pass "$check_1_2_4" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_6" + warn "$check_1_2_4" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi elif grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check_1_6" + pass "$check_1_2_4" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_6" + warn "$check_1_2_4" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi else - info "$check_1_6" - info " * Directory not found" + info "$check_1_2_4" + info " * Directory not found" resulttestjson "INFO" "Directory not found" currentScore=$((currentScore + 0)) fi } -# 1.7 -check_1_7() { - id_1_7="1.7" - desc_1_7="Ensure auditing is configured for Docker files and directories - /etc/docker" - check_1_7="$id_1_7 - $desc_1_7" - starttestjson "$id_1_7" "$desc_1_7" +# 1.2.5 +check_1_2_5() { + id_1_2_5="1.2.5" + desc_1_2_5="Ensure auditing is configured for Docker files and directories - /etc/docker" + check_1_2_5="$id_1_2_5 - $desc_1_2_5" + starttestjson "$id_1_2_5" "$desc_1_2_5" 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" + pass "$check_1_2_5" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_7" + warn "$check_1_2_5" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi elif grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check_1_7" + pass "$check_1_2_5" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_7" + warn "$check_1_2_5" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi else - info "$check_1_7" - info " * Directory not found" + info "$check_1_2_5" + info " * Directory not found" resulttestjson "INFO" "Directory not found" currentScore=$((currentScore + 0)) fi } -# 1.8 -check_1_8() { - id_1_8="1.8" - desc_1_8="Ensure auditing is configured for Docker files and directories - docker.service" - check_1_8="$id_1_8 - $desc_1_8" - starttestjson "$id_1_8" "$desc_1_8" +# 1.2.6 +check_1_2_6() { + id_1_2_6="1.2.6" + desc_1_2_6="Ensure auditing is configured for Docker files and directories - docker.service" + check_1_2_6="$id_1_2_6 - $desc_1_2_6" + starttestjson "$id_1_2_6" "$desc_1_2_6" 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" + pass "$check_1_2_6" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_8" + warn "$check_1_2_6" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check_1_8" + pass "$check_1_2_6" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_8" + warn "$check_1_2_6" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi else - info "$check_1_8" - info " * File not found" + info "$check_1_2_6" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi } -# 1.9 -check_1_9() { - id_1_9="1.9" - desc_1_9="Ensure auditing is configured for Docker files and directories - docker.socket" - check_1_9="$id_1_9 - $desc_1_9" - starttestjson "$id_1_9" "$desc_1_9" +# 1.2.7 +check_1_2_7() { + id_1_2_7="1.2.7" + desc_1_2_7="Ensure auditing is configured for Docker files and directories - docker.socket" + check_1_2_7="$id_1_2_7 - $desc_1_2_7" + starttestjson "$id_1_2_7" "$desc_1_2_7" 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" + pass "$check_1_2_7" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_9" + warn "$check_1_2_7" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check_1_9" + pass "$check_1_2_7" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_9" + warn "$check_1_2_7" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi else - info "$check_1_9" - info " * File not found" + info "$check_1_2_7" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi } -# 1.10 -check_1_10() { - id_1_10="1.10" - desc_1_10="Ensure auditing is configured for Docker files and directories - /etc/default/docker" - check_1_10="$id_1_10 - $desc_1_10" - starttestjson "$id_1_10" "$desc_1_10" +# 1.2.8 +check_1_2_8() { + id_1_2_8="1.2.8" + desc_1_2_8="Ensure auditing is configured for Docker files and directories - /etc/default/docker" + check_1_2_8="$id_1_2_8 - $desc_1_2_8" + starttestjson "$id_1_2_8" "$desc_1_2_8" 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" + pass "$check_1_2_8" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_10" + warn "$check_1_2_8" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check_1_10" + pass "$check_1_2_8" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_10" + warn "$check_1_2_8" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi else - info "$check_1_10" - info " * File not found" + info "$check_1_2_8" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi } -# 1.11 -check_1_11() { - id_1_11="1.11" - desc_1_11="Ensure auditing is configured for Docker files and directories - /etc/docker/daemon.json" - check_1_11="$id_1_11 - $desc_1_11" - starttestjson "$id_1_11" "$desc_1_11" +# 1.2.9 +check_1_2_9() { + id_1_2_9="1.2.9" + desc_1_2_9="Ensure auditing is configured for Docker files and directories - /etc/sysconfig/docker" + check_1_2_9="$id_1_2_9 - $desc_1_2_9" + starttestjson "$id_1_2_9" "$desc_1_2_9" + + 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_1_2_9" + resulttestjson "PASS" + currentScore=$((currentScore + 1)) + else + warn "$check_1_2_9" + resulttestjson "WARN" + currentScore=$((currentScore - 1)) + fi + elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then + pass "$check_1_2_9" + resulttestjson "PASS" + currentScore=$((currentScore + 1)) + else + warn "$check_1_2_9" + resulttestjson "WARN" + currentScore=$((currentScore - 1)) + fi + else + info "$check_1_2_9" + info " * File not found" + resulttestjson "INFO" "File not found" + currentScore=$((currentScore + 0)) + fi +} + +# 1.2.10 +check_1_2_10() { + id_1_2_10="1.2.10" + desc_1_2_10="Ensure auditing is configured for Docker files and directories - /etc/docker/daemon.json" + check_1_2_10="$id_1_2_10 - $desc_1_2_10" + starttestjson "$id_1_2_10" "$desc_1_2_10" 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" + pass "$check_1_2_10" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_11" + warn "$check_1_2_10" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check_1_11" + pass "$check_1_2_10" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_11" + warn "$check_1_2_10" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi else - info "$check_1_11" - info " * File not found" + info "$check_1_2_10" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi } -# 1.12 -check_1_12() { - id_1_12="1.12" - desc_1_12="Ensure auditing is configured for Docker files and directories - /usr/bin/docker-containerd" - check_1_12="$id_1_12 - $desc_1_12" - starttestjson "$id_1_12" "$desc_1_12" +# 1.2.11 +check_1_2_11() { + id_1_2_11="1.2.11" + desc_1_2_11="Ensure auditing is configured for Docker files and directories - /usr/bin/containerd" + check_1_2_11="$id_1_2_11 - $desc_1_2_11" + starttestjson "$id_1_2_11" "$desc_1_2_11" totalChecks=$((totalChecks + 1)) - file="/usr/bin/docker-containerd" + 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_1_12" + pass "$check_1_2_11" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_12" + warn "$check_1_2_11" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check_1_12" + pass "$check_1_2_11" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_12" + warn "$check_1_2_11" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi else - info "$check_1_12" - info " * File not found" + info "$check_1_2_11" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi } -# 1.13 -check_1_13() { - id_1_13="1.13" - desc_1_13="Ensure auditing is configured for Docker files and directories - /usr/bin/docker-runc" - check_1_13="$id_1_13 - $desc_1_13" - starttestjson "$id_1_13" "$desc_1_13" +# 1.2.12 +check_1_2_12() { + id_1_2_12="1.2.12" + desc_1_2_12="Ensure auditing is configured for Docker files and directories - /usr/sbin/runc" + check_1_2_12="$id_1_2_12 - $desc_1_2_12" + starttestjson "$id_1_2_12" "$desc_1_2_12" totalChecks=$((totalChecks + 1)) - file="/usr/bin/docker-runc" + 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_1_13" + pass "$check_1_2_12" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_13" + warn "$check_1_2_12" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then - pass "$check_1_13" + pass "$check_1_2_12" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_1_13" + warn "$check_1_2_12" resulttestjson "WARN" currentScore=$((currentScore - 1)) fi else - info "$check_1_13" - info " * File not found" + info "$check_1_2_12" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi @@ -415,4 +468,3 @@ check_1_13() { check_1_end() { endsectionjson } - diff --git a/tests/2_docker_daemon_configuration.sh b/tests/2_docker_daemon_configuration.sh index 9f24e8f..90210af 100644 --- a/tests/2_docker_daemon_configuration.sh +++ b/tests/2_docker_daemon_configuration.sh @@ -316,21 +316,22 @@ check_2_12() { # 2.13 check_2_13() { - docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \ - | awk '{print $NF; exit}' | tr -d '[:alpha:]-,.' | cut -c 1-4) - totalChecks=$((totalChecks + 1)) - id_2_13="2.13" - desc_2_13="Ensure operations on legacy registry (v1) are Disabled" + desc_2_13="Ensure live restore is Enabled" check_2_13="$id_2_13 - $desc_2_13" starttestjson "$id_2_13" "$desc_2_13" - if [ "$docker_version" -lt 1712 ]; then - if get_docker_configuration_file_args 'disable-legacy-registry' | grep 'true' >/dev/null 2>&1; then - pass "$check_2_13" + 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_13" + resulttestjson "PASS" + currentScore=$((currentScore + 1)) + else + if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then + pass "$check_2_13 (Incompatible with swarm mode)" resulttestjson "PASS" currentScore=$((currentScore + 1)) - elif get_docker_effective_command_line_args '--disable-legacy-registry' | grep "disable-legacy-registry" >/dev/null 2>&1; then + elif get_docker_effective_command_line_args '--live-restore' | grep "live-restore" >/dev/null 2>&1; then pass "$check_2_13" resulttestjson "PASS" currentScore=$((currentScore + 1)) @@ -339,94 +340,83 @@ check_2_13() { resulttestjson "WARN" currentScore=$((currentScore - 1)) fi - else - desc_2_13="$desc_2_13 (Deprecated)" - check_2_13="$id_2_13 - $desc_2_13" - info "$check_2_13" - resulttestjson "INFO" fi } # 2.14 check_2_14() { id_2_14="2.14" - desc_2_14="Ensure live restore is Enabled" + desc_2_14="Ensure Userland Proxy is Disabled" check_2_14="$id_2_14 - $desc_2_14" starttestjson "$id_2_14" "$desc_2_14" totalChecks=$((totalChecks + 1)) - if docker info 2>/dev/null | grep -e "Live Restore Enabled:\s*true\s*" >/dev/null 2>&1; then + if get_docker_configuration_file_args 'userland-proxy' | grep false >/dev/null 2>&1; then + pass "$check_2_14" + resulttestjson "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_14" resulttestjson "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)" - resulttestjson "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" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) - else - warn "$check_2_14" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) - fi + warn "$check_2_14" + resulttestjson "WARN" + currentScore=$((currentScore - 1)) fi } # 2.15 check_2_15() { id_2_15="2.15" - desc_2_15="Ensure Userland Proxy is Disabled" + desc_2_15="Ensure that a daemon-wide custom seccomp profile is applied if appropriate" check_2_15="$id_2_15 - $desc_2_15" starttestjson "$id_2_15" "$desc_2_15" totalChecks=$((totalChecks + 1)) - if get_docker_configuration_file_args 'userland-proxy' | grep false >/dev/null 2>&1; then - pass "$check_2_15" - resulttestjson "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 + if docker info --format '{{ .SecurityOptions }}' | grep 'name=seccomp,profile=default' 2>/dev/null 1>&2; then pass "$check_2_15" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - warn "$check_2_15" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) + info "$check_2_15" + resulttestjson "INFO" + currentScore=$((currentScore + 0)) fi } # 2.16 check_2_16() { id_2_16="2.16" - desc_2_16="Ensure daemon-wide custom seccomp profile is applied, if needed" + desc_2_16="Ensure that experimental features are not implemented in production" check_2_16="$id_2_16 - $desc_2_16" starttestjson "$id_2_16" "$desc_2_16" totalChecks=$((totalChecks + 1)) - if docker info --format '{{ .SecurityOptions }}' | grep 'name=seccomp,profile=default' 2>/dev/null 1>&2; then + if docker version -f '{{.Server.Experimental}}' | grep false 2>/dev/null 1>&2; then pass "$check_2_16" resulttestjson "PASS" currentScore=$((currentScore + 1)) else - info "$check_2_16" - resulttestjson "INFO" - currentScore=$((currentScore + 0)) + warn "$check_2_16" + resulttestjson "WARN" + currentScore=$((currentScore - 1)) fi } # 2.17 check_2_17() { id_2_17="2.17" - desc_2_17="Ensure experimental features are avoided in production" + desc_2_17="Ensure containers are restricted from acquiring new privileges" check_2_17="$id_2_17 - $desc_2_17" starttestjson "$id_2_17" "$desc_2_17" totalChecks=$((totalChecks + 1)) - if docker version -f '{{.Server.Experimental}}' | grep false 2>/dev/null 1>&2; then + if get_docker_effective_command_line_args '--no-new-privileges' | grep "no-new-privileges" >/dev/null 2>&1; then + pass "$check_2_17" + resulttestjson "PASS" + currentScore=$((currentScore + 1)) + elif get_docker_configuration_file_args 'no-new-privileges' | grep true >/dev/null 2>&1; then pass "$check_2_17" resulttestjson "PASS" currentScore=$((currentScore + 1)) @@ -437,29 +427,6 @@ check_2_17() { fi } -# 2.18 -check_2_18() { - id_2_18="2.18" - desc_2_18="Ensure containers are restricted from acquiring new privileges" - check_2_18="$id_2_18 - $desc_2_18" - starttestjson "$id_2_18" "$desc_2_18" - - totalChecks=$((totalChecks + 1)) - if get_docker_effective_command_line_args '--no-new-privileges' | grep "no-new-privileges" >/dev/null 2>&1; then - pass "$check_2_18" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) - elif get_docker_configuration_file_args 'no-new-privileges' | grep true >/dev/null 2>&1; then - pass "$check_2_18" - resulttestjson "PASS" - currentScore=$((currentScore + 1)) - else - warn "$check_2_18" - resulttestjson "WARN" - currentScore=$((currentScore - 1)) - fi -} - check_2_end() { endsectionjson } diff --git a/tests/3_docker_daemon_configuration_files.sh b/tests/3_docker_daemon_configuration_files.sh index 74831a6..ec440bb 100644 --- a/tests/3_docker_daemon_configuration_files.sh +++ b/tests/3_docker_daemon_configuration_files.sh @@ -40,7 +40,7 @@ check_3_1() { # 3.2 check_3_2() { id_3_2="3.2" - desc_3_2="Ensure that docker.service file permissions are set to 644 or more restrictive" + desc_3_2="Ensure that docker.service file permissions are appropriately set" check_3_2="$id_3_2 - $desc_3_2" starttestjson "$id_3_2" "$desc_3_2" @@ -299,13 +299,13 @@ check_3_10() { currentScore=$((currentScore + 1)) else warn "$check_3_10" - warn " * Wrong permissions for $tlscacert" + warn " * Wrong permissions for $tlscacert" resulttestjson "WARN" "Wrong permissions for $tlscacert" currentScore=$((currentScore - 1)) fi else info "$check_3_10" - info " * No TLS CA certificate found" + info " * No TLS CA certificate found" resulttestjson "INFO" "No TLS CA certificate found" currentScore=$((currentScore + 0)) fi @@ -331,13 +331,13 @@ check_3_11() { currentScore=$((currentScore + 1)) else warn "$check_3_11" - warn " * Wrong ownership for $tlscert" + warn " * Wrong ownership for $tlscert" resulttestjson "WARN" "Wrong ownership for $tlscert" currentScore=$((currentScore - 1)) fi else info "$check_3_11" - info " * No TLS Server certificate found" + info " * No TLS Server certificate found" resulttestjson "INFO" "No TLS Server certificate found" currentScore=$((currentScore + 0)) fi @@ -363,13 +363,13 @@ check_3_12() { currentScore=$((currentScore + 1)) else warn "$check_3_12" - warn " * Wrong permissions for $tlscert" + warn " * Wrong permissions for $tlscert" resulttestjson "WARN" "Wrong permissions for $tlscert" currentScore=$((currentScore - 1)) fi else info "$check_3_12" - info " * No TLS Server certificate found" + info " * No TLS Server certificate found" resulttestjson "INFO" "No TLS Server certificate found" currentScore=$((currentScore + 0)) fi @@ -395,13 +395,13 @@ check_3_13() { currentScore=$((currentScore + 1)) else warn "$check_3_13" - warn " * Wrong ownership for $tlskey" + warn " * Wrong ownership for $tlskey" resulttestjson "WARN" "Wrong ownership for $tlskey" currentScore=$((currentScore - 1)) fi else info "$check_3_13" - info " * No TLS Key found" + info " * No TLS Key found" resulttestjson "INFO" "No TLS Key found" currentScore=$((currentScore + 0)) fi @@ -427,13 +427,13 @@ check_3_14() { currentScore=$((currentScore + 1)) else warn "$check_3_14" - warn " * Wrong permissions for $tlskey" + warn " * Wrong permissions for $tlskey" resulttestjson "WARN" "Wrong permissions for $tlskey" currentScore=$((currentScore - 1)) fi else info "$check_3_14" - info " * No TLS Key found" + info " * No TLS Key found" resulttestjson "INFO" "No TLS Key found" currentScore=$((currentScore + 0)) fi @@ -455,13 +455,13 @@ check_3_15() { currentScore=$((currentScore + 1)) else warn "$check_3_15" - warn " * Wrong ownership for $file" + warn " * Wrong ownership for $file" resulttestjson "WARN" "Wrong ownership for $file" currentScore=$((currentScore - 1)) fi else info "$check_3_15" - info " * File not found" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi @@ -483,13 +483,13 @@ check_3_16() { currentScore=$((currentScore + 1)) else warn "$check_3_16" - warn " * Wrong permissions for $file" + warn " * Wrong permissions for $file" resulttestjson "WARN" "Wrong permissions for $file" currentScore=$((currentScore - 1)) fi else info "$check_3_16" - info " * File not found" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi @@ -511,13 +511,13 @@ check_3_17() { currentScore=$((currentScore + 1)) else warn "$check_3_17" - warn " * Wrong ownership for $file" + warn " * Wrong ownership for $file" resulttestjson "WARN" "Wrong ownership for $file" currentScore=$((currentScore - 1)) fi else info "$check_3_17" - info " * File not found" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi @@ -539,13 +539,13 @@ check_3_18() { currentScore=$((currentScore + 1)) else warn "$check_3_18" - warn " * Wrong permissions for $file" + warn " * Wrong permissions for $file" resulttestjson "WARN" "Wrong permissions for $file" currentScore=$((currentScore - 1)) fi else info "$check_3_18" - info " * File not found" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi @@ -567,13 +567,13 @@ check_3_19() { currentScore=$((currentScore + 1)) else warn "$check_3_19" - warn " * Wrong ownership for $file" + warn " * Wrong ownership for $file" resulttestjson "WARN" "Wrong ownership for $file" currentScore=$((currentScore - 1)) fi else info "$check_3_19" - info " * File not found" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi @@ -582,26 +582,82 @@ check_3_19() { # 3.20 check_3_20() { id_3_20="3.20" - desc_3_20="Ensure that /etc/default/docker file permissions are set to 644 or more restrictive" + desc_3_20="Ensure that the /etc/sysconfig/docker file ownership is set to root:root" check_3_20="$id_3_20 - $desc_3_20" starttestjson "$id_3_20" "$desc_3_20" totalChecks=$((totalChecks + 1)) - file="/etc/default/docker" + file="/etc/sysconfig/docker" if [ -f "$file" ]; then - if [ "$(stat -c %a $file)" -eq 644 ] || [ "$(stat -c %a $file)" -eq 600 ]; then + if [ "$(stat -c %U:%G $file)" = 'root:root' ]; then pass "$check_3_20" resulttestjson "PASS" currentScore=$((currentScore + 1)) else warn "$check_3_20" - warn " * Wrong permissions for $file" - resulttestjson "WARN" "Wrong permissions for $file" + warn " * Wrong ownership for $file" + resulttestjson "WARN" "Wrong ownership for $file" currentScore=$((currentScore - 1)) fi else info "$check_3_20" - info " * File not found" + info " * File not found" + resulttestjson "INFO" "File not found" + currentScore=$((currentScore + 0)) + fi +} + +# 3.21 +check_3_21() { + id_3_21="3.21" + desc_3_21="Ensure that /etc/default/docker file permissions are set to 644 or more restrictive" + check_3_21="$id_3_21 - $desc_3_21" + starttestjson "$id_3_21" "$desc_3_21" + + totalChecks=$((totalChecks + 1)) + file="/etc/default/docker" + if [ -f "$file" ]; then + if [ "$(stat -c %a $file)" -eq 644 ] || [ "$(stat -c %a $file)" -eq 600 ]; then + pass "$check_3_21" + resulttestjson "PASS" + currentScore=$((currentScore + 1)) + else + warn "$check_3_21" + warn " * Wrong permissions for $file" + resulttestjson "WARN" "Wrong permissions for $file" + currentScore=$((currentScore - 1)) + fi + else + info "$check_3_21" + info " * File not found" + resulttestjson "INFO" "File not found" + currentScore=$((currentScore + 0)) + fi +} + +# 3.22 +check_3_22() { + id_3_22="3.22" + desc_3_22="Ensure that /etc/default/docker file permissions are set to 644 or more restrictive" + check_3_22="$id_3_22 - $desc_3_22" + starttestjson "$id_3_22" "$desc_3_22" + + totalChecks=$((totalChecks + 1)) + file="/etc/default/docker" + if [ -f "$file" ]; then + if [ "$(stat -c %a $file)" -eq 644 ] || [ "$(stat -c %a $file)" -eq 600 ]; then + pass "$check_3_22" + resulttestjson "PASS" + currentScore=$((currentScore + 1)) + else + warn "$check_3_22" + warn " * Wrong permissions for $file" + resulttestjson "WARN" "Wrong permissions for $file" + currentScore=$((currentScore - 1)) + fi + else + info "$check_3_22" + info " * File not found" resulttestjson "INFO" "File not found" currentScore=$((currentScore + 0)) fi diff --git a/tests/4_container_images.sh b/tests/4_container_images.sh index 0df2676..2592952 100644 --- a/tests/4_container_images.sh +++ b/tests/4_container_images.sh @@ -79,7 +79,7 @@ check_4_1() { # 4.2 check_4_2() { id_4_2="4.2" - desc_4_2="Ensure that containers use trusted base images" + desc_4_2="Ensure that containers use only trusted base images" check_4_2="$id_4_2 - $desc_4_2" starttestjson "$id_4_2" "$desc_4_2" @@ -92,7 +92,7 @@ check_4_2() { # 4.3 check_4_3() { id_4_3="4.3" - desc_4_3="Ensure unnecessary packages are not installed in the container" + desc_4_3="Ensure that unnecessary packages are not installed in the container" check_4_3="$id_4_3 - $desc_4_3" starttestjson "$id_4_3" "$desc_4_3" @@ -137,7 +137,7 @@ check_4_5() { # 4.6 check_4_6() { id_4_6="4.6" - desc_4_6="Ensure HEALTHCHECK instructions have been added to the container image" + desc_4_6="Ensure that HEALTHCHECK instructions have been added to container images" check_4_6="$id_4_6 - $desc_4_6" starttestjson "$id_4_6" "$desc_4_6" @@ -203,7 +203,7 @@ check_4_7() { # 4.8 check_4_8() { id_4_8="4.8" - desc_4_8="Ensure setuid and setgid permissions are removed in the images" + desc_4_8="Ensure setuid and setgid permissions are removed" check_4_8="$id_4_8 - $desc_4_8" starttestjson "$id_4_8" "$desc_4_8" @@ -216,7 +216,7 @@ check_4_8() { # 4.9 check_4_9() { id_4_9="4.9" - desc_4_9="Ensure COPY is used instead of ADD in Dockerfile" + desc_4_9="Ensure that COPY is used instead of ADD in Dockerfiles" check_4_9="$id_4_9 - $desc_4_9" starttestjson "$id_4_9" "$desc_4_9" @@ -263,7 +263,7 @@ check_4_10() { # 4.11 check_4_11() { id_4_11="4.11" - desc_4_11="Ensure verified packages are only Installed" + desc_4_11="Ensure only verified packages are installed" check_4_11="$id_4_11 - $desc_4_11" starttestjson "$id_4_11" "$desc_4_11" diff --git a/tests/5_container_runtime.sh b/tests/5_container_runtime.sh index 9db54d8..343563c 100644 --- a/tests/5_container_runtime.sh +++ b/tests/5_container_runtime.sh @@ -12,7 +12,7 @@ check_5() { check_running_containers() { # If containers is empty, there are no running containers if [ -z "$containers" ]; then - info " * No containers running, skipping Section 5" + info " * No containers running, skipping Section 5" running_containers=0 else running_containers=1 @@ -29,7 +29,7 @@ check_5_1() { fi id_5_1="5.1" - desc_5_1="Ensure AppArmor Profile is Enabled" + desc_5_1="Ensure that, if applicable, an AppArmor Profile is enabled " check_5_1="$id_5_1 - $desc_5_1" starttestjson "$id_5_1" "$desc_5_1" @@ -71,7 +71,7 @@ check_5_2() { fi id_5_2="5.2" - desc_5_2="Ensure SELinux security options are set, if applicable" + desc_5_2="Ensure that, if applicable, SELinux security options are set" check_5_2="$id_5_2 - $desc_5_2" starttestjson "$id_5_2" "$desc_5_2" @@ -158,7 +158,7 @@ check_5_4() { fi id_5_4="5.4" - desc_5_4="Ensure privileged containers are not used" + desc_5_4="Ensure that privileged containers are not used" check_5_4="$id_5_4 - $desc_5_4" starttestjson "$id_5_4" "$desc_5_4" @@ -262,7 +262,7 @@ check_5_6() { fi id_5_6="5.6" - desc_5_6="Ensure ssh is not run within containers" + desc_5_6="Ensure sshd is not run within containers" check_5_6="$id_5_6 - $desc_5_6" starttestjson "$id_5_6" "$desc_5_6" @@ -364,7 +364,7 @@ check_5_8() { fi id_5_8="5.8" - desc_5_8="Ensure only needed ports are open on the container" + desc_5_8="Ensure that only needed ports are open on the container" check_5_8="$id_5_8 - $desc_5_8" starttestjson "$id_5_8" "$desc_5_8" @@ -423,7 +423,7 @@ check_5_10() { fi id_5_10="5.10" - desc_5_10="Ensure memory usage for container is limited" + desc_5_10="Ensure that the memory usage for containers is limited" check_5_10="$id_5_10 - $desc_5_10" starttestjson "$id_5_10" "$desc_5_10" @@ -515,7 +515,7 @@ check_5_12() { fi id_5_12="5.12" - desc_5_12="Ensure the container's root filesystem is mounted as read only" + desc_5_12="Ensure that the container's root filesystem is mounted as read only" check_5_12="$id_5_12 - $desc_5_12" starttestjson "$id_5_12" "$desc_5_12" @@ -557,7 +557,7 @@ check_5_13() { fi id_5_13="5.13" - desc_5_13="Ensure incoming container traffic is binded to a specific host interface" + desc_5_13="Ensure that incoming container traffic is bound to a specific host interface" check_5_13="$id_5_13 - $desc_5_13" starttestjson "$id_5_13" "$desc_5_13" @@ -599,7 +599,7 @@ check_5_14() { fi id_5_14="5.14" - desc_5_14="Ensure 'on-failure' container restart policy is set to '5'" + desc_5_14="Ensure that the 'on-failure' container restart policy is set to '5'" check_5_14="$id_5_14 - $desc_5_14" starttestjson "$id_5_14" "$desc_5_14" @@ -725,7 +725,7 @@ check_5_17() { fi id_5_17="5.17" - desc_5_17="Ensure host devices are not directly exposed to containers" + desc_5_17="Ensure that host devices are not directly exposed to containers" check_5_17="$id_5_17 - $desc_5_17" starttestjson "$id_5_17" "$desc_5_17" @@ -767,7 +767,7 @@ check_5_18() { fi id_5_18="5.18" - desc_5_18="Ensure the default ulimit is overwritten at runtime, only if needed" + desc_5_18="Ensure that the default ulimit is overwritten at runtime if needed" check_5_18="$id_5_18 - $desc_5_18" starttestjson "$id_5_18" "$desc_5_18" @@ -950,7 +950,7 @@ check_5_23() { fi id_5_23="5.23" - desc_5_23="Ensure docker exec commands are not used with user option" + desc_5_23="Ensure that docker exec commands are not used with the user=root option" check_5_23="$id_5_23 - $desc_5_23" starttestjson "$id_5_23" "$desc_5_23" @@ -967,7 +967,7 @@ check_5_24() { fi id_5_24="5.24" - desc_5_24="Ensure cgroup usage is confirmed" + desc_5_24="Ensure that cgroup usage is confirmed" check_5_24="$id_5_24 - $desc_5_24" starttestjson "$id_5_24" "$desc_5_24" @@ -1008,7 +1008,7 @@ check_5_25() { return fi id_5_25="5.25" - desc_5_25="Ensure the container is restricted from acquiring additional privileges" + desc_5_25="Ensure that the container is restricted from acquiring additional privileges" check_5_25="$id_5_25 - $desc_5_25" starttestjson "$id_5_25" "$desc_5_25" @@ -1048,7 +1048,7 @@ check_5_26() { fi id_5_26="5.26" - desc_5_26="Ensure container health is checked at runtime" + desc_5_26="Ensure that container health is checked at runtime" check_5_26="$id_5_26 - $desc_5_26" starttestjson "$id_5_26" "$desc_5_26" @@ -1086,7 +1086,7 @@ check_5_27() { fi id_5_27="5.27" - desc_5_27="Ensure docker commands always get the latest version of the image" + desc_5_27="Ensure that Docker commands always make use of the latest version of their image" check_5_27="$id_5_27 - $desc_5_27" starttestjson "$id_5_27" "$desc_5_27" @@ -1103,7 +1103,7 @@ check_5_28() { fi id_5_28="5.28" - desc_5_28="Ensure PIDs cgroup limit is used" + desc_5_28="Ensure that the PIDs cgroup limit is used" check_5_28="$id_5_28 - $desc_5_28" starttestjson "$id_5_28" "$desc_5_28" @@ -1112,9 +1112,9 @@ check_5_28() { fail=0 nopids_limit_containers="" for c in $containers; do - pidslimit=$(docker inspect --format '{{.HostConfig.PidsLimit }}' "$c") + pidslimit="$(docker inspect --format '{{.HostConfig.PidsLimit }}' "$c")" - if [ "$pidslimit" -le 0 ]; then + if [ "$pidslimit" = "0" ] || [ "$pidslimit" = "" ] || [ "$pidslimit" = "-1" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then warn "$check_5_28" @@ -1145,7 +1145,7 @@ check_5_29() { fi id_5_29="5.29" - desc_5_29="Ensure Docker's default bridge docker0 is not used" + desc_5_29="Ensure that Docker's default bridge 'docker0' is not used" check_5_29="$id_5_29 - $desc_5_29" starttestjson "$id_5_29" "$desc_5_29" @@ -1198,7 +1198,7 @@ check_5_30() { fi id_5_30="5.30" - desc_5_30="Ensure the host's user namespaces is not shared" + desc_5_30="Ensure that the host's user namespaces are not shared" check_5_30="$id_5_30 - $desc_5_30" starttestjson "$id_5_30" "$desc_5_30" @@ -1238,7 +1238,7 @@ check_5_31() { fi id_5_31="5.31" - desc_5_31="Ensure the Docker socket is not mounted inside any containers" + desc_5_31="Ensure that the Docker socket is not mounted inside any containers" check_5_31="$id_5_31 - $desc_5_31" starttestjson "$id_5_31" "$desc_5_31" diff --git a/tests/6_docker_security_operations.sh b/tests/6_docker_security_operations.sh index f2ec50c..9216e80 100644 --- a/tests/6_docker_security_operations.sh +++ b/tests/6_docker_security_operations.sh @@ -12,7 +12,7 @@ check_6() { # 6.1 check_6_1() { id_6_1="6.1" - desc_6_1="Avoid image sprawl" + desc_6_1="Ensure that image sprawl is avoided" check_6_1="$id_6_1 - $desc_6_1" starttestjson "$id_6_1" "$desc_6_1" @@ -39,7 +39,7 @@ check_6_1() { # 6.2 check_6_2() { id_6_2="6.2" - desc_6_2="Avoid container sprawl" + desc_6_2="Ensure that container sprawl is avoided" check_6_2="$id_6_2 - $desc_6_2" starttestjson "$id_6_2" "$desc_6_2" diff --git a/tests/7_docker_swarm_configuration.sh b/tests/7_docker_swarm_configuration.sh index be1dd7b..00d340f 100644 --- a/tests/7_docker_swarm_configuration.sh +++ b/tests/7_docker_swarm_configuration.sh @@ -31,14 +31,14 @@ check_7_1() { # 7.2 check_7_2() { id_7_2="7.2" - desc_7_2="Ensure the minimum number of manager nodes have been created in a swarm" + desc_7_2="Ensure that the minimum number of manager nodes have been created in a swarm" check_7_2="$id_7_2 - $desc_7_2" starttestjson "$id_7_2" "$desc_7_2" 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 + if [ "$managernodes" -eq 1 ]; then pass "$check_7_2" resulttestjson "PASS" currentScore=$((currentScore + 1)) @@ -57,7 +57,7 @@ check_7_2() { # 7.3 check_7_3() { id_7_3="7.3" - desc_7_3="Ensure swarm services are binded to a specific host interface" + desc_7_3="Ensure that swarm services are bound to a specific host interface" check_7_3="$id_7_3 - $desc_7_3" starttestjson "$id_7_3" "$desc_7_3" @@ -83,7 +83,7 @@ check_7_3() { # 7.4 check_7_4() { id_7_4="7.4" - desc_7_4="Ensure data exchanged between containers are encrypted on different nodes on the overlay network" + desc_7_4="Ensure that all Docker swarm overlay networks are encrypted" check_7_4="$id_7_4 - $desc_7_4" starttestjson "$id_7_4" "$desc_7_4" @@ -116,7 +116,7 @@ check_7_4() { # 7.5 check_7_5() { id_7_5="7.5" - desc_7_5="Ensure Docker's secret management commands are used for managing secrets in a Swarm cluster" + desc_7_5="Ensure that Docker's secret management commands are used for managing secrets in a swarm cluster" check_7_5="$id_7_5 - $desc_7_5" starttestjson "$id_7_5" "$desc_7_5" @@ -141,7 +141,7 @@ check_7_5() { # 7.6 check_7_6() { id_7_6="7.6" - desc_7_6="Ensure swarm manager is run in auto-lock mode" + desc_7_6="Ensure that swarm manager is run in auto-lock mode" check_7_6="$id_7_6 - $desc_7_6" starttestjson "$id_7_6" "$desc_7_6" @@ -166,7 +166,7 @@ check_7_6() { # 7.7 check_7_7() { id_7_7="7.7" - desc_7_7="Ensure swarm manager auto-lock key is rotated periodically" + desc_7_7="Ensure that the swarm manager auto-lock key is rotated periodically" check_7_7="$id_7_7 - $desc_7_7" starttestjson "$id_7_7" "$desc_7_7" @@ -185,7 +185,7 @@ check_7_7() { # 7.8 check_7_8() { id_7_8="7.8" - desc_7_8="Ensure node certificates are rotated as appropriate" + desc_7_8="Ensure that node certificates are rotated as appropriate" check_7_8="$id_7_8 - $desc_7_8" starttestjson "$id_7_8" "$desc_7_8" @@ -210,7 +210,7 @@ check_7_8() { # 7.9 check_7_9() { id_7_9="7.9" - desc_7_9="Ensure CA certificates are rotated as appropriate" + desc_7_9="Ensure that CA certificates are rotated as appropriate" check_7_9="$id_7_9 - $desc_7_9" starttestjson "$id_7_9" "$desc_7_9" @@ -229,7 +229,7 @@ check_7_9() { # 7.10 check_7_10() { id_7_10="7.10" - desc_7_10="Ensure management plane traffic has been separated from data plane traffic" + desc_7_10="Ensure that management plane traffic is separated from data plane traffic" check_7_10="$id_7_10 - $desc_7_10" starttestjson "$id_7_10" "$desc_7_10" diff --git a/tests/8_docker_enterprise_configuration.sh b/tests/8_docker_enterprise_configuration.sh new file mode 100644 index 0000000..29359fc --- /dev/null +++ b/tests/8_docker_enterprise_configuration.sh @@ -0,0 +1,182 @@ +#!/bin/sh + +check_8() { + logit "\n" + id_8="8" + desc_8="Docker Enterprise Configuration" + check_8="$id_8 - $desc_8" + info "$check_8" + startsectionjson "$id_8" "$desc_8" +} + +check_product_license() { + if docker version | grep -qi '^Client.*Community$'; then + info " * Community Engine license, skipping section 8" + enterprise_license=0 + else + enterprise_license=1 + fi +} + +check_8_1() { + if [ "$enterprise_license" -ne 1 ]; then + return + fi + + logit "\n" + id_8_1="8.1" + desc_8_1="Universal Control Plane Configuration" + check_8_1="$id_8_1 - $desc_8_1" + info "$check_8_1" +} + +# 8.1.1 +check_8_1_1() { + if [ "$enterprise_license" -ne 1 ]; then + return + fi + + id_8_1_1="8.1.1" + desc_8_1_1="Configure the LDAP authentication service" + check_8_1_1="$id_8_1_1 - $desc_8_1_1" + starttestjson "$id_8_1_1" "$desc_8_1_1" + + totalChecks=$((totalChecks + 1)) + note "$check_8_1_1" + resulttestjson "INFO" + currentScore=$((currentScore + 0)) +} + +# 8.1.2 +check_8_1_2() { + if [ "$enterprise_license" -ne 1 ]; then + return + fi + + id_8_1_2="8.1.2" + desc_8_1_2="Use external certificates" + check_8_1_2="$id_8_1_2 - $desc_8_1_2" + starttestjson "$id_8_1_2" "$desc_8_1_2" + + totalChecks=$((totalChecks + 1)) + note "$check_8_1_2" + resulttestjson "INFO" + currentScore=$((currentScore + 0)) +} + +# 8.1.3 +check_8_1_3() { + if [ "$enterprise_license" -ne 1 ]; then + return + fi + + id_8_1_3="8.1.3" + desc_8_1_3="Enforce the use of client certificate bundles for unprivileged users" + check_8_1_3="$id_8_1_3 - $desc_8_1_3" + starttestjson "$id_8_1_3" "$desc_8_1_3" + + totalChecks=$((totalChecks + 1)) + note "$check_8_1_3" + resulttestjson "INFO" + currentScore=$((currentScore + 0)) +} + +# 8.1.4 +check_8_1_4() { + if [ "$enterprise_license" -ne 1 ]; then + return + fi + + id_8_1_4="8.1.4" + desc_8_1_4="Configure applicable cluster role-based access control policies" + check_8_1_4="$id_8_1_4 - $desc_8_1_4" + starttestjson "$id_8_1_4" "$desc_8_1_4" + + totalChecks=$((totalChecks + 1)) + note "$check_8_1_4" + resulttestjson "INFO" + currentScore=$((currentScore + 0)) +} + +# 8.1.5 +check_8_1_5() { + if [ "$enterprise_license" -ne 1 ]; then + return + fi + + id_8_1_5="8.1.5" + desc_8_1_5="Enable signed image enforcement" + check_8_1_5="$id_8_1_5 - $desc_8_1_5" + starttestjson "$id_8_1_5" "$desc_8_1_5" + + totalChecks=$((totalChecks + 1)) + note "$check_8_1_5" + resulttestjson "INFO" + currentScore=$((currentScore + 0)) +} + +# 8.1.6 +check_8_1_6() { + if [ "$enterprise_license" -ne 1 ]; then + return + fi + + id_8_1_6="8.1.6" + desc_8_1_6="Set the Per-User Session Limit to a value of '3' or lower" + check_8_1_6="$id_8_1_6 - $desc_8_1_6" + starttestjson "$id_8_1_6" "$desc_8_1_6" + + totalChecks=$((totalChecks + 1)) + note "$check_8_1_6" + resulttestjson "INFO" + currentScore=$((currentScore + 0)) +} + +# 8.1.7 +check_8_1_7() { + if [ "$enterprise_license" -ne 1 ]; then + return + fi + + id_8_1_7="8.1.7" + desc_8_1_7="Set the 'Lifetime Minutes' and 'Renewal Threshold Minutes' values to '15' or lower and '0' respectively" + check_8_1_7="$id_8_1_7 - $desc_8_1_7" + starttestjson "$id_8_1_7" "$desc_8_1_7" + + totalChecks=$((totalChecks + 1)) + note "$check_8_1_7" + resulttestjson "INFO" + currentScore=$((currentScore + 0)) +} + +check_8_2() { + if [ "$enterprise_license" -ne 1 ]; then + return + fi + + logit "\n" + id_8_2="8.2" + desc_8_2="Docker Trusted Registry Configuration" + check_8_2="$id_8_2 - $desc_8_2" + info "$check_8_2" +} + +check_8_2_1() { + if [ "$enterprise_license" -ne 1 ]; then + return + fi + + id_8_2_1="8.2.1" + desc_8_2_1="Enable image vulnerability scanning" + check_8_2_1="$id_8_2_1 - $desc_8_2_1" + starttestjson "$id_8_2_1" "$desc_8_2_1" + + totalChecks=$((totalChecks + 1)) + note "$check_8_2_1" + resulttestjson "INFO" + currentScore=$((currentScore + 0)) +} + +check_8_end() { + endsectionjson +} diff --git a/tests/99_community_checks.sh b/tests/99_community_checks.sh index ef9177f..9ad1774 100644 --- a/tests/99_community_checks.sh +++ b/tests/99_community_checks.sh @@ -21,6 +21,39 @@ check_c_1() { 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)) + + id_c_2="C.2" + desc_c_2="Ensure operations on legacy registry (v1) are Disabled" + check_c_2="$id_c_2 - $desc_c_2" + starttestjson "$id_c_2" "$desc_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_c_2" + resulttestjson "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_c_2" + resulttestjson "PASS" + currentScore=$((currentScore + 1)) + else + warn "$check_c_2" + resulttestjson "WARN" + currentScore=$((currentScore - 1)) + fi + else + desc_c_2="$desc_c_2 (Deprecated)" + check_c_2="$id_c_2 - $desc_c_2" + info "$check_c_2" + resulttestjson "INFO" + fi +} + check_c_end() { endsectionjson }