Merge pull request #467 from razvanstoica89/master

Small improvement of user experience
This commit is contained in:
Thomas Sjögren 2021-04-27 08:46:53 +00:00 committed by GitHub
commit 6a8fdcf72e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 2563 additions and 2379 deletions

View file

@ -1,5 +1,6 @@
.git *
*.md !docker-bench-security.sh
*.png !functions/
distros !tests/
!log/
log/*

3
.gitignore vendored
View file

@ -1 +1,2 @@
*.log* log/*
*.swp*

View file

@ -5,17 +5,11 @@ LABEL \
org.label-schema.url="https://dockerbench.com" \ org.label-schema.url="https://dockerbench.com" \
org.label-schema.vcs-url="https://github.com/docker/docker-bench-security.git" org.label-schema.vcs-url="https://github.com/docker/docker-bench-security.git"
# Switch to the HTTPS endpoint for the apk repositories RUN apk add --no-cache iproute2 \
# https://github.com/gliderlabs/docker-alpine/issues/184 docker-cli \
RUN set -eux; \ dumb-init
sed -i 's!http://dl-cdn.alpinelinux.org/!https://alpine.global.ssl.fastly.net/!g' /etc/apk/repositories && \
apk add --no-cache \
iproute2 \
docker-cli \
dumb-init
COPY ./*.sh /usr/local/bin/ COPY . /usr/local/bin/
COPY ./tests/*.sh /usr/local/bin/tests/
HEALTHCHECK CMD exit 0 HEALTHCHECK CMD exit 0

135
README.md
View file

@ -1,24 +1,30 @@
# Docker Bench for Security # Docker Bench for Security
![Docker Bench for Security running](https://raw.githubusercontent.com/docker/docker-bench-security/master/benchmark_log.png) ![Docker Bench for Security running](img/benchmark_log.png)
The Docker Bench for Security is a script that checks for dozens of common 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 Benchmark v1.2.0](https://www.cisecurity.org/benchmark/docker/).
best-practices around deploying Docker containers in production. The tests are
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 The list with all tests is available [here](tests/TESTS.md).
can have an easy way to self-assess their hosts and docker containers against
this benchmark. 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 this benchmark.
## Running Docker Bench for Security ## Running Docker Bench for Security
We packaged docker bench as a small container for your convenience. Note that ### Run from your base host
this container is being run with a *lot* of privilege -- sharing the host's
filesystem, pid and network namespaces, due to portions of the benchmark
applying to the running host.
The easiest way to run your hosts against the Docker Bench for Security is by You can simply run this script from your base host by running:
running our pre-built container:
```sh
git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security
sudo sh docker-bench-security.sh
```
### Run with Docker
We packaged docker bench as a small container for your convenience. Note that this container is being run with a *lot* of privilege -- sharing the host's filesystem, pid and network namespaces, due to portions of the benchmark applying to the running host.
The easiest way to run your hosts against the Docker Bench for Security is by running our pre-built container:
```sh ```sh
docker run --rm --net host --pid host --userns host --cap-add audit_control \ docker run --rm --net host --pid host --userns host --cap-add audit_control \
@ -36,20 +42,7 @@ docker run --rm --net host --pid host --userns host --cap-add audit_control \
Don't forget to adjust the shared volumes according to your operating system. Don't forget to adjust the shared volumes according to your operating system.
Some examples are: Some examples are:
1. `Docker Desktop` on macOS doesn't have `/usr/lib/systemd` or the above Docker 1. On Ubuntu the `docker.service` and `docker.secret` files are located in
binaries.
```sh
docker run --rm --net host --pid host --userns host --cap-add audit_control \
-e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /etc:/etc \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--label docker_bench_security \
docker/docker-bench-security
```
2. On Ubuntu the `docker.service` and `docker.secret` files are located in
`/lib/systemd/system` folder by default. `/lib/systemd/system` folder by default.
```sh ```sh
@ -66,17 +59,24 @@ docker run --rm --net host --pid host --userns host --cap-add audit_control \
docker/docker-bench-security docker/docker-bench-security
``` ```
2. `Docker Desktop` on macOS doesn't have `/usr/lib/systemd` or the above Docker
binaries.
```sh
docker run --rm --net host --pid host --userns host --cap-add audit_control \
-e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /etc:/etc \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--label docker_bench_security \
docker/docker-bench-security
```
### Note
Docker bench requires Docker 1.13.0 or later in order to run. Docker bench requires Docker 1.13.0 or later in order to run.
Note that when distributions don't contain `auditctl`, the audit tests will Note that when distributions don't contain `auditctl`, the audit tests will check `/etc/audit/audit.rules` to see if a rule is present instead.
check `/etc/audit/audit.rules` to see if a rule is present instead.
Distribution specific Dockerfiles that fix these issues are available in the
[distros directory](https://github.com/docker/docker-bench-security/tree/master/distros).
The [distribution specific Dockerfiles](https://github.com/docker/docker-bench-security/tree/master/distros)
may also help if the distribution you're using hasn't yet shipped Docker
version 1.13.0 or later.
### Docker Bench for Security options ### Docker Bench for Security options
@ -84,47 +84,40 @@ version 1.13.0 or later.
-b optional Do not print colors -b optional Do not print colors
-h optional Print this help message -h optional Print this help message
-l FILE optional Log output in FILE, inside container if run using docker -l FILE optional Log output in FILE, inside container if run using docker
-c CHECK optional Comma delimited list of specific check(s) -u USERS optional Comma delimited list of trusted docker user(s)
-e CHECK optional Comma delimited list of specific check(s) to exclude -c CHECK optional Comma delimited list of specific check(s) id
-e CHECK optional Comma delimited list of specific check(s) id to exclude
-i INCLUDE optional Comma delimited list of patterns within a container or image name to check -i INCLUDE optional Comma delimited list of patterns within a container or image name to check
-x EXCLUDE optional Comma delimited list of patterns within a container or image name to exclude from check -x EXCLUDE optional Comma delimited list of patterns within a container or image name to exclude from check
-n LIMIT optional In JSON output, when reporting lists of items (containers, images, etc.), limit the number of reported items to LIMIT. Default 0 (no limit).
-p PRINT optional Disable the printing of remediation measures. Default: print remediation measures.
``` ```
By default the Docker Bench for Security script will run all available CIS tests By default the Docker Bench for Security script will run all available CIS tests and produce
and produce logs in the current directory, named `docker-bench-security.sh.log.json` logs in the log folder from current directory, named `docker-bench-security.sh.log.json` and
and `docker-bench-security.sh.log`. `docker-bench-security.sh.log`.
If the docker container is used then the log files will be created inside the container. If you wish to access them from the host after the container has been run you will need to mount a volume for storing them in. If the docker container is used then the log files will be created inside the container in location `/usr/local/bin/log/`. If you wish to access them from the host after the container has been run you will need to mount a volume for storing them in.
The CIS based checks are named `check_<section>_<number>`, e.g. `check_2_6` The CIS based checks are named `check_<section>_<number>`, e.g. `check_2_6` and community contributed checks are named `check_c_<number>`. A complete list of checks is present in [TESTS.md](tests/TESTS.md).
and community contributed checks are named `check_c_<number>`.
A complete list of checks is present in [functions_lib.sh](functions_lib.sh).
`sh docker-bench-security.sh -l /tmp/docker-bench-security.sh.log -c check_2_2` `sh docker-bench-security.sh -c check_2_2` will only run check `2.2 Ensure the logging level is set to 'info'`.
will only run check `2.2 Ensure the logging level is set to 'info'`.
`sh docker-bench-security.sh -l /tmp/docker-bench-security.sh.log -e check_2_2` `sh docker-bench-security.sh -e check_2_2` will run all available checks except `2.2 Ensure the logging level is set to 'info'`.
will run all available checks except `2.2 Ensure the logging level is set to 'info'`.
`sh docker-bench-security.sh -l /tmp/docker-bench-security.sh.log -e docker_enterprise_configuration` `sh docker-bench-security.sh -e docker_enterprise_configuration` will run all available checks except the docker_enterprise_configuration group
will run all available checks except the docker_enterprise_configuration group
`sh docker-bench-security.sh -l /tmp/docker-bench-security.sh.log -e docker_enterprise_configuration,check_2_2` `sh docker-bench-security.sh -e docker_enterprise_configuration,check_2_2` will run allavailable checks except the docker_enterprise_configuration group and `2.2 Ensure the logging level is set to 'info'`
will run all available checks except the docker_enterprise_configuration group
and `2.2 Ensure the logging level is set to 'info'`
`sh docker-bench-security.sh -l /tmp/docker-bench-security.sh.log -c container_images -e check_4_5` `sh docker-bench-security.sh -c container_images -e check_4_5` will run just the container_images checks except `4.5 Ensure Content trust for Docker is Enabled`
will run just the container_images checks except
`4.5 Ensure Content trust for Docker is Enabled`
Note that when submitting checks, provide information why it is a Note that when submitting checks, provide information why it is a reasonable test to add and please include some kind of official documentation verifying that information.
reasonable test to add and please include some kind of official documentation
verifying that information.
## Building Docker Bench for Security ## Building Docker image
If you wish to build and run this container yourself, you can follow the You have two options if you wish to build and run this container yourself:
following steps:
1. Use Docker Build:
```sh ```sh
git clone https://github.com/docker/docker-bench-security.git git clone https://github.com/docker/docker-bench-security.git
@ -132,8 +125,9 @@ cd docker-bench-security
docker build --no-cache -t docker-bench-security . docker build --no-cache -t docker-bench-security .
``` ```
followed by an appropriate `docker run` command as stated above Followed by an appropriate `docker run` command as stated above.
or use [Docker Compose](https://docs.docker.com/compose/):
2. Use Docker Compose:
```sh ```sh
git clone https://github.com/docker/docker-bench-security.git git clone https://github.com/docker/docker-bench-security.git
@ -141,13 +135,4 @@ cd docker-bench-security
docker-compose run --rm docker-bench-security docker-compose run --rm docker-bench-security
``` ```
Also, this script can also be simply run from your base host by running: This script was built to be POSIX 2004 compliant, so it should be portable across any Unix platform.
```sh
git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security
sudo sh docker-bench-security.sh
```
This script was built to be POSIX 2004 compliant, so it should be portable
across any Unix platform.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 275 KiB

View file

@ -1,21 +1,15 @@
FROM alpine:3.12 FROM alpine:3.13
LABEL \ LABEL \
org.label-schema.name="docker-bench-security" \ org.label-schema.name="docker-bench-security" \
org.label-schema.url="https://dockerbench.com" \ org.label-schema.url="https://dockerbench.com" \
org.label-schema.vcs-url="https://github.com/docker/docker-bench-security.git" org.label-schema.vcs-url="https://github.com/docker/docker-bench-security.git"
# Switch to the HTTPS endpoint for the apk repositories RUN apk add --no-cache iproute2 \
# https://github.com/gliderlabs/docker-alpine/issues/184 docker-cli \
RUN set -eux; \ dumb-init
sed -i 's!http://dl-cdn.alpinelinux.org/!https://alpine.global.ssl.fastly.net/!g' /etc/apk/repositories && \
apk add --no-cache \
iproute2 \
docker-cli \
dumb-init
COPY ./*.sh /usr/local/bin/ COPY . /usr/local/bin/
COPY ./tests/*.sh /usr/local/bin/tests/
HEALTHCHECK CMD exit 0 HEALTHCHECK CMD exit 0

View file

@ -1,21 +1,21 @@
#!/bin/sh #!/bin/sh
# ------------------------------------------------------------------------------ # --------------------------------------------------------------------------------------------
# Docker Bench for Security # Docker Bench for Security
# #
# Docker, Inc. (c) 2015- # Docker, Inc. (c) 2015-2021
# #
# Checks for dozens of common best-practices around deploying Docker containers in production. # Checks for dozens of common best-practices around deploying Docker containers in production.
# ------------------------------------------------------------------------------ # --------------------------------------------------------------------------------------------
version='1.3.5' version='1.3.6'
# Load dependencies # Load dependencies
. ./functions_lib.sh . ./functions/functions_lib.sh
. ./helper_lib.sh . ./functions/helper_lib.sh
# Setup the paths # Setup the paths
this_path=$(abspath "$0") ## Path of this file including filename this_path=$(abspath "$0") ## Path of this file including filename
myname=$(basename "${this_path}") ## file name of this script. myname=$(basename "${this_path%.*}") ## file name of this script.
readonly version readonly version
readonly this_path readonly this_path
@ -24,19 +24,7 @@ readonly myname
export PATH="$PATH:/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin/" export PATH="$PATH:/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin/"
# Check for required program(s) # Check for required program(s)
req_progs='awk docker grep stat' req_programs 'awk docker grep stat tee tail wc xargs truncate sed'
for p in $req_progs; do
command -v "$p" >/dev/null 2>&1 || { printf "%s command not found.\n" "$p"; exit 1; }
done
if command -v ss >/dev/null 2>&1; then
netbin=ss
elif command -v netstat >/dev/null 2>&1; then
netbin=netstat
else
echo "ss or netstat command not found."
exit 1
fi
# Ensure we can connect to docker daemon # Ensure we can connect to docker daemon
if ! docker ps -q >/dev/null 2>&1; then if ! docker ps -q >/dev/null 2>&1; then
@ -46,54 +34,76 @@ fi
usage () { usage () {
cat <<EOF cat <<EOF
usage: ${myname} [options] Docker Bench for Security - Docker, Inc. (c) 2015-$(date +"%Y")
Checks for dozens of common best-practices around deploying Docker containers in production.
Inspired by the CIS Docker Benchmark v1.2.0.
Usage: ${myname}.sh [OPTIONS]
Example:
- Only run check "2.2 - Ensure the logging level is set to 'info'":
sh docker-bench-security.sh -c check_2_2
- Run all available checks except the host_configuration group and "2.8 - Enable user namespace support":
sh docker-bench-security.sh -e host_configuration,check_2_8
- Run just the container_images checks except "4.5 - Ensure Content trust for Docker is Enabled":
sh docker-bench-security.sh -c container_images -e check_4_5
Options:
-b optional Do not print colors -b optional Do not print colors
-h optional Print this help message -h optional Print this help message
-l FILE optional Log output in FILE -l FILE optional Log output in FILE, inside container if run using docker
-c CHECK optional Comma delimited list of specific check(s) -u USERS optional Comma delimited list of trusted docker user(s)
-e CHECK optional Comma delimited list of specific check(s) to exclude -c CHECK optional Comma delimited list of specific check(s) id
-e CHECK optional Comma delimited list of specific check(s) id to exclude
-i INCLUDE optional Comma delimited list of patterns within a container or image name to check -i INCLUDE optional Comma delimited list of patterns within a container or image name to check
-x EXCLUDE optional Comma delimited list of patterns within a container or image name to exclude from check -x EXCLUDE optional Comma delimited list of patterns within a container or image name to exclude from check
-n LIMIT optional In JSON output, when reporting lists of items (containers, images, etc.), limit the number of reported items to LIMIT. Default 0 (no limit). -n LIMIT optional In JSON output, when reporting lists of items (containers, images, etc.), limit the number of reported items to LIMIT. Default 0 (no limit).
-p PRINT optional Disable the printing of remediation measures. Default: print remediation measures.
Complete list of checks: <https://github.com/docker/docker-bench-security/blob/master/tests/>
Full documentation: <https://github.com/docker/docker-bench-security>
Released under the Apache-2.0 License.
EOF EOF
} }
# Default values
if [ ! -d log ]; then
mkdir log
fi
logger="log/${myname}.log"
limit=0
printremediation="1"
globalRemediation=""
# Get the flags # Get the flags
# If you add an option here, please # If you add an option here, please
# remember to update usage() above. # remember to update usage() above.
while getopts bhl:c:e:i:x:t:n: args while getopts bhl:u:c:e:i:x:t:n:p args
do do
case $args in case $args in
b) nocolor="nocolor";; b) nocolor="nocolor";;
h) usage; exit 0 ;; h) usage; exit 0 ;;
l) logger="$OPTARG" ;; l) logger="$OPTARG" ;;
u) dockertrustusers="$OPTARG" ;;
c) check="$OPTARG" ;; c) check="$OPTARG" ;;
e) checkexclude="$OPTARG" ;; e) checkexclude="$OPTARG" ;;
i) include="$OPTARG" ;; i) include="$OPTARG" ;;
x) exclude="$OPTARG" ;; x) exclude="$OPTARG" ;;
n) limit="$OPTARG" ;; n) limit="$OPTARG" ;;
p) printremediation="0" ;;
*) usage; exit 1 ;; *) usage; exit 1 ;;
esac esac
done done
if [ -z "$logger" ]; then
logger="${myname}.log"
fi
if [ -z "$limit" ]; then
limit=0
fi
# Load output formating # Load output formating
. ./output_lib.sh . ./functions/output_lib.sh
yell_info yell_info
# Warn if not root # Warn if not root
ID=$(id -u) ID=$(id -u)
if [ "x$ID" != "x0" ]; then if [ "x$ID" != "x0" ]; then
warn "Some tests might require root to run" warn "$(yell 'Some tests might require root to run')\n"
sleep 3 sleep 3
fi fi
@ -103,11 +113,13 @@ fi
totalChecks=0 totalChecks=0
currentScore=0 currentScore=0
logit "Initializing $(date)\n" logit "Initializing $(date +%Y-%m-%dT%H:%M:%S%:z)\n"
beginjson "$version" "$(date +%s)" beginjson "$version" "$(date +%s)"
# Load all the tests from tests/ and run them # Load all the tests from tests/ and run them
main () { main () {
logit "\n${bldylw}Section A - Check results${txtrsr}"
# Get configuration location # Get configuration location
get_docker_configuration_file get_docker_configuration_file
@ -142,12 +154,6 @@ main () {
images=$(docker images -q | grep -v "$benchcont") images=$(docker images -q | grep -v "$benchcont")
fi fi
if [ -z "$containers" ]; then
running_containers=0
else
running_containers=1
fi
for test in tests/*.sh; do for test in tests/*.sh; do
. ./"$test" . ./"$test"
done done
@ -157,7 +163,7 @@ main () {
cis cis
elif [ -z "$check" ]; then elif [ -z "$check" ]; then
# No check defined but excludes defined set to calls in cis() function # No check defined but excludes defined set to calls in cis() function
check=$(sed -ne "/cis() {/,/}/{/{/d; /}/d; p}" functions_lib.sh) check=$(sed -ne "/cis() {/,/}/{/{/d; /}/d; p}" functions/functions_lib.sh)
fi fi
for c in $(echo "$check" | sed "s/,/ /g"); do for c in $(echo "$check" | sed "s/,/ /g"); do
@ -177,7 +183,7 @@ main () {
continue continue
elif echo "$c" | grep -vE 'check_[0-9]|check_[a-z]' 2>/dev/null 1>&2; then elif echo "$c" | grep -vE 'check_[0-9]|check_[a-z]' 2>/dev/null 1>&2; then
# Function not a check, fill loop_checks with all check from function # Function not a check, fill loop_checks with all check from function
loop_checks="$(sed -ne "/$c() {/,/}/{/{/d; /}/d; p}" functions_lib.sh)" loop_checks="$(sed -ne "/$c() {/,/}/{/{/d; /}/d; p}" functions/functions_lib.sh)"
else else
# Just one check # Just one check
loop_checks="$c" loop_checks="$c"
@ -192,9 +198,14 @@ main () {
fi fi
done done
printf "\n" if [ -n "${globalRemediation}" ] && [ "$printremediation" = "1" ]; then
logit "\n\n${bldylw}Section B - Remediation measures${txtrst}"
logit "${globalRemediation}"
fi
logit "\n\n${bldylw}Section C - Score${txtrst}\n"
info "Checks: $totalChecks" info "Checks: $totalChecks"
info "Score: $currentScore" info "Score: $currentScore\n"
endjson "$totalChecks" "$currentScore" "$(date +%s)" endjson "$totalChecks" "$currentScore" "$(date +%s)"
} }

View file

@ -41,6 +41,32 @@ host_configuration_level1() {
check_1_end check_1_end
} }
host_general_configuration() {
check_1
check_1_1
check_1_1_1
check_1_1_2
check_1_end
}
linux_hosts_specific_configuration() {
check_1
check_1_2
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
}
docker_daemon_configuration() { docker_daemon_configuration() {
check_2 check_2
check_2_1 check_2_1
@ -303,9 +329,30 @@ docker_enterprise_configuration_level1() {
check_8_end check_8_end
} }
universal_control_plane_configuration() {
check_8
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_end
}
docker_trusted_registry_configuration() {
check_8
check_8_2
check_8_2_1
check_8_end
}
community_checks() { community_checks() {
check_c check_c
check_c_1 check_c_1
check_c_1_1
check_c_2 check_c_2
check_c_end check_c_end
} }

View file

@ -6,6 +6,23 @@ abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; es
# Audit rules default path # Audit rules default path
auditrules="/etc/audit/audit.rules" auditrules="/etc/audit/audit.rules"
# Check for required program(s)
req_programs() {
for p in $1; do
command -v "$p" >/dev/null 2>&1 || { printf "Required program not found: %s\n" "$p"; exit 1; }
done
if command -v ss >/dev/null 2>&1; then
netbin=ss
return
fi
if command -v netstat >/dev/null 2>&1; then
netbin=netstat
return
fi
echo "ss or netstat command not found."
exit 1
}
# Compares versions of software of the format X.Y.Z # Compares versions of software of the format X.Y.Z
do_version_check() { do_version_check() {
[ "$1" = "$2" ] && return 10 [ "$1" = "$2" ] && return 10
@ -23,9 +40,8 @@ do_version_check() {
[ "$ver2front" = "$2" ] || [ -z "$ver2back" ] && ver2back=0 [ "$ver2front" = "$2" ] || [ -z "$ver2back" ] && ver2back=0
do_version_check "$ver1back" "$ver2back" do_version_check "$ver1back" "$ver2back"
return $? return $?
else
[ "$1" -gt "$2" ] && return 11 || return 9
fi fi
[ "$1" -gt "$2" ] && return 11 || return 9
} }
# Extracts commandline args from the newest running processes named like the first parameter # Extracts commandline args from the newest running processes named like the first parameter
@ -45,10 +61,9 @@ get_command_line_args() {
get_docker_cumulative_command_line_args() { get_docker_cumulative_command_line_args() {
OPTION="$1" OPTION="$1"
line_arg="dockerd"
if ! get_command_line_args "docker daemon" >/dev/null 2>&1 ; then if ! get_command_line_args "docker daemon" >/dev/null 2>&1 ; then
line_arg="docker daemon" line_arg="docker daemon"
else
line_arg="dockerd"
fi fi
get_command_line_args "$line_arg" | get_command_line_args "$line_arg" |
@ -88,11 +103,13 @@ get_docker_configuration_file() {
if [ -f "$FILE" ]; then if [ -f "$FILE" ]; then
CONFIG_FILE="$FILE" CONFIG_FILE="$FILE"
elif [ -f '/etc/docker/daemon.json' ]; then return
CONFIG_FILE='/etc/docker/daemon.json'
else
CONFIG_FILE='/dev/null'
fi fi
if [ -f '/etc/docker/daemon.json' ]; then
CONFIG_FILE='/etc/docker/daemon.json'
return
fi
CONFIG_FILE='/dev/null'
} }
get_docker_configuration_file_args() { get_docker_configuration_file_args() {
@ -108,13 +125,17 @@ get_service_file() {
if [ -f "/etc/systemd/system/$SERVICE" ]; then if [ -f "/etc/systemd/system/$SERVICE" ]; then
echo "/etc/systemd/system/$SERVICE" echo "/etc/systemd/system/$SERVICE"
elif [ -f "/lib/systemd/system/$SERVICE" ]; then return
echo "/lib/systemd/system/$SERVICE"
elif systemctl show -p FragmentPath "$SERVICE" 2> /dev/null 1>&2; then
systemctl show -p FragmentPath "$SERVICE" | sed 's/.*=//'
else
echo "/usr/lib/systemd/system/$SERVICE"
fi fi
if [ -f "/lib/systemd/system/$SERVICE" ]; then
echo "/lib/systemd/system/$SERVICE"
return
fi
if systemctl show -p FragmentPath "$SERVICE" 2> /dev/null 1>&2; then
systemctl show -p FragmentPath "$SERVICE" | sed 's/.*=//'
return
fi
echo "/usr/lib/systemd/system/$SERVICE"
} }
yell_info() { yell_info() {

190
functions/output_lib.sh Normal file
View file

@ -0,0 +1,190 @@
#!/bin/sh
bldred='\033[1;31m' # Bold Red
bldgrn='\033[1;32m' # Bold Green
bldblu='\033[1;34m' # Bold Blue
bldylw='\033[1;33m' # Bold Yellow
txtrst='\033[0m'
if [ -n "$nocolor" ] && [ "$nocolor" = "nocolor" ]; then
bldred=''
bldgrn=''
bldblu=''
bldylw=''
txtrst=''
fi
logit () {
printf "%b\n" "$1" | tee -a "$logger"
}
info () {
local infoCountCheck
local OPTIND c
while getopts c args
do
case $args in
c) infoCountCheck="true" ;;
*) exit 1 ;;
esac
done
if [ "$infoCountCheck" = "true" ]; then
printf "%b\n" "${bldblu}[INFO]${txtrst} $2" | tee -a "$logger"
totalChecks=$((totalChecks + 1))
return
fi
printf "%b\n" "${bldblu}[INFO]${txtrst} $1" | tee -a "$logger"
}
pass () {
local passScored
local passCountCheck
local OPTIND s c
while getopts sc args
do
case $args in
s) passScored="true" ;;
c) passCountCheck="true" ;;
*) exit 1 ;;
esac
done
if [ "$passScored" = "true" ] || [ "$passCountCheck" = "true" ]; then
printf "%b\n" "${bldgrn}[PASS]${txtrst} $2" | tee -a "$logger"
totalChecks=$((totalChecks + 1))
fi
if [ "$passScored" = "true" ]; then
currentScore=$((currentScore + 1))
fi
if [ "$passScored" != "true" ] && [ "$passCountCheck" != "true" ]; then
printf "%b\n" "${bldgrn}[PASS]${txtrst} $1" | tee -a "$logger"
fi
}
warn () {
local warnScored
local OPTIND s
while getopts s args
do
case $args in
s) warnScored="true" ;;
*) exit 1 ;;
esac
done
if [ "$warnScored" = "true" ]; then
printf "%b\n" "${bldred}[WARN]${txtrst} $2" | tee -a "$logger"
totalChecks=$((totalChecks + 1))
currentScore=$((currentScore - 1))
return
fi
printf "%b\n" "${bldred}[WARN]${txtrst} $1" | tee -a "$logger"
}
note () {
local noteCountCheck
local OPTIND c
while getopts c args
do
case $args in
c) noteCountCheck="true" ;;
*) exit 1 ;;
esac
done
if [ "$noteCountCheck" = "true" ]; then
printf "%b\n" "${bldylw}[NOTE]${txtrst} $2" | tee -a "$logger"
totalChecks=$((totalChecks + 1))
return
fi
printf "%b\n" "${bldylw}[NOTE]${txtrst} $1" | tee -a "$logger"
}
yell () {
printf "%b\n" "${bldylw}$1${txtrst}\n"
}
beginjson () {
printf "{\n \"dockerbenchsecurity\": \"%s\",\n \"start\": %s,\n \"tests\": [" "$1" "$2" | tee "$logger.json" 2>/dev/null 1>&2
}
endjson (){
printf "\n ],\n \"checks\": %s,\n \"score\": %s,\n \"end\": %s\n}" "$1" "$2" "$3" | tee -a "$logger.json" 2>/dev/null 1>&2
}
logjson (){
printf "\n \"%s\": \"%s\"," "$1" "$2" | tee -a "$logger.json" 2>/dev/null 1>&2
}
SSEP=
SEP=
startsectionjson() {
printf "%s\n {\n \"id\": \"%s\",\n \"desc\": \"%s\",\n \"results\": [" "$SSEP" "$1" "$2" | tee -a "$logger.json" 2>/dev/null 1>&2
SEP=
SSEP=","
}
endsectionjson() {
printf "\n ]\n }" | tee -a "$logger.json" 2>/dev/null 1>&2
}
starttestjson() {
printf "%s\n {\n \"id\": \"%s\",\n \"desc\": \"%s\",\n " "$SEP" "$1" "$2" | tee -a "$logger.json" 2>/dev/null 1>&2
SEP=","
}
log_to_json() {
if [ $# -eq 1 ]; then
printf "\"result\": \"%s\"" "$1" | tee -a "$logger.json" 2>/dev/null 1>&2
return
fi
if [ $# -eq 2 ] && [ $# -ne 1 ]; then
# Result also contains details
printf "\"result\": \"%s\",\n \"details\": \"%s\"" "$1" "$2" | tee -a "$logger.json" 2>/dev/null 1>&2
return
fi
# Result also includes details and a list of items. Add that directly to details and to an array property "items"
# Also limit the number of items to $limit, if $limit is non-zero
truncItems=$3
if [ $limit != 0 ]; then
truncItems=""
ITEM_COUNT=0
for item in $3; do
truncItems="$truncItems $item"
ITEM_COUNT=$((ITEM_COUNT + 1));
if [ "$ITEM_COUNT" == "$limit" ]; then
truncItems="$truncItems (truncated)"
break;
fi
done
fi
itemsJson=$(printf "[\n "; ISEP=""; ITEMCOUNT=0; for item in $truncItems; do printf "%s\"%s\"" "$ISEP" "$item"; ISEP=","; done; printf "\n ]")
printf "\"result\": \"%s\",\n \"details\": \"%s: %s\",\n \"items\": %s" "$1" "$2" "$truncItems" "$itemsJson" | tee -a "$logger.json" 2>/dev/null 1>&2
}
logcheckresult() {
# Log to JSON
log_to_json "$@"
# Log remediation measure to JSON
if [ -n "$remediation" ] && [ "$1" != "PASS" ] && [ "$printremediation" = "1" ]; then
printf ",\n \"remediation\": \"%s\"" "$remediation" | tee -a "$logger.json" 2>/dev/null 1>&2
if [ -n "$remediationImpact" ]; then
printf ",\n \"remediation-impact\": \"%s\"" "$remediationImpact" | tee -a "$logger.json" 2>/dev/null 1>&2
fi
fi
printf "\n }" | tee -a "$logger.json" 2>/dev/null 1>&2
# Save remediation measure for print log to stdout
if [ -n "$remediation" ] && [ "$1" != "PASS" ]; then
if [ -n "${checkHeader}" ]; then
if [ -n "${addSpaceHeader}" ]; then
globalRemediation="${globalRemediation}\n"
fi
globalRemediation="${globalRemediation}\n${bldblu}[INFO]${txtrst} ${checkHeader}"
checkHeader=""
addSpaceHeader="1"
fi
globalRemediation="${globalRemediation}\n${bldblu}[INFO]${txtrst} ${id} - ${remediation}"
if [ -n "${remediationImpact}" ]; then
globalRemediation="${globalRemediation} Remediation Impact: ${remediationImpact}"
fi
fi
}

BIN
img/benchmark_log.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 KiB

View file

@ -1,96 +0,0 @@
#!/bin/sh
if [ -n "$nocolor" ] && [ "$nocolor" = "nocolor" ]; then
bldred=''
bldgrn=''
bldblu=''
bldylw=''
txtrst=''
else
bldred='\033[1;31m'
bldgrn='\033[1;32m'
bldblu='\033[1;34m'
bldylw='\033[1;33m' # Yellow
txtrst='\033[0m'
fi
logit () {
printf "%b\n" "$1" | tee -a "$logger"
}
info () {
printf "%b\n" "${bldblu}[INFO]${txtrst} $1" | tee -a "$logger"
}
pass () {
printf "%b\n" "${bldgrn}[PASS]${txtrst} $1" | tee -a "$logger"
}
warn () {
printf "%b\n" "${bldred}[WARN]${txtrst} $1" | tee -a "$logger"
}
note () {
printf "%b\n" "${bldylw}[NOTE]${txtrst} $1" | tee -a "$logger"
}
yell () {
printf "%b\n" "${bldylw}$1${txtrst}\n"
}
beginjson () {
printf "{\n \"dockerbenchsecurity\": \"%s\",\n \"start\": %s,\n \"tests\": [" "$1" "$2" | tee "$logger.json" 2>/dev/null 1>&2
}
endjson (){
printf "\n ], \"checks\": %s, \"score\": %s, \"end\": %s \n}\n" "$1" "$2" "$3" | tee -a "$logger.json" 2>/dev/null 1>&2
}
logjson (){
printf "\n \"%s\": \"%s\"," "$1" "$2" | tee -a "$logger.json" 2>/dev/null 1>&2
}
SSEP=
SEP=
startsectionjson() {
printf "%s\n {\"id\": \"%s\", \"desc\": \"%s\", \"results\": [" "$SSEP" "$1" "$2" | tee -a "$logger.json" 2>/dev/null 1>&2
SEP=
SSEP=","
}
endsectionjson() {
printf "\n ]}" | tee -a "$logger.json" 2>/dev/null 1>&2
}
starttestjson() {
printf "%s\n {\"id\": \"%s\", \"desc\": \"%s\", " "$SEP" "$1" "$2" | tee -a "$logger.json" 2>/dev/null 1>&2
SEP=","
}
resulttestjson() {
if [ $# -eq 1 ]; then
printf "\"result\": \"%s\"}" "$1" | tee -a "$logger.json" 2>/dev/null 1>&2
elif [ $# -eq 2 ]; then
# Result also contains details
printf "\"result\": \"%s\", \"details\": \"%s\"}" "$1" "$2" | tee -a "$logger.json" 2>/dev/null 1>&2
else
# Result also includes details and a list of items. Add that directly to details and to an array property "items"
# Also limit the number of items to $limit, if $limit is non-zero
if [ $limit != 0 ]; then
truncItems=""
ITEM_COUNT=0
for item in $3; do
truncItems="$truncItems $item"
ITEM_COUNT=$((ITEM_COUNT + 1));
if [ "$ITEM_COUNT" == "$limit" ]; then
truncItems="$truncItems (truncated)"
break;
fi
done
else
truncItems=$3
fi
itemsJson=$(printf "["; ISEP=""; ITEMCOUNT=0; for item in $truncItems; do printf "%s\"%s\"" "$ISEP" "$item"; ISEP=","; done; printf "]")
printf "\"result\": \"%s\", \"details\": \"%s: %s\", \"items\": %s}" "$1" "$2" "$truncItems" "$itemsJson" | tee -a "$logger.json" 2>/dev/null 1>&2
fi
}

View file

@ -2,475 +2,461 @@
check_1() { check_1() {
logit "" logit ""
id_1="1" local id="1"
desc_1="Host Configuration" local desc="Host Configuration"
check_1="$id_1 - $desc_1" checkHeader="$id - $desc"
info "$check_1" info "$checkHeader"
startsectionjson "$id_1" "$desc_1" startsectionjson "$id" "$desc"
} }
check_1_1() { check_1_1() {
logit "" local id="1.1"
id_1_1="1.1" local desc="General Configuration"
desc_1_1="General Configuration" local check="$id - $desc"
check_1_1="$id_1_1 - $desc_1_1" info "$check"
info "$check_1_1"
} }
# 1.1.1
check_1_1_1() { check_1_1_1() {
id_1_1_1="1.1.1" local id="1.1.1"
desc_1_1_1="Ensure the container host has been Hardened (Not Scored)" local desc="Ensure the container host has been Hardened (Not Scored)"
check_1_1_1="$id_1_1_1 - $desc_1_1_1" local remediation="You may consider various Security Benchmarks for your container host."
starttestjson "$id_1_1_1" "$desc_1_1_1" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_1_1_1" logcheckresult "INFO"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
} }
# 1.1.2
check_1_1_2() { check_1_1_2() {
id_1_1_2="1.1.2" local id="1.1.2"
desc_1_1_2="Ensure that the version of Docker is up to date (Not Scored)" local desc="Ensure that the version of Docker is up to date (Not Scored)"
check_1_1_2="$id_1_1_2 - $desc_1_1_2" local remediation="You should monitor versions of Docker releases and make sure your software is updated as required."
starttestjson "$id_1_1_2" "$desc_1_1_2" local remediationImpact="You should perform a risk assessment regarding Docker version updates and review how they may impact your operations."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \ docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \
| awk '{print $NF; exit}' | tr -d '[:alpha:]-,') | awk '{print $NF; exit}' | tr -d '[:alpha:]-,')
docker_current_version="$(date +%y.%m.0 -d @$(( $(date +%s) - 2592000)))" docker_current_version="$(date +%y.%m.0 -d @$(( $(date +%s) - 2592000)))"
do_version_check "$docker_current_version" "$docker_version" do_version_check "$docker_current_version" "$docker_version"
if [ $? -eq 11 ]; then if [ $? -eq 11 ]; then
info "$check_1_1_2" pass -c "$check"
info " * Using $docker_version, verify is it up to date as deemed necessary" 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" logcheckresult "INFO" "Using $docker_version"
resulttestjson "INFO" "Using $docker_version" return
currentScore=$((currentScore + 0))
else
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 fi
pass -c "$check"
info " * Using $docker_version which is current"
info " * Check with your operating system vendor for support and security maintenance for Docker"
logcheckresult "PASS" "Using $docker_version"
} }
check_1_2() { check_1_2() {
logit "" local id="1.2"
id_1_2="1.2" local desc="Linux Hosts Specific Configuration"
desc_1_2="Linux Hosts Specific Configuration" local check="$id - $desc"
check_1_2="$id_1_2 - $desc_1_2" info "$check"
info "$check_1_2"
} }
# 1.2.1
check_1_2_1() { check_1_2_1() {
id_1_2_1="1.2.1" local id="1.2.1"
desc_1_2_1="Ensure a separate partition for containers has been created (Scored)" local desc="Ensure a separate partition for containers has been created (Scored)"
check_1_2_1="$id_1_2_1 - $desc_1_2_1" local remediation="For new installations, you should create a separate partition for the /var/lib/docker mount point. For systems that have already been installed, you should use the Logical Volume Manager (LVM) within Linux to create a new partition."
starttestjson "$id_1_2_1" "$desc_1_2_1" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
docker_root_dir=$(docker info -f '{{ .DockerRootDir }}') docker_root_dir=$(docker info -f '{{ .DockerRootDir }}')
if docker info | grep -q userns ; then if docker info | grep -q userns ; then
docker_root_dir=$(readlink -f "$docker_root_dir/..") docker_root_dir=$(readlink -f "$docker_root_dir/..")
fi fi
if mountpoint -q -- "$docker_root_dir" >/dev/null 2>&1; then if mountpoint -q -- "$docker_root_dir" >/dev/null 2>&1; then
pass "$check_1_2_1" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_1_2_1"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
warn -s "$check"
logcheckresult "WARN"
} }
# 1.2.2
check_1_2_2() { check_1_2_2() {
id_1_2_2="1.2.2" local id="1.2.2"
desc_1_2_2="Ensure only trusted users are allowed to control Docker daemon (Scored)" local desc="Ensure only trusted users are allowed to control Docker daemon (Scored)"
check_1_2_2="$id_1_2_2 - $desc_1_2_2" local remediation="You should remove any untrusted users from the docker group using command sudo gpasswd -d <your-user> docker or add trusted users to the docker group using command sudo usermod -aG docker <your-user>. You should not create a mapping of sensitive directories from the host to container volumes."
starttestjson "$id_1_2_2" "$desc_1_2_2" local remediationImpact="Only trust user are allow to build and execute containers as normal user."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) docker_users=$(grep 'docker' /etc/group)
if command -v getent >/dev/null 2>&1; then if command -v getent >/dev/null 2>&1; then
docker_users=$(getent group docker) docker_users=$(getent group docker)
else
docker_users=$(grep 'docker' /etc/group)
fi fi
info "$check_1_2_2" docker_users=$(printf "%s" "$docker_users" | awk -F: '{print $4}')
for u in $docker_users; do
info " * $u" local doubtfulusers=""
done if [ -n "$dockertrustusers" ]; then
resulttestjson "INFO" "users" "$docker_users" for u in $(printf "%s" "$docker_users" | sed "s/,/ /g"); do
currentScore=$((currentScore + 0)) if ! printf "%s" "$dockertrustusers" | grep -q "$u" ; then
doubtfulusers="$u"
if [ -n "${doubtfulusers}" ]; then
doubtfulusers="${doubtfulusers},$u"
fi
fi
done
else
info -c "$check"
info " * Users: $docker_users"
logcheckresult "INFO" "doubtfulusers" "$docker_users"
fi
if [ -n "${doubtfulusers}" ]; then
warn -s "$check"
warn " * Doubtful users: $doubtfulusers"
logcheckresult "WARN" "doubtfulusers" "$doubtfulusers"
fi
if [ -z "${doubtfulusers}" ] && [ -n "${dockertrustusers}" ]; then
pass -s "$check"
logcheckresult "PASS"
fi
} }
# 1.2.3
check_1_2_3() { check_1_2_3() {
id_1_2_3="1.2.3" local id="1.2.3"
desc_1_2_3="Ensure auditing is configured for the Docker daemon (Scored)" local desc="Ensure auditing is configured for the Docker daemon (Scored)"
check_1_2_3="$id_1_2_3 - $desc_1_2_3" local remediation="Install auditd. Add -w /usr/bin/dockerd -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart."
starttestjson "$id_1_2_3" "$desc_1_2_3" local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
file="/usr/bin/dockerd" file="/usr/bin/dockerd"
if command -v auditctl >/dev/null 2>&1; then if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep "$file" >/dev/null 2>&1; then if auditctl -l | grep "$file" >/dev/null 2>&1; then
pass "$check_1_2_3" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_1_2_3"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then warn -s "$check"
pass "$check_1_2_3" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
else
warn "$check_1_2_3"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
if grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
pass -s "$check"
logcheckresult "PASS"
return
fi
warn -s "$check"
logcheckresult "WARN"
} }
# 1.2.4
check_1_2_4() { check_1_2_4() {
id_1_2_4="1.2.4" local id="1.2.4"
desc_1_2_4="Ensure auditing is configured for Docker files and directories - /var/lib/docker (Scored)" local desc="Ensure auditing is configured for Docker files and directories - /var/lib/docker (Scored)"
check_1_2_4="$id_1_2_4 - $desc_1_2_4" local remediation="Install auditd. Add -w /var/lib/docker -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart."
starttestjson "$id_1_2_4" "$desc_1_2_4" local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
directory="/var/lib/docker" directory="/var/lib/docker"
if [ -d "$directory" ]; then if [ -d "$directory" ]; then
if command -v auditctl >/dev/null 2>&1; then if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $directory >/dev/null 2>&1; then if auditctl -l | grep $directory >/dev/null 2>&1; then
pass "$check_1_2_4" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_1_2_4"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
elif grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then warn -s "$check"
pass "$check_1_2_4" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
else
warn "$check_1_2_4"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else if grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
info "$check_1_2_4" pass -s "$check"
info " * Directory not found" logcheckresult "PASS"
resulttestjson "INFO" "Directory not found" return
currentScore=$((currentScore + 0)) fi
warn -s "$check"
logcheckresult "WARN"
return
fi fi
info -c "$check"
info " * Directory not found"
logcheckresult "INFO" "Directory not found"
} }
# 1.2.5
check_1_2_5() { check_1_2_5() {
id_1_2_5="1.2.5" local id="1.2.5"
desc_1_2_5="Ensure auditing is configured for Docker files and directories - /etc/docker (Scored)" local desc="Ensure auditing is configured for Docker files and directories - /etc/docker (Scored)"
check_1_2_5="$id_1_2_5 - $desc_1_2_5" local remediation="Install auditd. Add -w /etc/docker -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart."
starttestjson "$id_1_2_5" "$desc_1_2_5" local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
directory="/etc/docker" directory="/etc/docker"
if [ -d "$directory" ]; then if [ -d "$directory" ]; then
if command -v auditctl >/dev/null 2>&1; then if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $directory >/dev/null 2>&1; then if auditctl -l | grep $directory >/dev/null 2>&1; then
pass "$check_1_2_5" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_1_2_5"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
elif grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then warn -s "$check"
pass "$check_1_2_5" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
else
warn "$check_1_2_5"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else if grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
info "$check_1_2_5" pass -s "$check"
info " * Directory not found" logcheckresult "PASS"
resulttestjson "INFO" "Directory not found" return
currentScore=$((currentScore + 0)) fi
fi warn -s "$check"
logcheckresult "WARN"
return
fi
info -c "$check"
info " * Directory not found"
logcheckresult "INFO" "Directory not found"
} }
# 1.2.6
check_1_2_6() { check_1_2_6() {
id_1_2_6="1.2.6" local id="1.2.6"
desc_1_2_6="Ensure auditing is configured for Docker files and directories - docker.service (Scored)" local desc="Ensure auditing is configured for Docker files and directories - docker.service (Scored)"
check_1_2_6="$id_1_2_6 - $desc_1_2_6" local remediation
starttestjson "$id_1_2_6" "$desc_1_2_6" remediation="Install auditd. Add -w $(get_service_file docker.service) -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart."
local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
file="$(get_service_file docker.service)" file="$(get_service_file docker.service)"
if [ -f "$file" ]; then if [ -f "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep "$file" >/dev/null 2>&1; then if auditctl -l | grep "$file" >/dev/null 2>&1; then
pass "$check_1_2_6" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_1_2_6"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then warn -s "$check"
pass "$check_1_2_6" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
else
warn "$check_1_2_6"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else if grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
info "$check_1_2_6" pass -s "$check"
info " * File not found" logcheckresult "PASS"
resulttestjson "INFO" "File not found" return
currentScore=$((currentScore + 0)) fi
warn -s "$check"
logcheckresult "WARN"
return
fi fi
info -c "$check"
info " * File not found"
logcheckresult "INFO" "File not found"
} }
# 1.2.7
check_1_2_7() { check_1_2_7() {
id_1_2_7="1.2.7" local id="1.2.7"
desc_1_2_7="Ensure auditing is configured for Docker files and directories - docker.socket (Scored)" local desc="Ensure auditing is configured for Docker files and directories - docker.socket (Scored)"
check_1_2_7="$id_1_2_7 - $desc_1_2_7" local remediation
starttestjson "$id_1_2_7" "$desc_1_2_7" remediation="Install auditd. Add -w $(get_service_file docker.socket) -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart."
local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
file="$(get_service_file docker.socket)" file="$(get_service_file docker.socket)"
if [ -e "$file" ]; then if [ -e "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep "$file" >/dev/null 2>&1; then if auditctl -l | grep "$file" >/dev/null 2>&1; then
pass "$check_1_2_7" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_1_2_7"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then warn -s "$check"
pass "$check_1_2_7" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
else
warn "$check_1_2_7"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else if grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
info "$check_1_2_7" pass -s "$check"
info " * File not found" logcheckresult "PASS"
resulttestjson "INFO" "File not found" return
currentScore=$((currentScore + 0)) fi
warn -s "$check"
logcheckresult "WARN"
return
fi fi
info -c "$check"
info " * File not found"
logcheckresult "INFO" "File not found"
} }
# 1.2.8
check_1_2_8() { check_1_2_8() {
id_1_2_8="1.2.8" local id="1.2.8"
desc_1_2_8="Ensure auditing is configured for Docker files and directories - /etc/default/docker (Scored)" local desc="Ensure auditing is configured for Docker files and directories - /etc/default/docker (Scored)"
check_1_2_8="$id_1_2_8 - $desc_1_2_8" local remediation="Install auditd. Add -w /etc/default/docker -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart."
starttestjson "$id_1_2_8" "$desc_1_2_8" local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
file="/etc/default/docker" file="/etc/default/docker"
if [ -f "$file" ]; then if [ -f "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $file >/dev/null 2>&1; then if auditctl -l | grep $file >/dev/null 2>&1; then
pass "$check_1_2_8" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_1_2_8"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then warn -s "$check"
pass "$check_1_2_8" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
else
warn "$check_1_2_8"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else if grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
info "$check_1_2_8" pass -s "$check"
info " * File not found" logcheckresult "PASS"
resulttestjson "INFO" "File not found" return
currentScore=$((currentScore + 0)) fi
warn -s "$check"
logcheckresult "WARN"
return
fi fi
info -c "$check"
info " * File not found"
logcheckresult "INFO" "File not found"
} }
# 1.2.9
check_1_2_9() { check_1_2_9() {
id_1_2_9="1.2.9" local id="1.2.9"
desc_1_2_9="Ensure auditing is configured for Docker files and directories - /etc/sysconfig/docker (Scored)" local desc="Ensure auditing is configured for Docker files and directories - /etc/sysconfig/docker (Scored)"
check_1_2_9="$id_1_2_9 - $desc_1_2_9" local remediation="Install auditd. Add -w /etc/sysconfig/docker -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart."
starttestjson "$id_1_2_9" "$desc_1_2_9" local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
file="/etc/sysconfig/docker" file="/etc/sysconfig/docker"
if [ -f "$file" ]; then if [ -f "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $file >/dev/null 2>&1; then if auditctl -l | grep $file >/dev/null 2>&1; then
pass "$check_1_2_9" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_1_2_9"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then warn -s "$check"
pass "$check_1_2_9" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
else
warn "$check_1_2_9"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else if grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
info "$check_1_2_9" pass -s "$check"
info " * File not found" logcheckresult "PASS"
resulttestjson "INFO" "File not found" return
currentScore=$((currentScore + 0)) fi
warn -s "$check"
logcheckresult "WARN"
return
fi fi
info -c "$check"
info " * File not found"
logcheckresult "INFO" "File not found"
} }
# 1.2.10
check_1_2_10() { check_1_2_10() {
id_1_2_10="1.2.10" local id="1.2.10"
desc_1_2_10="Ensure auditing is configured for Docker files and directories - /etc/docker/daemon.json (Scored)" local desc="Ensure auditing is configured for Docker files and directories - /etc/docker/daemon.json (Scored)"
check_1_2_10="$id_1_2_10 - $desc_1_2_10" local remediation="Install auditd. Add -w /etc/docker/daemon.json -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart."
starttestjson "$id_1_2_10" "$desc_1_2_10" local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
file="/etc/docker/daemon.json" file="/etc/docker/daemon.json"
if [ -f "$file" ]; then if [ -f "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $file >/dev/null 2>&1; then if auditctl -l | grep $file >/dev/null 2>&1; then
pass "$check_1_2_10" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_1_2_10"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then warn -s "$check"
pass "$check_1_2_10" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
else
warn "$check_1_2_10"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else if grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
info "$check_1_2_10" pass -s "$check"
info " * File not found" logcheckresult "PASS"
resulttestjson "INFO" "File not found" return
currentScore=$((currentScore + 0)) fi
warn -s "$check"
logcheckresult "WARN"
return
fi fi
info -c "$check"
info " * File not found"
logcheckresult "INFO" "File not found"
} }
# 1.2.11
check_1_2_11() { check_1_2_11() {
id_1_2_11="1.2.11" local id="1.2.11"
desc_1_2_11="Ensure auditing is configured for Docker files and directories - /usr/bin/containerd (Scored)" local desc="Ensure auditing is configured for Docker files and directories - /usr/bin/containerd (Scored)"
check_1_2_11="$id_1_2_11 - $desc_1_2_11" local remediation="Install auditd. Add -w /usr/bin/containerd -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart."
starttestjson "$id_1_2_11" "$desc_1_2_11" local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
file="/usr/bin/containerd" file="/usr/bin/containerd"
if [ -f "$file" ]; then if [ -f "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $file >/dev/null 2>&1; then if auditctl -l | grep $file >/dev/null 2>&1; then
pass "$check_1_2_11" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_1_2_11"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then warn -s "$check"
pass "$check_1_2_11" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
else
warn "$check_1_2_11"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else if grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
info "$check_1_2_11" pass -s "$check"
info " * File not found" logcheckresult "PASS"
resulttestjson "INFO" "File not found" return
currentScore=$((currentScore + 0)) fi
warn -s "$check"
logcheckresult "WARN"
return
fi fi
info -c "$check"
info " * File not found"
logcheckresult "INFO" "File not found"
} }
# 1.2.12
check_1_2_12() { check_1_2_12() {
id_1_2_12="1.2.12" local id="1.2.12"
desc_1_2_12="Ensure auditing is configured for Docker files and directories - /usr/sbin/runc (Scored)" local desc="Ensure auditing is configured for Docker files and directories - /usr/sbin/runc (Scored)"
check_1_2_12="$id_1_2_12 - $desc_1_2_12" local remediation="Install auditd. Add -w /usr/sbin/runc -k docker to the /etc/audit/rules.d/audit.rules file. Then restart the audit daemon using command service auditd restart."
starttestjson "$id_1_2_12" "$desc_1_2_12" local remediationImpact="Audit can generate large log files. So you need to make sure that they are rotated and archived periodically. Create a separate partition for audit logs to avoid filling up other critical partitions."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
file="/usr/sbin/runc" file="/usr/sbin/runc"
if [ -f "$file" ]; then if [ -f "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $file >/dev/null 2>&1; then if auditctl -l | grep $file >/dev/null 2>&1; then
pass "$check_1_2_12" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_1_2_12"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then warn -s "$check"
pass "$check_1_2_12" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
else
warn "$check_1_2_12"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else if grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
info "$check_1_2_12" pass -s "$check"
info " * File not found" logcheckresult "PASS"
resulttestjson "INFO" "File not found" return
currentScore=$((currentScore + 0)) fi
warn -s "$check"
logcheckresult "WARN"
return
fi fi
info -c "$check"
info " * File not found"
logcheckresult "INFO" "File not found"
} }
check_1_end() { check_1_end() {

View file

@ -1,440 +1,415 @@
#!/bin/sh #!/bin/sh
check_2() { check_2() {
logit "\n" logit ""
id_2="2" local id="2"
desc_2="Docker daemon configuration" local desc="Docker daemon configuration"
check_2="$id_2 - $desc_2" checkHeader="$id - $desc"
info "$check_2" info "$checkHeader"
startsectionjson "$id_2" "$desc_2" startsectionjson "$id" "$desc"
} }
# 2.1
check_2_1() { check_2_1() {
id_2_1="2.1" local id="2.1"
desc_2_1="Ensure network traffic is restricted between containers on the default bridge (Scored)" local desc="Ensure network traffic is restricted between containers on the default bridge (Scored)"
check_2_1="$id_2_1 - $desc_2_1" local remediation="Edit the Docker daemon configuration file to ensure that inter-container communication is disabled: icc: false."
starttestjson "$id_2_1" "$desc_2_1" local remediationImpact="Inter-container communication is disabled on the default network bridge. If any communication between containers on the same host is desired, it needs to be explicitly defined using container linking or custom networks."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if get_docker_effective_command_line_args '--icc' | grep false >/dev/null 2>&1; then if get_docker_effective_command_line_args '--icc' | grep false >/dev/null 2>&1; then
pass "$check_2_1" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
elif get_docker_configuration_file_args 'icc' | grep "false" >/dev/null 2>&1; then
pass "$check_2_1"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_1"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
if get_docker_configuration_file_args 'icc' | grep "false" >/dev/null 2>&1; then
pass -s "$check"
logcheckresult "PASS"
return
fi
warn -s "$check"
logcheckresult "WARN"
} }
# 2.2
check_2_2() { check_2_2() {
id_2_2="2.2" local id="2.2"
desc_2_2="Ensure the logging level is set to 'info' (Scored)" local desc="Ensure the logging level is set to 'info' (Scored)"
check_2_2="$id_2_2 - $desc_2_2" local remediation="Ensure that the Docker daemon configuration file has the following configuration included log-level: info. Alternatively, run the Docker daemon as following: dockerd --log-level=info"
starttestjson "$id_2_2" "$desc_2_2" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if get_docker_configuration_file_args 'log-level' >/dev/null 2>&1; then if get_docker_configuration_file_args 'log-level' >/dev/null 2>&1; then
if get_docker_configuration_file_args 'log-level' | grep info >/dev/null 2>&1; then if get_docker_configuration_file_args 'log-level' | grep info >/dev/null 2>&1; then
pass "$check_2_2" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
elif [ -z "$(get_docker_configuration_file_args 'log-level')" ]; then
pass "$check_2_2"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_2"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
elif get_docker_effective_command_line_args '-l'; then if [ -z "$(get_docker_configuration_file_args 'log-level')" ]; then
pass -s "$check"
logcheckresult "PASS"
return
fi
warn -s "$check"
logcheckresult "WARN"
return
fi
if get_docker_effective_command_line_args '-l'; then
if get_docker_effective_command_line_args '-l' | grep "info" >/dev/null 2>&1; then if get_docker_effective_command_line_args '-l' | grep "info" >/dev/null 2>&1; then
pass "$check_2_2" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_2_2"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else warn -s "$check"
pass "$check_2_2" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
fi fi
pass -s "$check"
logcheckresult "PASS"
} }
# 2.3
check_2_3() { check_2_3() {
id_2_3="2.3" local id="2.3"
desc_2_3="Ensure Docker is allowed to make changes to iptables (Scored)" local desc="Ensure Docker is allowed to make changes to iptables (Scored)"
check_2_3="$id_2_3 - $desc_2_3" local remediation="Do not run the Docker daemon with --iptables=false option."
starttestjson "$id_2_3" "$desc_2_3" local remediationImpact="The Docker daemon service requires iptables rules to be enabled before it starts."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if get_docker_effective_command_line_args '--iptables' | grep "false" >/dev/null 2>&1; then if get_docker_effective_command_line_args '--iptables' | grep "false" >/dev/null 2>&1; then
warn "$check_2_3" warn -s "$check"
resulttestjson "WARN" logcheckresult "WARN"
currentScore=$((currentScore - 1)) return
elif get_docker_configuration_file_args 'iptables' | grep "false" >/dev/null 2>&1; then
warn "$check_2_3"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
else
pass "$check_2_3"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi fi
if get_docker_configuration_file_args 'iptables' | grep "false" >/dev/null 2>&1; then
warn -s "$check"
logcheckresult "WARN"
return
fi
pass -s "$check"
logcheckresult "PASS"
} }
# 2.4
check_2_4() { check_2_4() {
id_2_4="2.4" local id="2.4"
desc_2_4="Ensure insecure registries are not used (Scored)" local desc="Ensure insecure registries are not used (Scored)"
check_2_4="$id_2_4 - $desc_2_4" local remediation="You should ensure that no insecure registries are in use."
starttestjson "$id_2_4" "$desc_2_4" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if get_docker_effective_command_line_args '--insecure-registry' | grep "insecure-registry" >/dev/null 2>&1; then if get_docker_effective_command_line_args '--insecure-registry' | grep "insecure-registry" >/dev/null 2>&1; then
warn "$check_2_4" warn -s "$check"
resulttestjson "WARN" logcheckresult "WARN"
currentScore=$((currentScore - 1)) return
elif ! [ -z "$(get_docker_configuration_file_args 'insecure-registries')" ]; then fi
if ! [ -z "$(get_docker_configuration_file_args 'insecure-registries')" ]; then
if get_docker_configuration_file_args 'insecure-registries' | grep '\[]' >/dev/null 2>&1; then if get_docker_configuration_file_args 'insecure-registries' | grep '\[]' >/dev/null 2>&1; then
pass "$check_2_4" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_2_4"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else warn -s "$check"
pass "$check_2_4" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
fi fi
pass -s "$check"
logcheckresult "PASS"
} }
# 2.5
check_2_5() { check_2_5() {
id_2_5="2.5" local id="2.5"
desc_2_5="Ensure aufs storage driver is not used (Scored)" local desc="Ensure aufs storage driver is not used (Scored)"
check_2_5="$id_2_5 - $desc_2_5" local remediation="Do not start Docker daemon as using dockerd --storage-driver aufs option."
starttestjson "$id_2_5" "$desc_2_5" local remediationImpact="aufs is the only storage driver that allows containers to share executable and shared library memory. Its use should be reviewed in line with your organization's security policy."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "^\sStorage Driver:\s*aufs\s*$" >/dev/null 2>&1; then if docker info 2>/dev/null | grep -e "^\sStorage Driver:\s*aufs\s*$" >/dev/null 2>&1; then
warn "$check_2_5" warn -s "$check"
resulttestjson "WARN" logcheckresult "WARN"
currentScore=$((currentScore - 1)) return
else
pass "$check_2_5"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi fi
pass -s "$check"
logcheckresult "PASS"
} }
# 2.6
check_2_6() { check_2_6() {
id_2_6="2.6" local id="2.6"
desc_2_6="Ensure TLS authentication for Docker daemon is configured (Scored)" local desc="Ensure TLS authentication for Docker daemon is configured (Scored)"
check_2_6="$id_2_6 - $desc_2_6" local remediation="Follow the steps mentioned in the Docker documentation or other references. By default, TLS authentication is not configured."
starttestjson "$id_2_6" "$desc_2_6" local remediationImpact="You would need to manage and guard certificates and keys for the Docker daemon and Docker clients."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if [ $(get_docker_configuration_file_args 'tcp://') ] || \ if [ $(get_docker_configuration_file_args 'tcp://') ] || \
[ $(get_docker_cumulative_command_line_args '-H' | grep -vE '(unix|fd)://') >/dev/null 2>&1 ]; then [ $(get_docker_cumulative_command_line_args '-H' | grep -vE '(unix|fd)://') >/dev/null 2>&1 ]; then
if [ $(get_docker_configuration_file_args '"tlsverify":' | grep 'true') ] || \ if [ $(get_docker_configuration_file_args '"tlsverify":' | grep 'true') ] || \
[ $(get_docker_cumulative_command_line_args '--tlsverify' | grep 'tlsverify') >/dev/null 2>&1 ]; then [ $(get_docker_cumulative_command_line_args '--tlsverify' | grep 'tlsverify') >/dev/null 2>&1 ]; then
pass "$check_2_6" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
elif [ $(get_docker_configuration_file_args '"tls":' | grep 'true') ] || \ fi
if [ $(get_docker_configuration_file_args '"tls":' | grep 'true') ] || \
[ $(get_docker_cumulative_command_line_args '--tls' | grep 'tls$') >/dev/null 2>&1 ]; then [ $(get_docker_cumulative_command_line_args '--tls' | grep 'tls$') >/dev/null 2>&1 ]; then
warn "$check_2_6" warn -s "$check"
warn " * Docker daemon currently listening on TCP with TLS, but no verification" warn " * Docker daemon currently listening on TCP with TLS, but no verification"
resulttestjson "WARN" "Docker daemon currently listening on TCP with TLS, but no verification" logcheckresult "WARN" "Docker daemon currently listening on TCP with TLS, but no verification"
currentScore=$((currentScore - 1)) return
else
warn "$check_2_6"
warn " * Docker daemon currently listening on TCP without TLS"
resulttestjson "WARN" "Docker daemon currently listening on TCP without TLS"
currentScore=$((currentScore - 1))
fi fi
else warn -s "$check"
info "$check_2_6" warn " * Docker daemon currently listening on TCP without TLS"
info " * Docker daemon not listening on TCP" logcheckresult "WARN" "Docker daemon currently listening on TCP without TLS"
resulttestjson "INFO" "Docker daemon not listening on TCP" return
currentScore=$((currentScore + 0))
fi fi
info -c "$check"
info " * Docker daemon not listening on TCP"
logcheckresult "INFO" "Docker daemon not listening on TCP"
} }
# 2.7
check_2_7() { check_2_7() {
id_2_7="2.7" local id="2.7"
desc_2_7="Ensure the default ulimit is configured appropriately (Not Scored)" local desc="Ensure the default ulimit is configured appropriately (Not Scored)"
check_2_7="$id_2_7 - $desc_2_7" local remediation="Run Docker in daemon mode and pass --default-ulimit as option with respective ulimits as appropriate in your environment and in line with your security policy. Example: dockerd --default-ulimit nproc=1024:2048 --default-ulimit nofile=100:200"
starttestjson "$id_2_7" "$desc_2_7" local remediationImpact="If ulimits are set incorrectly this could cause issues with system resources, possibly causing a denial of service condition."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if get_docker_configuration_file_args 'default-ulimit' | grep -v '{}' >/dev/null 2>&1; then if get_docker_configuration_file_args 'default-ulimit' | grep -v '{}' >/dev/null 2>&1; then
pass "$check_2_7" pass -c "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
elif get_docker_effective_command_line_args '--default-ulimit' | grep "default-ulimit" >/dev/null 2>&1; then
pass "$check_2_7"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
info "$check_2_7"
info " * Default ulimit doesn't appear to be set"
resulttestjson "INFO" "Default ulimit doesn't appear to be set"
currentScore=$((currentScore + 0))
fi fi
if get_docker_effective_command_line_args '--default-ulimit' | grep "default-ulimit" >/dev/null 2>&1; then
pass -c "$check"
logcheckresult "PASS"
return
fi
info -c "$check"
info " * Default ulimit doesn't appear to be set"
logcheckresult "INFO" "Default ulimit doesn't appear to be set"
} }
# 2.8
check_2_8() { check_2_8() {
id_2_8="2.8" local id="2.8"
desc_2_8="Enable user namespace support (Scored)" local desc="Enable user namespace support (Scored)"
check_2_8="$id_2_8 - $desc_2_8" local remediation="Please consult the Docker documentation for various ways in which this can be configured depending upon your requirements. The high-level steps are: Ensure that the files /etc/subuid and /etc/subgid exist. Start the docker daemon with --userns-remap flag."
starttestjson "$id_2_8" "$desc_2_8" local remediationImpact="User namespace remapping is incompatible with a number of Docker features and also currently breaks some of its functionalities."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if get_docker_configuration_file_args 'userns-remap' | grep -v '""'; then if get_docker_configuration_file_args 'userns-remap' | grep -v '""'; then
pass "$check_2_8" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
elif get_docker_effective_command_line_args '--userns-remap' | grep "userns-remap" >/dev/null 2>&1; then
pass "$check_2_8"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_8"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
if get_docker_effective_command_line_args '--userns-remap' | grep "userns-remap" >/dev/null 2>&1; then
pass -s "$check"
logcheckresult "PASS"
return
fi
warn -s "$check"
logcheckresult "WARN"
} }
# 2.9
check_2_9() { check_2_9() {
id_2_9="2.9" local id="2.9"
desc_2_9="Ensure the default cgroup usage has been confirmed (Scored)" local desc="Ensure the default cgroup usage has been confirmed (Scored)"
check_2_9="$id_2_9 - $desc_2_9" local remediation="The default setting is in line with good security practice and can be left in situ."
starttestjson "$id_2_9" "$desc_2_9" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if get_docker_configuration_file_args 'cgroup-parent' | grep -v ''; then if get_docker_configuration_file_args 'cgroup-parent' | grep -v ''; then
warn "$check_2_9" warn -s "$check"
info " * Confirm cgroup usage" info " * Confirm cgroup usage"
resulttestjson "WARN" "Confirm cgroup usage" logcheckresult "WARN" "Confirm cgroup usage"
currentScore=$((currentScore + 0)) return
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"
resulttestjson "WARN" "Confirm cgroup usage"
currentScore=$((currentScore + 0))
else
pass "$check_2_9"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi fi
if get_docker_effective_command_line_args '--cgroup-parent' | grep "cgroup-parent" >/dev/null 2>&1; then
warn -s "$check"
info " * Confirm cgroup usage"
logcheckresult "WARN" "Confirm cgroup usage"
return
fi
pass -s "$check"
logcheckresult "PASS"
} }
# 2.10
check_2_10() { check_2_10() {
id_2_10="2.10" local id="2.10"
desc_2_10="Ensure base device size is not changed until needed (Scored)" local desc="Ensure base device size is not changed until needed (Scored)"
check_2_10="$id_2_10 - $desc_2_10" local remediation="Do not set --storage-opt dm.basesize until needed."
starttestjson "$id_2_10" "$desc_2_10" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if get_docker_configuration_file_args 'storage-opts' | grep "dm.basesize" >/dev/null 2>&1; then if get_docker_configuration_file_args 'storage-opts' | grep "dm.basesize" >/dev/null 2>&1; then
warn "$check_2_10" warn -s "$check"
resulttestjson "WARN" logcheckresult "WARN"
currentScore=$((currentScore - 1)) return
elif get_docker_effective_command_line_args '--storage-opt' | grep "dm.basesize" >/dev/null 2>&1; then
warn "$check_2_10"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
else
pass "$check_2_10"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi fi
if get_docker_effective_command_line_args '--storage-opt' | grep "dm.basesize" >/dev/null 2>&1; then
warn -s "$check"
logcheckresult "WARN"
return
fi
pass -s "$check"
logcheckresult "PASS"
} }
# 2.11
check_2_11() { check_2_11() {
id_2_11="2.11" local id="2.11"
desc_2_11="Ensure that authorization for Docker client commands is enabled (Scored)" local desc="Ensure that authorization for Docker client commands is enabled (Scored)"
check_2_11="$id_2_11 - $desc_2_11" local remediation="Install/Create an authorization plugin. Configure the authorization policy as desired. Start the docker daemon using command dockerd --authorization-plugin=<PLUGIN_ID>"
starttestjson "$id_2_11" "$desc_2_11" local remediationImpact="Each Docker command needs to pass through the authorization plugin mechanism. This may have a performance impact"
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if get_docker_configuration_file_args 'authorization-plugins' | grep -v '\[]'; then if get_docker_configuration_file_args 'authorization-plugins' | grep -v '\[]'; then
pass "$check_2_11" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
elif get_docker_effective_command_line_args '--authorization-plugin' | grep "authorization-plugin" >/dev/null 2>&1; then
pass "$check_2_11"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_11"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
if get_docker_effective_command_line_args '--authorization-plugin' | grep "authorization-plugin" >/dev/null 2>&1; then
pass -s "$check"
logcheckresult "PASS"
return
fi
warn -s "$check"
logcheckresult "WARN"
} }
# 2.12
check_2_12() { check_2_12() {
id_2_12="2.12" local id="2.12"
desc_2_12="Ensure centralized and remote logging is configured (Scored)" local desc="Ensure centralized and remote logging is configured (Scored)"
check_2_12="$id_2_12 - $desc_2_12" local remediation="Set up the desired log driver following its documentation. Start the docker daemon using that logging driver. Example: dockerd --log-driver=syslog --log-opt syslog-address=tcp://192.xxx.xxx.xxx"
starttestjson "$id_2_12" "$desc_2_12" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info --format '{{ .LoggingDriver }}' | grep 'json-file' >/dev/null 2>&1; then if docker info --format '{{ .LoggingDriver }}' | grep 'json-file' >/dev/null 2>&1; then
warn "$check_2_12" warn -s "$check"
resulttestjson "WARN" logcheckresult "WARN"
currentScore=$((currentScore - 1)) return
else
pass "$check_2_12"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi fi
pass -s "$check"
logcheckresult "PASS"
} }
# 2.13
check_2_13() { check_2_13() {
id_2_13="2.13" local id="2.13"
desc_2_13="Ensure live restore is enabled (Scored)" local desc="Ensure live restore is enabled (Scored)"
check_2_13="$id_2_13 - $desc_2_13" local remediation="Run Docker in daemon mode and pass --live-restore option."
starttestjson "$id_2_13" "$desc_2_13" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Live Restore Enabled:\s*true\s*" >/dev/null 2>&1; then if docker info 2>/dev/null | grep -e "Live Restore Enabled:\s*true\s*" >/dev/null 2>&1; then
pass "$check_2_13" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
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 '--live-restore' | grep "live-restore" >/dev/null 2>&1; then
pass "$check_2_13"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_13"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
fi fi
if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then
pass -s "$check (Incompatible with swarm mode)"
logcheckresult "PASS"
return
fi
if get_docker_effective_command_line_args '--live-restore' | grep "live-restore" >/dev/null 2>&1; then
pass -s "$check"
logcheckresult "PASS"
return
fi
warn -s "$check"
logcheckresult "WARN"
} }
# 2.14
check_2_14() { check_2_14() {
id_2_14="2.14" local id="2.14"
desc_2_14="Ensure Userland Proxy is Disabled (Scored)" local desc="Ensure Userland Proxy is Disabled (Scored)"
check_2_14="$id_2_14 - $desc_2_14" local remediation="You should run the Docker daemon using command: dockerd --userland-proxy=false"
starttestjson "$id_2_14" "$desc_2_14" local remediationImpact="Some systems with older Linux kernels may not be able to support hairpin NAT and therefore require the userland proxy service. Also, some networking setups can be impacted by the removal of the userland proxy."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if get_docker_configuration_file_args 'userland-proxy' | grep false >/dev/null 2>&1; then if get_docker_configuration_file_args 'userland-proxy' | grep false >/dev/null 2>&1; then
pass "$check_2_14" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
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
warn "$check_2_14"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
if get_docker_effective_command_line_args '--userland-proxy=false' 2>/dev/null | grep "userland-proxy=false" >/dev/null 2>&1; then
pass -s "$check"
logcheckresult "PASS"
return
fi
warn -s "$check"
logcheckresult "WARN"
} }
# 2.15
check_2_15() { check_2_15() {
id_2_15="2.15" local id="2.15"
desc_2_15="Ensure that a daemon-wide custom seccomp profile is applied if appropriate (Not Scored)" local desc="Ensure that a daemon-wide custom seccomp profile is applied if appropriate (Not Scored)"
check_2_15="$id_2_15 - $desc_2_15" local remediation="By default, Docker's default seccomp profile is applied. If this is adequate for your environment, no action is necessary."
starttestjson "$id_2_15" "$desc_2_15" local remediationImpact="A misconfigured seccomp profile could possibly interrupt your container environment. You should therefore exercise extreme care if you choose to override the default settings."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info --format '{{ .SecurityOptions }}' | grep 'name=seccomp,profile=default' 2>/dev/null 1>&2; then if docker info --format '{{ .SecurityOptions }}' | grep 'name=seccomp,profile=default' 2>/dev/null 1>&2; then
pass "$check_2_15" pass -c "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
info "$check_2_15"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
fi fi
info -c "$check"
logcheckresult "INFO"
} }
# 2.16
check_2_16() { check_2_16() {
docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \ docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \
| awk '{print $NF; exit}' | tr -d '[:alpha:]-,.' | cut -c 1-4) | awk '{print $NF; exit}' | tr -d '[:alpha:]-,.' | cut -c 1-4)
id_2_16="2.16" local id="2.16"
desc_2_16="Ensure that experimental features are not implemented in production (Scored)" local desc="Ensure that experimental features are not implemented in production (Scored)"
check_2_16="$id_2_16 - $desc_2_16" local remediation="You should not pass --experimental as a runtime parameter to the Docker daemon on production systems."
starttestjson "$id_2_16" "$desc_2_16" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if [ "$docker_version" -le 1903 ]; then if [ "$docker_version" -le 1903 ]; then
if docker version -f '{{.Server.Experimental}}' | grep false 2>/dev/null 1>&2; then if docker version -f '{{.Server.Experimental}}' | grep false 2>/dev/null 1>&2; then
pass "$check_2_16" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_2_16"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else warn -s "$check"
desc_2_16="$desc_2_16 (Deprecated)" logcheckresult "WARN"
check_2_16="$id_2_16 - $desc_2_16" return
info "$desc_2_16"
resulttestjson "INFO"
fi fi
local desc="$desc (Deprecated)"
local check="$id - $desc"
info -c "$desc"
logcheckresult "INFO"
} }
# 2.17
check_2_17() { check_2_17() {
id_2_17="2.17" local id="2.17"
desc_2_17="Ensure containers are restricted from acquiring new privileges (Scored)" local desc="Ensure containers are restricted from acquiring new privileges (Scored)"
check_2_17="$id_2_17 - $desc_2_17" local remediation="You should run the Docker daemon using command: dockerd --no-new-privileges"
starttestjson "$id_2_17" "$desc_2_17" local remediationImpact="no_new_priv prevents LSMs such as SELinux from escalating the privileges of individual containers."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if get_docker_effective_command_line_args '--no-new-privileges' | grep "no-new-privileges" >/dev/null 2>&1; then if get_docker_effective_command_line_args '--no-new-privileges' | grep "no-new-privileges" >/dev/null 2>&1; then
pass "$check_2_17" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
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))
else
warn "$check_2_17"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
if get_docker_configuration_file_args 'no-new-privileges' | grep true >/dev/null 2>&1; then
pass -s "$check"
logcheckresult "PASS"
return
fi
warn -s "$check"
logcheckresult "WARN"
} }
check_2_end() { check_2_end() {

File diff suppressed because it is too large Load diff

View file

@ -1,139 +1,130 @@
#!/bin/sh #!/bin/sh
check_4() { check_4() {
logit "\n" logit ""
id_4="4" local id="4"
desc_4="Container Images and Build File" local desc="Container Images and Build File"
check_4="$id_4 - $desc_4" checkHeader="$id - $desc"
info "$check_4" info "$checkHeader"
startsectionjson "$id_4" "$desc_4" startsectionjson "$id" "$desc"
} }
# 4.1
check_4_1() { check_4_1() {
id_4_1="4.1" local id="4.1"
desc_4_1="Ensure that a user for the container has been created (Scored)" local desc="Ensure that a user for the container has been created (Scored)"
check_4_1="$id_4_1 - $desc_4_1" local remediation="You should ensure that the Dockerfile for each container image contains the information: USER <username or ID>. If there is no specific user created in the container base image, then make use of the useradd command to add a specific user before the USER instruction in the Dockerfile."
starttestjson "$id_4_1" "$desc_4_1" local remediationImpact="Running as a non-root user can present challenges where you wish to bind mount volumes from the underlying host. In this case, care should be taken to ensure that the user running the contained process can read and write to the bound directory, according to their requirements."
local check="$id - $desc"
totalChecks=$((totalChecks + 1)) starttestjson "$id" "$desc"
# If container_users is empty, there are no running containers # If container_users is empty, there are no running containers
if [ -z "$containers" ]; then if [ -z "$containers" ]; then
info "$check_4_1" info -c "$check"
info " * No containers running" info " * No containers running"
resulttestjson "INFO" "No containers running" logcheckresult "INFO" "No containers running"
currentScore=$((currentScore + 0)) return
else
# We have some containers running, set failure flag to 0. Check for Users.
fail=0
# Make the loop separator be a new-line in POSIX compliant fashion
set -f; IFS=$'
'
root_containers=""
for c in $containers; do
user=$(docker inspect --format 'User={{.Config.User}}' "$c")
if [ "$user" = "User=0" ] || [ "$user" = "User=root" ] || [ "$user" = "User=" ] || [ "$user" = "User=[]" ] || [ "$user" = "User=<no value>" ]; then
# If it's the first container, fail the test
if [ $fail -eq 0 ]; then
warn "$check_4_1"
warn " * Running as root: $c"
root_containers="$root_containers $c"
fail=1
else
warn " * Running as root: $c"
root_containers="$root_containers $c"
fi
fi
done
# We went through all the containers and found none running as root
if [ $fail -eq 0 ]; then
pass "$check_4_1"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
resulttestjson "WARN" "running as root" "$root_containers"
currentScore=$((currentScore - 1))
fi
fi fi
# We have some containers running, set failure flag to 0. Check for Users.
fail=0
# Make the loop separator be a new-line in POSIX compliant fashion
set -f; IFS=$'
'
root_containers=""
for c in $containers; do
user=$(docker inspect --format 'User={{.Config.User}}' "$c")
if [ "$user" = "User=0" ] || [ "$user" = "User=root" ] || [ "$user" = "User=" ] || [ "$user" = "User=[]" ] || [ "$user" = "User=<no value>" ]; then
# If it's the first container, fail the test
if [ $fail -eq 0 ]; then
warn -s "$check"
warn " * Running as root: $c"
root_containers="$root_containers $c"
fail=1
continue
fi
warn " * Running as root: $c"
root_containers="$root_containers $c"
fi
done
# We went through all the containers and found none running as root
if [ $fail -eq 0 ]; then
pass -s "$check"
logcheckresult "PASS"
return
fi
logcheckresult "WARN" "running as root" "$root_containers"
# Make the loop separator go back to space # Make the loop separator go back to space
set +f; unset IFS set +f; unset IFS
} }
# 4.2
check_4_2() { check_4_2() {
id_4_2="4.2" local id="4.2"
desc_4_2="Ensure that containers use only trusted base images (Not Scored)" local desc="Ensure that containers use only trusted base images (Not Scored)"
check_4_2="$id_4_2 - $desc_4_2" local remediation="Configure and use Docker Content trust. View the history of each Docker image to evaluate its risk, dependent on the sensitivity of the application you wish to deploy using it. Scan Docker images for vulnerabilities at regular intervals."
starttestjson "$id_4_2" "$desc_4_2" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_4_2" logcheckresult "NOTE"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
} }
# 4.3
check_4_3() { check_4_3() {
id_4_3="4.3" local id="4.3"
desc_4_3="Ensure that unnecessary packages are not installed in the container (Not Scored)" local desc="Ensure that unnecessary packages are not installed in the container (Not Scored)"
check_4_3="$id_4_3 - $desc_4_3" local remediation="You should not install anything within the container that is not required. You should consider using a minimal base image if you can. Some of the options available include BusyBox and Alpine. Not only can this trim your image size considerably, but there would also be fewer pieces of software which could contain vectors for attack."
starttestjson "$id_4_3" "$desc_4_3" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_4_3" logcheckresult "NOTE"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
} }
# 4.4
check_4_4() { check_4_4() {
id_4_4="4.4" local id="4.4"
desc_4_4="Ensure images are scanned and rebuilt to include security patches (Not Scored)" local desc="Ensure images are scanned and rebuilt to include security patches (Not Scored)"
check_4_4="$id_4_4 - $desc_4_4" local remediation="Images should be re-built ensuring that the latest version of the base images are used, to keep the operating system patch level at an appropriate level. Once the images have been re-built, containers should be re-started making use of the updated images."
starttestjson "$id_4_4" "$desc_4_4" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_4_4" logcheckresult "NOTE"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
} }
# 4.5
check_4_5() { check_4_5() {
id_4_5="4.5" local id="4.5"
desc_4_5="Ensure Content trust for Docker is Enabled (Scored)" local desc="Ensure Content trust for Docker is Enabled (Scored)"
check_4_5="$id_4_5 - $desc_4_5" local remediation="Add DOCKER_CONTENT_TRUST variable to the /etc/environment file using command echo DOCKER_CONTENT_TRUST=1 | sudo tee -a /etc/environment."
starttestjson "$id_4_5" "$desc_4_5" local remediationImpact="This prevents users from working with tagged images unless they contain a signature."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if [ "x$DOCKER_CONTENT_TRUST" = "x1" ]; then if [ "x$DOCKER_CONTENT_TRUST" = "x1" ]; then
pass "$check_4_5" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_4_5"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
warn -s "$check"
logcheckresult "WARN"
} }
# 4.6
check_4_6() { check_4_6() {
id_4_6="4.6" local id="4.6"
desc_4_6="Ensure that HEALTHCHECK instructions have been added to container images (Scored)" local desc="Ensure that HEALTHCHECK instructions have been added to container images (Scored)"
check_4_6="$id_4_6 - $desc_4_6" local remediation="You should follow the Docker documentation and rebuild your container images to include the HEALTHCHECK instruction."
starttestjson "$id_4_6" "$desc_4_6" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
fail=0 fail=0
no_health_images="" no_health_images=""
for img in $images; do for img in $images; do
if docker inspect --format='{{.Config.Healthcheck}}' "$img" 2>/dev/null | grep -e "<nil>" >/dev/null 2>&1; then if docker inspect --format='{{.Config.Healthcheck}}' "$img" 2>/dev/null | grep -e "<nil>" >/dev/null 2>&1; then
if [ $fail -eq 0 ]; then if [ $fail -eq 0 ]; then
fail=1 fail=1
warn "$check_4_6" warn -s "$check"
fi fi
imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null) imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null)
if ! [ "$imgName" = '[]' ]; then if ! [ "$imgName" = '[]' ]; then
@ -146,30 +137,28 @@ check_4_6() {
fi fi
done done
if [ $fail -eq 0 ]; then if [ $fail -eq 0 ]; then
pass "$check_4_6" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
resulttestjson "WARN" "Images w/o HEALTHCHECK" "$no_health_images"
currentScore=$((currentScore - 1))
fi fi
logcheckresult "WARN" "Images w/o HEALTHCHECK" "$no_health_images"
} }
# 4.7
check_4_7() { check_4_7() {
id_4_7="4.7" local id="4.7"
desc_4_7="Ensure update instructions are not used alone in the Dockerfile (Not Scored)" local desc="Ensure update instructions are not used alone in the Dockerfile (Not Scored)"
check_4_7="$id_4_7 - $desc_4_7" local remediation="You should use update instructions together with install instructions and version pinning for packages while installing them. This prevent caching and force the extraction of the required versions. Alternatively, you could use the --no-cache flag during the docker build process to avoid using cached layers."
starttestjson "$id_4_7" "$desc_4_7" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
fail=0 fail=0
update_images="" update_images=""
for img in $images; do for img in $images; do
if docker history "$img" 2>/dev/null | grep -e "update" >/dev/null 2>&1; then if docker history "$img" 2>/dev/null | grep -e "update" >/dev/null 2>&1; then
if [ $fail -eq 0 ]; then if [ $fail -eq 0 ]; then
fail=1 fail=1
info "$check_4_7" info -c "$check"
fi fi
imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null) imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null)
if ! [ "$imgName" = '[]' ]; then if ! [ "$imgName" = '[]' ]; then
@ -179,36 +168,33 @@ check_4_7() {
fi fi
done done
if [ $fail -eq 0 ]; then if [ $fail -eq 0 ]; then
pass "$check_4_7" pass -c "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 0)) return
else
resulttestjson "INFO" "Update instructions found" "$update_images"
currentScore=$((currentScore + 0))
fi fi
logcheckresult "INFO" "Update instructions found" "$update_images"
} }
# 4.8
check_4_8() { check_4_8() {
id_4_8="4.8" local id="4.8"
desc_4_8="Ensure setuid and setgid permissions are removed (Not Scored)" local desc="Ensure setuid and setgid permissions are removed (Not Scored)"
check_4_8="$id_4_8 - $desc_4_8" local remediation="You should allow setuid and setgid permissions only on executables which require them. You could remove these permissions at build time by adding the following command in your Dockerfile, preferably towards the end of the Dockerfile: RUN find / -perm /6000 -type f -exec chmod a-s {} ; || true"
starttestjson "$id_4_8" "$desc_4_8" local remediationImpact="The above command would break all executables that depend on setuid or setgid permissions including legitimate ones. You should therefore be careful to modify the command to suit your requirements so that it does not reduce the permissions of legitimate programs excessively. Because of this, you should exercise a degree of caution and examine all processes carefully before making this type of modification in order to avoid outages."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_4_8" logcheckresult "NOTE"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
} }
# 4.9
check_4_9() { check_4_9() {
id_4_9="4.9" local id="4.9"
desc_4_9="Ensure that COPY is used instead of ADD in Dockerfiles (Not Scored)" local desc="Ensure that COPY is used instead of ADD in Dockerfiles (Not Scored)"
check_4_9="$id_4_9 - $desc_4_9" local remediation="You should use COPY rather than ADD instructions in Dockerfiles."
starttestjson "$id_4_9" "$desc_4_9" local remediationImpact="Care needs to be taken in implementing this control if the application requires functionality that is part of the ADD instruction, for example, if you need to retrieve files from remote URLS."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
fail=0 fail=0
add_images="" add_images=""
for img in $images; do for img in $images; do
@ -216,49 +202,45 @@ check_4_9() {
sed '$d' | grep -q 'ADD'; then sed '$d' | grep -q 'ADD'; then
if [ $fail -eq 0 ]; then if [ $fail -eq 0 ]; then
fail=1 fail=1
info "$check_4_9" info -c "$check"
fi fi
imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null) imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null)
if ! [ "$imgName" = '[]' ]; then if ! [ "$imgName" = '[]' ]; then
info " * ADD in image history: $imgName" info " * ADD in image history: $imgName"
add_images="$add_images $imgName" add_images="$add_images $imgName"
fi fi
currentScore=$((currentScore + 0))
fi fi
done done
if [ $fail -eq 0 ]; then if [ $fail -eq 0 ]; then
pass "$check_4_9" pass -c "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 0)) return
else
resulttestjson "INFO" "Images using ADD" "$add_images"
fi fi
logcheckresult "INFO" "Images using ADD" "$add_images"
} }
# 4.10
check_4_10() { check_4_10() {
id_4_10="4.10" local id="4.10"
desc_4_10="Ensure secrets are not stored in Dockerfiles (Not Scored)" local desc="Ensure secrets are not stored in Dockerfiles (Not Scored)"
check_4_10="$id_4_10 - $desc_4_10" local remediation="Do not store any kind of secrets within Dockerfiles. Where secrets are required during the build process, make use of a secrets management tool, such as the buildkit builder included with Docker."
starttestjson "$id_4_10" "$desc_4_10" local remediationImpact="A proper secrets management process will be required for Docker image building."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_4_10" logcheckresult "NOTE"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
} }
# 4.11
check_4_11() { check_4_11() {
id_4_11="4.11" local id="4.11"
desc_4_11="Ensure only verified packages are are installed (Not Scored)" local desc="Ensure only verified packages are are installed (Not Scored)"
check_4_11="$id_4_11 - $desc_4_11" local remediation="You should use a secure package distribution mechanism of your choice to ensure the authenticity of software packages."
starttestjson "$id_4_11" "$desc_4_11" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_4_11" logcheckresult "NOTE"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
} }
check_4_end() { check_4_end() {

File diff suppressed because it is too large Load diff

View file

@ -1,22 +1,22 @@
#!/bin/sh #!/bin/sh
check_6() { check_6() {
logit "\n" logit ""
id_6="6" local id="6"
desc_6="Docker Security Operations" local desc="Docker Security Operations"
check_6="$id_6 - $desc_6" checkHeader="$id - $desc"
info "$check_6" info "$checkHeader"
startsectionjson "$id_6" "$desc_6" startsectionjson "$id" "$desc"
} }
# 6.1
check_6_1() { check_6_1() {
id_6_1="6.1" local id="6.1"
desc_6_1="Ensure that image sprawl is avoided (Not Scored)" local desc="Ensure that image sprawl is avoided (Not Scored)"
check_6_1="$id_6_1 - $desc_6_1" local remediation="You should keep only the images that you actually need and establish a workflow to remove old or stale images from the host. Additionally, you should use features such as pull-by-digest to get specific images from the registry."
starttestjson "$id_6_1" "$desc_6_1" local remediationImpact="docker system prune -a removes all exited containers as well as all images and volumes that are not referenced by running containers, including for UCP and DTR."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
images=$(docker images -q | sort -u | wc -l | awk '{print $1}') images=$(docker images -q | sort -u | wc -l | awk '{print $1}')
active_images=0 active_images=0
@ -26,37 +26,33 @@ check_6_1() {
fi fi
done done
info "$check_6_1" info -c "$check"
info " * There are currently: $images images" info " * There are currently: $images images"
if [ "$active_images" -lt "$((images / 2))" ]; then if [ "$active_images" -lt "$((images / 2))" ]; then
info " * Only $active_images out of $images are in use" info " * Only $active_images out of $images are in use"
fi fi
resulttestjson "INFO" "$active_images active/$images in use" logcheckresult "INFO" "$active_images active/$images in use"
currentScore=$((currentScore + 0))
} }
# 6.2
check_6_2() { check_6_2() {
id_6_2="6.2" local id="6.2"
desc_6_2="Ensure that container sprawl is avoided (Not Scored)" local desc="Ensure that container sprawl is avoided (Not Scored)"
check_6_2="$id_6_2 - $desc_6_2" local remediation="You should periodically check your container inventory on each host and clean up containers which are not in active use with the command: docker container prune"
starttestjson "$id_6_2" "$desc_6_2" local remediationImpact="You should retain containers that are actively in use, and delete ones which are no longer needed."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
total_containers=$(docker info 2>/dev/null | grep "Containers" | awk '{print $2}') total_containers=$(docker info 2>/dev/null | grep "Containers" | awk '{print $2}')
running_containers=$(docker ps -q | wc -l | awk '{print $1}') running_containers=$(docker ps -q | wc -l | awk '{print $1}')
diff="$((total_containers - running_containers))" diff="$((total_containers - running_containers))"
info -c "$check"
if [ "$diff" -gt 25 ]; then if [ "$diff" -gt 25 ]; then
info "$check_6_2"
info " * There are currently a total of $total_containers containers, with only $running_containers of them currently running" info " * There are currently a total of $total_containers containers, with only $running_containers of them currently running"
resulttestjson "INFO" "$total_containers total/$running_containers running"
else else
info "$check_6_2"
info " * There are currently a total of $total_containers containers, with $running_containers of them currently running" info " * There are currently a total of $total_containers containers, with $running_containers of them currently running"
resulttestjson "INFO" "$total_containers total/$running_containers running"
fi fi
currentScore=$((currentScore + 0)) logcheckresult "INFO" "$total_containers total/$running_containers running"
} }
check_6_end() { check_6_end() {

View file

@ -1,93 +1,85 @@
#!/bin/sh #!/bin/sh
check_7() { check_7() {
logit "\n" logit ""
id_7="7" local id="7"
desc_7="Docker Swarm Configuration" local desc="Docker Swarm Configuration"
check_7="$id_7 - $desc_7" checkHeader="$id - $desc"
info "$check_7" info "$checkHeader"
startsectionjson "$id_7" "$desc_7" startsectionjson "$id" "$desc"
} }
# 7.1
check_7_1() { check_7_1() {
id_7_1="7.1" local id="7.1"
desc_7_1="Ensure swarm mode is not Enabled, if not needed (Scored)" local desc="Ensure swarm mode is not Enabled, if not needed (Scored)"
check_7_1="$id_7_1 - $desc_7_1" local remediation="If swarm mode has been enabled on a system in error, you should run the command: docker swarm leave"
starttestjson "$id_7_1" "$desc_7_1" local remediationImpact="Disabling swarm mode will impact the operation of Docker Enterprise components if these are in use."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:*\sinactive\s*" >/dev/null 2>&1; then if docker info 2>/dev/null | grep -e "Swarm:*\sinactive\s*" >/dev/null 2>&1; then
pass "$check_7_1" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_7_1"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
warn -s "$check"
logcheckresult "WARN"
} }
# 7.2
check_7_2() { check_7_2() {
id_7_2="7.2" local id="7.2"
desc_7_2="Ensure that the minimum number of manager nodes have been created in a swarm (Scored)" local desc="Ensure that the minimum number of manager nodes have been created in a swarm (Scored)"
check_7_2="$id_7_2 - $desc_7_2" local remediation="If an excessive number of managers is configured, the excess nodes can be demoted to workers using command: docker node demote <manager node ID to be demoted>"
starttestjson "$id_7_2" "$desc_7_2" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then
managernodes=$(docker node ls | grep -c "Leader") managernodes=$(docker node ls | grep -c "Leader")
if [ "$managernodes" -eq 1 ]; then if [ "$managernodes" -eq 1 ]; then
pass "$check_7_2" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_7_2"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else warn -s "$check"
pass "$check_7_2 (Swarm mode not enabled)" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
fi fi
pass -s "$check (Swarm mode not enabled)"
logcheckresult "PASS"
} }
# 7.3
check_7_3() { check_7_3() {
id_7_3="7.3" local id="7.3"
desc_7_3="Ensure that swarm services are bound to a specific host interface (Scored)" local desc="Ensure that swarm services are bound to a specific host interface (Scored)"
check_7_3="$id_7_3 - $desc_7_3" local remediation="Resolving this issues requires re-initialization of the swarm, specifying a specific interface for the --listen-addr parameter."
starttestjson "$id_7_3" "$desc_7_3" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then
$netbin -lnt | grep -e '\[::]:2377 ' -e ':::2377' -e '*:2377 ' -e ' 0\.0\.0\.0:2377 ' >/dev/null 2>&1 $netbin -lnt | grep -e '\[::]:2377 ' -e ':::2377' -e '*:2377 ' -e ' 0\.0\.0\.0:2377 ' >/dev/null 2>&1
if [ $? -eq 1 ]; then if [ $? -eq 1 ]; then
pass "$check_7_3" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
warn "$check_7_3"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else warn -s "$check"
pass "$check_7_3 (Swarm mode not enabled)" logcheckresult "WARN"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
fi fi
pass -s "$check (Swarm mode not enabled)"
logcheckresult "PASS"
} }
# 7.4
check_7_4() { check_7_4() {
id_7_4="7.4" local id="7.4"
desc_7_4="Ensure that all Docker swarm overlay networks are encrypted (Scored)" local desc="Ensure that all Docker swarm overlay networks are encrypted (Scored)"
check_7_4="$id_7_4 - $desc_7_4" local remediation="You should create overlay networks the with --opt encrypted flag."
starttestjson "$id_7_4" "$desc_7_4" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
fail=0 fail=0
unencrypted_networks="" unencrypted_networks=""
for encnet in $(docker network ls --filter driver=overlay --quiet); do for encnet in $(docker network ls --filter driver=overlay --quiet); do
@ -95,7 +87,7 @@ check_7_4() {
grep -v 'encrypted:' 2>/dev/null 1>&2; then grep -v 'encrypted:' 2>/dev/null 1>&2; then
# If it's the first container, fail the test # If it's the first container, fail the test
if [ $fail -eq 0 ]; then if [ $fail -eq 0 ]; then
warn "$check_7_4" warn -s "$check"
fail=1 fail=1
fi fi
warn " * Unencrypted overlay network: $(docker network inspect --format '{{ .Name }} ({{ .Scope }})' "$encnet")" warn " * Unencrypted overlay network: $(docker network inspect --format '{{ .Name }} ({{ .Scope }})' "$encnet")"
@ -104,145 +96,128 @@ check_7_4() {
done done
# We went through all the networks and found none that are unencrypted # We went through all the networks and found none that are unencrypted
if [ $fail -eq 0 ]; then if [ $fail -eq 0 ]; then
pass "$check_7_4" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
resulttestjson "WARN" "Unencrypted overlay networks:" "$unencrypted_networks"
currentScore=$((currentScore - 1))
fi fi
logcheckresult "WARN" "Unencrypted overlay networks:" "$unencrypted_networks"
} }
# 7.5
check_7_5() { check_7_5() {
id_7_5="7.5" local id="7.5"
desc_7_5="Ensure that Docker's secret management commands are used for managing secrets in a swarm cluster (Not Scored)" local desc="Ensure that Docker's secret management commands are used for managing secrets in a swarm cluster (Not Scored)"
check_7_5="$id_7_5 - $desc_7_5" local remediation="You should follow the docker secret documentation and use it to manage secrets effectively."
starttestjson "$id_7_5" "$desc_7_5" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then
if [ "$(docker secret ls -q | wc -l)" -ge 1 ]; then if [ "$(docker secret ls -q | wc -l)" -ge 1 ]; then
pass "$check_7_5" pass -c "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
info "$check_7_5"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
fi fi
else info -c "$check"
pass "$check_7_5 (Swarm mode not enabled)" logcheckresult "INFO"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
fi fi
pass -c "$check (Swarm mode not enabled)"
logcheckresult "PASS"
} }
# 7.6
check_7_6() { check_7_6() {
id_7_6="7.6" local id="7.6"
desc_7_6="Ensure that swarm manager is run in auto-lock mode (Scored)" local desc="Ensure that swarm manager is run in auto-lock mode (Scored)"
check_7_6="$id_7_6 - $desc_7_6" local remediation="If you are initializing a swarm, use the command: docker swarm init --autolock. If you want to set --autolock on an existing swarm manager node, use the command: docker swarm update --autolock."
starttestjson "$id_7_6" "$desc_7_6" local remediationImpact="A swarm in auto-lock mode will not recover from a restart without manual intervention from an administrator to enter the unlock key. This may not always be desirable, and should be reviewed at a policy level."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then if docker info 2>/dev/null | grep -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 if ! docker swarm unlock-key 2>/dev/null | grep 'SWMKEY' 2>/dev/null 1>&2; then
warn "$check_7_6" warn -s "$check"
resulttestjson "WARN" logcheckresult "WARN"
currentScore=$((currentScore - 1)) return
else
pass "$check_7_6"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi fi
else pass -s "$check"
pass "$check_7_6 (Swarm mode not enabled)" logcheckresult "PASS"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
fi fi
pass -s "$check (Swarm mode not enabled)"
logcheckresult "PASS"
} }
# 7.7
check_7_7() { check_7_7() {
id_7_7="7.7" local id="7.7"
desc_7_7="Ensure that the swarm manager auto-lock key is rotated periodically (Not Scored)" local desc="Ensure that the swarm manager auto-lock key is rotated periodically (Not Scored)"
check_7_7="$id_7_7 - $desc_7_7" local remediation="You should run the command docker swarm unlock-key --rotate to rotate the keys. To facilitate auditing of this recommendation, you should maintain key rotation records and ensure that you establish a pre-defined frequency for key rotation."
starttestjson "$id_7_7" "$desc_7_7" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then
note "$check_7_7" note -c "$check"
resulttestjson "NOTE" logcheckresult "NOTE"
currentScore=$((currentScore + 0)) return
else
pass "$check_7_7 (Swarm mode not enabled)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi fi
pass -c "$check (Swarm mode not enabled)"
logcheckresult "PASS"
} }
# 7.8
check_7_8() { check_7_8() {
id_7_8="7.8" local id="7.8"
desc_7_8="Ensure that node certificates are rotated as appropriate (Not Scored)" local desc="Ensure that node certificates are rotated as appropriate (Not Scored)"
check_7_8="$id_7_8 - $desc_7_8" local remediation="You should run the command docker swarm update --cert-expiry 48h to set the desired expiry time on the node certificate."
starttestjson "$id_7_8" "$desc_7_8" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then
if docker info 2>/dev/null | grep "Expiry Duration: 2 days"; then if docker info 2>/dev/null | grep "Expiry Duration: 2 days"; then
pass "$check_7_8" pass -c "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
else
info "$check_7_8"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
fi fi
else info -c "$check"
pass "$check_7_8 (Swarm mode not enabled)" logcheckresult "INFO"
resulttestjson "PASS" return
currentScore=$((currentScore + 1))
fi fi
pass -c "$check (Swarm mode not enabled)"
logcheckresult "PASS"
} }
# 7.9
check_7_9() { check_7_9() {
id_7_9="7.9" local id="7.9"
desc_7_9="Ensure that CA certificates are rotated as appropriate (Not Scored)" local desc="Ensure that CA certificates are rotated as appropriate (Not Scored)"
check_7_9="$id_7_9 - $desc_7_9" local remediation="You should run the command docker swarm ca --rotate to rotate a certificate."
starttestjson "$id_7_9" "$desc_7_9" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then
info "$check_7_9" info -c "$check"
resulttestjson "INFO" logcheckresult "INFO"
currentScore=$((currentScore + 0)) return
else
pass "$check_7_9 (Swarm mode not enabled)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi fi
pass -c "$check (Swarm mode not enabled)"
logcheckresult "PASS"
} }
# 7.10
check_7_10() { check_7_10() {
id_7_10="7.10" local id="7.10"
desc_7_10="Ensure that management plane traffic is separated from data plane traffic (Not Scored)" local desc="Ensure that management plane traffic is separated from data plane traffic (Not Scored)"
check_7_10="$id_7_10 - $desc_7_10" local remediation="You should initialize the swarm with dedicated interfaces for management and data planes respectively. Example: docker swarm init --advertise-addr=192.168.0.1 --data-path-addr=17.1.0.3"
starttestjson "$id_7_10" "$desc_7_10" local remediationImpact="This requires two network interfaces per node."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then
info "$check_7_10" info -c "$check"
resulttestjson "INFO" logcheckresult "INFO"
currentScore=$((currentScore + 0)) return
else
pass "$check_7_10 (Swarm mode not enabled)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi fi
pass -c "$check (Swarm mode not enabled)"
logcheckresult "PASS"
} }
check_7_end() { check_7_end() {

View file

@ -1,20 +1,19 @@
#!/bin/sh #!/bin/sh
check_8() { check_8() {
logit "\n" logit ""
id_8="8" local id="8"
desc_8="Docker Enterprise Configuration" local desc="Docker Enterprise Configuration"
check_8="$id_8 - $desc_8" checkHeader="$id - $desc"
info "$check_8" info "$checkHeader"
startsectionjson "$id_8" "$desc_8" startsectionjson "$id" "$desc"
} }
check_product_license() { check_product_license() {
enterprise_license=1
if docker version | grep -Eqi '^Server.*Community$|Version.*-ce$'; then if docker version | grep -Eqi '^Server.*Community$|Version.*-ce$'; then
info " * Community Engine license, skipping section 8" info " * Community Engine license, skipping section 8"
enterprise_license=0 enterprise_license=0
else
enterprise_license=1
fi fi
} }
@ -23,129 +22,120 @@ check_8_1() {
return return
fi fi
id_8_1="8.1" local id="8.1"
desc_8_1="Universal Control Plane Configuration" local desc="Universal Control Plane Configuration"
check_8_1="$id_8_1 - $desc_8_1" local check="$id - $desc"
info "$check_8_1" info "$check"
} }
# 8.1.1
check_8_1_1() { check_8_1_1() {
if [ "$enterprise_license" -ne 1 ]; then if [ "$enterprise_license" -ne 1 ]; then
return return
fi fi
id_8_1_1="8.1.1" local id="8.1.1"
desc_8_1_1="Configure the LDAP authentication service (Scored)" local desc="Configure the LDAP authentication service (Scored)"
check_8_1_1="$id_8_1_1 - $desc_8_1_1" local remediation="You can configure LDAP integration via the UCP Admin Settings UI. LDAP integration can also be enabled via a configuration file"
starttestjson "$id_8_1_1" "$desc_8_1_1" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_8_1_1" logcheckresult "INFO"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
} }
# 8.1.2
check_8_1_2() { check_8_1_2() {
if [ "$enterprise_license" -ne 1 ]; then if [ "$enterprise_license" -ne 1 ]; then
return return
fi fi
id_8_1_2="8.1.2" local id="8.1.2"
desc_8_1_2="Use external certificates (Scored)" local desc="Use external certificates (Scored)"
check_8_1_2="$id_8_1_2 - $desc_8_1_2" local remediation="You can configure your own certificates for UCP either during installation or after installation via the UCP Admin Settings user interface."
starttestjson "$id_8_1_2" "$desc_8_1_2" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_8_1_2" logcheckresult "INFO"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
} }
# 8.1.3
check_8_1_3() { check_8_1_3() {
if [ "$enterprise_license" -ne 1 ]; then if [ "$enterprise_license" -ne 1 ]; then
return return
fi fi
id_8_1_3="8.1.3" local id="8.1.3"
desc_8_1_3="Enforce the use of client certificate bundles for unprivileged users (Not Scored)" local desc="Enforce the use of client certificate bundles for unprivileged users (Not Scored)"
check_8_1_3="$id_8_1_3 - $desc_8_1_3" local remediation="Client certificate bundles can be created in one of two ways. User Management UI: UCP Administrators can provision client certificate bundles on behalf of users. Self-Provision: Users with access to the UCP console can create client certificate bundles themselves."
starttestjson "$id_8_1_3" "$desc_8_1_3" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_8_1_3" logcheckresult "INFO"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
} }
# 8.1.4
check_8_1_4() { check_8_1_4() {
if [ "$enterprise_license" -ne 1 ]; then if [ "$enterprise_license" -ne 1 ]; then
return return
fi fi
id_8_1_4="8.1.4" local id="8.1.4"
desc_8_1_4="Configure applicable cluster role-based access control policies (Not Scored)" local desc="Configure applicable cluster role-based access control policies (Not Scored)"
check_8_1_4="$id_8_1_4 - $desc_8_1_4" local remediation="UCP RBAC components can be configured as required via the UCP User Management UI."
starttestjson "$id_8_1_4" "$desc_8_1_4" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_8_1_4" logcheckresult "INFO"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
} }
# 8.1.5
check_8_1_5() { check_8_1_5() {
if [ "$enterprise_license" -ne 1 ]; then if [ "$enterprise_license" -ne 1 ]; then
return return
fi fi
id_8_1_5="8.1.5" local id="8.1.5"
desc_8_1_5="Enable signed image enforcement (Scored)" local desc="Enable signed image enforcement (Scored)"
check_8_1_5="$id_8_1_5 - $desc_8_1_5" local check="$id - $desc"
starttestjson "$id_8_1_5" "$desc_8_1_5" starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_8_1_5" logcheckresult "INFO"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
} }
# 8.1.6
check_8_1_6() { check_8_1_6() {
if [ "$enterprise_license" -ne 1 ]; then if [ "$enterprise_license" -ne 1 ]; then
return return
fi fi
id_8_1_6="8.1.6" local id="8.1.6"
desc_8_1_6="Set the Per-User Session Limit to a value of '3' or lower (Scored)" local desc="Set the Per-User Session Limit to a value of '3' or lower (Scored)"
check_8_1_6="$id_8_1_6 - $desc_8_1_6" local remediation="Retrieve a UCP API token. Retrieve and save UCP config. Open the ucp-config.toml file, set the per_user_limit entry under the [auth.sessions] section to a value of 3 or lower, but greater than 0. Update UCP with the new configuration."
starttestjson "$id_8_1_6" "$desc_8_1_6" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_8_1_6" logcheckresult "INFO"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
} }
# 8.1.7
check_8_1_7() { check_8_1_7() {
if [ "$enterprise_license" -ne 1 ]; then if [ "$enterprise_license" -ne 1 ]; then
return return
fi fi
id_8_1_7="8.1.7" local id="8.1.7"
desc_8_1_7="Set the 'Lifetime Minutes' and 'Renewal Threshold Minutes' values to '15' or lower and '0' respectively (Scored)" local desc="Set the 'Lifetime Minutes' and 'Renewal Threshold Minutes' values to '15' or lower and '0' respectively (Scored)"
check_8_1_7="$id_8_1_7 - $desc_8_1_7" local remediation="Retrieve a UCP API token. Retrieve and save UCP config. Open the ucp-config.toml file, set the lifetime_minutes and renewal_threshold_minutes entries under the [auth.sessions] section to values of 15 or lower and 0 respectively. Update UCP with the new configuration."
starttestjson "$id_8_1_7" "$desc_8_1_7" local remediationImpact="Setting the Lifetime Minutes setting to a value that is too lower would result in users having to constantly re-authenticate to their Docker Enterprise cluster."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_8_1_7" logcheckresult "INFO"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
} }
check_8_2() { check_8_2() {
@ -153,11 +143,10 @@ check_8_2() {
return return
fi fi
logit "\n" local id="8.2"
id_8_2="8.2" local desc="Docker Trusted Registry Configuration"
desc_8_2="Docker Trusted Registry Configuration" local check="$id - $desc"
check_8_2="$id_8_2 - $desc_8_2" info "$check"
info "$check_8_2"
} }
check_8_2_1() { check_8_2_1() {
@ -165,15 +154,15 @@ check_8_2_1() {
return return
fi fi
id_8_2_1="8.2.1" local id="8.2.1"
desc_8_2_1="Enable image vulnerability scanning (Scored)" local desc="Enable image vulnerability scanning (Scored)"
check_8_2_1="$id_8_2_1 - $desc_8_2_1" local remediation="You can navigate to DTR Settings UI and select the Security tab to access the image scanning configuration. Select the Enable Scanning slider to enable this functionality."
starttestjson "$id_8_2_1" "$desc_8_2_1" local remediationImpact="None."
local check="$id - $desc"
starttestjson "$id" "$desc"
totalChecks=$((totalChecks + 1)) note -c "$check"
note "$check_8_2_1" logcheckresult "INFO"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
} }
check_8_end() { check_8_end() {

View file

@ -1,57 +1,87 @@
#!/bin/sh #!/bin/sh
check_c() { check_c() {
logit "\n" logit ""
id_99="99" local id="99"
desc_99="Community contributed checks" local desc="Community contributed checks"
check_99="$id_99 - $desc_99" checkHeader="$id - $desc"
info "$check_99" info "$checkHeader"
startsectionjson "$id_99" "$desc_99" startsectionjson "$id" "$desc"
} }
# check_c_1
check_c_1() { check_c_1() {
check_c_1="C.1 - This is a example check" local id="C.1"
totalChecks=$((totalChecks + 1)) local desc="This is a example check for a Scored check"
local remediation="This is an example remediation measure for a Scored check"
local remediationImpact="This is an example remediation impact for a Scored check"
local check="$id - $desc"
starttestjson "$id" "$desc"
if docker info --format='{{ .Architecture }}' | grep 'x86_64' 2>/dev/null 1>&2; then if docker info --format='{{ .Architecture }}' | grep 'x86_64' 2>/dev/null 1>&2; then
pass "$check_c_1" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
else return
warn "$check_c_1"
resulttestjson "WARN"
fi fi
if docker info --format='{{ .Architecture }}' | grep 'aarch64' 2>/dev/null 1>&2; then
info -c "$check"
logcheckresult "INFO"
return
fi
warn -s "$check"
logcheckresult "WARN"
}
check_c_1_1() {
local id="C.1.1"
local desc="This is a example check for a Not Scored check"
local remediation="This is an example remediation measure for a Not Scored check"
local remediationImpact="This is an example remediation impact for a Not Scored check"
local check="$id - $desc"
starttestjson "$id" "$desc"
if docker info --format='{{ .Architecture }}' | grep 'x86_64' 2>/dev/null 1>&2; then
pass -c "$check"
logcheckresult "PASS"
return
fi
if docker info --format='{{ .Architecture }}' | grep 'aarch64' 2>/dev/null 1>&2; then
info -c "$check"
logcheckresult "INFO"
return
fi
warn -c "$check"
logcheckresult "WARN"
} }
# check_c_2
check_c_2() { check_c_2() {
docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \ docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \
| awk '{print $NF; exit}' | tr -d '[:alpha:]-,.' | cut -c 1-4) | awk '{print $NF; exit}' | tr -d '[:alpha:]-,.' | cut -c 1-4)
totalChecks=$((totalChecks + 1))
id_c_2="C.2" local id="C.2"
desc_c_2="Ensure operations on legacy registry (v1) are Disabled" local desc="Ensure operations on legacy registry (v1) are Disabled"
check_c_2="$id_c_2 - $desc_c_2" local remediation="Start docker daemon with --disable-legacy-registry=false flag. Starting with Docker 17.12, support for V1 registries has been removed, and the --disable-legacy-registry flag can no longer be used."
starttestjson "$id_c_2" "$desc_c_2" local remediationImpact="Prevents the docker daemon from pull, push, and login operations against v1 registries."
local check="$id - $desc"
starttestjson "$id" "$desc"
if [ "$docker_version" -lt 1712 ]; then if [ "$docker_version" -lt 1712 ]; then
if get_docker_configuration_file_args 'disable-legacy-registry' | grep 'true' >/dev/null 2>&1; then if get_docker_configuration_file_args 'disable-legacy-registry' | grep 'true' >/dev/null 2>&1; then
pass "$check_c_2" pass -s "$check"
resulttestjson "PASS" logcheckresult "PASS"
currentScore=$((currentScore + 1)) return
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 fi
else if get_docker_effective_command_line_args '--disable-legacy-registry' | grep "disable-legacy-registry" >/dev/null 2>&1; then
desc_c_2="$desc_c_2 (Deprecated)" pass -s "$check"
check_c_2="$id_c_2 - $desc_c_2" logcheckresult "PASS"
info "$check_c_2" return
resulttestjson "INFO" fi
warn -s "$check"
logcheckresult "WARN"
return
fi fi
local desc="$desc (Deprecated)"
local check="$id - $desc"
info -c "$check"
logcheckresult "INFO"
} }
check_c_end() { check_c_end() {

266
tests/TESTS.md Normal file
View file

@ -0,0 +1,266 @@
# Available Checks
Check ID | Category | Subcategory | Check Name
------------ | ------------ | ------------ | ------------
`host_configuration` | Host Configuration
`host_general_configuration` | | General Configuration
`check_1_1_1` | | | Ensure the container host has been Hardened (Not Scored)
`check_1_1_2` | | | Ensure that the version of Docker is up to date (Not Scored)
`linux_hosts_specific_configuration` | | Linux Hosts Specific Configuration
`check_1_2_1` | | | Ensure a separate partition for containers has been created (Scored)
`check_1_2_2` | | | Ensure only trusted users are allowed to control Docker daemon (Scored)
`check_1_2_3` | | | Ensure auditing is configured for the Docker daemon (Scored)
`check_1_2_4` | | | Ensure auditing is configured for Docker files and directories - /var/lib/docker (Scored)
`check_1_2_5` | | | Ensure auditing is configured for Docker files and directories - /etc/docker (Scored)
`check_1_2_6` | | | Ensure auditing is configured for Docker files and directories - docker.service (Scored)
`check_1_2_7` | | | Ensure auditing is configured for Docker files and directories - docker.socket (Scored)
`check_1_2_8` | | | Ensure auditing is configured for Docker files and directories - /etc/default/docker (Scored)
`check_1_2_9` | | | Ensure auditing is configured for Docker files and directories - /etc/sysconfig/docker (Scored)
`check_1_2_10` | | | Ensure auditing is configured for Docker files and directories - /etc/docker/daemon.json (Scored)
`check_1_2_11` | | | Ensure auditing is configured for Docker files and directories - /usr/bin/containerd (Scored)
`check_1_2_12` | | | Ensure auditing is configured for Docker files and directories - /usr/sbin/runc (Scored)
`docker_daemon_configuration` | Docker daemon configuration
`check_2_1` | | Ensure network traffic is restricted between containers on the default bridge (Scored)
`check_2_2` | | Ensure the logging level is set to 'info' (Scored)
`check_2_3` | | Ensure Docker is allowed to make changes to iptables (Scored)
`check_2_4` | | Ensure insecure registries are not used (Scored)
`check_2_5` | | Ensure aufs storage driver is not used (Scored)
`check_2_6` | | Ensure TLS authentication for Docker daemon is configured (Scored)
`check_2_7` | | Ensure the default ulimit is configured appropriately (Not Scored)
`check_2_8` | | Enable user namespace support (Scored)
`check_2_9` | | Ensure the default cgroup usage has been confirmed (Scored)
`check_2_10` | | Ensure base device size is not changed until needed (Scored)
`check_2_11` | | Ensure that authorization for Docker client commands is enabled (Scored)
`check_2_12` | | Ensure centralized and remote logging is configured (Scored)
`check_2_13` | | Ensure live restore is enabled (Scored)
`check_2_14` | | Ensure Userland Proxy is Disabled (Scored)
`check_2_15` | | Ensure that a daemon-wide custom seccomp profile is applied if appropriate (Not Scored)
`check_2_16` | | Ensure that experimental features are not implemented in production (Scored)
`check_2_17` | | Ensure containers are restricted from acquiring new privileges (Scored)
`docker_daemon_files` | Docker daemon configuration files
`check_3_1` | | Ensure that the docker.service file ownership is set to root:root (Scored)
`check_3_2` | | Ensure that docker.service file permissions are appropriately set (Scored)
`check_3_3` | | Ensure that docker.socket file ownership is set to root:root (Scored)
`check_3_4` | | Ensure that docker.socket file permissions are set to 644 or more restrictive (Scored)
`check_3_5` | | Ensure that the /etc/docker directory ownership is set to root:root (Scored)
`check_3_6` | | Ensure that /etc/docker directory permissions are set to 755 or more restrictively (Scored)
`check_3_7` | | Ensure that registry certificate file ownership is set to root:root (Scored)
`check_3_8` | | Ensure that registry certificate file permissions are set to 444 or more restrictively (Scored)
`check_3_9` | | Ensure that TLS CA certificate file ownership is set to root:root (Scored)
`check_3_10` | | Ensure that TLS CA certificate file permissions are set to 444 or more restrictively (Scored)
`check_3_11` | | Ensure that Docker server certificate file ownership is set to root:root (Scored)
`check_3_12` | | Ensure that the Docker server certificate file permissions are set to 444 or more restrictively (Scored)
`check_3_13` | | Ensure that the Docker server certificate key file ownership is set to root:root (Scored)
`check_3_14` | | Ensure that the Docker server certificate key file permissions are set to 400 (Scored)
`check_3_15` | | Ensure that the Docker socket file ownership is set to root:docker (Scored)
`check_3_16` | | Ensure that the Docker socket file permissions are set to 660 or more restrictively (Scored)
`check_3_17` | | Ensure that the daemon.json file ownership is set to root:root (Scored)
`check_3_18` | | Ensure that daemon.json file permissions are set to 644 or more restrictive (Scored)
`check_3_19` | | Ensure that the /etc/default/docker file ownership is set to root:root (Scored)
`check_3_20` | | Ensure that the /etc/sysconfig/docker file ownership is set to root:root (Scored)
`check_3_21` | | Ensure that the /etc/sysconfig/docker file permissions are set to 644 or more restrictively (Scored)
`check_3_22` | | Ensure that the /etc/default/docker file permissions are set to 644 or more restrictively (Scored)
`container_images` | Container Images and Build File
`check_4.1` | | Ensure that a user for the container has been created (Scored)
`check_4.2` | | Ensure that containers use only trusted base images (Not Scored)
`check_4.3` | | Ensure that unnecessary packages are not installed in the container (Not Scored)
`check_4.4` | | Ensure images are scanned and rebuilt to include security patches (Not Scored)
`check_4.5` | | Ensure Content trust for Docker is Enabled (Scored)
`check_4.6` | | Ensure that HEALTHCHECK instructions have been added to container images (Scored)
`check_4.7` | | Ensure update instructions are not used alone in the Dockerfile (Not Scored)
`check_4.8` | | Ensure setuid and setgid permissions are removed (Not Scored)
`check_4.9` | | Ensure that COPY is used instead of ADD in Dockerfiles (Not Scored)
`check_4.10` | | Ensure secrets are not stored in Dockerfiles (Not Scored)
`check_4.11` | | Ensure only verified packages are are installed (Not Scored)
`container_runtime` | Container Runtime
`check_running_containers` | | Check if exists running containers
`check_5_1` | | Ensure that, if applicable, an AppArmor Profile is enabled (Scored)
`check_5_2` | | Ensure that, if applicable, SELinux security options are set (Scored)
`check_5_3` | | Ensure that Linux kernel capabilities are restricted within containers (Scored)
`check_5_4` | | Ensure that privileged containers are not used (Scored)
`check_5_5` | | Ensure sensitive host system directories are not mounted on containers (Scored)
`check_5_6` | | Ensure sshd is not run within containers (Scored)
`check_5_7` | | Ensure privileged ports are not mapped within containers (Scored)
`check_5_8` | | Ensure that only needed ports are open on the container (Not Scored)
`check_5_9` | | Ensure that the host's network namespace is not shared (Scored)
`check_5_10` | | Ensure that the memory usage for containers is limited (Scored)
`check_5_11` | | Ensure that CPU priority is set appropriately on containers (Scored)
`check_5_12` | | Ensure that the container's root filesystem is mounted as read only (Scored)
`check_5_13` | | Ensure that incoming container traffic is bound to a specific host interface (Scored)
`check_5_14` | | Ensure that the 'on-failure' container restart policy is set to '5' (Scored)
`check_5_15` | | Ensure that the host's process namespace is not shared (Scored)
`check_5_16` | | Ensure that the host's IPC namespace is not shared (Scored)
`check_5_17` | | Ensure that host devices are not directly exposed to containers (Not Scored)
`check_5_18` | | Ensure that the default ulimit is overwritten at runtime if needed (Not Scored)
`check_5_19` | | Ensure mount propagation mode is not set to shared (Scored)
`check_5_20` | | Ensure that the host's UTS namespace is not shared (Scored)
`check_5_21` | | Ensurethe default seccomp profile is not Disabled (Scored)
`check_5_22` | | Ensure that docker exec commands are not used with the privileged option (Scored)
`check_5_23` | | Ensure that docker exec commands are not used with the user=root option (Not Scored)
`check_5_24` | | Ensure that cgroup usage is confirmed (Scored)
`check_5_25` | | Ensure that the container is restricted from acquiring additional privileges (Scored)
`check_5_26` | | Ensure that container health is checked at runtime (Scored)
`check_5_27` | | Ensure that Docker commands always make use of the latest version of their image (Not Scored)
`check_5_28` | | Ensure that the PIDs cgroup limit is used (Scored)
`check_5_29` | | Ensure that Docker's default bridge docker0 is not used (Not Scored)
`check_5_30` | | Ensure that the host's user namespaces are not shared (Scored)
`check_5_31` | | Ensure that the Docker socket is not mounted inside any containers (Scored)
`docker_security_operations` | Docker Security Operations
`check_6.1` | | Ensure that image sprawl is avoided (Not Scored)
`check_6.2` | | Ensure that container sprawl is avoided (Not Scored)
`docker_swarm_configuration` | Docker Swarm Configuration
`check_7.1` | | Ensure swarm mode is not Enabled, if not needed (Scored)
`check_7.2` | | Ensure that the minimum number of manager nodes have been created in a swarm (Scored) (Swarm mode not enabled)
`check_7.3` | | Ensure that swarm services are bound to a specific host interface (Scored) (Swarm mode not enabled)
`check_7.4` | | Ensure that all Docker swarm overlay networks are encrypted (Scored)
`check_7.5` | | Ensure that Docker's secret management commands are used for managing secrets in a swarm cluster (Not Scored) (Swarm mode not enabled)
`check_7.6` | | Ensure that swarm manager is run in auto-lock mode (Scored) (Swarm mode not enabled)
`check_7.7` | | Ensure that the swarm manager auto-lock key is rotated periodically (Not Scored) (Swarm mode not enabled)
`check_7.8` | | Ensure that node certificates are rotated as appropriate (Not Scored) (Swarm mode not enabled)
`check_7.9` | | Ensure that CA certificates are rotated as appropriate (Not Scored) (Swarm mode not enabled)
`check_7.10` | | Ensure that management plane traffic is separated from data plane traffic (Not Scored) (Swarm mode not enabled)
`docker_enterprise_configuration` | Docker Enterprise Configuration
`check_product_license` | | Check Docker license
`universal_control_plane_configuration` | | Universal Control Plane Configuration
`check_8.1.1` | | | Configure the LDAP authentication service (Scored)
`check_8.1.2` | | | Use external certificates (Scored)
`check_8.1.3` | | | Enforce the use of client certificate bundles for unprivileged users (Not Scored)
`check_8.1.4` | | | Configure applicable cluster role-based access control policies (Not Scored)
`check_8.1.5` | | | Enable signed image enforcement (Scored)
`check_8.1.6` | | | Set the Per-User Session Limit to a value of '3' or lower (Scored)
`check_8.1.7` | | | Set the 'Lifetime Minutes' and 'Renewal Threshold Minutes' values to '15' or lower and '0' respectively (Scored)
`docker_trusted_registry_configuration` | | Docker Trusted Registry Configuration
`check_8.2.1` | | | Enable image vulnerability scanning (Scored)
`community_checks` | Community contributed checks
`check_c_1` | | This is a example check
`check_c_2` | | Ensure operations on legacy registry (v1) are Disabled (Deprecated)
## Another Check ID are:
- `community_checks` -> Run all community checks
- `community` -> Is an alias for `community_checks`
- `cis` -> Run all bellow checks category:
- `host_configuration`
- `docker_daemon_configuration`
- `docker_daemon_files`
- `container_images`
- `container_runtime`
- `docker_security_operations`
- `docker_swarm_configuration`
- `docker_enterprise_configuration`
- `all` -> Run all bellow checks category:
- `cis`
- `community`
- `cis_level1` -> Run all bellow checks:
- `host_configuration_level1`
- `docker_daemon_configuration_level1`
- `docker_daemon_files_level1`
- `container_images_level1`
- `container_runtime_level1`
- `docker_security_operations_level1`
- `docker_swarm_configuration_level1`
- `docker_enterprise_configuration_level1`
- `host_configuration_level1` -> Run all bellow checks:
- `check_1_1_1`
- `check_1_1_2`
- `check_1_2_1`
- `check_1_2_2`
- `check_1_2_3`
- `check_1_2_5`
- `check_1_2_6`
- `check_1_2_7`
- `check_1_2_8`
- `check_1_2_9`
- `check_1_2_10`
- `check_1_2_11`
- `check_1_2_12`
- `docker_daemon_configuration_level1` -> Run all bellow checks:
- `check_2_1`
- `check_2_2`
- `check_2_3`
- `check_2_4`
- `check_2_5`
- `check_2_6`
- `check_2_7`
- `check_2_13`
- `check_2_14`
- `check_2_16`
- `check_2_17`
- `docker_daemon_files_level1` -> Run all bellow checks:
- `check_3_1`
- `check_3_2`
- `check_3_3`
- `check_3_4`
- `check_3_5`
- `check_3_6`
- `check_3_7`
- `check_3_8`
- `check_3_9`
- `check_3_10`
- `check_3_11`
- `check_3_12`
- `check_3_13`
- `check_3_14`
- `check_3_15`
- `check_3_16`
- `check_3_17`
- `check_3_18`
- `check_3_19`
- `check_3_20`
- `check_3_21`
- `check_3_22`
- `container_images_level1` -> Run all bellow checks:
- `check_4_1`
- `check_4_2`
- `check_4_3`
- `check_4_4`
- `check_4_6`
- `check_4_7`
- `check_4_9`
- `check_4_10`
- `container_runtime_level1` -> Run all bellow checks:
- `check_running_containers`
- `check_5_1`
- `check_5_3`
- `check_5_4`
- `check_5_5`
- `check_5_6`
- `check_5_7`
- `check_5_8`
- `check_5_9`
- `check_5_10`
- `check_5_11`
- `check_5_12`
- `check_5_13`
- `check_5_14`
- `check_5_15`
- `check_5_16`
- `check_5_17`
- `check_5_18`
- `check_5_19`
- `check_5_20`
- `check_5_21`
- `check_5_24`
- `check_5_25`
- `check_5_26`
- `check_5_27`
- `check_5_28`
- `check_5_30`
- `check_5_31`
- `docker_security_operations_level1` -> Run all bellow checks:
- `check_6_1`
- `check_6_2`
- `docker_swarm_configuration_level1` -> Run all bellow checks:
- `check_7_1`
- `check_7_2`
- `check_7_3`
- `check_7_4`
- `check_7_7`
- `docker_enterprise_configuration_level1` -> Run all bellow checks:
- `check_product_license`
- `check_8_1_1`
- `check_8_1_2`
- `check_8_1_3`
- `check_8_1_4`
- `check_8_1_5`
- `check_8_1_6`
- `check_8_1_7`
- `check_8_2_1`