Docker IT Audit
Docker IT Audit
configration posture for Docker Engine v26.1.4 and intended for system and
application administrators, security specialists, auditors, help desk, and platform
deployment personnel who plan to develop, deploy, assess, or secure solutions
that incorporate Docker Engine 26.1 or later technology on Linux based platforms.
This section covers security recommendations that you should follow to prepare the host machine that you plan to us
infrastructure
Control security
Control namebest practices would buildDescription
a solid and secure foundation for executing containerized workloads
ref.
1.1.1 Ensure separate partition for containers Create a separate partition for
/var/lib/docker.
1.1.2 Ensure only trusted users control Ensure only trusted users are part of the
Docker daemon docker group.
1.1.3 Ensure auditing is configured for Audit all Docker daemon activities.
Docker daemon
1.1.4 Ensure auditing is configured for Audit /run/containerd directory.
/run/containerd
1.2.1 Ensure the container host has been A container host is able to run one or
Hardened (Manual) more containers. It is of utmost
importance to harden the host to mitigate
host security misconfiguration.
1.2.2 Ensure that the version of Docker is up Frequent releases for Docker are issued
to date (Manual) which address security vulnerabilities,
resolve product bugs and bring in new
functionality. You should keep a tab on
these product updates and upgrade as
frequently as possible in line with the
general IT security policy of your
organization.
are the host machine that you plan to use for executing containerized workloads. Securing the Docker host and following your
n for executing
Auditcontainerized
Check workloads. Remediation steps (if not compliant)
Check partition configuration. For new installations, create a
separate partition for /var/lib/docker.
At the Docker host execute one of the below For existing systems, use Logical
commands: Volume Manager (LVM) within Linux to
grep '/var/lib/docker\s' /proc/mounts create a new partition.
Execute the following command on the docker host: Remove untrusted users from the
getent group docker. docker group and do not map sensitive
Ensure only trusted users are members. directories from host to container.
Verify audit rules for Docker daemon using: Add audit rules for Docker daemon and
auditctl -l | grep /usr/bin/dockerd. restart auditd if not compliant.
Verify audit rules using: Add an audit rule for /run/containerd
auditctl -l | grep /run/containerd. in /etc/audit/rules.d/audit.rules and
restart auditd.
Verify audit rules using: Add an audit rule for /var/lib/docker
auditctl -l | grep /var/lib/docker. in /etc/audit/rules.d/audit.rules and
restart auditd.
Verify audit rules using: Add an audit rule for /etc/docker in
auditctl -l | grep /etc/docker. /etc/audit/rules.d/audit.rules and restart
auditd.
Find file location: If the file exists, add an audit rule for
systemctl show -p FragmentPath docker.service docker.service in
If file exists, check audit rules: /etc/audit/rules.d/audit.rules and restart
auditctl -l | grep docker.service. auditd.
Find file location: If the file exists, add an audit rule for
grep 'containerd.sock' /etc/containerd/config.toml containerd.sock in
If file exists, check audit rules: /etc/audit/rules.d/audit.rules and restart
auditctl -l | grep containerd.sock auditd.
Find file location: If the file exists, add an audit rule for
systemctl show -p FragmentPath docker.sock docker.sock in
Locate socket file: /etc/audit/rules.d/audit.rules and restart
grep ListenStream <FragmentPath> auditd.
Check audit rules:
auditctl -l | grep docker.sock.
Not Applicable
Not applicable
This section lists the recommendations that alter and secure the behavior of the Docker daemon. The settings that are
Control ref. Control name Description
2.1 Run the Docker daemon as a non- Run Docker daemon in rootless mode to
root user, if possible enhance security.
2.2 Ensure network traffic is restricted Restrict inter-container communication on
between containers on the default the default network bridge.
bridge
2.3 Ensure the logging level is set to Set Docker daemon log level to 'info'.
'info'
2.4 Ensure Docker is allowed to make The Docker daemon should be allowed to
changes to iptables make changes to iptables.
2.5 Ensure insecure registries are not Avoid using insecure registries that do
used not have valid certificates or TLS.
2.6 Ensure aufs storage driver is not Do not use aufs as the storage driver.
used
2.7 Ensure TLS authentication for Use TLS authentication for Docker
Docker daemon is configured daemon if exposed over a network.
2.8 Ensure the default ulimit is Set appropriate ulimit options for resource
configured appropriately control.
2.11 Ensure base device size is not Only increase base device size if
changed until needed necessary.
2.13 Ensure centralized and remote Enable centralized logging for Docker
logging is configured daemon.
2.14 Ensure containers are restricted from Restrict containers from gaining
acquiring new privileges additional privileges.
2.15 Ensure live restore is enabled Enable live restore to prevent container
downtime.
2.16 Ensure Userland Proxy is Disabled Disable the userland proxy if hairpin NAT
is available.
2.17 Ensure a daemon-wide custom Use a custom seccomp profile to restrict
seccomp profile is applied if system calls.
2.18 appropriate
Ensure experimental features are not Avoid using experimental features in
implemented in production production.
the Docker daemon. The settings that are under this section affect ALL container instances.
Audit Check Remediation steps (if not
Check running processes: compliant)
Follow Docker documentation to install
ps -fe | grep 'dockerd'. the Docker daemon as a non-root
Check network settings: user.
Edit daemon.json to disable ICC:
docker network ls --quiet | xargs docker {"icc": false} or use dockerd --
network inspect --format '{{ .Name }}: icc=false.
{{ .Options }}'.
Should return
com.docker.network.bridge.enable_icc:false.
Check daemon settings: Edit daemon.json to set log-level: 'info'
ps -ef | grep dockerd. or start dockerd with --log-
Review /etc/docker/daemon.json for 'log-level': level='info'.
'info'.
Check daemon settings: Do not run Docker with --
ps -ef | grep dockerd. iptables=false.
Ensure --iptables is either not present or not set
to false.
Check Docker info: Ensure no insecure registries are in
docker info --format 'Insecure Registries: use.
{{.RegistryConfig.InsecureRegistryCIDRs}}'.
Check storage driver: Do not start Docker with dockerd --
docker info --format 'Storage Driver: storage-driver aufs.
{{ .Driver }}'.
Shoulddaemon
Check not return 'aufs'.
settings: Follow Docker documentation to
ps -ef | grep dockerd. configure TLS authentication.
Ensure --tlsverify, --tlscacert, --tlscert, and --
tlskey are present.
Check daemon settings: Configure ulimit in daemon.json or
ps -ef | grep dockerd. start dockerd with --default-ulimit.
Ensure --default-ulimit parameter is set.
Check user namespace settings: Start Docker with --userns-
docker info --format '{{ .SecurityOptions }}'. remap=default.
Check daemon settings: Do not modify --cgroup-parent unless
ps -ef | grep dockerd. necessary.
Ensure --cgroup-parent is either not set or is set
appropriately.
Check daemon settings: Do not set --storage-opt dm.basesize
ps -ef | grep dockerd. unless required.
Should not show --storage-opt dm.basesize.
Check daemon settings: Install and configure an authorization
ps -ef | grep dockerd. plugin.
Ensure --authorization-plugin is set.
Check logging driver: Start Docker with dockerd --log-
docker info --format '{{ .LoggingDriver }}'. driver=syslog --log-opt syslog-
address=tcp://192.xxx.xxx.xxx.
Check daemon settings: Start Docker with dockerd --no-new-
ps -ef | grep dockerd. privileges.
Ensure --no-new-privileges is present.
Check daemon settings: Start Docker with dockerd --live-
docker info --format restore.
'{{ .LiveRestoreEnabled
Check daemon settings: }}'. Start Docker with dockerd --userland-
ps -ef | grep dockerd. proxy=false.
Ensure --userland-proxy=false.
Check seccomp profile: Start Docker with dockerd --seccomp-
docker info --format '{{ .SecurityOptions }}'. profile </path/to/seccomp/profile>.
Check Docker version: Do not start Docker with --
docker version --format experimental in production.
'{{ .Server.Experimental }}'.
stances.
Default value Compliance Status
The Docker daemon runs as the root user
by default.
By default, all inter-container
communication is allowed on the default
network bridge.
3.2 Ensure that docker.service file You should verify that the docker.service
permissions are appropriately set file permissions are either set to 644 or to
(Automated) a more restrictive value.
3.3 Ensure that docker.socket file ownership You should verify that the docker.socket
is set to root:root (Automated) file ownership and group ownership are
correctly set to root.
3.4 Ensure that docker.socket file You should verify that the file permissions
permissions are set to 644 or more on the docker.socket file are correctly set
restrictive (Automated) to 644 or more restrictively.
3.5 Ensure that the /etc/docker directory You should verify that the /etc/docker
ownership is set to root:root (Automated) directory ownership and group ownership
is correctly set to root.
3.6 Ensure that /etc/docker directory You should verify that the /etc/docker
permissions are set to 755 or more directory permissions are correctly set to
restrictively (Automated) 755 or more restrictively.
3.7 Ensure that registry certificate file You should verify that all the registry
ownership is set to root:root (Manual) certificate files (usually found under
/etc/docker/certs.d/<registry-name>
directory) are individually owned and
group owned by root.
3.8 Ensure that registry certificate file Verify registry certificate file permissions
permissions are set to 444 or more are set to 444 or more restrictively.
restrictively
3.9 Ensure that TLS CA certificate file Verify TLS CA certificate file ownership is
ownership is set to root:root set to root:root.
3.10 Ensure that TLS CA certificate file Verify TLS CA certificate file permissions
permissions are set to 444 or more are set to 444 or more restrictively.
restrictively
3.11 Ensure that Docker server certificate file Verify Docker server certificate file
ownership is set to root:root ownership is set to root:root.
3.12 Ensure that the Docker server certificate Verify Docker server certificate file
file permissions are set to 444 or more permissions are set to 444 or more
restrictively restrictively.
3.13 Ensure that the Docker server certificate Verify Docker server certificate key file
key file ownership is set to root:root ownership is set to root:root.
3.14 Ensure that the Docker server certificate Verify Docker server certificate key file
key file permissions are set to 400 permissions are set to 400.
3.15 Ensure that the Docker socket file Verify Docker socket file is owned by root
ownership is set to root:docker and group owned by docker.
3.16 Ensure that the Docker socket file Verify Docker socket file has permissions
permissions are set to 660 or more of 660 or more restrictive.
restrictively
3.17 Ensure that the daemon.json file Verify daemon.json file is owned and
ownership is set to root:root group owned by root.
3.18 Ensure that daemon.json file Verify daemon.json file has permissions
permissions are set to 644 or more of 644 or more restrictive.
3.19 restrictive
Ensure that the /etc/default/docker file Verify /etc/default/docker file is owned
ownership is set to root:root and group owned by root.
3.20 Ensure that the /etc/default/docker file Verify /etc/default/docker file has
permissions are set to 644 or more permissions of 644 or more restrictive.
restrictively
3.21 Ensure that the /etc/sysconfig/docker file Verify /etc/sysconfig/docker file has
permissions are set to 644 or more permissions of 644 or more restrictive.
restrictively
3.22 Ensure that the /etc/sysconfig/docker file Verify /etc/sysconfig/docker file is owned
ownership is set to root:root and group owned by root.
3.23 Ensure that the Containerd socket file Verify Containerd socket file is owned
ownership is set to root:root and group owned by root.
3.24 Ensure that the Containerd socket file Verify Containerd socket file has
permissions are set to 660 or more permissions of 660 or more restrictive.
restrictively
hip. Keeping the files and directories, that may contain sensitive parameters, secure is important for correct and secure functionin
Audit Check Remediation steps (if not compliant)
Step 1: Find out the file location: Step 1: Find out the file location: systemctl show -
systemctl show -p FragmentPath docker.service p FragmentPath docker.service
Step 2: If the file does not exist, this recommendation is Step 2: If the file does not exist, this
not applicable. If the file exists, execute the command recommendation is not applicable. If the file does
below including the correct file path in order to verify that exist, you should execute the command below,
the file is owned and group owned by root. For example: including the correct file path, in order to set the
stat -c %U:%G /usr/lib/systemd/system/docker.service ownership and group ownership for the file to root.
| grep -v root:root For example,
The command above should not return anything.
chown root:root
/usr/lib/systemd/system/docker.service
The docker.service file contains sensitive parameters that Step 1: Find out the file location: systemctl show -
may alter the behavior of the Docker daemon. It should p FragmentPath docker.service
therefore not be writable by any other user other than root Step 2: If the file does not exist, this
in order to ensure that it can not be modified by less recommendation is not applicable. If the file exists,
privileged users. execute the command below, including the correct
file path in order to verify that the file permissions
are set to 644 or a more restrictive value. For
example: stat -c %a
/usr/lib/systemd/system/docker.service
Step 1: Find out the file location: Step 1: Find out the file location: systemctl show -
systemctl show -p FragmentPath docker.socket p FragmentPath docker.socket
Step 2: If the file does not exist, this recommendation is Step 2: If the file does not exist, this
not applicable. If the file exists, execute the command recommendation is not applicable. If the file exists,
below, including the correct file path to verify that the file is execute the command below, including the correct
owned and group-owned by root. For example, file path to set the ownership and group ownership
stat -c %U:%G /usr/lib/systemd/system/docker.socket for the file to root. For example,
| grep -v root:root
The command above should not return a value. chown root:root
/usr/lib/systemd/system/docker.socket
Step 1: Find out the file location: Step 1: Find out the file location: systemctl show -
systemctl show -p FragmentPath docker.socket p FragmentPath docker.socket
Step 2: If the file does not exist, this recommendation is Step 2: If the file does not exist, this
not applicable. If the file exists, you should execute the recommendation is not applicable. If the file does
command below, including the correct file path in order to exist, you should execute the command below,
verify that the file permissions are set to 644 or more including the correct file path to set the file
restrictively. For example: permissions to 644. For example,
stat -c %a /usr/lib/systemd/system/docker.socket chmod 644 /usr/lib/systemd/system/docker.socket
You should execute the command below to verify that the To resolve this issue you should run the following
directory is owned and group owned by root: command: chown root:root /etc/docker
stat -c %U:%G /etc/docker | grep -v root:root This sets the ownership and group ownership for
This command should not return any data. the directory to root.
You should execute the command below to verify that the You should run the following command: chmod
directory has permissions of 755 or more restrictive ones: 755 /etc/docker
stat -c %a /etc/docker This sets the permissions for the directory to 755.
You should execute the command below to verify that the The following command could be executed:
registry certificate files are individually owned and group
owned by root: chown root:root /etc/docker/certs.d/<registry-
name>/*
stat -c %U:%G /etc/docker/certs.d/* | grep -v root:root
stat -c %U:%G <path to TLS CA certificate file> | grep - Run: chown root:root <path to TLS CA
v root:root certificate file>
stat -c %a <path to TLS CA certificate file> Run: chmod 444 <path to TLS CA certificate
file>
stat -c %U:%G <path to Docker server certificate file> | Run: chown root:root <path to Docker server
grep -v root:root certificate file>
stat -c %a <path to Docker server certificate file> Run: chmod 444 <path to Docker server
certificate file>
stat -c %U:%G <path to Docker server certificate key Run: chown root:root <path to Docker server
file> | grep -v root:root certificate key file>
stat -c %a <path to Docker server certificate key file> Run: chmod 400 <path to Docker server
certificate key file>
stat -c %U:%G /var/run/docker.sock | grep -v chown root:docker /var/run/docker.sock
root:docker
stat -c %a /var/run/docker.sock chmod 660 /var/run/docker.sock
4.2 Ensure that containers use only Ensure container images are either
trusted base images built from scratch or based on a trusted
image.
4.3 Ensure that unnecessary packages Containers should not have
are not installed in the container unnecessary software packages to
minimize attack surface.
4.4 Ensure images are scanned and Images should be frequently scanned
rebuilt to include security patches for vulnerabilities and rebuilt to include
patches.
4.5 Ensure Content trust for Docker is Enable content trust to verify image
Enabled provenance using digital signatures.
4.6 Ensure HEALTHCHECK instructions HEALTHCHECK ensures the Docker
have been added to container engine checks container health.
images
4.7 Ensure update instructions are not Avoid using `apt-get update` or `yum
used alone in Dockerfiles update` alone in Dockerfiles.
4.8 Ensure setuid and setgid Remove setuid and setgid permissions
permissions are removed to prevent privilege escalation attacks.
4.9 Ensure that COPY is used instead of Use COPY instead of ADD in
ADD in Dockerfiles Dockerfiles to avoid security risks from
4.1 Ensure secrets are not stored in remote URLs.secrets in Dockerfiles as
Avoid storing
Dockerfiles they are visible in image history.
4.11 Ensure only verified packages are Verify package authenticity before
installed installing them into images.
4.12 Ensure all signed artifacts are Validate artifact signatures before
validated uploading to package registry.
container instance from a particular image would behave. Ensuring that you are using proper base images and appropriate build f
ns that you should follow for container base images and build files to ensure that your containerized infrastructure is secure.
Audit Check
Run:
docker ps --quiet | xargs --max-args=1 -I{} docker exec
{} cat /proc/1/status | grep '^Uid:' | awk '{print $3}'
Use Docker Content Trust, validate image history, and Not Applicable.
scan images for vulnerabilities.
Rebuild images with updated base images and restart Containers and images are not
containers with patched images. automatically updated.
Combine update instructions with package installation Docker does not enforce update
and use version pinning. restrictions.
Remove setuid/setgid bits with `RUN find / -perm Not Applicable.
/6000 -type f -exec chmod a-s {} \; || true` in Dockerfile.
Replace ADD instructions with COPY. Not Applicable.
Use secret management tools like Docker BuildKit. No restrictions on storing secrets
in Dockerfiles.
Use secure package distribution mechanisms (GPG Not Applicable.
keys, etc.).
Validate every artifact signature automatically. Not Applicable.
There are many security implications associated with the ways that containers are started. Some runtime parameters c
therefore
Control very important
Control nameto verify the way in which containers are started, and which parameters are associated with th
Description
ref.
5.1 Ensure swarm mode is not Enabled, Do not enable swarm mode on a Docker
if not needed (Manual) engine instance unless this is needed.
5.5 Ensure that privileged containers are Using the --privileged flag provides all Linux
not used (Manual) kernel capabilities to the container to which it
is applied and therefore overwrites the --cap-
add and --cap-drop flags. For this reason you
should ensure that it is not used.
5.6 Ensure sensitive host system You should not allow sensitive host system
directories are not mounted on directories such as those listed below to be
containers (Manual) mounted as container volumes, especially in
read-write mode.
/
/boot
/dev
/etc
/lib
/lib64
/proc
/sys
/usr
5.7 Ensure sshd is not run within The SSH daemon should not be running
containers (Manual) within the container. You should SSH into the
Docker host, and use docker exec to enter a
container.
5.8 Ensure privileged ports are not The TCP/IP port numbers below 1024 are
mapped within containers (Manual) considered privileged ports. Normal users
and processes are not allowed to use them
for various security reasons. Docker does,
however allow a container port to be mapped
to a privileged port.
5.9 Ensure that only needed ports are The dockerfile for a container image defines
open on the container (Manual) the ports which are opened by default on a
container instance. The list of ports are
relevant to the application you are running
within the container and should only be open
if they are needed.
5.10 Ensure that the host's network When the networking mode on a container is
namespace is not shared (Manual) set to --net=host, the container is not placed
inside a separate network stack. Effectively,
applying this option instructs Docker to not
containerize the container's networking. The
consequence of this is that the container
lives "outside" in the main Docker host and
has full access to its network interfaces.
5.11 Ensure that the memory usage for By default, all containers on a Docker host
containers is limited (Manual) share resources equally. By using the
resource management capabilities of the
Docker host, you can control the amount of
memory that a container is able to use.
5.12 Ensure that CPU priority is set By default, all containers on a Docker host
appropriately on containers (Manual) share resources equally. By using the
resource management capabilities of the
Docker host you can control the host CPU
resources that a container may consume.
5.13 Ensure that the container's root The container's root filesystem should be
filesystem is mounted as read only treated as a 'golden image' by using Docker
(Manual) run's --read-only option. This prevents any
writes to the container's root filesystem at
container runtime and enforces the principle
of immutable infrastructure.
5.14 Ensure that incoming container traffic By default, Docker containers can make
is bound to a specific host interface connections to the outside world, but the
(Manual) outside world cannot connect to containers
and each outgoing connection will appear to
originate from one of the host machine's own
IP addresses. You should only allow
container services to be contacted through a
specific external interface on the host
machine.
5.15 Ensure that the 'on-failure' container By using the --restart flag in the docker run
restart policy is set to '5' (Manual) command you can specify a restart policy for
how a container should or should not be
restarted on exit. You should choose the on-
failure restart policy and limit the restart
attempts to 5.
5.16 Ensure that the host's process The Process ID (PID) namespace isolates
namespace is not shared (Manual) the process ID space, meaning that
processes in different PID namespaces can
have the same PID. This creates process
level isolation between the containers and
the host.
5.17 Ensure that the host's IPC IPC (POSIX/SysV IPC) namespace provides
namespace is not shared (Manual) separation of named shared memory
segments, semaphores and message
queues. The IPC namespace on the host
should therefore not be shared with
containers and should remain isolated.
5.18 Ensure that host devices are not Host devices can be directly exposed to
directly exposed to containers containers at runtime. Do not directly expose
(Manual) host devices to containers, especially to
containers that are not trusted.
5.19 Ensure that the default ulimit is The default ulimit is set at the Docker
overwritten at runtime if needed daemon level. However, if you need to, you
(Manual) may override the default ulimit setting during
container runtime.
5.20 Ensure mount propagation mode is Mount propagation mode allows mounting
not set to shared (Manual) volumes in shared, slave or private mode on
a container. Do not use shared mount
propagation mode unless explicitly needed.
5.21 Ensure that the host's UTS UTS namespaces provide isolation between
namespace is not shared (Manual) two system identifiers: the hostname and the
NIS domain name. It is used to set the
hostname and the domain which are visible
to running processes in that namespace.
Processes running within containers do not
typically require to know either the hostname
or the domain name. The UTS namespace
should therefore not be shared with the host.
5.22 Ensure the default seccomp profile is Seccomp filtering provides a means for a
not Disabled (Manual) process to specify a filter for incoming system
calls. The default Docker seccomp profile
works on a whitelist basis and allows for a
large number of common system calls, whilst
blocking all others. This filtering should not
be disabled unless it causes a problem with
your container application usage.
5.23 Ensure that docker exec commands You should not use docker exec with the --
are not used with the privileged privileged option.
option (Manual)
5.24 Ensure that docker exec commands You should not use docker exec with the --
are not used with the user=root user=root option.
option (Manual)
5.26 Ensure that the container is restricted You should restrict the container from
from acquiring additional privileges acquiring additional privileges via suid or sgid
(Manual) bits.
5.27 Ensure that container health is If the container image does not have an
checked at runtime (Manual) HEALTHCHECK instruction defined, you
should use the --health-cmd parameter at
container runtime to check container health.
5.28 Ensure that Docker commands You should always ensure that you are using
always make use of the latest version the latest version of the images within your
of their image (Manual) repository and not cached older versions.
5.29 Ensure that the PIDs cgroup limit is You should use the --pids-limit flag at
used (Manual) container runtime.
5.30 Ensure that Docker's default bridge You should not use Docker's default bridge
"docker0" is not used (Manual) docker0. Instead you should use Docker's
user-defined networks for container
networking.
5.31 Ensure that the host's user You should not share the host's user
namespaces are not shared (Manual) namespaces with containers running on it.
5.32 Ensure that the Docker socket is not The Docker socket docker.sock should not
mounted inside any containers be mounted inside a container.
(Manual)
are started. Some runtime parameters can be supplied that have security consequences that could compromise the host and the
which parameters are associated with them. Container runtime
Audit Check configuration
Remediation should
steps (if notbe reviewed in line with organizational secur
compliant)
You should run the command below: If AppArmor is applicable for your Linux OS, you
docker ps --quiet --all | xargs docker inspect -- should enable it.
format '{{ .Id }}: 1.Verify AppArmor is installed.
AppArmorProfile={{ .AppArmorProfile }}' 2.Create or import a AppArmor profile for Docker
This command should return a valid AppArmor containers.
Profile for each container instance. 3.Enable enforcement of the policy.
4.Start your Docker container using the customized
AppArmor profile.
For example:
docker run --interactive --tty --security-
opt="apparmor:PROFILENAME" ubuntu /bin/bash
Alternatively, Docker's default AppArmor policy can
be used.
You should run the following command If SELinux is applicable for your Linux OS, you should
docker ps --quiet --all | xargs docker inspect -- use it.
format '{{ .Id }}: 1.Set the SELinux State.
SecurityOpt={{ .HostConfig.SecurityOpt }} 2.Set the SELinux Policy.
MountLabel={{ .MountLabel }} 3.Create or import a SELinux policy template for
ProcessLabel={{ .ProcessLabel }}' Docker containers.
4.Start Docker in daemon mode with SELinux
This command returns all the security options enabled.
currently configured on the containers listed. Note For example:
that even if an empty SecurityOpt is returned, the
MountLabel and ProcessLabel values will indicate if docker daemon --selinux-enabled
SELinux is in use. or by adding the following to the daemon.json
configuration file:
{ "selinux-enabled": true }
You should run the command below: You should not run containers with the --privileged
docker ps --quiet --all | xargs docker inspect -- flag. For example, do not start a container using the
format '{{ .Id }}: command below:
Privileged={{ .HostConfig.Privileged }}'
docker run --interactive --tty --privileged centos
The above command should return /bin/bash
Privileged=false for each container instance.
You should run the following command: You should not mount directories which are security
docker ps --quiet --all | xargs docker inspect -- sensitive on the host within containers, especially in
format '{{ .Id }}: Volumes={{ .Mounts }}' read-write mode.
You can list all running containers instances and You should not map container ports to privileged host
their port mappings by executing the command ports when starting a container. You should also,
below: ensure that there is no such container to host
docker ps --quiet | xargs docker inspect -- privileged port mapping declarations in the Dockerfile.
format '{{ .Id }}: Ports={{ .NetworkSettings.Ports
}}'
You should list all the running instances of You should ensure that the Dockerfile for each
containers and their associated port mappings by container image only exposes needed ports. You can
executing the command below: also completely ignore the list of ports defined in the
docker ps --quiet | xargs docker inspect -- Dockerfile by NOT using -P (UPPERCASE) or the --
format '{{ .Id }}: Ports={{ .NetworkSettings.Ports publish-all flag when starting the container. Instead,
}}' use the -p (lowercase) or --publish flag to explicitly
define the ports that you need for a particular
You should then review the list and ensure that all container instance. For example:
the ports mapped are in fact genuinely required by
each container. docker run --interactive --tty --publish 5000 --
publish 5001 --publish 5002 centos /bin/bash
You should use the command below: You should not pass the --net=host option when
docker ps --quiet --all | xargs docker inspect -- starting any container.
format '{{ .Id }}:
NetworkMode={{ .HostConfig.NetworkMode }}'
You should run the following command. You should manage the CPU runtime between your
docker ps --quiet --all | xargs docker inspect -- containers dependent on their priority within your
format '{{ .Id }}: organization. To do so start the container using the --
CpuShares={{ .HostConfig.CpuShares }}' cpu-shares argument. For example, you could run a
container as below:
If the above command returns 0 or 1024, it means
that CPU shares are not in place. If it returns a docker run -d --cpu-shares 512 centos sleep 1000
non-zero value other than 1024, it means that they
are in place. In the example above, the container is started with
CPU shares of 50% of what other containers use. So
if the other container has CPU shares of 80%, this
container will have CPU shares of 40%. Every new
container will have 1024 shares of CPU by default.
However, this value is shown as 0 if you run the
command mentioned in the audit section. If you set
one container’s CPU shares to 512 it will receive half
of the CPU time compared to the other containers. So
if you take 1024 as 100% you can then derive the
number that you should set for respective CPU
shares. For example, use 512 if you want to set it to
50% and 256 if you want to set it 25%. You can also
view the current CPU shares in the file
/sys/fs/cgroup/cpu/docker/<CONTAINER
ID>/cpu.shares.
You should run the following command on the You should add a --read-only flag at a container's
docker host: runtime to enforce the container's root filesystem
docker ps --quiet --all | xargs docker inspect -- being mounted as read only.
format '{{ .Id }}:
ReadonlyRootfs={{ .HostConfig.ReadonlyRootfs docker run <Run arguments> --read-only
}}' <Container Image Name or ID> <Command>
If the above command returns true, it means the Enabling the --read-only option at a container's
container's root filesystem is mounted read-only. If runtime should be used by administrators to force a
the above command returns false, it means the container's executable processes to only write
container's root filesystem is writeable. container data to explicit storage locations during its
lifetime. Examples of explicit storage locations during
a container's runtime include, but are not limited to:
1. Using the --tmpfs option to mount a temporary file
system for non-persistent data writes.
docker run --interactive --tty --read-only --tmpfs
"/run" --tmpfs "/tmp" centos /bin/bash
2. Enabling Docker rw mounts at a container's
runtime to persist container data directly on the
Docker host filesystem.
docker run --interactive --tty --read-only -v
/opt/app/data:/run/app/data:rw centos /bin/bash
3. Utilizing the Docker shared-storage volume plugin
for Docker data volume to persist container data.
docker volume create -d convoy --opt
o=size=20GB my-named-volume docker run --
interactive --tty --read-only -v
my-named-volume:/run/app/data centos /bin/bash
4. Transmitting container data outside of the Docker
controlled area during the container's runtime for
container data in order to ensure that it is persistent.
Examples include hosted databases, network file
shares and APIs.
You should list all running instances of containers You should bind the container port to a specific host
and their port mappings by executing the command interface on the desired host port. For example,
below:
docker ps --quiet | xargs docker inspect -- docker run --detach --publish 10.2.3.4:49153:80
format '{{ .Id }}: Ports={{ .NetworkSettings.Ports nginx
}}'
In the example above, the container port 80 is bound
Then review the list and ensure that the exposed to the host port on 49153 and would accept incoming
container ports are bound to a specific interface connection only from the 10.2.3.4 external interface.
and not to the wildcard IP address 0.0.0.0. For
example, if the command above returns the results
below, this is non-compliant and the container can
accept connections on any host interface on the
specified port 49153. Ports=map[443/tcp:<nil>
80/tcp:[map[HostPort:49153 HostIp:0.0.0.0]]]
However, if the exposed port is bound to a specific
interface on the host as below, then this is
configured in line with good security practice.
Ports=map[443/tcp:<nil> 80/tcp:
[map[HostIp:10.2.3.4 HostPort:49153]]]
You should use the command below If you wish a container to be automatically restarted,
docker ps --quiet --all | xargs docker inspect -- a sample command is as below:
format '{{ .Id }}:
RestartPolicyName={{ .HostConfig.RestartPolic docker run --detach --restart=on-failure:5 nginx
y.Name }}
MaximumRetryCount={{ .HostConfig.RestartPoli
cy.MaximumRetryCount }}'
You should run the following command: You should not start a container with the --ipc=host
docker ps --quiet --all | xargs docker inspect -- argument. For example, do not start a container as
format '{{ .Id }}: below:
IpcMode={{ .HostConfig.IpcMode }}'
docker run --interactive --tty --ipc=host centos
If the command returns host, it means that the host /bin/bash
IPC namespace is shared with the container. Any
other result means that it is not shared, and that
the system is therefore configured in line with good
security practice.
You should use the command below: You should not directly expose host devices to
containers. If you do need to expose host devices to
docker ps --quiet --all | xargs docker inspect -- containers, you should use granular permissions as
format '{{ .Id }}: Devices={{ .HostConfig.Devices appropriate to your organization:
}}' For example, do not start a container using the
command below:
The above command would list out each device docker run --interactive --tty
with below information: --device=/dev/tty0:/dev/tty0:rwm
--device=/dev/temp_sda:/dev/temp_sda:rwm
•CgroupPermissions - For example, rwm centos bash
•PathInContainer - Device path within the container
•PathOnHost - Device path on the host You should only share the host device using
appropriate permissions: docker run --interactive --tty
You should verify that the host device is needed to --device=/dev/tty0:/dev/tty0:rw
be accessed from within the container and that the --device=/dev/temp_sda:/dev/temp_sda:r centos bash
permissions required are correctly set. If the above
command returns [], then the container does not
have access to host devices and is configured in
line with good security practice.
You should run the command below: You should only override the default ulimit settings if
docker ps --quiet --all | xargs docker inspect -- needed in a specific case. For example, to override
format '{{ .Id }}: default ulimit settings start a container as below:
Ulimits={{ .HostConfig.Ulimits }}'
docker run -ti -d --ulimit nofile=1024:1024 centos
This command should return Ulimits=<no value> sleep 1000
for each container instance unless there is a need
in a specific case to override the default settings.
docker ps --quiet --all | xargs docker inspect -- Do not mount volumes in shared mode propagation.
format '{{ .Id }}: Propagation={{range For example, do not start a container as below:
$mnt := .Mounts}} {{json $mnt.Propagation}}
{{end}}' docker run <Run arguments>
--volume=/hostPath:/containerPath:shared
The above command returns the propagation mode <Container Image Name or ID> <Command>
for mounted volumes. The propagation mode
should not be set to shared unless needed. The
above command might throw errors if there are no
mounts. In that case, this recommendation is not
applicable.
You should run the following command: You should not start a container with the --uts=host
docker ps --quiet --all | xargs docker inspect -- argument. For example, do not start a container using
format '{{ .Id }}: the command below:
UTSMode={{ .HostConfig.UTSMode }}'
docker run --rm --interactive --tty --uts=host
If the above command returns host, it means the rhel7.2
host UTS namespace is shared with the container
and this recommendation is non-compliant. If the
above command returns nothing, then the host's
UTS namespace is not shared. This
recommendation is then compliant.
You should run the following command: By default, seccomp profiles are enabled. You do not
docker ps --quiet --all | xargs docker inspect -- need to do anything unless you want to modify and
format '{{ .Id }}: use a modified seccomp profile.
SecurityOpt={{ .HostConfig.SecurityOpt }}'
If you have auditing enabled as recommended in You should not use the --privileged option in docker
Section 1, you can use the command below to filter exec commands.
out docker exec commands that use the --
privileged option.
If you have auditing enabled as recommended in You should not use the --user=root option in docker
Section 1, you can use the command below to filter exec commands.
out docker exec commands that use the --
user=root option.
You should run the following command: You should not use the --cgroup-parent option within
the docker run command unless strictly required.
docker ps --quiet --all | xargs docker inspect --
format '{{ .Id }}:
CgroupParent={{ .HostConfig.CgroupParent }}'
You should run the following command: You should start your container with the options
docker ps --quiet --all | xargs docker inspect -- below:
format '{{ .Id }}:
SecurityOpt={{ .HostConfig.SecurityOpt }}' docker run --rm -it --security-opt=no-new-
privileges ubuntu bash
This command should return all the security options
currently configured for containers. no-new-
privileges should be one of them. Note that the
SecurityOpt response will be empty (i.e.
SecurityOpt=<no value>) even if "no-new-
privileges": true has been configured in the Docker
daemon.json configuration file.
You should run the command below and ensure You should run the container using the --health-cmd
that all containers are reporting their health status: parameter. For example:
You should run the command below and ensure Use --pids-limit flag with an appropriate value when
that PidsLimit is not set to 0 or -1. A PidsLimit of 0 launching the container. For example:
or -1 means that any number of processes can be
forked concurrently inside the container. docker run -it --pids-limit 100 <Image ID>
docker ps --quiet --all | xargs docker inspect -- In the above example, the number of processes
format '{{ .Id }}: allowed to run at any given time is set to 100. After a
PidsLimit={{ .HostConfig.PidsLimit }}' limit of 100 concurrently running processes is
reached, Docker would restrict any new process
creation.
You should run the command below, and verify that You should follow the Docker documentation and set
containers are on a user-defined network and not up a user-defined network. All the containers should
the default docker0 bridge. be run in this network.
You should run the following command: You should ensure that no containers mount
docker.sock as a volume.
docker ps --quiet --all | xargs docker inspect --
format '{{ .Id }}: Volumes={{ .Mounts }}' | grep
docker.sock
AUDIT_WRITE CHOWN
DAC_OVERRIDE FOWNER FSETID
KILL MKNOD NET_BIND_SERVICE
NET_RAW SETFCAP SETGID
SETPCAP SETUID SYS_CHROOT
FALSE
7.2 Ensure that swarm services are By default, Docker swarm services will listen on
bound to a specific host interface all interfaces on the host. This may not be
(Manual) necessary for the operation of the swarm where
the host has multiple network interfaces.
7.3 Ensure that all Docker swarm overlay Ensure that all Docker swarm overlay networks
networks are encrypted (Manual) are encrypted.
7.4 Ensure that Docker's secret You should use Docker's in-built secret
management commands are used for management command for control of secrets.
managing secrets in a swarm cluster
(Manual)
7.5 Ensure that swarm manager is run in You should review whether you wish to run
auto-lock mode (Manual) Docker swarm manager in auto-lock mode.
7.6 Ensure that the swarm manager auto- You should rotate the swarm manager auto-lock
lock key is rotated periodically key periodically.
(Manual)
7.7 Ensure that node certificates are You should rotate swarm node certificates in
rotated as appropriate (Manual) line with your organizational security policy.
7.8 Ensure that CA certificates are You should rotate root CA certificates as
rotated as appropriate (Manual) appropriate.
7.9 Ensure that management plane traffic You should separate management plane traffic
is separated from data plane traffic from data plane traffic.
(Manual)
cker Swarm. If you are not using Docker Swarm then the recommendations in this section do not apply.
Audit Check Remediation steps (if not compliant)
Run docker info and verify the number of managers. If an excessive number of managers is configured, the
docker info --format '{{ .Swarm.Managers }}' excess nodes can be demoted to workers using the
following command:
Alternatively run the below command.
docker node demote <ID>
docker node ls | grep 'Leader'
Where <ID> is the node ID value of the manager to be
demoted.
You should check the network listener on port 2377 Resolving this issues requires re-initialization of the
(the default for docker swarm) and 7946 (container swarm, specifying a specific interface for the --listen-addr
network discovery), and confirm that it is only parameter.
listening on specific interfaces. For example, in this
could be done using the following command:
You should run the command below to ensure that You should create overlay networks the with --opt
each overlay network has been encrypted. encrypted flag.
On a swarm manager node, you should run the You should follow the docker secret documentation and
command below and ensure docker secret use it to manage secrets effectively.
management is used in your environment where this
is in line with your IT security policy.
docker secret ls
You should run the command below If you are initializing a swarm, use the command below.
Currently, there is no mechanism to find out when You should run the command below to rotate the keys.
the key was last rotated on a swarm manager node.
You should check with the system administrator to docker swarm unlock-key --rotate
see if there is a key rotation process, and how often
the key is rotated. Additionally, to facilitate auditing of this recommendation,
you should maintain key rotation records and ensure that
you establish a pre-defined frequency for key rotation.
Run one of the commands below and ensure that You should run the command to set the desired expiry
the node certificate Expiry Duration is set as time on the node certificate. For example:
appropriate.
docker swarm update --cert-expiry 48h
docker info | grep "Expiry Duration"
docker info --format 'NodeCertExpiry:
{{ .Swarm.Cluster.Spec.CAConfig.NodeCertExpir
You should check the time stamp on the root CA You should run the command below to rotate a certificate.
certificate file. For example:
docker swarm ca --rotate
ls -l /var/lib/docker/swarm/certificates/swarm-
root-ca.crt
You should run the command below on each swarm You should initialize the swarm with dedicated interfaces
node and ensure that the management plane for management and data planes respectively. For
address is different from the data plane address. example,
docker node inspect --format '{{ .Status.Addr }}' docker swarm init --advertise-addr=192.168.0.1 --data-
self path-addr=17.1.0.3
Default value Compliance Status
Only a single manager is required to start a given
cluster.
Not Applicable