This commit is contained in:
music.apple.com 2020-11-30 06:08:33 +00:00 committed by GitHub
commit 5928ecb73f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 4303 additions and 948 deletions

View file

@ -1 +1,5 @@
.git .git
*.md
*.png
distros

2
.gitignore vendored
View file

@ -1 +1 @@
*.log *.log*

View file

@ -3,46 +3,62 @@
Want to hack on Docker Bench? Awesome! Here are instructions to get you Want to hack on Docker Bench? Awesome! Here are instructions to get you
started. started.
The Docker Bench for Security is a part of the [Docker](https://www.docker.com) project, and follows The Docker Bench for Security is a part of the [Docker](https://www.docker.com)
the same rules and principles. If you're already familiar with the way project, and follows the same rules and principles. If you're already familiar
Docker does things, you'll feel right at home. with the way Docker does things, you'll feel right at home.
Otherwise, go read Otherwise, go read
[Docker's contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md). [Docker's contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md).
### Development Environment Setup ## Development Environment Setup
The only thing you need to hack on Docker Bench for Security is a POSIX 2004 compliant shell. We try to keep the project compliant for maximum portability The only thing you need to hack on Docker Bench for Security is a POSIX 2004
compliant shell. We try to keep the project compliant for maximum portability.
#### Start hacking ### Start hacking
You can build the container that wraps the docker-bench for security: You can build the container that wraps the docker-bench for security:
```sh ```sh
✗ git clone git@github.com:docker/docker-bench-security.git git clone git@github.com:docker/docker-bench-security.git
✗ docker build -t diogomonica/docker-bench-security . cd docker-bench-security
docker build -t docker-bench-security .
``` ```
Or you can simply run the shell script locally: Or you can simply run the shell script locally:
```sh ```sh
✗ sh docker-bench-security.sh git clone git@github.com:docker/docker-bench-security.git
cd docker-bench-security
sudo sh docker-bench-security.sh
``` ```
The Docker Bench has the main script called `docker-bench-security.sh`. This is the main script that checks for all the dependencies, deals with command line arguments and loads all the tests. The Docker Bench has the main script called `docker-bench-security.sh`.
This is the main script that checks for all the dependencies, deals with
command line arguments and loads all the tests.
The tests are split in 6 different files: The tests are split into the following files:
```sh ```sh
✗ docker-bench-security git:(master) ✗ tree tests tests/
tests
├── 1_host_configuration.sh ├── 1_host_configuration.sh
├── 2_docker_daemon_configuration.sh ├── 2_docker_daemon_configuration.sh
├── 3_docker_daemon_configuration_files.sh ├── 3_docker_daemon_configuration_files.sh
├── 4_container_images.sh ├── 4_container_images.sh
├── 5_container_runtime.sh ├── 5_container_runtime.sh
└── 6_docker_security_operations.sh ├── 6_docker_security_operations.sh
├── 7_docker_swarm_configuration.sh
├── 8_docker_enterprise_configuration.sh
└── 99_community_checks.sh
``` ```
To modify the Docker Bench for Security you should first clone the repository, make your changes, and then sign off on your commits. After that feel free to send us a pull-request with the changes. To modify the Docker Bench for Security you should first clone the repository,
make your changes, check your code with `shellcheck`, `checkbashisms` or similar
tools, and then sign off on your commits. After that feel free to send us a
pull request with the changes.
While this tool is inspired in the CIS Docker 1.6 Benchmark, feel free to add new tests. We will try to turn dockerbench.com into a list of good community benchmarks for both security and performance, and we would love community contributions. While this tool was inspired by the [CIS Docker 1.11.0 benchmark](https://www.cisecurity.org/benchmark/docker/)
and its successors, feel free to add new tests. We will try to turn
[dockerbench.com](https://dockerbench.com) into a list of good community
benchmarks for both security and performance, and we would love community
contributions.

58
CONTRIBUTORS.md Normal file
View file

@ -0,0 +1,58 @@
The following people, listed in alphabetical order, have contributed to docker-bench-security:
* alberto <alberto@tutum.co>
* Andreas Stieger <astieger@suse.com>
* Anthony Roger <aroger@softwaymedical.fr>
* Aurélien Gasser <aurelien.gasser@gmail.com>
* binary <binary@webdev.fritz.box>
* Boris Gorbylev <ekho@ekho.name>
* Cheng-Li Jerry Ma <chengli.ma@gmail.com>
* Csaba Palfi <csaba@palfi.me>
* Daniele Marcocci <daniele.marcocci@par-tec.it>
* Dhawal Patel <dhawal.patel@nordstrom.com>
* Diogo Monica <diogo@docker.com>
* Diogo Mónica <diogo.monica@gmail.com>
* Ernst de Haan <ernst@ernstdehaan.com>
* HuKeping <hukeping@huawei.com>
* Ivan Angelov <iangelov@users.noreply.github.com>
* J0WI <J0WI@users.noreply.github.com>
* jammasterj89 <jammasterj89@gmail.com>
* Jessica Frazelle <princess@docker.com>
* Joachim Lusiardi <jlusiardi@users.noreply.github.com>
* Joachim Lusiardi <joachim@lusiardi.de>
* Joachim Lusiardi <shing19m@dev1.lusiardi.de>
* Joe Williams <joe.williams@github.com>
* Julien Garcia Gonzalez <julien@giantswarm.io>
* Jürgen Hermann <jh@web.de>
* kakakakakku <y.yoshida22@gmail.com>
* Karol Babioch <kbabioch@suse.de>
* Kevin Lim <kevin.lim@sap.com>
* kevinll <imhael@gmail.com>
* Liron Levin <liron@twistlock.com>
* liron-l <levinlir@gmail.com>
* LorensK <LorensK@users.noreply.github.com>
* lusitania <lusitania@users.noreply.github.com>
* Maik Ellerbrock <opensource@frapsoft.com>
* Mark Stemm <mark.stemm@gmail.com>
* Matt Fellows <matt.fellows@onegeek.com.au>
* Michael Crosby <crosbymichael@gmail.com>
* Michael Stahn <michael.stahn.42@gmail.com>
* Mike Ritter <mike.ritter@target.com>
* Mr. Secure <ben.github@mrsecure.org>
* MrSecure <MrSecure@users.noreply.github.com>
* Nigel Brown <nigel@windsock.io>
* Paul Czarkowski <username.taken@gmail.com>
* Paul Morgan <jumanjiman@gmail.com>
* Pete Sellars <psellars@gmail.com>
* Peter <lusitania@users.noreply.github.com>
* Ravi Kumar Vadapalli <vadapalli.ravikumar@gmail.com>
* Scott McCarty <scott.mccarty@gmail.com>
* Sebastiaan van Stijn <github@gone.nl>
* telepresencebot2 <telepresencebot2@users.noreply.github.com>
* Thomas Sjögren <konstruktoid@users.noreply.github.com>
* Tom Partington <tom.partington@cevo.com.au>
* Werner Buck <wernerbuck@gmail.com>
* will Farrell <willfarrell@users.noreply.github.com>
* Zvi "Viz" Effron <zeffron@riotgames.com>
This list was generated Tue Nov 5 09:45:35 UTC 2019.

View file

@ -1,11 +1,25 @@
FROM alpine:3.1 FROM alpine:3.12
RUN apk --update add docker LABEL \
org.label-schema.name="docker-bench-security" \
org.label-schema.url="https://dockerbench.com" \
org.label-schema.vcs-url="https://github.com/docker/docker-bench-security.git"
RUN mkdir /docker-bench-security # Switch to the HTTPS endpoint for the apk repositories
# https://github.com/gliderlabs/docker-alpine/issues/184
RUN set -eux; \
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 . /docker-bench-security COPY ./*.sh /usr/local/bin/
COPY ./tests/*.sh /usr/local/bin/tests/
WORKDIR /docker-bench-security HEALTHCHECK CMD exit 0
ENTRYPOINT ["/bin/sh", "docker-bench-security.sh"] WORKDIR /usr/local/bin
ENTRYPOINT [ "/usr/bin/dumb-init", "docker-bench-security.sh" ]
CMD [""]

34
MAINTAINERS Normal file
View file

@ -0,0 +1,34 @@
# Docker Bench for Security maintainers file
#
# This file describes who runs the docker/docker-bench-security project and how.
# This is a living document - if you see something out of date or missing, speak up!
#
# It is structured to be consumable by both humans and programs.
# To extract its contents programmatically, use any TOML-compliant parser.
#
# This file is compiled into the MAINTAINERS file in docker/opensource.
#
[Org]
[Org."Core maintainers"]
people = [
"diogomonica",
"konstruktoid",
]
[people]
# A reference list of all people associated with the project.
# All other sections should refer to people by their canonical key
# in the people section.
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
[people.diogomonica]
Name = "Dr. Diogo Mónica"
Email = "diogo@docker.com"
GitHub = "diogomonica"
[people.konstruktoid]
Name = "Thomas Sjögren"
Email = "thomas.sjogren@protonmail.com"
GitHub = "konstruktoid"

149
README.md
View file

@ -1,45 +1,150 @@
# Docker Bench for Security # Docker Bench for Security
![Docker Bench for Security running](https://github.com/diogomonica/docker-bench-security/raw/master/benchmark_log.png?raw=true "Docker Bench for Security running") ![Docker Bench for Security running](https://raw.githubusercontent.com/docker/docker-bench-security/master/benchmark_log.png)
The Docker Bench for Security is a script that checks for all the automatable tests included in the [CIS Docker 1.6 Benchmark](https://benchmarks.cisecurity.org/tools2/docker/CIS_Docker_1.6_Benchmark_v1.0.0.pdf). We are releasing this as a follow-up to our [Understanding Docker Security and Best Practices](https://blog.docker.com/2015/05/understanding-docker-security-and-best-practices/) blog post. 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/).
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. 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 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. 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 CIS Docker 1.6 benchmark is by running our pre-built container: The easiest way to run your hosts against the Docker Bench for Security is by
running our pre-built container:
```sh
``` docker run --rm --net host --pid host --userns host --cap-add audit_control \
docker run -it --net host --pid host -v /var/run/docker.sock:/var/run/docker.sock \ -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /usr/lib/systemd:/usr/lib/systemd -v /etc:/etc --label docker-bench-security \ -v /etc:/etc:ro \
diogomonica/docker-bench-security -v /usr/bin/containerd:/usr/bin/containerd:ro \
-v /usr/bin/runc:/usr/bin/runc:ro \
-v /usr/lib/systemd:/usr/lib/systemd:ro \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--label docker_bench_security \
docker/docker-bench-security
``` ```
Docker bench requires Docker 1.6.2 or later in order to run, since it depends on the `--label` to exclude the current container from being inspected. If you can't upgrade to 1.6.2, I feel free to remove the `--label` flag or run the shell script locally (see below). Don't forget to adjust the shared volumes according to your operating system.
Some examples are:
Additionally, there was a bug in Docker 1.6.0 that would not allow mounting `-v /dev:/dev`. If you are getting an error while accessing `resolv.conf`, please update your docker to 1.6.2. 1. `Docker Desktop` on macOS don'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
```
2. On Ubuntu the `docker.service` and `docker.secret` files are located in
`/lib/systemd/system` folder by default.
```sh
docker run --rm --net host --pid host --userns host --cap-add audit_control \
-e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /etc:/etc:ro \
-v /lib/systemd/system:/lib/systemd/system:ro \
-v /usr/bin/containerd:/usr/bin/containerd:ro \
-v /usr/bin/runc:/usr/bin/runc:ro \
-v /usr/lib/systemd:/usr/lib/systemd:ro \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--label docker_bench_security \
docker/docker-bench-security
```
Docker bench requires Docker 1.13.0 or later in order to run.
Note that when distributions doesn't contain `auditctl`, the audit tests will
check `/etc/audit/audit.rules` to see if a rule is present instead.
Distribution specific Dockerfiles that fixes this issue 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 haven't yet shipped Docker
version 1.13.0 or later.
### Docker Bench for Security options
```sh
-b optional Do not print colors
-h optional Print this help message
-l FILE optional Log output in FILE
-c CHECK optional Comma delimited list of specific check(s)
-e CHECK optional Comma delimited list of specific check(s) to exclude
-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
```
By default the Docker Bench for Security script will run all available CIS tests
and produce logs in the current directory named `docker-bench-security.sh.log.json`
and `docker-bench-security.sh.log`.
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 are present in [functions_lib.sh](functions_lib.sh).
`sh docker-bench-security.sh -l /tmp/docker-bench-security.sh.log -c check_2_2`
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`
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`
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`
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`
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
reasonable test to add and please include some kind of official documentation
verifying that information.
## Building Docker Bench for Security ## Building Docker Bench for Security
If you wish to build and run this container yourself, you can follow the following steps: If you wish to build and run this container yourself, you can follow the
following steps:
```sh
git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security
docker build --no-cache -t docker-bench-security .
``` ```
git clone https://github.com/diogomonica/docker-bench-security.git
cd docker-bench-security; docker build -t docker-bench-security . followed by an appropriate `docker run` command as stated above
docker run -it --net host --pid host -v /var/run/docker.sock:/var/run/docker.sock \ or use [Docker Compose](https://docs.docker.com/compose/):
-v /usr/lib/systemd:/usr/lib/systemd -v /etc:/etc --label security-benchmark \
docker-bench-security ```sh
git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security
docker-compose run --rm docker-bench-security
``` ```
Also, this script can also be simply run from your base host by running: Also, this script can also be simply run from your base host by running:
``` ```sh
git clone https://github.com/diogomonica/docker-bench-security.git git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security; sh docker-bench-security.sh cd docker-bench-security
sudo sh docker-bench-security.sh
``` ```
This script was build to be POSIX 2004 compliant, so it should be portable across any Unix platform. This script was built to be POSIX 2004 compliant, so it should be portable
across any Unix platform.

Binary file not shown.

Before

(image error) Size: 180 KiB

After

(image error) Size: 275 KiB

Before After
Before After

25
distros/Dockerfile.alpine Normal file
View file

@ -0,0 +1,25 @@
FROM alpine:3.12
LABEL \
org.label-schema.name="docker-bench-security" \
org.label-schema.url="https://dockerbench.com" \
org.label-schema.vcs-url="https://github.com/docker/docker-bench-security.git"
# Switch to the HTTPS endpoint for the apk repositories
# https://github.com/gliderlabs/docker-alpine/issues/184
RUN set -eux; \
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 ./tests/*.sh /usr/local/bin/tests/
HEALTHCHECK CMD exit 0
WORKDIR /usr/local/bin
ENTRYPOINT [ "/usr/bin/dumb-init", "docker-bench-security.sh" ]
CMD [""]

15
distros/Dockerfile.centos Normal file
View file

@ -0,0 +1,15 @@
# REPOSITORY https://github.com/fatherlinux/docker-bench-security
FROM centos
MAINTAINER smccarty@redhat.com
RUN yum install -y docker iproute audit procps-ng; yum clean all
RUN mkdir /docker-bench-security
COPY . /docker-bench-security
WORKDIR /docker-bench-security
ENTRYPOINT ["/bin/sh", "docker-bench-security.sh"]

24
distros/Dockerfile.debian Normal file
View file

@ -0,0 +1,24 @@
FROM debian:sid
LABEL org.label-schema.name="docker-bench-security" \
org.label-schema.url="https://github.com/konstruktoid/docker-bench-security" \
org.label-schema.vcs-url="https://github.com/konstruktoid/docker-bench-security.git"
RUN \
apt-get update && \
apt-get -y upgrade && \
apt-get -y install auditd ca-certificates docker.io \
gawk iproute2 procps --no-install-recommends && \
apt-get -y clean && \
apt-get -y autoremove && \
rm -rf /var/lib/apt/lists/* \
/usr/share/doc /usr/share/doc-base \
/usr/share/man /usr/share/locale /usr/share/zoneinfo
RUN mkdir /docker-bench-security
COPY . /docker-bench-security
WORKDIR /docker-bench-security
ENTRYPOINT ["/bin/sh", "docker-bench-security.sh"]

View file

@ -0,0 +1,13 @@
# REPOSITORY https://github.com/docker/docker-bench-security
FROM opensuse/leap:latest
RUN zypper -n in audit docker iproute2 && \
mkdir /docker-bench-security && \
rm /usr/bin/awk && \
cp /usr/bin/gawk /usr/bin/awk
COPY . /docker-bench-security
WORKDIR /docker-bench-security
ENTRYPOINT ["/bin/bash", "docker-bench-security.sh"]

18
distros/Dockerfile.rhel Normal file
View file

@ -0,0 +1,18 @@
# REPOSITORY https://github.com/fatherlinux/docker-bench-security
FROM rhel7
MAINTAINER smccarty@redhat.com
RUN yum install -y yum-utils; yum clean all
RUN yum-config-manager --disable "*" &>/dev/null
RUN yum-config-manager --enable rhel-7-server-rpms --enable rhel-7-server-extras-rpms
RUN yum install -y docker iproute audit procps-ng; yum clean all
RUN mkdir /docker-bench-security
COPY . /docker-bench-security
WORKDIR /docker-bench-security
ENTRYPOINT ["/bin/sh", "docker-bench-security.sh"]

21
distros/README.md Normal file
View file

@ -0,0 +1,21 @@
# Distribution specific Dockerfiles
## Requirements
### Dockerfile name
The format should be `Dockerfile.{distribution name}`.
### Keep your images up-to-date
Use the distribution package manager to keep your image up-to-date.
### Labels
Use the following labels in your Dockerfile:
```
LABEL org.label-schema.name="docker-bench-security" \
org.label-schema.url="<YOUR GIT REPOSITORY HTTPS ADDRESS>" \
org.label-schema.vcs-url="<YOUR REPOSITORY HTTPS GIT ADDRESS"
```

View file

@ -1,91 +1,202 @@
#!/bin/sh #!/bin/sh
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# CIS Docker 1.6 Benchmark v1.0.0 checker # Docker Bench for Security
# #
# Docker, Inc. (c) 2015 # Docker, Inc. (c) 2015-
#
# Provides automated tests for the CIS Docker 1.6 Benchmark:
# https://benchmarks.cisecurity.org/tools2/docker/CIS_Docker_1.6_Benchmark_v1.0.0.pdf
# #
# Checks for dozens of common best-practices around deploying Docker containers in production.
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
version='1.3.5'
# Load dependencies # Load dependencies
. ./output_lib.sh . ./functions_lib.sh
. ./helper_lib.sh . ./helper_lib.sh
# Setup the paths # Setup the paths
this_path=$(abspath "$0") ## Path of this file including filenamel 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.
export PATH=/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin/ readonly version
logger="${myname}.log" readonly this_path
readonly myname
export PATH="$PATH:/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin/"
# Check for required program(s) # Check for required program(s)
req_progs='docker netstat grep awk' req_progs='awk docker grep stat'
for p in $req_progs; do for p in $req_progs; do
command -v "$p" >/dev/null 2>&1 || { printf "%s command not found.\n" "$p"; exit 1; } command -v "$p" >/dev/null 2>&1 || { printf "%s command not found.\n" "$p"; exit 1; }
done 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
docker ps -q >/dev/null 2>&1 if ! docker ps -q >/dev/null 2>&1; then
if [ $? -ne 0 ]; then
printf "Error connecting to docker daemon (does docker ps work?)\n" printf "Error connecting to docker daemon (does docker ps work?)\n"
exit 1 exit 1
fi fi
usage () { usage () {
printf " cat <<EOF
usage: %s [options] usage: ${myname} [options]
-h optional Print this help message\n" "$myname" -b optional Do not print colors
exit 1 -h optional Print this help message
-l FILE optional Log output in FILE
-c CHECK optional Comma delimited list of specific check(s)
-e CHECK optional Comma delimited list of specific check(s) to exclude
-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
-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).
EOF
} }
yell "# ------------------------------------------------------------------------------ # Get the flags
# CIS Docker 1.6 Benchmark v1.0.0 checker # If you add an option here, please
# # remember to update usage() above.
# Docker, Inc. (c) 2015 while getopts bhl:c:e:i:x:t:n: args
# do
# Provides automated tests for the CIS Docker 1.6 Benchmark: case $args in
# https://benchmarks.cisecurity.org/tools2/docker/CIS_Docker_1.6_Benchmark_v1.0.0.pdf b) nocolor="nocolor";;
# ------------------------------------------------------------------------------" h) usage; exit 0 ;;
l) logger="$OPTARG" ;;
c) check="$OPTARG" ;;
e) checkexclude="$OPTARG" ;;
i) include="$OPTARG" ;;
x) exclude="$OPTARG" ;;
n) limit="$OPTARG" ;;
*) usage; exit 1 ;;
esac
done
logit "Initializing $(date)\n" if [ -z "$logger" ]; then
logger="${myname}.log"
fi
if [ -z "$limit" ]; then
limit=0
fi
# Load output formating
. ./output_lib.sh
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 "Some tests might require root to run"
sleep 3 sleep 3
fi fi
# Get the flags # Total Score
while getopts :hlfi: args # Warn Scored -1, Pass Scored +1, Not Score -0
do
case $args in totalChecks=0
h) usage ;; currentScore=0
l) logger="$OPTARG" ;;
*) usage ;; logit "Initializing $(date)\n"
esac beginjson "$version" "$(date +%s)"
done
# Load all the tests from tests/ and run them # Load all the tests from tests/ and run them
main () { main () {
# List all running containers # Get configuration location
containers=$(docker ps -q) get_docker_configuration_file
# If there is a container with label docker-bench, memorize it:
benchcont="nil"
for c in $containers; do
labels=$(docker inspect --format '{{ .Config.Labels }}' "$c")
contains "$labels" "docker-bench" && benchcont="$c"
done
# List all running containers except docker-bench
containers=$(docker ps -q | grep -v "$benchcont")
for test in tests/*.sh # If there is a container with label docker_bench_security, memorize it:
do benchcont="nil"
. ./"$test" for c in $(docker ps | sed '1d' | awk '{print $NF}'); do
if docker inspect --format '{{ .Config.Labels }}' "$c" | \
grep -e 'docker.bench.security' >/dev/null 2>&1; then
benchcont="$c"
fi
done done
# Get the image id of the docker_bench_security_image, memorize it:
benchimagecont="nil"
for c in $(docker images | sed '1d' | awk '{print $3}'); do
if docker inspect --format '{{ .Config.Labels }}' "$c" | \
grep -e 'docker.bench.security' >/dev/null 2>&1; then
benchimagecont="$c"
fi
done
if [ -n "$include" ]; then
pattern=$(echo "$include" | sed 's/,/|/g')
containers=$(docker ps | sed '1d' | awk '{print $NF}' | grep -v "$benchcont" | grep -E "$pattern")
images=$(docker images | sed '1d' | grep -E "$pattern" | awk '{print $3}' | grep -v "$benchimagecont")
elif [ -n "$exclude" ]; then
pattern=$(echo "$exclude" | sed 's/,/|/g')
containers=$(docker ps | sed '1d' | awk '{print $NF}' | grep -v "$benchcont" | grep -Ev "$pattern")
images=$(docker images | sed '1d' | grep -Ev "$pattern" | awk '{print $3}' | grep -v "$benchimagecont")
else
containers=$(docker ps | sed '1d' | awk '{print $NF}' | grep -v "$benchcont")
images=$(docker images -q | grep -v "$benchcont")
fi
if [ -z "$containers" ]; then
running_containers=0
else
running_containers=1
fi
for test in tests/*.sh; do
. ./"$test"
done
if [ -z "$check" ] && [ ! "$checkexclude" ]; then
# No options just run
cis
elif [ -z "$check" ]; then
# No check defined but excludes defined set to calls in cis() function
check=$(sed -ne "/cis() {/,/}/{/{/d; /}/d; p}" functions_lib.sh)
fi
for c in $(echo "$check" | sed "s/,/ /g"); do
if ! command -v "$c" 2>/dev/null 1>&2; then
echo "Check \"$c\" doesn't seem to exist."
continue
fi
if [ -z "$checkexclude" ]; then
# No excludes just run the checks specified
"$c"
else
# Exludes specified and check exists
checkexcluded="$(echo ",$checkexclude" | sed -e 's/^/\^/g' -e 's/,/\$|/g' -e 's/$/\$/g')"
if echo "$c" | grep -E "$checkexcluded" 2>/dev/null 1>&2; then
# Excluded
continue
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
loop_checks="$(sed -ne "/$c() {/,/}/{/{/d; /}/d; p}" functions_lib.sh)"
else
# Just one check
loop_checks="$c"
fi
for lc in $loop_checks; do
if echo "$lc" | grep -vE "$checkexcluded" 2>/dev/null 1>&2; then
# Not excluded
"$lc"
fi
done
fi
done
printf "\n"
info "Checks: $totalChecks"
info "Score: $currentScore"
endjson "$totalChecks" "$currentScore" "$(date +%s)"
} }
main "$@" main "$@"

21
docker-compose.yml Normal file
View file

@ -0,0 +1,21 @@
docker-bench-security:
# use image if you have a dedicated build step:
# docker build --rm -t docker-bench-security .
# image: docker-bench-security
# use build path to Dockerfile if docker-compose should build the image
build: .
cap_add:
- audit_control
labels:
- docker_bench_security
net: host
pid: host
stdin_open: true
tty: true
volumes:
- /var/lib:/var/lib:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /usr/lib/systemd:/usr/lib/systemd:ro
- /etc:/etc:ro

345
functions_lib.sh Normal file
View file

@ -0,0 +1,345 @@
#!/bin/sh
host_configuration() {
check_1
check_1_1
check_1_1_1
check_1_1_2
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
}
host_configuration_level1() {
check_1
check_1_1
check_1_1_1
check_1_1_2
check_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
check_1_end
}
docker_daemon_configuration() {
check_2
check_2_1
check_2_2
check_2_3
check_2_4
check_2_5
check_2_6
check_2_7
check_2_8
check_2_9
check_2_10
check_2_11
check_2_12
check_2_13
check_2_14
check_2_15
check_2_16
check_2_17
check_2_end
}
docker_daemon_configuration_level1() {
check_2
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
check_2_end
}
docker_daemon_files() {
check_3
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
check_3_end
}
docker_daemon_files_level1() {
check_3
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
check_3_end
}
container_images() {
check_4
check_4_1
check_4_2
check_4_3
check_4_4
check_4_5
check_4_6
check_4_7
check_4_8
check_4_9
check_4_10
check_4_11
check_4_end
}
container_images_level1() {
check_4
check_4_1
check_4_2
check_4_3
check_4_4
check_4_6
check_4_7
check_4_9
check_4_10
check_4_end
}
container_runtime() {
check_5
check_running_containers
check_5_1
check_5_2
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_22
check_5_23
check_5_24
check_5_25
check_5_26
check_5_27
check_5_28
check_5_29
check_5_30
check_5_31
check_5_end
}
container_runtime_level1() {
check_5
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
check_5_end
}
docker_security_operations() {
check_6
check_6_1
check_6_2
check_6_end
}
docker_security_operations_level1() {
check_6
check_6_1
check_6_2
check_6_end
}
docker_swarm_configuration() {
check_7
check_7_1
check_7_2
check_7_3
check_7_4
check_7_5
check_7_6
check_7_7
check_7_8
check_7_9
check_7_10
check_7_end
}
docker_swarm_configuration_level1() {
check_7
check_7_1
check_7_2
check_7_3
check_7_4
check_7_7
check_7_end
}
docker_enterprise_configuration() {
check_8
check_product_license
check_8_1
check_8_1_1
check_8_1_2
check_8_1_3
check_8_1_4
check_8_1_5
check_8_1_6
check_8_1_7
check_8_2
check_8_2_1
check_8_end
}
docker_enterprise_configuration_level1() {
check_8
check_product_license
check_8_1
check_8_1_1
check_8_1_2
check_8_1_3
check_8_1_4
check_8_1_5
check_8_1_6
check_8_1_7
check_8_2
check_8_2_1
check_8_end
}
community_checks() {
check_c
check_c_1
check_c_2
check_c_end
}
# CIS
cis() {
host_configuration
docker_daemon_configuration
docker_daemon_files
container_images
container_runtime
docker_security_operations
docker_swarm_configuration
docker_enterprise_configuration
}
cis_level1() {
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
}
# Community contributed
community() {
community_checks
}
# All
all() {
cis
community
}

View file

@ -3,36 +3,127 @@
# Returns the absolute path of a given string # Returns the absolute path of a given string
abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; esac; } abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; esac; }
# Audit rules default path
auditrules="/etc/audit/audit.rules"
# 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
ver1front=$(printf "%s" "$1" | cut -d "." -f -1) ver1front=$(printf "%s" "$1" | cut -d "." -f -1)
ver1back=$(printf "%s" "$1" | cut -d "." -f 2-) ver1back=$(printf "%s" "$1" | cut -d "." -f 2-)
ver2front=$(printf "%s" "$2" | cut -d "." -f -1) ver2front=$(printf "%s" "$2" | cut -d "." -f -1)
ver2back=$(printf "%s" "$2" | cut -d "." -f 2-) ver2back=$(printf "%s" "$2" | cut -d "." -f 2-)
if [ "$ver1front" != "$1" ] || [ "$ver2front" != "$2" ]; then if [ "$ver1front" != "$1" ] || [ "$ver2front" != "$2" ]; then
[ "$ver1front" -gt "$ver2front" ] && return 11 [ "$ver1front" -gt "$ver2front" ] && return 11
[ "$ver1front" -lt "$ver2front" ] && return 9 [ "$ver1front" -lt "$ver2front" ] && return 9
[ "$ver1front" = "$1" ] || [ -z "$ver1back" ] && ver1back=0 [ "$ver1front" = "$1" ] || [ -z "$ver1back" ] && ver1back=0
[ "$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 else
[ "$1" -gt "$2" ] && return 11 || return 9 [ "$1" -gt "$2" ] && return 11 || return 9
fi fi
} }
# Compares two strings and returns 0 if the second is a substring of the first # Extracts commandline args from the newest running processes named like the first parameter
contains() { get_command_line_args() {
string="$1" PROC="$1"
substring="$2"
if [ "${string#*$substring}" != "$string" ] for PID in $(pgrep -f -n "$PROC"); do
then tr "\0" " " < /proc/"$PID"/cmdline
return 0 # $substring is in $string done
else }
return 1 # $substring is not in $string
fi # Extract the cumulative command line arguments for the docker daemon
#
# If specified multiple times, all matches are returned.
# Accounts for long and short variants, call with short option.
# Does not account for option defaults or implicit options.
get_docker_cumulative_command_line_args() {
OPTION="$1"
if ! get_command_line_args "docker daemon" >/dev/null 2>&1 ; then
line_arg="docker daemon"
else
line_arg="dockerd"
fi
get_command_line_args "$line_arg" |
# normalize known long options to their short versions
sed \
-e 's/\-\-debug/-D/g' \
-e 's/\-\-host/-H/g' \
-e 's/\-\-log-level/-l/g' \
-e 's/\-\-version/-v/g' \
|
# normalize parameters separated by space(s) to -O=VALUE
sed \
-e 's/\-\([DHlv]\)[= ]\([^- ][^ ]\)/-\1=\2/g' \
|
# get the last interesting option
tr ' ' "\n" |
grep "^${OPTION}" |
# normalize quoting of values
sed \
-e 's/"//g' \
-e "s/'//g"
}
# Extract the effective command line arguments for the docker daemon
#
# Accounts for multiple specifications, takes the last option.
# Accounts for long and short variants, call with short option
# Does not account for option default or implicit options.
get_docker_effective_command_line_args() {
OPTION="$1"
get_docker_cumulative_command_line_args "$OPTION" | tail -n1
}
get_docker_configuration_file() {
FILE="$(get_docker_effective_command_line_args '--config-file' | \
sed 's/.*=//g')"
if [ -f "$FILE" ]; then
CONFIG_FILE="$FILE"
elif [ -f '/etc/docker/daemon.json' ]; then
CONFIG_FILE='/etc/docker/daemon.json'
else
CONFIG_FILE='/dev/null'
fi
}
get_docker_configuration_file_args() {
OPTION="$1"
get_docker_configuration_file
grep "$OPTION" "$CONFIG_FILE" | sed 's/.*://g' | tr -d '" ',
}
get_service_file() {
SERVICE="$1"
if [ -f "/etc/systemd/system/$SERVICE" ]; then
echo "/etc/systemd/system/$SERVICE"
elif [ -f "/lib/systemd/system/$SERVICE" ]; then
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
}
yell_info() {
yell "# ------------------------------------------------------------------------------
# Docker Bench for Security v$version
#
# Docker, Inc. (c) 2015-
#
# Checks for dozens of common best-practices around deploying Docker containers in production.
# Inspired by the CIS Docker Benchmark v1.2.0.
# ------------------------------------------------------------------------------"
} }

View file

@ -1,9 +1,18 @@
#!/bin/sh #!/bin/sh
bldred='\033[1;31m'
bldgrn='\033[1;32m' if [ -n "$nocolor" ] && [ "$nocolor" = "nocolor" ]; then
bldblu='\033[1;34m' bldred=''
bldylw='\033[1;33m' # Yellow bldgrn=''
txtrst='\033[0m' 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 () { logit () {
printf "%b\n" "$1" | tee -a "$logger" printf "%b\n" "$1" | tee -a "$logger"
@ -21,6 +30,67 @@ warn () {
printf "%b\n" "${bldred}[WARN]${txtrst} $1" | tee -a "$logger" printf "%b\n" "${bldred}[WARN]${txtrst} $1" | tee -a "$logger"
} }
note () {
printf "%b\n" "${bldylw}[NOTE]${txtrst} $1" | tee -a "$logger"
}
yell () { yell () {
printf "%b\n" "${bldylw}$1${txtrst}\n" 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

@ -1,210 +1,478 @@
#!/bin/sh #!/bin/sh
logit "" check_1() {
info "1 - Host Configuration" logit ""
id_1="1"
desc_1="Host Configuration"
check_1="$id_1 - $desc_1"
info "$check_1"
startsectionjson "$id_1" "$desc_1"
}
# 1.1 check_1_1() {
check_1_1="1.1 - Create a separate partition for containers" logit ""
grep /var/lib/docker /etc/fstab >/dev/null 2>&1 id_1_1="1.1"
if [ $? -eq 0 ]; then desc_1_1="General Configuration"
pass "$check_1_1" check_1_1="$id_1_1 - $desc_1_1"
else info "$check_1_1"
warn "$check_1_1" }
fi
# 1.2 # 1.1.1
check_1_2="1.2 - Use an updated Linux Kernel" check_1_1_1() {
kernel_version=$(uname -r | cut -d "-" -f 1) id_1_1_1="1.1.1"
do_version_check 3.10 "$kernel_version" desc_1_1_1="Ensure the container host has been Hardened (Not Scored)"
if [ $? -eq 11 ]; then check_1_1_1="$id_1_1_1 - $desc_1_1_1"
warn "$check_1_2" starttestjson "$id_1_1_1" "$desc_1_1_1"
else
pass "$check_1_2"
fi
# 1.5 totalChecks=$((totalChecks + 1))
check_1_5="1.5 - Remove all non-essential services from the host - Network" note "$check_1_1_1"
# Check for listening network services. resulttestjson "INFO"
listening_services=$(netstat -na | grep -v tcp6 | grep -v unix | grep -c LISTEN) currentScore=$((currentScore + 0))
if [ "$listening_services" -eq 0 ]; then }
warn "1.5 - Failed to get listening services for check: $check_1_5"
else # 1.1.2
if [ "$listening_services" -gt 5 ]; then check_1_1_2() {
warn "$check_1_5" id_1_1_2="1.1.2"
warn " * Host listening on: $listening_services ports" desc_1_1_2="Ensure that the version of Docker is up to date (Not Scored)"
check_1_1_2="$id_1_1_2 - $desc_1_1_2"
starttestjson "$id_1_1_2" "$desc_1_1_2"
totalChecks=$((totalChecks + 1))
docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \
| awk '{print $NF; exit}' | tr -d '[:alpha:]-,')
docker_current_version="$(date +%y.%m.0 -d @$(( $(date +%s) - 2592000)))"
do_version_check "$docker_current_version" "$docker_version"
if [ $? -eq 11 ]; then
info "$check_1_1_2"
info " * Using $docker_version, verify is it up to date as deemed necessary"
info " * Your operating system vendor may provide support and security maintenance for Docker"
resulttestjson "INFO" "Using $docker_version"
currentScore=$((currentScore + 0))
else else
pass "$check_1_5" 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
fi }
# 1.6 check_1_2() {
check_1_6="1.6 - Keep Docker up to date" logit ""
docker_version=$(docker version | grep 'Server version' | awk '{print $3}') id_1_2="1.2"
do_version_check 1.6.2 $docker_version desc_1_2="Linux Hosts Specific Configuration"
if [ $? -eq 11 ]; then check_1_2="$id_1_2 - $desc_1_2"
warn "$check_1_6" info "$check_1_2"
else }
pass "$check_1_6"
fi
# 1.7 # 1.2.1
check_1_7="1.7 - Only allow trusted users to control Docker daemon" check_1_2_1() {
docker_users=$(grep docker /etc/group) id_1_2_1="1.2.1"
info "$check_1_7" desc_1_2_1="Ensure a separate partition for containers has been created (Scored)"
for u in $docker_users; do check_1_2_1="$id_1_2_1 - $desc_1_2_1"
info " * $u" starttestjson "$id_1_2_1" "$desc_1_2_1"
done
# 1.8 totalChecks=$((totalChecks + 1))
check_1_8="1.8 - Audit docker daemon" docker_root_dir=$(docker info -f '{{ .DockerRootDir }}')
command -v auditctl >/dev/null 2>&1 if docker info | grep -q userns ; then
if [ $? -eq 0 ]; then docker_root_dir=$(readlink -f "$docker_root_dir/..")
auditctl -l | grep /usr/bin/docker >/dev/null 2>&1 fi
if [ $? -eq 0 ]; then
pass "$check_1_8" if mountpoint -q -- "$docker_root_dir" >/dev/null 2>&1; then
pass "$check_1_2_1"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else else
warn "$check_1_8" warn "$check_1_2_1"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else }
warn "1.8 - Failed to inspect: auditctl command not found."
fi
# 1.9 # 1.2.2
check_1_9="1.9 - Audit Docker files and directories - /var/lib/docker" check_1_2_2() {
command -v auditctl >/dev/null 2>&1 id_1_2_2="1.2.2"
if [ $? -eq 0 ]; then desc_1_2_2="Ensure only trusted users are allowed to control Docker daemon (Scored)"
auditctl -l | grep /var/lib/docker >/dev/null 2>&1 check_1_2_2="$id_1_2_2 - $desc_1_2_2"
if [ $? -eq 0 ]; then starttestjson "$id_1_2_2" "$desc_1_2_2"
pass "$check_1_9"
else
warn "$check_1_9"
fi
else
warn "1.9 - Failed to inspect: auditctl command not found."
fi
# 1.10 totalChecks=$((totalChecks + 1))
check_1_10="1.10 - Audit Docker files and directories - /etc/docker" if command -v getent >/dev/null 2>&1; then
command -v auditctl >/dev/null 2>&1 docker_users=$(getent group docker)
if [ $? -eq 0 ]; then
auditctl -l | grep /etc/docker >/dev/null 2>&1
if [ $? -eq 0 ]; then
pass "$check_1_10"
else else
warn "$check_1_10" docker_users=$(grep 'docker' /etc/group)
fi fi
else info "$check_1_2_2"
warn "1.10 - Failed to inspect: auditctl command not found." for u in $docker_users; do
fi info " * $u"
done
resulttestjson "INFO" "users" "$docker_users"
currentScore=$((currentScore + 0))
}
# 1.11 # 1.2.3
check_1_11="1.11 - Audit Docker files and directories - docker-registry.service" check_1_2_3() {
command -v auditctl >/dev/null 2>&1 id_1_2_3="1.2.3"
if [ $? -eq 0 ]; then desc_1_2_3="Ensure auditing is configured for the Docker daemon (Scored)"
auditctl -l | grep /usr/lib/systemd/system/docker-registry.service >/dev/null 2>&1 check_1_2_3="$id_1_2_3 - $desc_1_2_3"
if [ $? -eq 0 ]; then starttestjson "$id_1_2_3" "$desc_1_2_3"
pass "$check_1_11"
else
warn "$check_1_11"
fi
else
warn "1.11 - Failed to inspect: auditctl command not found."
fi
# 1.12 totalChecks=$((totalChecks + 1))
check_1_12="1.12 - Audit Docker files and directories - docker.service" file="/usr/bin/dockerd"
command -v auditctl >/dev/null 2>&1 if command -v auditctl >/dev/null 2>&1; then
if [ $? -eq 0 ]; then if auditctl -l | grep "$file" >/dev/null 2>&1; then
auditctl -l | grep /usr/lib/systemd/system/docker.service >/dev/null 2>&1 pass "$check_1_2_3"
if [ $? -eq 0 ]; then resulttestjson "PASS"
pass "$check_1_12" currentScore=$((currentScore + 1))
else
warn "$check_1_2_3"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
pass "$check_1_2_3"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else else
warn "$check_1_12" warn "$check_1_2_3"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi fi
else }
warn "1.12 - Failed to inspect: auditctl command not found."
fi
# 1.13 # 1.2.4
check_1_13="1.13 - Audit Docker files and directories - /var/run/docker.sock" check_1_2_4() {
command -v auditctl >/dev/null 2>&1 id_1_2_4="1.2.4"
if [ $? -eq 0 ]; then desc_1_2_4="Ensure auditing is configured for Docker files and directories - /var/lib/docker (Scored)"
auditctl -l | grep /var/run/docker.sock >/dev/null 2>&1 check_1_2_4="$id_1_2_4 - $desc_1_2_4"
if [ $? -eq 0 ]; then starttestjson "$id_1_2_4" "$desc_1_2_4"
pass "$check_1_13"
else
warn "$check_1_13"
fi
else
warn "1.13 - Failed to inspect: auditctl command not found."
fi
# 1.14 totalChecks=$((totalChecks + 1))
check_1_14="1.14 - Audit Docker files and directories - /etc/sysconfig/docker" directory="/var/lib/docker"
command -v auditctl >/dev/null 2>&1 if [ -d "$directory" ]; then
if [ $? -eq 0 ]; then if command -v auditctl >/dev/null 2>&1; then
auditctl -l | grep /etc/sysconfig/docker >/dev/null 2>&1 if auditctl -l | grep $directory >/dev/null 2>&1; then
if [ $? -eq 0 ]; then pass "$check_1_2_4"
pass "$check_1_14" resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_4"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
elif grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
pass "$check_1_2_4"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_4"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else else
warn "$check_1_14" info "$check_1_2_4"
info " * Directory not found"
resulttestjson "INFO" "Directory not found"
currentScore=$((currentScore + 0))
fi fi
else }
warn "1.14 - Failed to inspect: auditctl command not found."
fi
# 1.15 # 1.2.5
check_1_15="1.15 - Audit Docker files and directories - /etc/sysconfig/docker-network" check_1_2_5() {
command -v auditctl >/dev/null 2>&1 id_1_2_5="1.2.5"
if [ $? -eq 0 ]; then desc_1_2_5="Ensure auditing is configured for Docker files and directories - /etc/docker (Scored)"
auditctl -l | grep /etc/sysconfig/docker-network >/dev/null 2>&1 check_1_2_5="$id_1_2_5 - $desc_1_2_5"
if [ $? -eq 0 ]; then starttestjson "$id_1_2_5" "$desc_1_2_5"
pass "$check_1_15"
else
warn "$check_1_15"
fi
else
warn "1.15 - Failed to inspect: auditctl command not found."
fi
# 1.16 totalChecks=$((totalChecks + 1))
check_1_16="1.16 - Audit Docker files and directories - /etc/sysconfig/docker-registry" directory="/etc/docker"
command -v auditctl >/dev/null 2>&1 if [ -d "$directory" ]; then
if [ $? -eq 0 ]; then if command -v auditctl >/dev/null 2>&1; then
auditctl -l | grep /etc/sysconfig/docker-registry >/dev/null 2>&1 if auditctl -l | grep $directory >/dev/null 2>&1; then
if [ $? -eq 0 ]; then pass "$check_1_2_5"
pass "$check_1_16" resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_5"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
elif grep -s "$directory" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
pass "$check_1_2_5"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_5"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else else
warn "$check_1_16" info "$check_1_2_5"
fi info " * Directory not found"
else resulttestjson "INFO" "Directory not found"
warn "1.16 - Failed to inspect: auditctl command not found." currentScore=$((currentScore + 0))
fi fi
}
# 1.17 # 1.2.6
check_1_17="1.17 - Audit Docker files and directories - /etc/sysconfig/docker-storage" check_1_2_6() {
command -v auditctl >/dev/null 2>&1 id_1_2_6="1.2.6"
if [ $? -eq 0 ]; then desc_1_2_6="Ensure auditing is configured for Docker files and directories - docker.service (Scored)"
auditctl -l | grep /etc/sysconfig/docker-storage >/dev/null 2>&1 check_1_2_6="$id_1_2_6 - $desc_1_2_6"
if [ $? -eq 0 ]; then starttestjson "$id_1_2_6" "$desc_1_2_6"
pass "$check_1_17"
else
warn "$check_1_17"
fi
else
warn "1.17 - Failed to inspect: auditctl command not found."
fi
# 1.18 totalChecks=$((totalChecks + 1))
check_1_18="1.18 - Audit Docker files and directories - /etc/default/docker" file="$(get_service_file docker.service)"
command -v auditctl >/dev/null 2>&1 if [ -f "$file" ]; then
if [ $? -eq 0 ]; then if command -v auditctl >/dev/null 2>&1; then
auditctl -l | grep /etc/default/docker >/dev/null 2>&1 if auditctl -l | grep "$file" >/dev/null 2>&1; then
if [ $? -eq 0 ]; then pass "$check_1_2_6"
pass "$check_1_18" resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_6"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
pass "$check_1_2_6"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_6"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else else
warn "$check_1_18" info "$check_1_2_6"
info " * File not found"
resulttestjson "INFO" "File not found"
currentScore=$((currentScore + 0))
fi fi
else }
warn "1.18 - Failed to inspect: auditctl command not found."
fi # 1.2.7
check_1_2_7() {
id_1_2_7="1.2.7"
desc_1_2_7="Ensure auditing is configured for Docker files and directories - docker.socket (Scored)"
check_1_2_7="$id_1_2_7 - $desc_1_2_7"
starttestjson "$id_1_2_7" "$desc_1_2_7"
totalChecks=$((totalChecks + 1))
file="$(get_service_file docker.socket)"
if [ -e "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep "$file" >/dev/null 2>&1; then
pass "$check_1_2_7"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_7"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
pass "$check_1_2_7"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_7"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
info "$check_1_2_7"
info " * File not found"
resulttestjson "INFO" "File not found"
currentScore=$((currentScore + 0))
fi
}
# 1.2.8
check_1_2_8() {
id_1_2_8="1.2.8"
desc_1_2_8="Ensure auditing is configured for Docker files and directories - /etc/default/docker (Scored)"
check_1_2_8="$id_1_2_8 - $desc_1_2_8"
starttestjson "$id_1_2_8" "$desc_1_2_8"
totalChecks=$((totalChecks + 1))
file="/etc/default/docker"
if [ -f "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $file >/dev/null 2>&1; then
pass "$check_1_2_8"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_8"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
pass "$check_1_2_8"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_8"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
info "$check_1_2_8"
info " * File not found"
resulttestjson "INFO" "File not found"
currentScore=$((currentScore + 0))
fi
}
# 1.2.9
check_1_2_9() {
id_1_2_9="1.2.9"
desc_1_2_9="Ensure auditing is configured for Docker files and directories - /etc/sysconfig/docker (Scored)"
check_1_2_9="$id_1_2_9 - $desc_1_2_9"
starttestjson "$id_1_2_9" "$desc_1_2_9"
totalChecks=$((totalChecks + 1))
file="/etc/sysconfig/docker"
if [ -f "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $file >/dev/null 2>&1; then
pass "$check_1_2_9"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_9"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
pass "$check_1_2_9"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_9"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
info "$check_1_2_9"
info " * File not found"
resulttestjson "INFO" "File not found"
currentScore=$((currentScore + 0))
fi
}
# 1.2.10
check_1_2_10() {
id_1_2_10="1.2.10"
desc_1_2_10="Ensure auditing is configured for Docker files and directories - /etc/docker/daemon.json (Scored)"
check_1_2_10="$id_1_2_10 - $desc_1_2_10"
starttestjson "$id_1_2_10" "$desc_1_2_10"
totalChecks=$((totalChecks + 1))
file="/etc/docker/daemon.json"
if [ -f "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $file >/dev/null 2>&1; then
pass "$check_1_2_10"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_10"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
pass "$check_1_2_10"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_10"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
info "$check_1_2_10"
info " * File not found"
resulttestjson "INFO" "File not found"
currentScore=$((currentScore + 0))
fi
}
# 1.2.11
check_1_2_11() {
id_1_2_11="1.2.11"
desc_1_2_11="Ensure auditing is configured for Docker files and directories - /usr/bin/containerd (Scored)"
check_1_2_11="$id_1_2_11 - $desc_1_2_11"
starttestjson "$id_1_2_11" "$desc_1_2_11"
totalChecks=$((totalChecks + 1))
file="/usr/bin/containerd"
if [ -f "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $file >/dev/null 2>&1; then
pass "$check_1_2_11"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_11"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
pass "$check_1_2_11"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_11"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
info "$check_1_2_11"
info " * File not found"
resulttestjson "INFO" "File not found"
currentScore=$((currentScore + 0))
fi
}
# 1.2.12
check_1_2_12() {
id_1_2_12="1.2.12"
desc_1_2_12="Ensure auditing is configured for Docker files and directories - /usr/sbin/runc (Scored)"
check_1_2_12="$id_1_2_12 - $desc_1_2_12"
starttestjson "$id_1_2_12" "$desc_1_2_12"
totalChecks=$((totalChecks + 1))
file="/usr/sbin/runc"
if [ -f "$file" ]; then
if command -v auditctl >/dev/null 2>&1; then
if auditctl -l | grep $file >/dev/null 2>&1; then
pass "$check_1_2_12"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_12"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
elif grep -s "$file" "$auditrules" | grep "^[^#;]" 2>/dev/null 1>&2; then
pass "$check_1_2_12"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_1_2_12"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
info "$check_1_2_12"
info " * File not found"
resulttestjson "INFO" "File not found"
currentScore=$((currentScore + 0))
fi
}
check_1_end() {
endsectionjson
}

View file

@ -1,105 +1,442 @@
#!/bin/sh #!/bin/sh
logit "\n" check_2() {
info "2 - Docker Daemon Configuration" logit "\n"
id_2="2"
desc_2="Docker daemon configuration"
check_2="$id_2 - $desc_2"
info "$check_2"
startsectionjson "$id_2" "$desc_2"
}
# 2.1 # 2.1
check_2_1="2.1 - Do not use lxc execution driver" check_2_1() {
pgrep -lf docker | grep lxc >/dev/null 2>&1 id_2_1="2.1"
if [ $? -eq 0 ]; then desc_2_1="Ensure network traffic is restricted between containers on the default bridge (Scored)"
warn "$check_2_1" check_2_1="$id_2_1 - $desc_2_1"
else starttestjson "$id_2_1" "$desc_2_1"
pass "$check_2_1"
fi totalChecks=$((totalChecks + 1))
if get_docker_effective_command_line_args '--icc' | grep false >/dev/null 2>&1; then
pass "$check_2_1"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
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
}
# 2.2 # 2.2
check_2_2="2.2 - Restrict network traffic between containers" check_2_2() {
pgrep -lf docker | grep "icc=false" >/dev/null 2>&1 id_2_2="2.2"
if [ $? -eq 0 ]; then desc_2_2="Ensure the logging level is set to 'info' (Scored)"
pass "$check_2_2" check_2_2="$id_2_2 - $desc_2_2"
else starttestjson "$id_2_2" "$desc_2_2"
warn "$check_2_2"
fi totalChecks=$((totalChecks + 1))
if get_docker_configuration_file_args 'log-level' >/dev/null 2>&1; then
if get_docker_configuration_file_args 'log-level' | grep info >/dev/null 2>&1; then
pass "$check_2_2"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
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
elif get_docker_effective_command_line_args '-l'; then
if get_docker_effective_command_line_args '-l' | grep "info" >/dev/null 2>&1; then
pass "$check_2_2"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_2"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
pass "$check_2_2"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 2.3 # 2.3
check_2_3="2.3 - Set the logging level" check_2_3() {
pgrep -lf docker | grep "log-level=\"debug\"" >/dev/null 2>&1 id_2_3="2.3"
if [ $? -eq 0 ]; then desc_2_3="Ensure Docker is allowed to make changes to iptables (Scored)"
warn "$check_2_3" check_2_3="$id_2_3 - $desc_2_3"
else starttestjson "$id_2_3" "$desc_2_3"
pass "$check_2_3"
fi totalChecks=$((totalChecks + 1))
if get_docker_effective_command_line_args '--iptables' | grep "false" >/dev/null 2>&1; then
warn "$check_2_3"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
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
}
# 2.4 # 2.4
check_2_4="2.4 - Allow Docker to make changes to iptables" check_2_4() {
pgrep -lf docker | grep "iptables=false" >/dev/null 2>&1 id_2_4="2.4"
if [ $? -eq 0 ]; then desc_2_4="Ensure insecure registries are not used (Scored)"
warn "$check_2_4" check_2_4="$id_2_4 - $desc_2_4"
else starttestjson "$id_2_4" "$desc_2_4"
pass "$check_2_4"
fi totalChecks=$((totalChecks + 1))
if get_docker_effective_command_line_args '--insecure-registry' | grep "insecure-registry" >/dev/null 2>&1; then
warn "$check_2_4"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
elif ! [ -z "$(get_docker_configuration_file_args 'insecure-registries')" ]; then
if get_docker_configuration_file_args 'insecure-registries' | grep '\[]' >/dev/null 2>&1; then
pass "$check_2_4"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_4"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
pass "$check_2_4"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 2.5 # 2.5
check_2_5="2.5 - Do not use insecure registries" check_2_5() {
pgrep -lf docker | grep "insecure-registry" >/dev/null 2>&1 id_2_5="2.5"
if [ $? -eq 0 ]; then desc_2_5="Ensure aufs storage driver is not used (Scored)"
warn "$check_2_5" check_2_5="$id_2_5 - $desc_2_5"
else starttestjson "$id_2_5" "$desc_2_5"
pass "$check_2_5"
fi totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "^\sStorage Driver:\s*aufs\s*$" >/dev/null 2>&1; then
warn "$check_2_5"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
else
pass "$check_2_5"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 2.6 # 2.6
check_2_6="2.6 - Setup a local registry mirror" check_2_6() {
pgrep -lf docker | grep "registry-mirror" >/dev/null 2>&1 id_2_6="2.6"
if [ $? -eq 0 ]; then desc_2_6="Ensure TLS authentication for Docker daemon is configured (Scored)"
pass "$check_2_6" check_2_6="$id_2_6 - $desc_2_6"
else starttestjson "$id_2_6" "$desc_2_6"
info "$check_2_6"
info " * No local registry currently configured" totalChecks=$((totalChecks + 1))
fi if [ $(get_docker_configuration_file_args 'tcp://') ] || \
[ $(get_docker_cumulative_command_line_args '-H' | grep -vE '(unix|fd)://') >/dev/null 2>&1 ]; then
if [ $(get_docker_configuration_file_args '"tlsverify":' | grep 'true') ] || \
[ $(get_docker_cumulative_command_line_args '--tlsverify' | grep 'tlsverify') >/dev/null 2>&1 ]; then
pass "$check_2_6"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
elif [ $(get_docker_configuration_file_args '"tls":' | grep 'true') ] || \
[ $(get_docker_cumulative_command_line_args '--tls' | grep 'tls$') >/dev/null 2>&1 ]; then
warn "$check_2_6"
warn " * Docker daemon currently listening on TCP with TLS, but no verification"
resulttestjson "WARN" "Docker daemon currently listening on TCP with TLS, but no verification"
currentScore=$((currentScore - 1))
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
else
info "$check_2_6"
info " * Docker daemon not listening on TCP"
resulttestjson "INFO" "Docker daemon not listening on TCP"
currentScore=$((currentScore + 0))
fi
}
# 2.7 # 2.7
check_2_7="2.7 - Do not use the aufs storage driver" check_2_7() {
docker info 2>/dev/null | grep -e "^Storage Driver:\s*aufs\s*$" >/dev/null 2>&1 id_2_7="2.7"
if [ $? -eq 0 ]; then desc_2_7="Ensure the default ulimit is configured appropriately (Not Scored)"
warn "$check_2_7" check_2_7="$id_2_7 - $desc_2_7"
else starttestjson "$id_2_7" "$desc_2_7"
pass "$check_2_7"
fi totalChecks=$((totalChecks + 1))
if get_docker_configuration_file_args 'default-ulimit' | grep -v '{}' >/dev/null 2>&1; then
pass "$check_2_7"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
elif get_docker_effective_command_line_args '--default-ulimit' | grep "default-ulimit" >/dev/null 2>&1; then
pass "$check_2_7"
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
}
# 2.8 # 2.8
check_2_8="2.8 - Do not bind Docker to another IP/Port or a Unix socket" check_2_8() {
pgrep -lf docker | grep "\-H" >/dev/null 2>&1 id_2_8="2.8"
if [ $? -eq 0 ]; then desc_2_8="Enable user namespace support (Scored)"
info "$check_2_8" check_2_8="$id_2_8 - $desc_2_8"
info " * Docker daemon running with -H" starttestjson "$id_2_8" "$desc_2_8"
else
pass "$check_2_8" totalChecks=$((totalChecks + 1))
fi if get_docker_configuration_file_args 'userns-remap' | grep -v '""'; then
pass "$check_2_8"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
elif get_docker_effective_command_line_args '--userns-remap' | grep "userns-remap" >/dev/null 2>&1; then
pass "$check_2_8"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_8"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
}
# 2.9 # 2.9
check_2_9="2.9 - Configure TLS authentication for Docker daemon" check_2_9() {
pgrep -lf docker | grep "tcp://" >/dev/null 2>&1 id_2_9="2.9"
if [ $? -eq 0 ]; then desc_2_9="Ensure the default cgroup usage has been confirmed (Scored)"
pgrep -lf docker | grep "tlsverify" | grep "tlskey" >/dev/null 2>&1 check_2_9="$id_2_9 - $desc_2_9"
if [ $? -eq 0 ]; then starttestjson "$id_2_9" "$desc_2_9"
pass "$check_2_9"
info " * Docker daemon currently listening on TCP" totalChecks=$((totalChecks + 1))
else if get_docker_configuration_file_args 'cgroup-parent' | grep -v ''; then
warn "$check_2_9" warn "$check_2_9"
warn " * Docker daemon currently listening on TCP without --tlsverify" info " * Confirm cgroup usage"
resulttestjson "WARN" "Confirm cgroup usage"
currentScore=$((currentScore + 0))
elif get_docker_effective_command_line_args '--cgroup-parent' | grep "cgroup-parent" >/dev/null 2>&1; then
warn "$check_2_9"
info " * Confirm cgroup usage"
resulttestjson "WARN" "Confirm cgroup usage"
currentScore=$((currentScore + 0))
else
pass "$check_2_9"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi fi
else }
info "$check_2_9"
info " * Docker daemon not listening on TCP"
fi
# 2.10 # 2.10
check_2_10="2.10 - Set default ulimit as appropriate" check_2_10() {
pgrep -lf docker | grep "default-ulimit" >/dev/null 2>&1 id_2_10="2.10"
if [ $? -eq 0 ]; then desc_2_10="Ensure base device size is not changed until needed (Scored)"
pass "$check_2_10" check_2_10="$id_2_10 - $desc_2_10"
else starttestjson "$id_2_10" "$desc_2_10"
info "$check_2_10"
info " * Default ulimit doesn't appear to be set" totalChecks=$((totalChecks + 1))
fi if get_docker_configuration_file_args 'storage-opts' | grep "dm.basesize" >/dev/null 2>&1; then
warn "$check_2_10"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
elif get_docker_effective_command_line_args '--storage-opt' | grep "dm.basesize" >/dev/null 2>&1; then
warn "$check_2_10"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
else
pass "$check_2_10"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 2.11
check_2_11() {
id_2_11="2.11"
desc_2_11="Ensure that authorization for Docker client commands is enabled (Scored)"
check_2_11="$id_2_11 - $desc_2_11"
starttestjson "$id_2_11" "$desc_2_11"
totalChecks=$((totalChecks + 1))
if get_docker_configuration_file_args 'authorization-plugins' | grep -v '\[]'; then
pass "$check_2_11"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
elif get_docker_effective_command_line_args '--authorization-plugin' | grep "authorization-plugin" >/dev/null 2>&1; then
pass "$check_2_11"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_11"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
}
# 2.12
check_2_12() {
id_2_12="2.12"
desc_2_12="Ensure centralized and remote logging is configured (Scored)"
check_2_12="$id_2_12 - $desc_2_12"
starttestjson "$id_2_12" "$desc_2_12"
totalChecks=$((totalChecks + 1))
if docker info --format '{{ .LoggingDriver }}' | grep 'json-file' >/dev/null 2>&1; then
warn "$check_2_12"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
else
pass "$check_2_12"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 2.13
check_2_13() {
id_2_13="2.13"
desc_2_13="Ensure live restore is enabled (Scored)"
check_2_13="$id_2_13 - $desc_2_13"
starttestjson "$id_2_13" "$desc_2_13"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Live Restore Enabled:\s*true\s*" >/dev/null 2>&1; then
pass "$check_2_13"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then
pass "$check_2_13 (Incompatible with swarm mode)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
elif get_docker_effective_command_line_args '--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
}
# 2.14
check_2_14() {
id_2_14="2.14"
desc_2_14="Ensure Userland Proxy is Disabled (Scored)"
check_2_14="$id_2_14 - $desc_2_14"
starttestjson "$id_2_14" "$desc_2_14"
totalChecks=$((totalChecks + 1))
if get_docker_configuration_file_args 'userland-proxy' | grep false >/dev/null 2>&1; then
pass "$check_2_14"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
elif get_docker_effective_command_line_args '--userland-proxy=false' 2>/dev/null | grep "userland-proxy=false" >/dev/null 2>&1; then
pass "$check_2_14"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_14"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
}
# 2.15
check_2_15() {
id_2_15="2.15"
desc_2_15="Ensure that a daemon-wide custom seccomp profile is applied if appropriate (Not Scored)"
check_2_15="$id_2_15 - $desc_2_15"
starttestjson "$id_2_15" "$desc_2_15"
totalChecks=$((totalChecks + 1))
if docker info --format '{{ .SecurityOptions }}' | grep 'name=seccomp,profile=default' 2>/dev/null 1>&2; then
pass "$check_2_15"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
info "$check_2_15"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
fi
}
# 2.16
check_2_16() {
docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \
| awk '{print $NF; exit}' | tr -d '[:alpha:]-,.' | cut -c 1-4)
id_2_16="2.16"
desc_2_16="Ensure that experimental features are not implemented in production (Scored)"
check_2_16="$id_2_16 - $desc_2_16"
starttestjson "$id_2_16" "$desc_2_16"
totalChecks=$((totalChecks + 1))
if [ "$docker_version" -le 1903 ]; then
if docker version -f '{{.Server.Experimental}}' | grep false 2>/dev/null 1>&2; then
pass "$check_2_16"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_16"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
desc_2_16="$desc_2_16 (Deprecated)"
check_2_16="$id_2_16 - $desc_2_16"
info "$desc_2_16"
resulttestjson "INFO"
fi
}
# 2.17
check_2_17() {
id_2_17="2.17"
desc_2_17="Ensure containers are restricted from acquiring new privileges (Scored)"
check_2_17="$id_2_17 - $desc_2_17"
starttestjson "$id_2_17" "$desc_2_17"
totalChecks=$((totalChecks + 1))
if get_docker_effective_command_line_args '--no-new-privileges' | grep "no-new-privileges" >/dev/null 2>&1; then
pass "$check_2_17"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
elif get_docker_configuration_file_args 'no-new-privileges' | grep true >/dev/null 2>&1; then
pass "$check_2_17"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_2_17"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
}
check_2_end() {
endsectionjson
}

File diff suppressed because it is too large Load diff

View file

@ -1,39 +1,266 @@
#!/bin/sh #!/bin/sh
logit "\n" check_4() {
info "4 - Container Images and Build Files" logit "\n"
id_4="4"
desc_4="Container Images and Build File"
check_4="$id_4 - $desc_4"
info "$check_4"
startsectionjson "$id_4" "$desc_4"
}
# 4.1 # 4.1
check_4_1="4.1 - Create a user for the container" check_4_1() {
id_4_1="4.1"
desc_4_1="Ensure that a user for the container has been created (Scored)"
check_4_1="$id_4_1 - $desc_4_1"
starttestjson "$id_4_1" "$desc_4_1"
# If container_users is empty, there are no running containers totalChecks=$((totalChecks + 1))
if [ -z "$containers" ]; then
info "$check_4_1" # If container_users is empty, there are no running containers
info " * No containers running" if [ -z "$containers" ]; then
else info "$check_4_1"
# We have some containers running, set failure flag to 0. Check for Users. info " * No containers running"
resulttestjson "INFO" "No containers running"
currentScore=$((currentScore + 0))
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
# Make the loop separator go back to space
set +f; unset IFS
}
# 4.2
check_4_2() {
id_4_2="4.2"
desc_4_2="Ensure that containers use only trusted base images (Not Scored)"
check_4_2="$id_4_2 - $desc_4_2"
starttestjson "$id_4_2" "$desc_4_2"
totalChecks=$((totalChecks + 1))
note "$check_4_2"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
}
# 4.3
check_4_3() {
id_4_3="4.3"
desc_4_3="Ensure that unnecessary packages are not installed in the container (Not Scored)"
check_4_3="$id_4_3 - $desc_4_3"
starttestjson "$id_4_3" "$desc_4_3"
totalChecks=$((totalChecks + 1))
note "$check_4_3"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
}
# 4.4
check_4_4() {
id_4_4="4.4"
desc_4_4="Ensure images are scanned and rebuilt to include security patches (Not Scored)"
check_4_4="$id_4_4 - $desc_4_4"
starttestjson "$id_4_4" "$desc_4_4"
totalChecks=$((totalChecks + 1))
note "$check_4_4"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
}
# 4.5
check_4_5() {
id_4_5="4.5"
desc_4_5="Ensure Content trust for Docker is Enabled (Scored)"
check_4_5="$id_4_5 - $desc_4_5"
starttestjson "$id_4_5" "$desc_4_5"
totalChecks=$((totalChecks + 1))
if [ "x$DOCKER_CONTENT_TRUST" = "x1" ]; then
pass "$check_4_5"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_4_5"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
}
# 4.6
check_4_6() {
id_4_6="4.6"
desc_4_6="Ensure that HEALTHCHECK instructions have been added to container images (Scored)"
check_4_6="$id_4_6 - $desc_4_6"
starttestjson "$id_4_6" "$desc_4_6"
totalChecks=$((totalChecks + 1))
fail=0 fail=0
# Make the loop separator be a new-line in POSIX compliant fashion no_health_images=""
set -f; IFS=$' for img in $images; do
' if docker inspect --format='{{.Config.Healthcheck}}' "$img" 2>/dev/null | grep -e "<nil>" >/dev/null 2>&1; then
for c in $containers; do
user=$(docker inspect --format 'User={{.Config.User}}' "$c")
if [ "$user" = "User=" -o "$user" = "User=[]" -o "$user" = "User=<no value>" ]; then
# If it's the first container, fail the test
if [ $fail -eq 0 ]; then if [ $fail -eq 0 ]; then
warn "$check_4_1"
warn " * Running as root: $c"
fail=1 fail=1
warn "$check_4_6"
fi
imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null)
if ! [ "$imgName" = '[]' ]; then
warn " * No Healthcheck found: $imgName"
no_health_images="$no_health_images $imgName"
else else
warn " * Running as root: $c" warn " * No Healthcheck found: $img"
no_health_images="$no_health_images $img"
fi fi
fi fi
done done
# We went through all the containers and found none running as root
if [ $fail -eq 0 ]; then if [ $fail -eq 0 ]; then
pass "$check_4_1" pass "$check_4_6"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
resulttestjson "WARN" "Images w/o HEALTHCHECK" "$no_health_images"
currentScore=$((currentScore - 1))
fi fi
fi }
# Make the loop separator go back to space
set +f; unset IFS # 4.7
check_4_7() {
id_4_7="4.7"
desc_4_7="Ensure update instructions are not use alone in the Dockerfile (Not Scored)"
check_4_7="$id_4_7 - $desc_4_7"
starttestjson "$id_4_7" "$desc_4_7"
totalChecks=$((totalChecks + 1))
fail=0
update_images=""
for img in $images; do
if docker history "$img" 2>/dev/null | grep -e "update" >/dev/null 2>&1; then
if [ $fail -eq 0 ]; then
fail=1
info "$check_4_7"
fi
imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null)
if ! [ "$imgName" = '[]' ]; then
info " * Update instruction found: $imgName"
update_images="$update_images $imgName"
fi
fi
done
if [ $fail -eq 0 ]; then
pass "$check_4_7"
resulttestjson "PASS"
currentScore=$((currentScore + 0))
else
resulttestjson "INFO" "Update instructions found" "$update_images"
currentScore=$((currentScore + 0))
fi
}
# 4.8
check_4_8() {
id_4_8="4.8"
desc_4_8="Ensure setuid and setgid permissions are removed (Not Scored)"
check_4_8="$id_4_8 - $desc_4_8"
starttestjson "$id_4_8" "$desc_4_8"
totalChecks=$((totalChecks + 1))
note "$check_4_8"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
}
# 4.9
check_4_9() {
id_4_9="4.9"
desc_4_9="Ensure that COPY is used instead of ADD in Dockerfiles (Not Scored)"
check_4_9="$id_4_9 - $desc_4_9"
starttestjson "$id_4_9" "$desc_4_9"
totalChecks=$((totalChecks + 1))
fail=0
add_images=""
for img in $images; do
if docker history --format "{{ .CreatedBy }}" --no-trunc "$img" | \
sed '$d' | grep -q 'ADD'; then
if [ $fail -eq 0 ]; then
fail=1
info "$check_4_9"
fi
imgName=$(docker inspect --format='{{.RepoTags}}' "$img" 2>/dev/null)
if ! [ "$imgName" = '[]' ]; then
info " * ADD in image history: $imgName"
add_images="$add_images $imgName"
fi
currentScore=$((currentScore + 0))
fi
done
if [ $fail -eq 0 ]; then
pass "$check_4_9"
resulttestjson "PASS"
currentScore=$((currentScore + 0))
else
resulttestjson "INFO" "Images using ADD" "$add_images"
fi
}
# 4.10
check_4_10() {
id_4_10="4.10"
desc_4_10="Ensure secrets are not stored in Dockerfiles (Not Scored)"
check_4_10="$id_4_10 - $desc_4_10"
starttestjson "$id_4_10" "$desc_4_10"
totalChecks=$((totalChecks + 1))
note "$check_4_10"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
}
# 4.11
check_4_11() {
id_4_11="4.11"
desc_4_11="Ensure only verified packages are are installed (Not Scored)"
check_4_11="$id_4_11 - $desc_4_11"
starttestjson "$id_4_11" "$desc_4_11"
totalChecks=$((totalChecks + 1))
note "$check_4_11"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
}
check_4_end() {
endsectionjson
}

File diff suppressed because it is too large Load diff

View file

@ -1,71 +1,64 @@
#!/bin/sh #!/bin/sh
logit "\n" check_6() {
info "6 - Docker Security Operations" logit "\n"
id_6="6"
desc_6="Docker Security Operations"
check_6="$id_6 - $desc_6"
info "$check_6"
startsectionjson "$id_6" "$desc_6"
}
# 6.5 # 6.1
check_6_5="6.5 - Use a centralized and remote log collection service" check_6_1() {
id_6_1="6.1"
desc_6_1="Ensure that image sprawl is avoided (Not Scored)"
check_6_1="$id_6_1 - $desc_6_1"
starttestjson "$id_6_1" "$desc_6_1"
# If containers is empty, there are no running containers totalChecks=$((totalChecks + 1))
if [ -z "$containers" ]; then images=$(docker images -q | sort -u | wc -l | awk '{print $1}')
info "$check_6_5" active_images=0
info " * No containers running"
else
fail=0
set -f; IFS=$'
'
for c in $containers; do
volumes=$(docker inspect --format '{{ .Volumes }}' "$c")
if [ "$volumes" = "map[]" ]; then for c in $(docker inspect --format "{{.Image}}" $(docker ps -qa) 2>/dev/null); do
# If it's the first container, fail the test if docker images --no-trunc -a | grep "$c" > /dev/null ; then
if [ $fail -eq 0 ]; then active_images=$(( active_images += 1 ))
info "$check_6_5"
info " * Container has no volumes, ensure centralized logging is enabled : $c"
fail=1
else
info " * Container has no volumes, ensure centralized logging is enabled : $c"
fi
fi fi
done done
# Only alert if there are no volumes. If there are volumes, can't know if they
# are used for logs
fi
# Make the loop separator go back to space
set +f; unset IFS
# 6.6 info "$check_6_1"
check_6_6="6.6 - Avoid image sprawl" info " * There are currently: $images images"
images=$(docker images -q | wc -l | awk '{print $1}')
active_images=0
for c in $(docker inspect -f "{{.Image}}" $(docker ps -qa)); do if [ "$active_images" -lt "$((images / 2))" ]; then
if docker images --no-trunc -a | grep $c > /dev/null ; then info " * Only $active_images out of $images are in use"
active_images=$(( active_images += 1 ))
fi fi
done resulttestjson "INFO" "$active_images active/$images in use"
currentScore=$((currentScore + 0))
}
if [ "$images" -gt 100 ]; then # 6.2
warn "$check_6_6" check_6_2() {
warn " * There are currently: $images images" id_6_2="6.2"
else desc_6_2="Ensure that container sprawl is avoided (Not Scored)"
info "$check_6_6" check_6_2="$id_6_2 - $desc_6_2"
info " * There are currently: $images images" starttestjson "$id_6_2" "$desc_6_2"
fi
if [ "$active_images" -lt "$((images / 2))" ]; then totalChecks=$((totalChecks + 1))
warn " * Only $active_images out of $images are in use" total_containers=$(docker info 2>/dev/null | grep "Containers" | awk '{print $2}')
fi running_containers=$(docker ps -q | wc -l | awk '{print $1}')
diff="$((total_containers - running_containers))"
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"
resulttestjson "INFO" "$total_containers total/$running_containers running"
else
info "$check_6_2"
info " * There are currently a total of $total_containers containers, with $running_containers of them currently running"
resulttestjson "INFO" "$total_containers total/$running_containers running"
fi
currentScore=$((currentScore + 0))
}
# 6.7 check_6_end() {
check_6_7="6.7 - Avoid container sprawl" endsectionjson
total_containers=$(docker info 2>/dev/null | grep "Containers" | awk '{print $2}') }
running_containers=$(docker ps -q | wc -l | awk '{print $1}')
diff="$(($total_containers - $running_containers))"
if [ "$diff" -gt 25 ]; then
warn "$check_6_7"
warn " * There are currently a total of $total_containers containers, with only $running_containers of them currently running"
else
info "$check_6_7"
info " * There are currently a total of $total_containers containers, with $running_containers of them currently running"
fi

View file

@ -0,0 +1,250 @@
#!/bin/sh
check_7() {
logit "\n"
id_7="7"
desc_7="Docker Swarm Configuration"
check_7="$id_7 - $desc_7"
info "$check_7"
startsectionjson "$id_7" "$desc_7"
}
# 7.1
check_7_1() {
id_7_1="7.1"
desc_7_1="Ensure swarm mode is not Enabled, if not needed (Scored)"
check_7_1="$id_7_1 - $desc_7_1"
starttestjson "$id_7_1" "$desc_7_1"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:*\sinactive\s*" >/dev/null 2>&1; then
pass "$check_7_1"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_7_1"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
}
# 7.2
check_7_2() {
id_7_2="7.2"
desc_7_2="Ensure that the minimum number of manager nodes have been created in a swarm (Scored)"
check_7_2="$id_7_2 - $desc_7_2"
starttestjson "$id_7_2" "$desc_7_2"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then
managernodes=$(docker node ls | grep -c "Leader")
if [ "$managernodes" -eq 1 ]; then
pass "$check_7_2"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_7_2"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
pass "$check_7_2 (Swarm mode not enabled)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 7.3
check_7_3() {
id_7_3="7.3"
desc_7_3="Ensure that swarm services are bound to a specific host interface (Scored)"
check_7_3="$id_7_3 - $desc_7_3"
starttestjson "$id_7_3" "$desc_7_3"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:*\sactive\s*" >/dev/null 2>&1; then
$netbin -lnt | grep -e '\[::]:2377 ' -e ':::2377' -e '*:2377 ' -e ' 0\.0\.0\.0:2377 ' >/dev/null 2>&1
if [ $? -eq 1 ]; then
pass "$check_7_3"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_7_3"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
pass "$check_7_3 (Swarm mode not enabled)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 7.4
check_7_4() {
id_7_4="7.4"
desc_7_4="Ensure that all Docker swarm overlay networks are encrypted (Scored)"
check_7_4="$id_7_4 - $desc_7_4"
starttestjson "$id_7_4" "$desc_7_4"
totalChecks=$((totalChecks + 1))
fail=0
unencrypted_networks=""
for encnet in $(docker network ls --filter driver=overlay --quiet); do
if docker network inspect --format '{{.Name}} {{ .Options }}' "$encnet" | \
grep -v 'encrypted:' 2>/dev/null 1>&2; then
# If it's the first container, fail the test
if [ $fail -eq 0 ]; then
warn "$check_7_4"
fail=1
fi
warn " * Unencrypted overlay network: $(docker network inspect --format '{{ .Name }} ({{ .Scope }})' "$encnet")"
unencrypted_networks="$unencrypted_networks $(docker network inspect --format '{{ .Name }} ({{ .Scope }})' "$encnet")"
fi
done
# We went through all the networks and found none that are unencrypted
if [ $fail -eq 0 ]; then
pass "$check_7_4"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
resulttestjson "WARN" "Unencrypted overlay networks:" "$unencrypted_networks"
currentScore=$((currentScore - 1))
fi
}
# 7.5
check_7_5() {
id_7_5="7.5"
desc_7_5="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"
starttestjson "$id_7_5" "$desc_7_5"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then
if [ "$(docker secret ls -q | wc -l)" -ge 1 ]; then
pass "$check_7_5"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
info "$check_7_5"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
fi
else
pass "$check_7_5 (Swarm mode not enabled)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 7.6
check_7_6() {
id_7_6="7.6"
desc_7_6="Ensure that swarm manager is run in auto-lock mode (Scored)"
check_7_6="$id_7_6 - $desc_7_6"
starttestjson "$id_7_6" "$desc_7_6"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then
if ! docker swarm unlock-key 2>/dev/null | grep 'SWMKEY' 2>/dev/null 1>&2; then
warn "$check_7_6"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
else
pass "$check_7_6"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
else
pass "$check_7_6 (Swarm mode not enabled)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 7.7
check_7_7() {
id_7_7="7.7"
desc_7_7="Ensure that the swarm manager auto-lock key is rotated periodically (Not Scored)"
check_7_7="$id_7_7 - $desc_7_7"
starttestjson "$id_7_7" "$desc_7_7"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then
note "$check_7_7"
resulttestjson "NOTE"
currentScore=$((currentScore + 0))
else
pass "$check_7_7 (Swarm mode not enabled)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 7.8
check_7_8() {
id_7_8="7.8"
desc_7_8="Ensure that node certificates are rotated as appropriate (Not Scored)"
check_7_8="$id_7_8 - $desc_7_8"
starttestjson "$id_7_8" "$desc_7_8"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then
if docker info 2>/dev/null | grep "Expiry Duration: 2 days"; then
pass "$check_7_8"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
info "$check_7_8"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
fi
else
pass "$check_7_8 (Swarm mode not enabled)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 7.9
check_7_9() {
id_7_9="7.9"
desc_7_9="Ensure that CA certificates are rotated as appropriate (Not Scored)"
check_7_9="$id_7_9 - $desc_7_9"
starttestjson "$id_7_9" "$desc_7_9"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then
info "$check_7_9"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
else
pass "$check_7_9 (Swarm mode not enabled)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
# 7.10
check_7_10() {
id_7_10="7.10"
desc_7_10="Ensure that management plane traffic is separated from data plane traffic (Not Scored)"
check_7_10="$id_7_10 - $desc_7_10"
starttestjson "$id_7_10" "$desc_7_10"
totalChecks=$((totalChecks + 1))
if docker info 2>/dev/null | grep -e "Swarm:\s*active\s*" >/dev/null 2>&1; then
info "$check_7_10"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
else
pass "$check_7_10 (Swarm mode not enabled)"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
fi
}
check_7_end() {
endsectionjson
}

View file

@ -0,0 +1,181 @@
#!/bin/sh
check_8() {
logit "\n"
id_8="8"
desc_8="Docker Enterprise Configuration"
check_8="$id_8 - $desc_8"
info "$check_8"
startsectionjson "$id_8" "$desc_8"
}
check_product_license() {
if docker version | grep -Eqi '^Server.*Community$|Version.*-ce$'; then
info " * Community Engine license, skipping section 8"
enterprise_license=0
else
enterprise_license=1
fi
}
check_8_1() {
if [ "$enterprise_license" -ne 1 ]; then
return
fi
id_8_1="8.1"
desc_8_1="Universal Control Plane Configuration"
check_8_1="$id_8_1 - $desc_8_1"
info "$check_8_1"
}
# 8.1.1
check_8_1_1() {
if [ "$enterprise_license" -ne 1 ]; then
return
fi
id_8_1_1="8.1.1"
desc_8_1_1="Configure the LDAP authentication service (Scored)"
check_8_1_1="$id_8_1_1 - $desc_8_1_1"
starttestjson "$id_8_1_1" "$desc_8_1_1"
totalChecks=$((totalChecks + 1))
note "$check_8_1_1"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
}
# 8.1.2
check_8_1_2() {
if [ "$enterprise_license" -ne 1 ]; then
return
fi
id_8_1_2="8.1.2"
desc_8_1_2="Use external certificates (Scored)"
check_8_1_2="$id_8_1_2 - $desc_8_1_2"
starttestjson "$id_8_1_2" "$desc_8_1_2"
totalChecks=$((totalChecks + 1))
note "$check_8_1_2"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
}
# 8.1.3
check_8_1_3() {
if [ "$enterprise_license" -ne 1 ]; then
return
fi
id_8_1_3="8.1.3"
desc_8_1_3="Enforce the use of client certificate bundles for unprivileged users (Not Scored)"
check_8_1_3="$id_8_1_3 - $desc_8_1_3"
starttestjson "$id_8_1_3" "$desc_8_1_3"
totalChecks=$((totalChecks + 1))
note "$check_8_1_3"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
}
# 8.1.4
check_8_1_4() {
if [ "$enterprise_license" -ne 1 ]; then
return
fi
id_8_1_4="8.1.4"
desc_8_1_4="Configure applicable cluster role-based access control policies (Not Scored)"
check_8_1_4="$id_8_1_4 - $desc_8_1_4"
starttestjson "$id_8_1_4" "$desc_8_1_4"
totalChecks=$((totalChecks + 1))
note "$check_8_1_4"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
}
# 8.1.5
check_8_1_5() {
if [ "$enterprise_license" -ne 1 ]; then
return
fi
id_8_1_5="8.1.5"
desc_8_1_5="Enable signed image enforcement (Scored)"
check_8_1_5="$id_8_1_5 - $desc_8_1_5"
starttestjson "$id_8_1_5" "$desc_8_1_5"
totalChecks=$((totalChecks + 1))
note "$check_8_1_5"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
}
# 8.1.6
check_8_1_6() {
if [ "$enterprise_license" -ne 1 ]; then
return
fi
id_8_1_6="8.1.6"
desc_8_1_6="Set the Per-User Session Limit to a value of '3' or lower (Scored)"
check_8_1_6="$id_8_1_6 - $desc_8_1_6"
starttestjson "$id_8_1_6" "$desc_8_1_6"
totalChecks=$((totalChecks + 1))
note "$check_8_1_6"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
}
# 8.1.7
check_8_1_7() {
if [ "$enterprise_license" -ne 1 ]; then
return
fi
id_8_1_7="8.1.7"
desc_8_1_7="Set the 'Lifetime Minutes' and 'Renewal Threshold Minutes' values to '15' or lower and '0' respectively (Scored)"
check_8_1_7="$id_8_1_7 - $desc_8_1_7"
starttestjson "$id_8_1_7" "$desc_8_1_7"
totalChecks=$((totalChecks + 1))
note "$check_8_1_7"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
}
check_8_2() {
if [ "$enterprise_license" -ne 1 ]; then
return
fi
logit "\n"
id_8_2="8.2"
desc_8_2="Docker Trusted Registry Configuration"
check_8_2="$id_8_2 - $desc_8_2"
info "$check_8_2"
}
check_8_2_1() {
if [ "$enterprise_license" -ne 1 ]; then
return
fi
id_8_2_1="8.2.1"
desc_8_2_1="Enable image vulnerability scanning (Scored)"
check_8_2_1="$id_8_2_1 - $desc_8_2_1"
starttestjson "$id_8_2_1" "$desc_8_2_1"
totalChecks=$((totalChecks + 1))
note "$check_8_2_1"
resulttestjson "INFO"
currentScore=$((currentScore + 0))
}
check_8_end() {
endsectionjson
}

View file

@ -0,0 +1,59 @@
#!/bin/sh
check_c() {
logit "\n"
id_99="99"
desc_99="Community contributed checks"
check_99="$id_99 - $desc_99"
info "$check_99"
startsectionjson "$id_99" "$desc_99"
}
# check_c_1
check_c_1() {
check_c_1="C.1 - This is a example check"
totalChecks=$((totalChecks + 1))
if docker info --format='{{ .Architecture }}' | grep 'x86_64' 2>/dev/null 1>&2; then
pass "$check_c_1"
resulttestjson "PASS"
else
warn "$check_c_1"
resulttestjson "WARN"
fi
}
# check_c_2
check_c_2() {
docker_version=$(docker version | grep -i -A2 '^server' | grep ' Version:' \
| awk '{print $NF; exit}' | tr -d '[:alpha:]-,.' | cut -c 1-4)
totalChecks=$((totalChecks + 1))
id_c_2="C.2"
desc_c_2="Ensure operations on legacy registry (v1) are Disabled"
check_c_2="$id_c_2 - $desc_c_2"
starttestjson "$id_c_2" "$desc_c_2"
if [ "$docker_version" -lt 1712 ]; then
if get_docker_configuration_file_args 'disable-legacy-registry' | grep 'true' >/dev/null 2>&1; then
pass "$check_c_2"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
elif get_docker_effective_command_line_args '--disable-legacy-registry' | grep "disable-legacy-registry" >/dev/null 2>&1; then
pass "$check_c_2"
resulttestjson "PASS"
currentScore=$((currentScore + 1))
else
warn "$check_c_2"
resulttestjson "WARN"
currentScore=$((currentScore - 1))
fi
else
desc_c_2="$desc_c_2 (Deprecated)"
check_c_2="$id_c_2 - $desc_c_2"
info "$check_c_2"
resulttestjson "INFO"
fi
}
check_c_end() {
endsectionjson
}