mirror of
https://github.com/docker/docker-bench-security.git
synced 2025-06-28 07:36:43 +00:00
Merge 010b4a20ff
into fb28d00c02
This commit is contained in:
commit
dac8422579
17 changed files with 997 additions and 0 deletions
.gitignore.gitmodulesREADME.mdbats.Dockerfile
bats_tests
1_host_configuration.bats2_docker_daemon_configuration.bats3_docker_daemon_configuration_files.bats4_1_create_user_in_container.bats.template4_container_images.bats5_container_runtime.bats.template6_docker_security_operations.bats
test_helper
config
generate_tests.shrun_tests.sh
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
*.log
|
||||
config/*_config.sh
|
||||
|
|
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
|
@ -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
README.md
55
README.md
|
@ -45,6 +45,61 @@ The [distribution specific Dockerfiles](https://github.com/docker/docker-bench-s
|
|||
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
|
||||
|
|
42
bats.Dockerfile
Normal file
42
bats.Dockerfile
Normal file
|
@ -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
bats_tests/1_host_configuration.bats
Normal file
128
bats_tests/1_host_configuration.bats
Normal file
|
@ -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
bats_tests/2_docker_daemon_configuration.bats
Normal file
102
bats_tests/2_docker_daemon_configuration.bats
Normal file
|
@ -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
|
||||
}
|
223
bats_tests/3_docker_daemon_configuration_files.bats
Normal file
223
bats_tests/3_docker_daemon_configuration_files.bats
Normal file
|
@ -0,0 +1,223 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load "test_helper/bats-support/load"
|
||||
load "test_helper/bats-assert/load"
|
||||
load "$BATS_TEST_DIRNAME/../helper_lib.sh"
|
||||
|
||||
# 3.1
|
||||
@test "3.1 - Verify that docker.service file ownership is set to root:root" {
|
||||
file="$(get_systemd_service_file docker.service)"
|
||||
if [ -f "$file" ]; then
|
||||
if [ "$(stat -c %u%g "$file")" -ne 00 ]; then
|
||||
fail "Wrong ownership for $file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.2
|
||||
@test "3.2 - Verify that docker.service file permissions are set to 644" {
|
||||
file="$(get_systemd_service_file docker.service)"
|
||||
if [ -f "$file" ]; then
|
||||
if [ "$(stat -c %a "$file")" -ne 644 ]; then
|
||||
fail "Wrong permissions for $file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.3
|
||||
@test "3.3 - Verify that docker.socket file ownership is set to root:root" {
|
||||
file="$(get_systemd_service_file docker.socket)"
|
||||
if [ -f "$file" ]; then
|
||||
if [ "$(stat -c %u%g "$file")" -ne 00 ]; then
|
||||
fail "Wrong ownership for $file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.4
|
||||
@test "3.4 - Verify that docker.socket file permissions are set to 644" {
|
||||
file="$(get_systemd_service_file docker.socket)"
|
||||
if [ -f "$file" ]; then
|
||||
if [ "$(stat -c %a "$file")" -ne 644 ]; then
|
||||
fail "Wrong permissions for $file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.5
|
||||
@test "3.5 - Verify that /etc/docker directory ownership is set to root:root" {
|
||||
directory="/etc/docker"
|
||||
if [ -d "$directory" ]; then
|
||||
if [ "$(stat -c %u%g $directory)" -ne 00 ]; then
|
||||
fail "Wrong ownership for $directory"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.6
|
||||
@test "3.6 - Verify that /etc/docker directory permissions are set to 755 or 700" {
|
||||
directory="/etc/docker"
|
||||
if [ -d "$directory" ]; then
|
||||
if [ "$(stat -c %a $directory)" -ne 755 ] && [ "$(stat -c %a $directory)" -ne 700 ]; then
|
||||
fail "Wrong permissions for $directory : $(stat -c %a $directory)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.7
|
||||
@test "3.7 - Verify that registry certificate file ownership is set to root:root" {
|
||||
directory="/etc/docker/certs.d/"
|
||||
if [ -d "$directory" ]; then
|
||||
fail=0
|
||||
owners=$(ls -lL $directory | grep ".crt" | awk '{print $3, $4}')
|
||||
for p in $owners; do
|
||||
printf "%s" "$p" | grep "root" >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
fail=1
|
||||
fi
|
||||
done
|
||||
if [ $fail -eq 1 ]; then
|
||||
fail "Wrong ownership for $directory"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.8
|
||||
@test "3.8 - Verify that registry certificate file permissions are set to 444" {
|
||||
directory="/etc/docker/certs.d/"
|
||||
if [ -d "$directory" ]; then
|
||||
fail=0
|
||||
perms=$(ls -lL $directory | grep ".crt" | awk '{print $1}')
|
||||
for p in $perms; do
|
||||
if [ "$p" != "-r--r--r--." ] && [ "$p" = "-r--------." ]; then
|
||||
fail=1
|
||||
fi
|
||||
done
|
||||
if [ $fail -eq 1 ]; then
|
||||
fail "Wrong permissions for $directory"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.9
|
||||
@test "3.9 - Verify that TLS CA certificate file ownership is set to root:root" {
|
||||
tlscacert=$(get_docker_effective_command_line_args '--tlscacert' | sed -n 's/.*tlscacert=\([^s]\)/\1/p' | sed 's/--/ --/g' | cut -d " " -f 1)
|
||||
if [ -f "$tlscacert" ]; then
|
||||
if [ "$(stat -c %u%g "$tlscacert")" -ne 00 ]; then
|
||||
fail "Wrong ownership for $tlscacert : $(stat -c %u%g "$tlscacert")"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.10
|
||||
@test "3.10 - Verify that TLS CA certificate file permissions are set to 444" {
|
||||
tlscacert=$(get_docker_effective_command_line_args '--tlscacert' | sed -n 's/.*tlscacert=\([^s]\)/\1/p' | sed 's/--/ --/g' | cut -d " " -f 1)
|
||||
if [ -f "$tlscacert" ]; then
|
||||
perms=$(ls -ld "$tlscacert" | awk '{print $1}')
|
||||
if [ "$perms" != "-r--r--r--" ]; then
|
||||
fail "Wrong permissions for $tlscacert"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.11
|
||||
@test "3.11 - Verify that Docker server certificate file ownership is set to root:root" {
|
||||
tlscert=$(get_docker_effective_command_line_args '--tlscert' | sed -n 's/.*tlscert=\([^s]\)/\1/p' | sed 's/--/ --/g' | cut -d " " -f 1)
|
||||
if [ -f "$tlscert" ]; then
|
||||
if [ "$(stat -c %u%g "$tlscert")" -ne 00 ]; then
|
||||
fail "Wrong ownership for $tlscert : $(stat -c %u%g "$tlscert")"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.12
|
||||
@test "3.12 - Verify that Docker server certificate file permissions are set to 444" {
|
||||
tlscert=$(get_docker_effective_command_line_args '--tlscert' | sed -n 's/.*tlscert=\([^s]\)/\1/p' | sed 's/--/ --/g' | cut -d " " -f 1)
|
||||
if [ -f "$tlscert" ]; then
|
||||
perms=$(ls -ld "$tlscert" | awk '{print $1}')
|
||||
if [ "$perms" != "-r--r--r--" ]; then
|
||||
fail "Wrong permissions for $tlscert"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.13
|
||||
@test "3.13 - Verify that Docker server key file ownership is set to root:root" {
|
||||
tlskey=$(get_docker_effective_command_line_args '--tlskey' | sed -n 's/.*tlskey=\([^s]\)/\1/p' | sed 's/--/ --/g' | cut -d " " -f 1)
|
||||
if [ -f "$tlskey" ]; then
|
||||
if [ "$(stat -c %u%g "$tlskey")" -ne 00 ]; then
|
||||
fail "Wrong ownership for $tlskey : $(stat -c %u%g "$tlskey")"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.14
|
||||
@test "3.14 - Verify that Docker server key file permissions are set to 400" {
|
||||
tlskey=$(get_docker_effective_command_line_args '--tlskey' | sed -n 's/.*tlskey=\([^s]\)/\1/p' | sed 's/--/ --/g' | cut -d " " -f 1)
|
||||
if [ -f "$tlskey" ]; then
|
||||
perms=$(ls -ld "$tlskey" | awk '{print $1}')
|
||||
if [ "$perms" != "-r--------" ]; then
|
||||
fail "Wrong permissions for $tlskey"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.15
|
||||
@test "3.15 - Verify that Docker socket file ownership is set to root:docker" {
|
||||
file="/var/run/docker.sock"
|
||||
if [ -S "$file" ]; then
|
||||
if [ "$(stat -c %U:%G $file)" != 'root:docker' ]; then
|
||||
fail "Wrong ownership for $file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.16
|
||||
@test "3.16 - Verify that Docker socket file permissions are set to 660" {
|
||||
file="/var/run/docker.sock"
|
||||
if [ -S "$file" ]; then
|
||||
if [ "$(stat -c %a $file)" -ne 660 ]; then
|
||||
fail "Wrong permissions for $file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.17
|
||||
@test "3.17 - Verify that daemon.json file ownership is set to root:root" {
|
||||
file="/etc/docker/daemon.json"
|
||||
if [ -f "$file" ]; then
|
||||
if [ "$(stat -c %U:%G $file)" != 'root:root' ]; then
|
||||
fail "Wrong ownership for $file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.18
|
||||
@test "3.18 - Verify that daemon.json file permissions are set to 644" {
|
||||
file="/etc/docker/daemon.json"
|
||||
if [ -f "$file" ]; then
|
||||
if [ "$(stat -c %a $file)" -ne 644 ]; then
|
||||
fail "Wrong permissions for $file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.19
|
||||
@test "3.19 - Verify that /etc/default/docker file ownership is set to root:root" {
|
||||
file="/etc/default/docker"
|
||||
if [ -f "$file" ]; then
|
||||
if [ "$(stat -c %U:%G $file)" != 'root:root' ]; then
|
||||
fail "Wrong ownership for $file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 3.20
|
||||
@test "3.20 - Verify that /etc/default/docker file permissions are set to 644" {
|
||||
file="/etc/default/docker"
|
||||
if [ -f "$file" ]; then
|
||||
if [ "$(stat -c %a $file)" -ne 644 ]; then
|
||||
fail "Wrong permissions for $file"
|
||||
fi
|
||||
fi
|
||||
}
|
18
bats_tests/4_1_create_user_in_container.bats.template
Normal file
18
bats_tests/4_1_create_user_in_container.bats.template
Normal file
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load "test_helper/bats-support/load"
|
||||
load "test_helper/bats-assert/load"
|
||||
load "$BATS_TEST_DIRNAME/../helper_lib.sh"
|
||||
|
||||
|
||||
# 4.1
|
||||
@test "4.1 - Create a user for the container: {{c}}" {
|
||||
user=$(docker inspect --format 'User={{.Config.User}}' "{{c}}")
|
||||
if [ "$user" = "User=" ] || [ "$user" = "User=[]" ] || [ "$user" = "User=<no value>" ]; then
|
||||
# get PID 1 and check if it's running as root (uid=0)
|
||||
uid=$(docker exec {{c}} awk '/^Uid:/{print $2}' /proc/1/status)
|
||||
if [ $uid -eq 0 ]; then
|
||||
fail "Running as root: {{c}}"
|
||||
fi
|
||||
fi
|
||||
}
|
9
bats_tests/4_container_images.bats
Normal file
9
bats_tests/4_container_images.bats
Normal file
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load "test_helper/bats-support/load"
|
||||
load "test_helper/bats-assert/load"
|
||||
|
||||
# 4.5
|
||||
@test "4.5 - Enable Content trust for Docker" {
|
||||
assert [ "x$DOCKER_CONTENT_TRUST" = "x1" ]
|
||||
}
|
202
bats_tests/5_container_runtime.bats.template
Normal file
202
bats_tests/5_container_runtime.bats.template
Normal file
|
@ -0,0 +1,202 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load "test_helper/bats-support/load"
|
||||
load "test_helper/bats-assert/load"
|
||||
load "$BATS_TEST_DIRNAME/../helper_lib.sh"
|
||||
|
||||
# 5.1
|
||||
@test "5.1 - Verify AppArmor Profile, if applicable: {{c}}" {
|
||||
policy=$(docker inspect --format 'AppArmorProfile={{ .AppArmorProfile }}' "{{c}}")
|
||||
if [ "$policy" = "AppArmorProfile=" ] || [ "$policy" = "AppArmorProfile=[]" ] || [ "$policy" = "AppArmorProfile=<no value>" ]; then
|
||||
fail "No AppArmorProfile Found: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.2
|
||||
@test "5.2 - Verify SELinux security options, if applicable: {{c}}" {
|
||||
policy=$(docker inspect --format 'SecurityOpt={{ .HostConfig.SecurityOpt }}' "{{c}}")
|
||||
if [ "$policy" = "SecurityOpt=" ] || [ "$policy" = "SecurityOpt=[]" ] || [ "$policy" = "SecurityOpt=<no value>" ]; then
|
||||
fail "No SecurityOptions Found: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.3
|
||||
@test "5.3 - Restrict Linux Kernel Capabilities within containers: {{c}}" {
|
||||
caps=$(docker inspect --format 'CapAdd={{ .HostConfig.CapAdd}}' "{{c}}")
|
||||
if [ "$caps" != 'CapAdd=' ] && [ "$caps" != 'CapAdd=[]' ] && [ "$caps" != 'CapAdd=<no value>' ] && [ "$caps" != 'CapAdd=<nil>' ]; then
|
||||
fail "Capabilities added: $caps to {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.4
|
||||
@test "5.4 - Do not use privileged containers: {{c}}" {
|
||||
privileged=$(docker inspect --format '{{ .HostConfig.Privileged }}' "{{c}}")
|
||||
if [ "$privileged" = "true" ]; then
|
||||
fail "Container running in Privileged mode: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.5
|
||||
@test "5.5 - Do not mount sensitive host system directories on containers: {{c}}" {
|
||||
# List of sensitive directories to test for. Script uses new-lines as a separator.
|
||||
# Note the lack of identation. It needs it for the substring comparison.
|
||||
sensitive_dirs=(/boot /dev /etc /lib /proc /sys /usr)
|
||||
run docker inspect --format '{{ .VolumesRW }}' "{{c}}"
|
||||
if [ $status -eq 0 ]; then
|
||||
volumes=$(docker inspect --format '{{ .VolumesRW }}' "{{c}}")
|
||||
else
|
||||
volumes=$(docker inspect --format '{{ .Mounts }}' "{{c}}")
|
||||
fi
|
||||
# Go over each directory in sensitive dir and see if they exist in the volumes
|
||||
for v in "${sensitive_dirs[@]}"; do
|
||||
run contains "$volumes" "$v"
|
||||
if [ $status -eq 0 ]; then
|
||||
fail "Sensitive directory $v mounted in: {{c}}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# 5.7
|
||||
@test "5.7 - Do not map privileged ports within containers: {{c}}" {
|
||||
# Port format is private port -> ip: public port
|
||||
ports=$(docker port "{{c}}" | awk '{print $3}' | cut -d ':' -f2 | tr "\n" " ")
|
||||
# iterate through port range (line delimited)
|
||||
for port in $ports; do
|
||||
if [ ! -z "$port" ] && [ "0$port" -lt 1024 ]; then
|
||||
fail "Privileged Port in use: $port in {{c}}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# 5.9
|
||||
@test "5.9 - Do not share the host's network namespace: {{c}}" {
|
||||
mode=$(docker inspect --format 'NetworkMode={{ .HostConfig.NetworkMode }}' "{{c}}")
|
||||
if [ "$mode" = "NetworkMode=host" ]; then
|
||||
fail "Container running with networking mode 'host': {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.10
|
||||
@test "5.10 - Limit memory usage for container: {{c}}" {
|
||||
run docker inspect --format '{{ .Config.Memory }}' "{{c}}"
|
||||
if [ $status -eq 0 ]; then
|
||||
memory=$(docker inspect --format '{{ .Config.Memory }}' "{{c}}")
|
||||
else
|
||||
memory=$(docker inspect --format '{{ .HostConfig.Memory }}' "{{c}}")
|
||||
fi
|
||||
if [ "$memory" = "0" ]; then
|
||||
fail "Container running without memory restrictions: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.11
|
||||
@test "5.11 - Set container CPU priority appropriately: {{c}}" {
|
||||
run docker inspect --format '{{ .Config.CpuShares }}' "{{c}}"
|
||||
if [ $status -eq 0 ]; then
|
||||
shares=$(docker inspect --format '{{ .Config.CpuShares }}' "{{c}}")
|
||||
else
|
||||
shares=$(docker inspect --format '{{ .HostConfig.CpuShares }}' "{{c}}")
|
||||
fi
|
||||
if [ "$shares" = "0" ]; then
|
||||
fail "Container running without CPU restrictions: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.12
|
||||
@test "5.12 - Mount container's root filesystem as read only: {{c}}" {
|
||||
read_status=$(docker inspect --format '{{ .HostConfig.ReadonlyRootfs }}' "{{c}}")
|
||||
if [ "$read_status" = "false" ]; then
|
||||
fail "Container running with root FS mounted R/W: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.13
|
||||
@test "5.13 - Bind incoming container traffic to a specific host interface: {{c}}" {
|
||||
for ip in $(docker port "{{c}}" | awk '{print $3}' | cut -d ':' -f1 | tr "\n" " "); do
|
||||
if [ "$ip" = "0.0.0.0" ]; then
|
||||
fail "Port being bound to wildcard IP: $ip in {{c}}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# 5.14
|
||||
@test "5.14 - Set the 'on-failure' container restart policy to 5: {{c}}" {
|
||||
policy=$(docker inspect --format MaximumRetryCount='{{ .HostConfig.RestartPolicy.MaximumRetryCount }}' "{{c}}")
|
||||
if [ "$policy" != "MaximumRetryCount=5" ]; then
|
||||
fail "MaximumRetryCount is not set to 5: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.15
|
||||
@test "5.15 - Do not share the host's process namespace: {{c}}" {
|
||||
mode=$(docker inspect --format 'PidMode={{.HostConfig.PidMode }}' "{{c}}")
|
||||
if [ "$mode" = "PidMode=host" ]; then
|
||||
fail "Host PID namespace being shared with: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.16
|
||||
@test "5.16 - Do not share the host's IPC namespace: {{c}}" {
|
||||
mode=$(docker inspect --format 'IpcMode={{.HostConfig.IpcMode }}' "{{c}}")
|
||||
if [ "$mode" = "IpcMode=host" ]; then
|
||||
fail "Host IPC namespace being shared with: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.17
|
||||
@test "5.17 - Do not directly expose host devices to containers: {{c}}" {
|
||||
devices=$(docker inspect --format 'Devices={{ .HostConfig.Devices }}' "{{c}}")
|
||||
if [ "$devices" != "Devices=" ] && [ "$devices" != "Devices=[]" ] && [ "$devices" != "Devices=<no value>" ]; then
|
||||
fail "Container has devices exposed directly: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.18
|
||||
@test "5.18 - Override default ulimit at runtime only if needed: {{c}}" {
|
||||
ulimits=$(docker inspect --format 'Ulimits={{ .HostConfig.Ulimits }}' "{{c}}")
|
||||
if [ "$ulimits" = "Ulimits=" ] || [ "$ulimits" = "Ulimits=[]" ] || [ "$ulimits" = "Ulimits=<no value>" ]; then
|
||||
fail "Container no default ulimit override: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.19
|
||||
@test "5.19 - Do not set mount propagation mode to shared: {{c}}" {
|
||||
mode=$(docker inspect --format 'Propagation={{range $mnt := .Mounts}} {{json $mnt.Propagation}} {{end}}' "{{c}}")
|
||||
if [ "$mode" = "Propagation=shared" ]; then
|
||||
fail "Mount propagation mode is shared: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.20
|
||||
@test "5.20 - Do not share the host's UTS namespace: {{c}}" {
|
||||
mode=$(docker inspect --format 'UTSMode={{.HostConfig.UTSMode }}' "{{c}}")
|
||||
if [ "$mode" = "UTSMode=host" ]; then
|
||||
fail "Host UTS namespace being shared with: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.21
|
||||
@test "5.21 - Do not disable default seccomp profile: {{c}}" {
|
||||
result=$(docker inspect --format 'SecurityOpt={{.HostConfig.SecurityOpt }}' "{{c}}")
|
||||
run grep "seccomp:unconfined" <<< "$result"
|
||||
if [ $status -eq 0 ]; then
|
||||
fail "Default seccomp profile disabled: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.24
|
||||
@test "5.24 - Confirm cgroup usage: {{c}}" {
|
||||
mode=$(docker inspect --format 'CgroupParent={{.HostConfig.CgroupParent }}x' "{{c}}")
|
||||
if [ "$mode" != "CgroupParent=x" ]; then
|
||||
fail "Confirm cgroup usage: {{c}}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 5.25
|
||||
@test "5.25 - Restrict container from acquiring additional privileges: {{c}}" {
|
||||
result=$(docker inspect --format 'SecurityOpt={{.HostConfig.SecurityOpt }}' "{{c}}")
|
||||
run grep "no-new-privileges" <<< "$result"
|
||||
if [ $status -ne 0 ]; then
|
||||
fail "Privileges not restricted: {{c}}"
|
||||
fi
|
||||
}
|
36
bats_tests/6_docker_security_operations.bats
Normal file
36
bats_tests/6_docker_security_operations.bats
Normal file
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load "test_helper/bats-support/load"
|
||||
load "test_helper/bats-assert/load"
|
||||
load "$BATS_TEST_DIRNAME/../helper_lib.sh"
|
||||
|
||||
|
||||
# 6.4
|
||||
@test "6.4 - Avoid image sprawl" {
|
||||
images=$(docker images -q | sort -u | wc -l | awk '{print $1}')
|
||||
active_images=0
|
||||
|
||||
for c in $(docker inspect -f "{{.Image}}" $(docker ps -qa)); do
|
||||
if docker images --no-trunc -a | grep "$c" > /dev/null ; then
|
||||
active_images=$(( active_images += 1 ))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$images" -gt 100 ]; then
|
||||
fail "There are currently: $images images"
|
||||
fi
|
||||
|
||||
if [ "$active_images" -lt "$((images / 2))" ]; then
|
||||
fail "Only $active_images out of $images are in use"
|
||||
fi
|
||||
}
|
||||
|
||||
# 6.5
|
||||
@test "6.5 - Avoid container sprawl" {
|
||||
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
|
||||
fail "There are currently a total of $total_containers containers, with only $running_containers of them currently running"
|
||||
fi
|
||||
}
|
1
bats_tests/test_helper/bats-assert
Submodule
1
bats_tests/test_helper/bats-assert
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 9f88b4207da750093baabc4e3f41bf68f0dd3630
|
1
bats_tests/test_helper/bats-support
Submodule
1
bats_tests/test_helper/bats-support
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit d0a131831c487a1f1141e76d3ab386c89642cdff
|
4
config/0_config.sh
Normal file
4
config/0_config.sh
Normal file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
|
||||
# trusted users that can control Docker daemon
|
||||
config_trusted_users=(vagrant docker ubuntu)
|
4
config/0_config.sh.example
Normal file
4
config/0_config.sh.example
Normal file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
|
||||
# trusted users that can control Docker daemon
|
||||
config_trusted_users=(vagrant docker ubuntu)
|
46
generate_tests.sh
Normal file
46
generate_tests.sh
Normal file
|
@ -0,0 +1,46 @@
|
|||
#!/bin/bash
|
||||
|
||||
. ./helper_lib.sh
|
||||
|
||||
TEST_SRC=./bats_tests
|
||||
BENCH_ROOT=/var/docker-bench
|
||||
TEST_ROOT=$BENCH_ROOT/bats_tests
|
||||
|
||||
prepare_tests_directory()
|
||||
{
|
||||
mkdir -p $BENCH_ROOT
|
||||
if [ -d "$TEST_ROOT" ]; then
|
||||
rm -rf $TEST_ROOT
|
||||
fi
|
||||
if [ ! -f "$BENCH_ROOT/helper_lib.sh" ]; then
|
||||
cp helper_lib.sh $BENCH_ROOT
|
||||
fi
|
||||
cp -r $TEST_SRC $TEST_ROOT
|
||||
}
|
||||
|
||||
list_running_containers() {
|
||||
# List all running containers
|
||||
containers=($(docker ps | sed '1d' | awk '{print $NF}' | tr "\n" " "))
|
||||
# If there is a container with label docker_bench_security, memorize it:
|
||||
local benchcont="nil"
|
||||
for c in "${containers[@]}"; do
|
||||
labels=$(docker inspect --format '{{ .Config.Labels }}' "$c")
|
||||
contains "$labels" "docker_bench_security" && benchcont="$c"
|
||||
done
|
||||
# List all running containers except docker-bench (use names to improve readability in logs)
|
||||
docker ps -aq --format="{{.Names}}" | grep -v "$benchcont" | tr "\n" " "
|
||||
}
|
||||
|
||||
generate_all_tests() {
|
||||
# prepare test direcory: copy tests and templates
|
||||
prepare_tests_directory
|
||||
# generate tests from templates for running containers
|
||||
containers=($(list_running_containers))
|
||||
( cd $TEST_ROOT || exit 1
|
||||
for c in "${containers[@]}"; do
|
||||
for t in *.bats.template; do
|
||||
sed -e "s/{{c}}/$c/g" "${t}" > "${t%.*.*}_${c}.bats"
|
||||
done
|
||||
done
|
||||
)
|
||||
}
|
119
run_tests.sh
Executable file
119
run_tests.sh
Executable file
|
@ -0,0 +1,119 @@
|
|||
#!/bin/bash
|
||||
|
||||
. ./generate_tests.sh
|
||||
. ./config/0_config.sh
|
||||
|
||||
TEST_RESULTS=$BENCH_ROOT/results
|
||||
|
||||
# make result folder (inside VOLUME)
|
||||
# mkdir -p $TEST_RESULTS
|
||||
# generate all tests: copy host and daemon level tests and generate container level tests for running containers
|
||||
# generate_all_tests
|
||||
# run bats with all tests or passed tests
|
||||
# bats $TEST_ROOT >
|
||||
|
||||
#Set Script Name variable
|
||||
SCRIPT="run_tests.sh"
|
||||
|
||||
#Initialize variables to default values.
|
||||
OPT_FORMAT="t"
|
||||
OPT_OUTPUT=$TEST_RESULTS
|
||||
OPT_RESULTS=1
|
||||
|
||||
#Set fonts for Help.
|
||||
if [ -e "/usr/bin/tput" ]; then
|
||||
BOLD=$(tput bold)
|
||||
REV=$(tput smso)
|
||||
NORM=$(tput sgr0)
|
||||
else
|
||||
BOLD=""
|
||||
REV=""
|
||||
NORM=""
|
||||
fi
|
||||
|
||||
#Help function
|
||||
HELP() {
|
||||
echo -e \\n"Help documentation for ${BOLD}${SCRIPT}${NORM}"\\n
|
||||
echo -e "Basic usage: ${BOLD}$SCRIPT [-c] [-p|-t] [-o path] <test> [<test> ...]${NORM}"\\n
|
||||
echo -e "Command line switches are optional. The following switches are recognized."
|
||||
echo -e "${REV}-c${NORM} --Displays number of tests. No further functions are performed."
|
||||
echo -e "${REV}-g${NORM} --Generates all CIS Bats tests without execution. No further functions are performed."
|
||||
echo -e "${REV}-p${NORM} --Show results in pretty format."
|
||||
echo -e "${REV}-t${NORM} --Show results in TAP format. This is the default format."
|
||||
echo -e "${REV}-r${NORM} --Create test results files: ${BOLD}tests_<timestamp>.tap${NORM} in test result folder."
|
||||
echo -e "${REV}-o${NORM} --Specify test result folder. Default to ${BOLD}$TEST_RESULTS${NORM}."
|
||||
echo -e "${REV}-h${NORM} --Displays this help message. No further functions are performed."\\n
|
||||
echo -e "Example: ${BOLD}$SCRIPT -t -o $TEST_RESULTS${NORM}"\\n
|
||||
exit 1
|
||||
}
|
||||
|
||||
#Check the number of arguments. If none are passed, print help and exit.
|
||||
NUMARGS=$#
|
||||
if [ "$NUMARGS" -eq 0 ]; then
|
||||
HELP
|
||||
fi
|
||||
|
||||
### Start getopts code ###
|
||||
|
||||
#Parse command line flags
|
||||
while getopts o:rptcgh FLAG; do
|
||||
case $FLAG in
|
||||
o) # output test results into specified folder
|
||||
OPT_OUTPUT=$OPTARG
|
||||
;;
|
||||
p) # output test results in TAP format
|
||||
OPT_FORMAT="p"
|
||||
;;
|
||||
t) # output test results in pretty format
|
||||
OPT_FORMAT="t"
|
||||
;;
|
||||
r) # save test results into file
|
||||
OPT_RESULTS=0
|
||||
;;
|
||||
c) # count tests
|
||||
if [ -d "$TEST_ROOT" ]; then
|
||||
echo -e "There are ${BOLD}$(bats "${TEST_ROOT}" -c)${NORM} tests in ${BOLD}${TEST_ROOT}${NORM}"
|
||||
else
|
||||
echo -e "No tests found, run ${BOLD}${SCRIPT}${NORM} with ${REV}-g${NORM} option first."
|
||||
fi
|
||||
exit 1
|
||||
;;
|
||||
g) # genetate all Bats tests: copy tests and generate tests (per container) from templates
|
||||
generate_all_tests
|
||||
exit 1
|
||||
;;
|
||||
h) #show help
|
||||
HELP
|
||||
;;
|
||||
\?) #unrecognized option - show help
|
||||
echo -e \\n"Option -${BOLD}$OPTARG${NORM} not allowed."
|
||||
HELP
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1)) #This tells getopts to move on to the next argument.
|
||||
|
||||
### End getopts code ###
|
||||
|
||||
### Run Bats tests ###
|
||||
|
||||
TESTS="${TEST_ROOT}"
|
||||
if [ ! -d "${TEST_ROOT}" ]; then # generate tests if needed
|
||||
generate_all_tests
|
||||
fi
|
||||
|
||||
if [ $# -ne 0 ]; then # get tests from command line
|
||||
TESTS=$*
|
||||
fi
|
||||
|
||||
if [ ${OPT_RESULTS} -eq 0 ]; then # run tests and [create test result file]
|
||||
if [ ! -d "$OPT_OUTPUT" ]; then
|
||||
mkdir -p "$OPT_OUTPUT"
|
||||
fi
|
||||
bats "${TESTS}" -${OPT_FORMAT} > "${OPT_OUTPUT}/tests_$(date +%s).tap"
|
||||
else
|
||||
bats "${TESTS}" -${OPT_FORMAT}
|
||||
fi
|
||||
|
||||
exit 0
|
Loading…
Add table
Add a link
Reference in a new issue