diff --git a/docker-bench-security.sh b/docker-bench-security.sh index 7e69de0..43d5846 100755 --- a/docker-bench-security.sh +++ b/docker-bench-security.sh @@ -126,7 +126,7 @@ main () { cis elif [ -z "$check" ] && [ "$checkexclude" ]; then checkexcluded="$(echo ",$checkexclude" | sed -e 's/^/\^/g' -e 's/,/\$|/g' -e 's/$/\$/g')" - for c in $(grep 'check_[0-9]_' functions_lib.sh | grep -vE "\'$checkexcluded\'"); do + grep 'check_[0-9]_' functions_lib.sh | grep -vE "\'$checkexcluded\'" | while read -r c; do "$c" done else diff --git a/docker-bench-security.sh.bak b/docker-bench-security.sh.bak new file mode 100755 index 0000000..7e69de0 --- /dev/null +++ b/docker-bench-security.sh.bak @@ -0,0 +1,150 @@ +#!/bin/sh +# ------------------------------------------------------------------------------ +# Docker Bench for Security +# +# Docker, Inc. (c) 2015- +# +# Checks for dozens of common best-practices around deploying Docker containers in production. +# ------------------------------------------------------------------------------ + +version='1.3.4' + +# Load dependencies +. ./functions_lib.sh +. ./helper_lib.sh + +# Setup the paths +this_path=$(abspath "$0") ## Path of this file including filename +myname=$(basename "${this_path}") ## file name of this script. + +readonly version +readonly this_path +readonly myname + +export PATH=$PATH:/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin/ + +# Check for required program(s) +req_progs='awk docker grep ss stat' +for p in $req_progs; do + command -v "$p" >/dev/null 2>&1 || { printf "%s command not found.\n" "$p"; exit 1; } +done + +# Ensure we can connect to docker daemon +if ! docker ps -q >/dev/null 2>&1; then + printf "Error connecting to docker daemon (does docker ps work?)\n" + exit 1 +fi + +usage () { + cat </dev/null 2>&1; then + benchcont="$c" + fi + done + + if [ -n "$include" ]; then + pattern=$(echo "$include" | sed 's/,/|/g') + containers=$(docker ps | sed '1d' | awk '{print $NF}' | grep -v "$benchcont" | grep -E "$pattern") + elif [ -n "$exclude" ]; then + pattern=$(echo "$exclude" | sed 's/,/|/g') + containers=$(docker ps | sed '1d' | awk '{print $NF}' | grep -v "$benchcont" | grep -Ev "$pattern") + else + containers=$(docker ps | sed '1d' | awk '{print $NF}' | grep -v "$benchcont") + fi + + if [ -z "$containers" ]; then + running_containers=0 + else + running_containers=1 + fi + + for test in tests/*.sh; do + . ./"$test" + done + + if [ -z "$check" ] && [ ! "$checkexclude" ]; then + cis + elif [ -z "$check" ] && [ "$checkexclude" ]; then + checkexcluded="$(echo ",$checkexclude" | sed -e 's/^/\^/g' -e 's/,/\$|/g' -e 's/$/\$/g')" + for c in $(grep 'check_[0-9]_' functions_lib.sh | grep -vE "\'$checkexcluded\'"); do + "$c" + done + else + for i in $(echo "$check" | sed "s/,/ /g"); do + if command -v "$i" 2>/dev/null 1>&2; then + "$i" + else + echo "Check \"$i\" doesn't seem to exist." + continue + fi + done + fi + + printf "\n" + info "Checks: $totalChecks" + info "Score: $currentScore" + + endjson "$totalChecks" "$currentScore" "$(date +%s)" +} + +main "$@" diff --git a/tests/2_docker_daemon_configuration.sh b/tests/2_docker_daemon_configuration.sh index 5d79a23..f4cea69 100644 --- a/tests/2_docker_daemon_configuration.sh +++ b/tests/2_docker_daemon_configuration.sh @@ -4,7 +4,7 @@ check_2() { logit "\n" id_2="2" desc_2="Docker daemon configuration" - check_2="id_2 - $desc_2" + check_2="$id_2 - $desc_2" info "$check_2" startsectionjson "$id_2" "$desc_2" } diff --git a/tests/3_docker_daemon_configuration_files.sh b/tests/3_docker_daemon_configuration_files.sh index 6481b0d..74831a6 100644 --- a/tests/3_docker_daemon_configuration_files.sh +++ b/tests/3_docker_daemon_configuration_files.sh @@ -47,7 +47,7 @@ check_3_2() { 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 + if [ "$(stat -c %a $file)" -eq 644 ] || [ "$(stat -c %a $file)" -eq 600 ]; then pass "$check_3_2" resulttestjson "PASS" currentScore=$((currentScore + 1)) @@ -103,7 +103,7 @@ check_3_4() { 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 + if [ "$(stat -c %a $file)" -eq 644 ] || [ "$(stat -c %a $file)" -eq 600 ]; then pass "$check_3_4" resulttestjson "PASS" currentScore=$((currentScore + 1)) @@ -159,7 +159,7 @@ check_3_6() { 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 + if [ "$(stat -c %a $directory)" -eq 755 ] || [ "$(stat -c %a $directory)" -eq 700 ]; then pass "$check_3_6" resulttestjson "PASS" currentScore=$((currentScore + 1)) @@ -225,7 +225,7 @@ check_3_8() { fail=0 perms=$(find "$directory" -type f -name '*.crt') for p in $perms; do - if [ "$(stat -c %a $p)" -ne 444 -a "$(stat -c %a $p)" -ne 400 ]; then + if [ "$(stat -c %a $p)" -ne 444 ] && [ "$(stat -c %a $p)" -ne 400 ]; then fail=1 fi done @@ -293,7 +293,7 @@ check_3_10() { tlscacert=$(get_docker_effective_command_line_args '--tlscacert' | sed -n 's/.*tlscacert=\([^s]\)/\1/p' | sed 's/--/ --/g' | cut -d " " -f 1) fi if [ -f "$tlscacert" ]; then - if [ "$(stat -c %a $tlscacert)" -eq 444 -o "$(stat -c %a $tlscacert)" -eq 400 ]; then + if [ "$(stat -c %a $tlscacert)" -eq 444 ] || [ "$(stat -c %a $tlscacert)" -eq 400 ]; then pass "$check_3_10" resulttestjson "PASS" currentScore=$((currentScore + 1)) @@ -357,7 +357,7 @@ check_3_12() { tlscert=$(get_docker_effective_command_line_args '--tlscert' | sed -n 's/.*tlscert=\([^s]\)/\1/p' | sed 's/--/ --/g' | cut -d " " -f 1) fi if [ -f "$tlscert" ]; then - if [ "$(stat -c %a $tlscert)" -eq 444 -o "$(stat -c %a $tlscert)" -eq 400 ]; then + if [ "$(stat -c %a $tlscert)" -eq 444 ] || [ "$(stat -c %a $tlscert)" -eq 400 ]; then pass "$check_3_12" resulttestjson "PASS" currentScore=$((currentScore + 1)) @@ -477,7 +477,7 @@ check_3_16() { 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 + if [ "$(stat -c %a $file)" -eq 660 ] || [ "$(stat -c %a $file)" -eq 600 ]; then pass "$check_3_16" resulttestjson "PASS" currentScore=$((currentScore + 1)) @@ -533,7 +533,7 @@ check_3_18() { 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 640 -o "$(stat -c %a $file)" -eq 600 ]; then + if [ "$(stat -c %a $file)" -eq 644 ] || [ "$(stat -c %a $file)" -eq 640 ] || [ "$(stat -c %a $file)" -eq 600 ]; then pass "$check_3_18" resulttestjson "PASS" currentScore=$((currentScore + 1)) @@ -589,7 +589,7 @@ check_3_20() { 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 + if [ "$(stat -c %a $file)" -eq 644 ] || [ "$(stat -c %a $file)" -eq 600 ]; then pass "$check_3_20" resulttestjson "PASS" currentScore=$((currentScore + 1)) diff --git a/tests/4_container_images.sh b/tests/4_container_images.sh index cc227db..4dbace6 100644 --- a/tests/4_container_images.sh +++ b/tests/4_container_images.sh @@ -36,7 +36,7 @@ check_4_1() { for c in $containers; do user=$(docker inspect --format 'User={{.Config.User}}' "$c") - if [ "$user" = "User=" -o "$user" = "User=[]" -o "$user" = "User=" ]; then + if [ "$user" = "User=" ] || [ "$user" = "User=[]" ] || [ "$user" = "User=" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then warn "$check_4_1" diff --git a/tests/5_container_runtime.sh b/tests/5_container_runtime.sh index eaa9ada..9db54d8 100644 --- a/tests/5_container_runtime.sh +++ b/tests/5_container_runtime.sh @@ -40,7 +40,7 @@ check_5_1() { for c in $containers; do policy=$(docker inspect --format 'AppArmorProfile={{ .AppArmorProfile }}' "$c") - if [ "$policy" = "AppArmorProfile=" -o "$policy" = "AppArmorProfile=[]" -o "$policy" = "AppArmorProfile=" ]; then + if [ "$policy" = "AppArmorProfile=" ] || [ "$policy" = "AppArmorProfile=[]" ] || [ "$policy" = "AppArmorProfile=" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then warn "$check_5_1" @@ -82,7 +82,7 @@ check_5_2() { for c in $containers; do policy=$(docker inspect --format 'SecurityOpt={{ .HostConfig.SecurityOpt }}' "$c") - if [ "$policy" = "SecurityOpt=" -o "$policy" = "SecurityOpt=[]" -o "$policy" = "SecurityOpt=" ]; then + if [ "$policy" = "SecurityOpt=" ] || [ "$policy" = "SecurityOpt=[]" ] || [ "$policy" = "SecurityOpt=" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then warn "$check_5_2" @@ -127,7 +127,7 @@ check_5_3() { sed 's/CAPADD/CapAdd/' | \ sed -r "s/AUDIT_WRITE|CHOWN|DAC_OVERRIDE|FOWNER|FSETID|KILL|MKNOD|NET_BIND_SERVICE|NET_RAW|SETFCAP|SETGID|SETPCAP|SETUID|SYS_CHROOT|\s//g") - if [ "$caps" != 'CapAdd=' -a "$caps" != 'CapAdd=[]' -a "$caps" != 'CapAdd=' -a "$caps" != 'CapAdd=' ]; then + if [ "$caps" != 'CapAdd=' ] && [ "$caps" != 'CapAdd=[]' ] && [ "$caps" != 'CapAdd=' ] && [ "$caps" != 'CapAdd=' ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then warn "$check_5_3" @@ -736,7 +736,7 @@ check_5_17() { for c in $containers; do devices=$(docker inspect --format 'Devices={{ .HostConfig.Devices }}' "$c") - if [ "$devices" != "Devices=" -a "$devices" != "Devices=[]" -a "$devices" != "Devices=" ]; then + if [ "$devices" != "Devices=" ] && [ "$devices" != "Devices=[]" ] && [ "$devices" != "Devices=" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then info "$check_5_17" @@ -778,7 +778,7 @@ check_5_18() { for c in $containers; do ulimits=$(docker inspect --format 'Ulimits={{ .HostConfig.Ulimits }}' "$c") - if [ "$ulimits" = "Ulimits=" -o "$ulimits" = "Ulimits=[]" -o "$ulimits" = "Ulimits=" ]; then + if [ "$ulimits" = "Ulimits=" ] || [ "$ulimits" = "Ulimits=[]" ] || [ "$ulimits" = "Ulimits=" ]; then # If it's the first container, fail the test if [ $fail -eq 0 ]; then info "$check_5_18"