Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
480fdf2
migrating shell scripts to bats testing framework
May 2, 2016
5c34a41
Add bats-support library
alexei-led May 5, 2016
78fdb9a
Add bats-assert library
alexei-led May 5, 2016
370e331
fighting with bats
alexei-led May 5, 2016
09f1948
convert second CIS section to bats
May 7, 2016
a91d991
Implemented tests for CIS 3.x section
May 13, 2016
0e5cada
run tests with run_test.sh; automatically generates tests per each ru…
alexei-led May 15, 2016
28d3a4b
fix/ignore non working xterm (due to /etc volume); download latest do…
alexei-led May 16, 2016
100b33c
update README.md file with info about running Bats tests
alexei-led May 16, 2016
1f856a7
converted tests for section 5 and 6
May 17, 2016
a888600
fix submodules path rename
May 17, 2016
b86b18a
migrating shell scripts to bats testing framework
May 2, 2016
47fab87
Add bats-support library
alexei-led May 5, 2016
fc42e54
Add bats-assert library
alexei-led May 5, 2016
bd56792
fighting with bats
alexei-led May 5, 2016
ccfcf00
convert second CIS section to bats
May 7, 2016
72a4a79
Implemented tests for CIS 3.x section
May 13, 2016
1fffe84
run tests with run_test.sh; automatically generates tests per each ru…
alexei-led May 15, 2016
c29c5ed
fix/ignore non working xterm (due to /etc volume); download latest do…
alexei-led May 16, 2016
ce64bc1
update README.md file with info about running Bats tests
alexei-led May 16, 2016
25adacb
converted tests for section 5 and 6
May 17, 2016
96d841d
fix submodules path rename
May 17, 2016
dd9b62f
resolve merge
May 17, 2016
a913b25
shellcheck cleaning
May 17, 2016
e074995
spellcheck error fix
alexei-led May 18, 2016
3775700
cleanup merge confict comment
alexei-led May 18, 2016
7ae9249
verify hash for downloaded Bats archive
alexei-led May 18, 2016
f6cdaa3
external test configuration can be specified in 0_config file; it's r…
alexei-led May 18, 2016
e68b554
fix flag in help (-r for creating test results folder); also do not m…
alexei-led May 18, 2016
ff1e347
move test configuration into separate directory
alexei-led May 19, 2016
010b4a2
update .gitignore to ignore user config files
alexei-led May 19, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.log
config/*_config.sh
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "bats_tests/test_helper/bats-assert"]
path = bats_tests/test_helper/bats-assert
url = https://github.com/ztombol/bats-assert
[submodule "bats_tests/test_helper/bats-support"]
path = bats_tests/test_helper/bats-support
url = https://github.com/ztombol/bats-support
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,61 @@ Also note that the default image and `Dockerfile` uses `FROM: alpine` which does

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.10.0 or later.

## Running Docker Bench Bats tests

[Bats](https://github.com/sstephenson/bats) is a [TAP](http://testanything.org/)-compliant testing framework for Bash. It provides a simple way to verify that the UNIX programs you write behave as expected.

All Docker Bench scipts are also available as Bats tests. Also container level (and image level) tests are automatically generated for all containers available on host. It's possible to run all or only selected test(s), if you like.

By default TAP test results are reported, but it's possible to produce a "pretty" printed output too.

Use the following command to run Docker Bench Bats tests:

```
Help documentation for run_tests.sh

Basic usage: run_tests.sh [-c] [-p|-t] [-o path] <test> [<test> ...]

Command line switches are optional. The following switches are recognized.
-c --Displays number of tests. No further functions are performed.
-g --Generates all CIS Bats tests without execution. No further functions are performed.
-p --Show results in pretty format.
-t --Show results in TAP format. This is the default format.
-r --Create test results files: tests_<timestamp>.tap in test result folder.
-o --Specify test result folder. Default to /var/docker-bench/results.
-h --Displays this help message. No further functions are performed.

Example: run_tests.sh -t -o /var/docker-bench/results
```

**Note:**: You need to run `run_tests.sh` on Docker host as `root` user.

### Running Docker Bench Bats tests from Docker image

First, clone and compile your `docker-bench-tests` Docker image.

```sh
git clone https://github.com/gaia-adm/docker-bench-security.git
cd docker-bench-security
docker build -t docker-bench-tests -f bats.Dockerfile .
```

Then run `docker-bench-tests` container (as bellow). Test results will be saved into `/var/docker-bench` folder in TAP format. Test results file is named accoring to the `test_<timestamp>.tap` pattern.

```sh
docker run -it --net host --pid host --cap-add audit_control \
-v /var/lib:/var/lib \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/lib/systemd:/usr/lib/systemd \
-v /var/docker-bench:/var/docker-bench \
-v /etc/fstab:/etc/fstab \
-v /etc/docker:/etc/docker \
-v /etc/default/docker:/etc/default/docker \
-v /etc/group:/etc/group \
--label docker_bench_security \
docker-bench-tests
```

## Building Docker Bench for Security

If you wish to build and run this container yourself, you can follow the following steps:
Expand Down
42 changes: 42 additions & 0 deletions bats.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# REPOSITORY https://github.com/docker/docker-bench-securit
FROM alpine:3.3

MAINTAINER dockerbench.com
MAINTAINER Alexei Ledenev <alexei.led@gmail.com>

ENV VERSION 1.11.1
ENV BATS_VERSION 0.4.0
ENV BATS_SHA_256 480d8d64f1681eee78d1002527f3f06e1ac01e173b761bc73d0cf33f4dc1d8d7

LABEL docker_bench_security=true

RUN apk --update add curl bash ncurses \
&& rm -rf /var/lib/apt/lists/* \
&& rm /var/cache/apk/*

RUN curl -o "/tmp/v${BATS_VERSION}.tar.gz" -LS "https://github.com/sstephenson/bats/archive/v${BATS_VERSION}.tar.gz" && \
echo "${BATS_SHA_256} v${BATS_VERSION}.tar.gz" > /tmp/v${BATS_VERSION}.tar.gz.sha256 && \
cd /tmp && sha256sum -c v${BATS_VERSION}.tar.gz.sha256 && \
tar -xvzf "/tmp/v${BATS_VERSION}.tar.gz" -C /tmp/ && \
bash "/tmp/bats-${BATS_VERSION}/install.sh" /usr/local && \
rm -rf /tmp/*

RUN curl -o "/tmp/docker-$VERSION.tgz" -LS "https://get.docker.com/builds/Linux/x86_64/docker-$VERSION.tgz" && \
curl -o "/tmp/docker-$VERSION.tgz.sha256" -LS "https://get.docker.com/builds/Linux/x86_64/docker-$VERSION.tgz.sha256" && \
cd /tmp && sha256sum -c docker-$VERSION.tgz.sha256 && \
tar -xvzf "/tmp/docker-$VERSION.tgz" -C /tmp/ && \
chmod u+x /tmp/docker/docker && mv /tmp/docker/docker /usr/bin/ && \
rm -rf /tmp/*


RUN mkdir /docker-bench-security

COPY . /docker-bench-security
RUN chmod +x /docker-bench-security/run_tests.sh

WORKDIR /docker-bench-security

VOLUME /var/docker-bench

CMD ["-r"]
ENTRYPOINT ["./run_tests.sh"]
128 changes: 128 additions & 0 deletions bats_tests/1_host_configuration.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/usr/bin/env bats

load "test_helper/bats-support/load"
load "test_helper/bats-assert/load"
load "$BATS_TEST_DIRNAME/../helper_lib.sh"

# 1.1
@test "1.1 - Create a separate partition for containers" {
run grep /var/lib/docker /etc/fstab
assert_success
}

# 1.2
@test "1.2 - Use an updated Linux Kernel" {
kernel_version=$(uname -r | cut -d "-" -f 1)
run do_version_check 3.10 "$kernel_version"
assert [ $status -eq 9 -o $status -eq 10 ]
}

# 1.4
@test "1.4 - Remove all non-essential services from the host - Network" {
# Check for listening network services.
listening_services=$(netstat -na | grep -v tcp6 | grep -v unix | grep -c LISTEN)
if [ "$listening_services" -eq 0 ]; then
fail "Failed to get listening services for check: $BATS_TEST_NAME"
else
if [ "$listening_services" -gt 5 ]; then
fail "Host listening on: $listening_services ports"
fi
fi
}

# 1.5
@test "1.5 - Keep Docker up to date" {
docker_version=$(docker version | grep -i -A1 '^server' | grep -i 'version:' \
| awk '{print $NF; exit}' | tr -d '[:alpha:]-,')
docker_current_version="1.11.1"
docker_current_date="2016-04-27"
run do_version_check "$docker_current_version" "$docker_version"
if [ $status -eq 11 ]; then
fail "Using $docker_version, when $docker_current_version is current as of $docker_current_date. Your operating system vendor may provide support and security maintenance for docker."
fi
assert [ $status -eq 9 -o $status -eq 10 ]
}

# 1.6
@test "1.6 - Only allow trusted users to control Docker daemon" {
users_string=$(awk -F':' '/^docker/{print $4}' /etc/group)
docker_users=(${users_string//,/ })
for u in "${docker_users[@]}"; do
local found=1
for tu in "${config_trusted_users[@]}"; do
if [ "$u" = "$tu" ]; then
found=0
fi
done
if [ $found -eq 1 ]; then
fail "User $u is not a trusted user!"
fi
done
}

# 1.7
@test "1.7 - Audit docker daemon - /usr/bin/docker" {
file="/usr/bin/docker"
run command -v auditctl
assert_success
run auditctl -l | grep "$file"
assert_success
}

test_audit_directory() {
local directory="$1"
assert [ -d "$directory" ]
run command -v auditctl >/dev/null
assert_success
run auditctl -l | grep "$directory"
assert_success
}

test_audit_file() {
file="$1"
assert [ -f "$file" ]
run command -v auditctl
assert_success
run auditctl -l | grep "$file"
assert_success
}

# 1.8
@test "1.8 - Audit Docker files and directories - /var/lib/docker" {
test_audit_directory "/var/lib/docker"
}

# 1.9
@test "1.9 - Audit Docker files and directories - /etc/docker" {
test_audit_directory "/etc/docker"
}

# 1.10
@test "1.10 - Audit Docker files and directories - docker.service" {
test_audit_file "$(get_systemd_service_file docker.service)"
}

# 1.11
@test "1.11 - Audit Docker files and directories - docker.socket" {
test_audit_file "$(get_systemd_service_file docker.socket)"
}

# 1.12
@test "1.12 - Audit Docker files and directories - /etc/default/docker" {
test_audit_file "/etc/default/docker"
}

# 1.13
@test "1.13 - Audit Docker files and directories - /etc/docker/daemon.json" {
test_audit_file "/etc/docker/daemon.json"
}

# 1.14
@test "1.14 - Audit Docker files and directories - /usr/bin/docker-containerd" {
test_audit_file "/usr/bin/docker-containerd"
}

# 1.15
@test "1.15 - Audit Docker files and directories - /usr/bin/docker-runc" {
test_audit_file "/usr/bin/docker-runc"
}
102 changes: 102 additions & 0 deletions bats_tests/2_docker_daemon_configuration.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env bats

load "test_helper/bats-support/load"
load "test_helper/bats-assert/load"
load "$BATS_TEST_DIRNAME/../helper_lib.sh"

# 2.1
@test "2.1 - Restrict network traffic between containers" {
result=$(get_docker_effective_command_line_args '--icc')
run grep "false" <<< "$result"
assert_success
}

# 2.2
@test "2.2 - Set the logging level" {
result=$(get_docker_effective_command_line_args '-l')
run grep 'debug' <<< "$result"
assert_failure
}

# 2.3
@test "2.3 - Allow Docker to make changes to iptables" {
result=$(get_docker_effective_command_line_args '--iptables')
run grep "false" <<< "$result"
assert_failure
}

# 2.4
@test "2.4 - Do not use insecure registries" {
result=$(get_docker_effective_command_line_args '--insecure-registry')
run grep "insecure-registry" <<< "$result"
assert_failure
}

# 2.5
@test "2.5 - Do not use the aufs storage driver" {
result=$(docker info 2>/dev/null)
run grep -e "^Storage Driver:\s*aufs\s*$" <<< "$result"
assert_failure
}

# 2.6
@test "2.6 - Configure TLS authentication for Docker daemon" {
result=$(get_docker_cumulative_command_line_args '-H')
run grep -vE '(unix|fd)://' <<< "$result"
if [ $status -eq 0 ]; then
result=$(get_command_line_args docker)
run $(grep "tlsverify" <<< "$result" | grep "tlskey")
assert_success
fi
}

# 2.7
@test "2.7 - Set default ulimit as appropriate" {
result=$(get_docker_effective_command_line_args '--default-ulimit')
run grep "default-ulimit" <<< "$result"
assert_success
}

# 2.8
@test "2.8 - Enable user namespace support" {
result=$(get_docker_effective_command_line_args '--userns-remap')
run grep "userns-remap" <<< "$result"
assert_success
}

# 2.9
@test "2.9 - Confirm default cgroup usage" {
result=$(get_docker_effective_command_line_args '--cgroup-parent')
run grep "cgroup-parent" <<< "$result"
if [ $status -eq 0 ]; then
assert_output_contains "docker"
fi
}

# 2.10
@test "2.10 - Do not change base device size until needed" {
result=$(get_docker_effective_command_line_args '--storage-opt')
run grep "dm.basesize" <<< "$result"
assert_failure
}

# 2.11
@test "2.11 - Use authorization plugin" {
result=$(get_docker_effective_command_line_args '--authorization-plugin')
run grep "authorization-plugin" <<< "$result"
assert_success
}

# 2.12
@test "2.12 - Configure centralized and remote logging" {
result=$(get_docker_effective_command_line_args '--log-driver')
run grep "log-driver" <<< "$result"
assert_success
}

# 2.13
@test "2.13 - Disable operations on legacy registry (v1)" {
result=$(get_docker_effective_command_line_args '--disable-legacy-registry')
run grep "disable-legacy-registry" <<< "$result"
assert_success
}
Loading