docker-bench簡介
docker-bench用于檢查有關在生產中部署Docker容器的安全問題。docker-bench當前支持對多個版本的Docker(1.13和17.06)進行測試,并且將基于主機上運行的Docker版本確定要運行的測試集,同時也可以使用--version <ver>命令行標志手動指定要運行測試的版本。
docker-bench源碼分析
入口文件main.go
入口文件就執行一行代碼Execute,調用root.go的Execute()函數:
func main() {
Execute()
}
cmd包文件root.go
1. 定義變量
var(
noResults? bool
noSummary? bool
noRemediations? bool
dockerVersion? string
cfgDir? string
cfgFile? string
checkList? string
name string
jsonFmt bool
includeTestOutput bool
outputFile string
)
2. RootCmd命令行配置及執行app.go文件
命令行結構體中的字段配置:
// RootCmd represents the base command when called without any subcommands
var RootCmd=&cobra.Command{
Use:"docker-bench",? ?//命令名
Short:"Docker-bench is a Go application that checks whether Docker is deployed securely",? ?//幫助信息的文字內容
Long:`This tool runs the CIS Docker Benchmark (https://www.cisecurity.org/benchmark/docker/)`, //幫助信息的文字內容
Run:app,? //運行命令的邏輯或者運行命令后執行的文件
}
3. 初始化加載配置函數initConfig(),RootCmd配置上面的變量
func init() {
cobra.OnInitialize(initConfig)? //加載配置文件
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags, which, if defined here,
// will be global for your application.
// RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.docker-bench.yaml)")
// Cobra also supports local flags, which will only run
// when this action is called directly.
//給上面定義的變量賦值
RootCmd.PersistentFlags().BoolVar(&noResults,"noresults",false,"Disable printing of results section")
RootCmd.PersistentFlags().BoolVar(&noSummary,"nosummary",false,"Disable printing of summary section")
RootCmd.PersistentFlags().BoolVar(&noRemediations,"noremediations",false,"Disable printing of remediations section")
RootCmd.Flags().StringVarP(&dockerVersion,"version","","17.06","Specify Docker version, automatically detected if unset")
RootCmd.Flags().StringVarP(&cfgDir,"config-dir","D","cfg","directory to get benchmark definitions")
RootCmd.PersistentFlags().BoolVar(&jsonFmt,"json",false,"Prints the results as JSON")
RootCmd.PersistentFlags().BoolVar(&includeTestOutput,"include-test-output",false,"Prints the test's output")
RootCmd.PersistentFlags().StringVar(&outputFile,"outputfile","","Writes the JSON results to output file")
RootCmd.PersistentFlags().StringVarP(
&checkList,
"check",
"c",
"",
`A comma-delimited list of checks to run as specified in CIS document. Example --check="1.1.1,1.1.2"`,
)
goflag.CommandLine.VisitAll(func(goflag*goflag.Flag) {
RootCmd.PersistentFlags().AddGoFlag(goflag)
})
}
4. initConfig()加載CIS基準配置文件
默認的配置文件definitions.yaml
// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile!=""{// enable ability to specify config file via flag
viper.SetConfigFile(cfgFile)
}
viper.SetConfigName(".docker-bench")// name of config file (without extension)
viper.AddConfigPath("$HOME")// adding home directory as first search path
viper.AutomaticEnv()// read in environment variables that match
// If a config file is found, read it in.
if err:=viper.ReadInConfig();err==nil{
fmt.Println("Using config file:",viper.ConfigFileUsed())
}
}
5. 執行main入口函數調用的execute
// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
goflag.Set("logtostderr","true")
goflag.CommandLine.Parse([] string{})
if err:=RootCmd.Execute();err!=nil{
fmt.Println(err)
os.Exit(-1)
}
}
執行檢查文件app.go
func app(cmd *cobra.Command,args[]string) {
var version string
var err error
// Get version of Docker benchmark to run
if dockerVersion!=""{
version=dockerVersion
}else{
version,err=getDockerVersion()??// getDockerVersion returns the docker server engine version.
if err!=nil{
util.ExitWithError(
fmt.Errorf("Version check failed: %s\nAlternatively, you can specify the version with --version",
err))
}
}
path,err:=getDefinitionFilePath(version) //根據docker安裝版本,判斷使用的是哪個版本的CIS配置文件
if err!=nil{
util.ExitWithError(err)
}
controls,err:=getControls(path)? //讀取CIS基準配置文件
if err!=nil{
util.ExitWithError(err)
}
summary:=runControls(controls,checkList) //根據CIS基準配置文件執行檢查
err=outputResults(controls,summary) //輸出檢查結果
if err!=nil{
util.ExitWithError(err)
}
}
配置文件
1. 配置文件一共這四個目錄
1.13.0 Fix test 2.5 syntax 11 months ago? //docker 1.13.0CIS基準
17.06 Fixed bad test syntax in tests: (#37) 10 months ago?//docker 1.17.06 CIS基準?
18.09 Add support for new 18.09 version (#57) 2 months ago?//docker 1.18.09 CIS基準?
ocp-3.9 Fix test 2.5 syntax? ? 11 months ago //openshift 3.9 版本的CIS基準
2. docker 1.13.0?CIS基準默認配置文件
-
controls:
id:""
description:"CIS Docker Community Edition Benchmark"
groups:
-id:1
description:"Host Configuration"
checks:
-id:1.1
description:"Ensure a separate partition for containers has been created (Scored)"
audit:grep /var/lib/docker /etc/fstab
tests:
test_items:
-flag:"/var/lib/docker"
set:true
remediation:"For new installations, create a separate partition for /var/lib/docker
? ? mount point. For systems that were previously installed, use the Logical Volume Manager
(LVM) to create partitions."
scored:true
-id:1.2
description:"Ensure the container host has been Hardened (Not Scored)"
type:manual
remediation:"You may consider various CIS Security Benchmarks for your container host.
? ? If you have other security guidelines or regulatory requirements to adhere to, please
? ? follow them as suitable in your environment.
? ? Additionally, you can run a kernel with grsecurity and PaX . This would add many safety
? ? checks, both at compile-time and run-time. It is also designed to defeat many exploits and
? ? has powerful security features. These features do not require Docker-specific
configuration, since those security features apply system-wide, independent of containers."
scored:false
-id:1.3
description:"Ensure Docker is up to date (Not Scored)"
audit:"docker version"
type:manual
remediation:"Keep a track of Docker releases and update as necessary."
scored:false
-id:1.4
description:"Ensure only trusted users are allowed to control Docker daemon (Scored)"
audit:"getent group docker"
type:manual
remediation:"Remove any users from the docker group that are not trusted. Additionally,
do not create a mapping of sensitive directories on host to container volumes."
scored:true
-id:1.5
description:"Ensure auditing is configured for the docker daemon (Scored)"
audit:"auditctl -l | grep /usr/bin/docker"
tests:
test_items:
-flag:"/usr/bin/docker"
compare:
op:has
value:"/usr/bin/docker"
set:true
remediation:"Add a rule for Docker daemon.
? ? ? ? For example,
Add the line as below line in /etc/audit/audit.rules file:\n
-w /usr/bin/docker -k docker\n
Then, restart the audit daemon. For example,\n
service auditd restart"
scored:true
-id:1.6
description:"Ensure auditing is configured for Docker files and directories -
/var/lib/docker (Scored)"
audit:"auditctl -l | grep /var/lib/docker"
tests:
test_items:
-flag:"/var/lib/docker"
compare:
op:has
value:"/var/lib/docker"
set:true
remediation:"Add a rule for /var/lib/docker directory.
? ? For example,
Add the line as below in /etc/audit/audit.rules file:\n
-w /var/lib/docker -k docker\n
Then, restart the audit daemon. For example,\n
service auditd restart"
scored:true
-id:1.7
description:"Ensure auditing is configured for Docker files and directories -
/etc/docker (Scored)"
audit:"auditctl -l | grep /etc/docker"
tests:
test_items:
-flag:"/etc/docker"
compare:
op:has
value:"/etc/docker"
set:true
remediation:"Add a rule for /etc/docker directory.
? ? For example,
Add the line as below in /etc/audit/audit.rules file:\n
-w /etc/docker -k docker\n
Then, restart the audit daemon. For example,\n
service auditd restart"
scored:true
#Revisit this check
-id:1.8
description:"Ensure auditing is configured for Docker files and directories -
docker.service (Scored)"
audit:"auditctl -l | grep docker.service"
tests:
test_items:
-flag:"docker.service"
compare:
op:has
value:"docker.service"
set:true
remediation:"If the file exists, add a rule for it.
? ? For example,
Add the line as below in /etc/audit/audit.rules file:\n
-w /usr/lib/systemd/system/docker.service -k docker\n
Then, restart the audit daemon. For example,\n
service auditd restart"
scored:true
#Revisit this check
-id:1.9
description:"Ensure auditing is configured for Docker files and directories -
docker.socket (Scored)"
audit:"auditctl -l | grep docker.socket"
tests:
test_items:
-flag:"docker.socket"
compare:
op:has
value:"docker.socket"
set:true
remediation:"If the file exists, add a rule for it.
? ? For example,
Add the line as below in /etc/audit/audit.rules file:\n
-w /usr/lib/systemd/system/docker.socket -k docker\n
Then, restart the audit daemon. For example,\n
service auditd restart"
scored:true
-id:1.10
description:"Ensure auditing is configured for Docker files and directories -
/etc/default/docker (Scored)"
audit:"auditctl -l | grep /etc/default/docker"
tests:
test_items:
-flag:"/etc/default/docker"
compare:
op:has
value:"/etc/default/docker"
set:true
remediation:"Add a rule for /etc/default/docker file.
? ? For example,
Add the line as below in /etc/audit/audit.rules file:\n
-w /etc/default/docker -k docker\n
Then, restart the audit daemon. For example,\n
service auditd restart"
scored:true
-id:1.11
description:"Ensure auditing is configured for Docker files and directories -
/etc/docker/daemon.json (Scored)"
audit:"auditctl -l | grep /etc/docker/daemon.json"
tests:
test_items:
-flag:"/etc/docker/daemon.json"
compare:
op:has
value:"/etc/docker/daemon.json"
set:true
remediation:"Add a rule for /etc/docker/daemon.json file.
? ? For example,
Add the line as below in /etc/audit/audit.rules file:\n
-w /etc/docker/daemon.json -k docker\n
Then, restart the audit daemon. For example,\n
service auditd restart"
scored:true
-id:1.12
description:"Ensure auditing is configured for Docker files and directories -
/usr/bin/docker-containerd (Scored)"
audit:"auditctl -l | grep /usr/bin/docker-containerd"
tests:
test_items:
-flag:"/usr/bin/docker-containerd"
compare:
op:has
value:"/usr/bin/docker-containerd"
set:true
remediation:"Add a rule for /usr/bin/docker-containerd file.
? ? For example,
Add the line as below in /etc/audit/audit.rules file:\n
-w /usr/bin/docker-containerd -k docker\n
Then, restart the audit daemon. For example,\n
service auditd restart"
scored:true
-id:1.13
description:"Ensure auditing is configured for Docker files and directories -
/usr/bin/docker-runc (Scored)"
audit:"auditctl -l | grep /usr/bin/docker-runc"
tests:
test_items:
-flag:"/usr/bin/docker-runc"
compare:
op:has
value:"/usr/bin/docker-runc"
set:true
remediation:"Add a rule for /usr/bin/docker-runc file.
? ? For example,
Add the line as below in /etc/audit/audit.rules file:\n
-w /usr/bin/docker-runc -k docker\n
Then, restart the audit daemon. For example,\n
service auditd restart"
scored:true
-id:2
description:"Docker daemon configuration"
checks:
-id:2.1
description:"Restrict network traffic between containers (Scored)"
audit:"docker network ls --quiet | xargs docker network inspect --format '{{ .Name }}: {{ .Options }}'"
tests:
test_items:
-flag:"com.docker.network.bridge.enable_icc:false"
compare:
op:has
value:"com.docker.network.bridge.enable_icc:false"
set:true
remediation:|
? ? ? Run the docker in daemon mode and pass --icc=false as an argument.
? ? ? For Example,
? ? ? dockerd --icc=false
? ? ? Alternatively, you can follow the Docker documentation and create a custom network and
? ? ? only join containers that need to communicate to that custom network. The --icc
? ? ? parameter only applies to the default docker bridge, if custom networks are used then the
? ? ? approach of segmenting networks should be adopted instead.
scored:true
-id:2.2
description:"Set the logging level (Scored)"
audit:"ps -ef | grep docker"
tests:
bin_op:or
test_items:
-flag:"--log-level"
set:false
-flag:"--log-level"
compare:
op:eq
value:"info"
set:true
remediation:|
? ? ? ps -ef | grep docker
scored:true
-id:2.3
description:"Allow Docker to make changes to iptables (Scored)"
audit:"ps -ef | grep dockerd"
tests:
bin_op:or
test_items:
-flag:"--iptables"
set:false
-flag:"--iptables"
compare:
op:eq
value:true
set:true
remediation:|
? ? ? Do not run the Docker daemon with --iptables=false parameter. For example, do not
? ? ? start the Docker daemon as below:
? ? ? dockerd --iptables=false
scored:true
-id:2.4
description:"Do not use insecure registries (Scored)"
audit:"ps -ef | grep dockerd"
tests:
test_items:
-flag:"--insecure-registry"
set:false
remediation:|
? ? ? Do not use any insecure registries.
? ? ? For example, do not start the Docker daemon as below:
? ? ? dockerd --insecure-registry 10.1.0.0/16
scored:true
-id:2.5
description:"Do not use the aufs storage driver (Scored)"
audit:docker info | grep -e "^Storage Driver:\s*aufs\s*$"
tests:
test_items:
-flag:"Storage Driver: aufs"
set:false
remediation:|
? ? ? Do not explicitly use aufs as storage driver.
? ? ? For example, do not start Docker daemon as below:
? ? ? dockerd --storage-driver aufs
scored:true
-id:2.6
description:"Configure TLS authentication for Docker daemon (Scored)"
audit:ps -ef | grep dockerd
tests:
test_items:
-flag:"--tlsverify"
set:true
-flag:"--tlscacert"
set:true
-flag:"--tlscert"
set:true
-flag:"--tlskey"
set:true
remediation:|
? ? ? Follow the steps mentioned in the Docker documentation or other references.
scored:true
-id:2.7
description:"Set default ulimit as appropriate (Not Scored)"
audit:ps -ef | grep dockerd
type:manual
tests:
test_items:
-flag:"--default-ulimit"
set:true
remediation:|
? ? ? Run the docker in daemon mode and pass --default-ulimit as argument with respective
? ? ? ulimits as appropriate in your environment.
? ? ? For Example,
? ? ? dockerd --default-ulimit nproc=1024:2048 --default-ulimit nofile=100:200
scored:false
-id:2.8
description:"Enable user namespace support (Scored)"
audit:docker info --format '{{ .SecurityOptions }}'
tests:
test_items:
-flag:"userns"
compare:
op:has
value:"userns"
set:true
remediation:|
? ? ? Please consult Docker documentation for various ways in which this can be configured
? ? ? depending upon your requirements. Your steps might also vary based on platform - For
? ? ? example, on Red Hat, sub-UIDs and sub-GIDs mapping creation does not work
? ? ? automatically. You might have to create your own mapping.
? ? ? However, the high-level steps are as below:
? ? ? Step 1: Ensure that the files /etc/subuid and /etc/subgid exist.
? ? ? touch /etc/subuid /etc/subgid
? ? ? Step 2: Start the docker daemon with --userns-remap flag
? ? ? dockerd --userns-remap=default
scored:true
-id:2.9
description:"Confirm default cgroup usage (Scored)"
audit:ps -ef | grep dockerd
tests:
bin_op:or
test_items:
-flag:"--cgroup-parent"
set:false
-flag:"--cgroup-parent"
compare:
op:nothave
value:"/docker"
set:true
remediation:|
? ? ? The default setting is good enough and can be left as-is. If you want to specifically set a non-
? ? ? default cgroup, pass --cgroup-parent parameter to the docker daemon when starting it.
? ? ? For Example,
? ? ? dockerd --cgroup-parent=/foobar
scored:true
-id:2.10
description:"Do not change base device size until needed (Scored)"
audit:ps -ef | grep dockerd
tests:
test_items:
-flag:"--storage-opt"
set:false
remediation:|
? ? ? Do not set --storage-opt dm.basesize until needed.
scored:true
-id:2.11
description:"Use authorization plugin (Scored)"
audit:ps -ef | grep dockerd
tests:
test_items:
-flag:"--authorization-plugin"
set:true
remediation:|
? ? ? Step 1: Install/Create an authorization plugin.
? ? ? Step 2: Configure the authorization policy as desired.
? ? ? Step 3: Start the docker daemon as below:
? ? ? dockerd --authorization-plugin=<PLUGIN_ID>
scored:true
-id:2.12
description:"Configure centralized and remote logging (Scored)"
audit:ps -ef | grep dockerd
type:manual
tests:
test_items:
-flag:"--log-driver"
set:true
remediation:|
? ? ? Step 1: Setup the desired log driver by following its documentation.
? ? ? Step 2: Start the docker daemon with that logging driver.
? ? ? For example,
? ? ? dockerd --log-driver=syslog --log-opt syslog-address=tcp://192.xxx.xxx.xxx
scored:true
-id:2.13
description:"Disable operations on legacy registry (v1) (Scored)"
audit:ps -ef | grep dockerd
tests:
test_items:
-flag:"--disable-legacy-registry"
set:true
remediation:|
? ? ? Start the docker daemon as below:
? ? ? dockerd --disable-legacy-registry
scored:true
-id:2.14
description:"Enable live restore (Scored)"
audit:ps -ef | grep dockerd
tests:
test_items:
-flag:"--live-restore"
set:true
remediation:|
? ? ? Run the docker in daemon mode and pass --live-restore as an argument.
? ? ? For Example,
? ? ? dockerd --live-restore
scored:true
-id:2.15
description:"Do not enable swarm mode, if not needed (Scored)"
audit:docker info --format '{{ .Swarm }}'
type:manual
remediation:|
? ? ? If swarm mode has been enabled on a system in error, run
? ? ? docker swarm leave
scored:true
-id:2.16
description:"Control the number of manager nodes in a swarm (Scored)"
audit:docker info --format '{{ .Swarm.Managers }}'
type:manual
remediation:|
? ? ? If an excessive number of managers is configured, the excess can be demoted as worker
? ? ? using the following command:
? ? ? ? docker node demote <ID>
? ? ? Where <ID> is the node ID value of the manager to be demoted.
scored:true
-id:2.17
description:"Bind swarm services to a specific host interface (Scored)"
audit:netstat -lt | grep -i 2377
type:manual
remediation:|
? ? ? Remediation of this requires re-initialization of the swarm specifying a specific interface
? ? ? for the --listen-addr parameter.
scored:true
-id:2.18
description:"Disable Userland Proxy (Scored)"
audit:ps -ef | grep dockerd
tests:
test_items:
-flag:"--userland-proxy"
compare:
op:eq
value:"false"
set:true
remediation:|
? ? ? Run the Docker daemon as below:
? ? ? dockerd --userland-proxy=false
scored:true
-id:2.19
description:"Encrypt data exchanged between containers on different nodes
on the overlay network (Scored)"
audit:docker network ls --filter driver=overlay --quiet | xargs docker network inspect --format '{{.Name}} {{ .Options }}' | grep encrypted
tests:
test_items:
-flag:"encrypted"
compare:
op:have
value:"encrypted"
set:true
remediation:|
? ? ? Create overlay network with --opt encrypted flag.
scored:true
-id:2.20
description:"Apply a daemon-wide custom seccomp profile, if needed (Not Scored)"
audit:docker info --format '{{ .SecurityOptions }}'
tests:
test_items:
-flag:"profile"
compare:
op:has
value:"default"
set:true
remediation:|
? ? ? By default, Docker's default seccomp profile is applied. If this is good for your environment,
? ? ? no action is necessary. Alternatively, if you choose to apply your own seccomp profile, use
? ? ? the --seccomp-profile flag at daemon start or put it in the daemon runtime parameters
? ? ? file.
? ? ? dockerd --seccomp-profile </path/to/seccomp/profile>
scored:false
-id:2.21
description:"Avoid experimental features in production (Scored)"
audit:docker version --format '{{ .Server.Experimental }}'
tests:
test_items:
-flag:"false"
compare:
op:eq
value:"false"
set:true
remediation:|
? ? ? Do not pass --experimental as a runtime parameter to the docker daemon.
scored:true
-id:3
description:"Docker daemon configuration files"
checks:
-id:3.1
description:"Ensure that docker.service file ownership is set to root:root (Scored)"
audit:systemctl show -p FragmentPath docker.service | cut -d= -f2 | xargs stat -c %U:%G
tests:
test_items:
-flag:"root:root"
compare:
op:eq
value:"root:root"
set:true
remediation:|
? ? ? Step 1: Find out the file location:
? ? ? systemctl show -p FragmentPath docker.service
? ? ? Step 2: If the file does not exist, this recommendation is not applicable. If the file exists,
? ? ? execute the below command with the correct file path to set the ownership and group
? ? ? ownership for the file to root .
? ? ? For example,
? ? ? chown root:root /usr/lib/systemd/system/docker.service
scored:true
-id:3.2
description:"Ensure that docker.service file permissions are set to 644 or more
restrictive (Scored)"
audit:systemctl show -p FragmentPath docker.service | cut -d= -f2 | xargs stat -c %a
tests:
test_items:
-flag:"644"
compare:
op:eq
value:"644"
set:true
remediation:|
? ? ? Step 1: Find out the file location:
? ? ? systemctl show -p FragmentPath docker.service
? ? ? Step 2: If the file does not exist, this recommendation is not applicable. If the file exists,
? ? ? execute the below command with the correct file path to set the file permissions to 644 .
? ? ? For example,
? ? ? chmod 644 /usr/lib/systemd/system/docker.service
scored:true
-id:3.3
description:"Ensure that docker.socket file ownership is set to root:root (Scored)"
audit:systemctl show -p FragmentPath docker.socket | cut -d= -f2 | xargs stat -c %U:%G
tests:
test_items:
-flag:"root:root"
compare:
op:eq
value:"root:root"
set:true
remediation:|
? ? ? Step 1: Find out the file location:
? ? ? systemctl show -p FragmentPath docker.socket
? ? ? Step 2: If the file does not exist, this recommendation is not applicable. If the file exists,
? ? ? execute the below command with the correct file path to set the ownership and group
? ? ? ownership for the file to root .
? ? ? For example,
? ? ? chown root:root /usr/lib/systemd/system/docker.socket
scored:true
-id:3.4
description:"Ensure that docker.socket file permissions are set to 644 or more
restrictive (Scored)"
audit:systemctl show -p FragmentPath docker.socket | cut -d= -f2 | xargs stat -c %a
tests:
test_items:
-flag:"644"
compare:
op:eq
value:"644"
set:true
remediation:|
? ? ? Step 1: Find out the file location:
? ? ? systemctl show -p FragmentPath docker.socket
? ? ? Step 2: If the file does not exist, this recommendation is not applicable. If the file exists,
? ? ? execute the below command with the correct file path to set the file permissions to 644 .
? ? ? For example,
? ? ? chmod 644 /usr/lib/systemd/system/docker.socket
scored:true
-id:3.5
description:"Ensure that /etc/docker directory ownership is set to root:root
(Scored)"
audit:stat -c %U:%G /etc/docker
tests:
test_items:
-flag:"root:root"
compare:
op:eq
value:"root:root"
set:true
remediation:|
? ? ? chown root:root /etc/docker
? ? ? This would set the ownership and group-ownership for the directory to root .
scored:true
-id:3.6
description:"Ensure that /etc/docker directory permissions are set to 755 or more
restrictive (Scored)"
audit:stat -c %a /etc/docker
tests:
bin_op:or
test_items:
-flag:"755"
compare:
op:eq
value:"755"
set:true
-flag:"750"
compare:
op:eq
value:"750"
set:true
-flag:"700"
compare:
op:eq
value:"700"
set:true
remediation:|
? ? ? chmod 755 /etc/docker
? ? ? This would set the permissions for the directory to 755 .
scored:true
-id:3.7
description:"Ensure that registry certificate file ownership is set to root:root
(Scored)"
audit:/bin/sh -c "if [ -d /etc/docker/certs.d ]; then stat -c %U:%G /etc/docker/certs.d/*; fi"
tests:
test_items:
-flag:"root:root"
compare:
op:eq
value:""
set:true
remediation:|
? ? ? chown root:root /etc/docker/certs.d/<registry-name>/*
? ? ? This would set the ownership and group-ownership for the registry certificate files to root .
scored:true
-id:3.8
description:"Ensure that registry certificate file permissions are set to 444 or
more restrictive (Scored)"
audit:/bin/sh -c "if [ -d /etc/docker/certs.d ]; then stat -c %a /etc/docker/certs.d/*; fi"
tests:
test_items:
-flag:"444"
compare:
op:eq
value:"444"
set:true
remediation:|
? ? ? chmod 444 /etc/docker/certs.d/<registry-name>/*
? ? ? This would set the permissions for registry certificate files to 444 .
scored:true
-id:3.9
description:"Ensure that TLS CA certificate file ownership is set to root:root
(Scored)"
type:manual
remediation:|
? ? ? chown root:root <path to TLS CA certificate file>
? ? ? This would set the ownership and group-ownership for the TLS CA certificate file to root .
scored:true
-id:3.10
description:"Ensure that TLS CA certificate file permissions are set to 444 or
more restrictive (Scored)"
type:manual
remediation:|
? ? ? chmod 444 <path to TLS CA certificate file>
? ? ? This would set the file permissions of the TLS CA file to 444 .
scored:true
-id:3.11
description:"Ensure that Docker server certificate file ownership is set to
root:root (Scored)"
type:manual
remediation:|
? ? ? chown root:root <path to Docker server certificate file>
? ? ? This would set the ownership and group-ownership for the Docker server certificate file to
? ? ? root .
scored:true
-id:3.12
description:"Ensure that Docker server certificate file permissions are set to 444
or more restrictive (Scored)"
type:manual
remediation:|
? ? ? chmod 444 <path to Docker server certificate file>
? ? ? This would set the file permissions of the Docker server file to 444 .
scored:true
-id:3.13
description:"Ensure that Docker server certificate key file ownership is set to
root:root (Scored)"
type:manual
remediation:|
? ? ? chown root:root <path to Docker server certificate key file>
? ? ? This would set the ownership and group-ownership for the Docker server certificate key
? ? ? file to root.
scored:true
-id:3.14
description:"Ensure that Docker server certificate key file permissions are set to
400 (Scored)"
type:manual
remediation:|
? ? ? chmod 400 <path to Docker server certificate key file>
? ? ? This would set the Docker server certificate key file permissions to 400 .
scored:true
-id:3.15
description:"Ensure that Docker socket file ownership is set to root:docker
(Scored)"
audit:/bin/sh -c "if [ -f /var/run/docker.sock ]; then stat -c %U:%G /var/run/docker.sock; fi"
tests:
test_items:
-flag:"root:docker"
compare:
op:eq
value:"root:docker"
set:true
remediation:|
? ? ? chown root:docker /var/run/docker.sock
? ? ? This would set the ownership to root and group-ownership to docker for default Docker
? ? ? socket file.
scored:true
-id:3.16
description:"Ensure that Docker socket file permissions are set to 660 or more
restrictive (Scored)"
audit:/bin/sh -c "if [ -f /var/run/docker.sock ]; then stat -c %a /var/run/docker.sock; fi"
tests:
bin_op:or
test_items:
-flag:"660"
compare:
op:eq
value:"660"
set:true
test_items:
-flag:"600"
compare:
op:eq
value:"600"
set:true
remediation:|
? ? ? chmod 660 /var/run/docker.sock
? ? ? This would set the file permissions of the Docker socket file to 660 .
scored:true
-id:3.17
description:"Ensure that daemon.json file ownership is set to root:root (Scored)"
audit:/bin/sh -c "if [ -f /etc/docker/daemon.json ]; then stat -c %U:%G /etc/docker/daemon.json; fi"
tests:
test_items:
-flag:"root:root"
compare:
op:eq
value:"root:root"
set:true
remediation:|
? ? ? chown root:root /etc/docker/daemon.json
? ? ? This would set the ownership and group-ownership for the file to root .
scored:true
-id:3.18
description:"Ensure that daemon.json file permissions are set to 644 or more
restrictive (Scored)"
audit:/bin/sh -c "if [ -f /etc/docker/daemon.json ]; then stat -c %a /etc/docker/daemon.json; fi"
tests:
bin_op:or
test_items:
-flag:"644"
compare:
op:eq
value:"644"
set:true
-flag:"640"
compare:
op:eq
value:"640"
set:true
-flag:"600"
compare:
op:eq
value:"600"
set:true
remediation:|
? ? ? chown root:root /etc/default/docker
? ? ? This would set the ownership and group-ownership for the file to root .
scored:true
-id:3.19
description:"Ensure that /etc/default/docker file ownership is set to root:root
(Scored)"
audit:/bin/sh -c "if [ -f /etc/default/docker ]; then stat -c %U:%G /etc/default/docker; fi"
tests:
test_items:
-flag:"root:root"
compare:
op:eq
value:"root:root"
set:true
remediation:|
? ? ? chown root:root /etc/default/docker
? ? ? This would set the ownership and group-ownership for the file to root .
scored:true
-id:3.20
description:"Ensure that /etc/default/docker file permissions are set to 644 or
more restrictive (Scored)"
audit:/bin/sh -c "if [ -f /etc/default/docker ]; then stat -c %a /etc/default/docker; fi"
tests:
bin_op:or
test_items:
-flag:"644"
compare:
op:eq
value:"644"
set:true
-flag:"640"
compare:
op:eq
value:"640"
set:true
-flag:"600"
compare:
op:eq
value:"600"
set:true
remediation:|
? ? ? chmod 644 /etc/default/docker
? ? ? This would set the file permissions for this file to 644.
scored:true
-id:4
description:"Container Images and Build File"
checks:
-id:4.1
description:"Ensure a user for the container has been created (Scored)"
audit:"docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}: User={{ .Config.User }}'"
tests:
test_items:
-flag:"root"
compare:
op:nothave
value:"root"
set:true
remediation:|
? ? ? Ensure that the Dockerfile for the container image contains below instruction:
? ? ? USER <username or ID>
? ? ? where username or ID refers to the user that could be found in the container base image. If
? ? ? there is no specific user created in the container base image, then add a useradd command
? ? ? to add the specific user before USER instruction.
? ? ? For example, add the below lines in the Dockerfile to create a user in the container:
? ? ? RUN useradd -d /home/username -m -s /bin/bash username
? ? ? USER username
? ? ? Note: If there are users in the image that the containers do not need, consider deleting
? ? ? them. After deleting those users, commit the image and then generate new instances of
? ? ? containers for use.
scored:true
-id:4.2
description:"Ensure that containers use trusted base images (Not Scored)"
type:manual
remediation:|
? ? ? - Configure and use Docker Content trust.
? ? ? - Inspect Docker image history to evaluate their risk to operate on your network.
? ? ? - Scan Docker images for vulnerabilities in their dependencies and configurations
? ? ? ? they will impose upon your network.
scored:false
-id:4.3
description:"Ensure unnecessary packages are not installed in the container (Not Scored)"
type:manual
remediation:|
? ? ? At the outset, do not install anything on the container that does not justify the purpose. If
? ? ? the image had some packages that your container does not use, uninstall them.
? ? ? Consider using a minimal base image rather than the standard Redhat/Centos/Debian
? ? ? images if you can. Some of the options include BusyBox and Alpine.
? ? ? Not only does this trim your image size from >150Mb to ~20 Mb, there are also fewer tools
? ? ? and paths to escalate privileges. You can even remove the package installer as a final
? ? ? hardening measure for leaf/production containers.
scored:false
-id:4.4
description:"Ensure images are scanned and rebuilt to include security patches
(Not Scored)"
type:manual
remediation:|
? ? ? Follow the below steps to rebuild the images with security patches:
? ? ? Step 1: Pull all the base images (i.e., given your set of Dockerfiles, extract all images
? ? ? declared in FROM instructions, and re-pull them to check for an updated/patched versions).
? ? ? Patch the packages within the images too.
? ? ? docker pull
? ? ? Step 2: Force a rebuild of each image:
? ? ? docker build --no-cache
? ? ? Step 3: Restart all containers with the updated images.
? ? ? You could also use ONBUILD directive in the Dockerfile to trigger particular update
? ? ? instructions for images that you know are used as base images frequently.
scored:false
#### Come back here
-id:4.5
description:"Ensure Content trust for Docker is Enabled (Scored)"
audit:echo $DOCKER_CONTENT_TRUST
tests:
test_items:
-flag:1
compare:
op:has
value:1
set:true
remediation:|
? ? ? To enable content trust in a bash shell, enter the following command:
? ? ? export DOCKER_CONTENT_TRUST=1
? ? ? Alternatively, set this environment variable in your profile file so that content trust in
? ? ? enabled on every login.
scored:true
-id:4.6
description:"Ensure HEALTHCHECK instructions have been added to the container
image (Scored)"
type:manual
remediation:|
? ? ? Follow Docker documentation and rebuild your container image with HEALTHCHECK
? ? ? instruction.
scored:true
-id:4.7
description:"Ensure update instructions are not use alone in the Dockerfile (Not
Scored)"
type:manual
remediation:|
? ? ? Use update instructions along with install instructions (or any other) and version pinning
? ? ? for packages while installing them. This would bust the cache and force to extract the
? ? ? required versions.
? ? ? Alternatively, you could use --no-cache flag during docker build process to avoid using
? ? ? cached layers.
scored:false
-id:4.8
description:"Ensure setuid and setgid permissions are removed in the images
(Not Scored)"
type:manual
remediation:|
? ? ? Allow setuid and setgid permissions only on executables which need them. You could
? ? ? remove these permissions during build time by adding the following command in your
? ? ? Dockerfile, preferably towards the end of the Dockerfile:
RUN find / -perm +6000 -type f -exec chmod a-s {} \; ||true
scored:false
-id:4.9
description:"Ensure COPY is used instead of ADD in Dockerfile (Not Scored)"
type:manual
remediation:|
? ? ? Use COPY instructions in Dockerfiles.
scored:false
-id:4.10
description:"Ensure secrets are not stored in Dockerfiles (Not Scored)"
type:manual
remediation:|
scored:false
-id:4.11
description:"Ensure verified packages are only Installed (Not Scored)"
type:manual
remediation:|
? ? ? Use GPG keys for downloading and verifying packages or any other secure package
? ? ? distribution mechanism of your choice.
scored:false
-id:5
description:"Container Runtime"
checks:
-id:5.1
description:"Ensure AppArmor Profile is Enabled (Scored)"
type:manual
remediation:|
? ? ? If AppArmor is applicable for your Linux OS, use it. You may have to follow below set of
? ? ? steps:
? ? ? ? ? ? 1. Verify if AppArmor is installed. If not, install it.
? ? ? ? ? ? 2. Create or import a AppArmor profile for Docker containers.
? ? ? ? ? ? 3. Put this profile in enforcing mode.
? ? ? ? ? ? 4. Start your Docker container using the customized AppArmor profile. For example,
? ? ? docker run --interactive --tty --security-opt="apparmor:PROFILENAME" centos
? ? ? /bin/bash
scored:true
-id:5.2
description:"Ensure SELinux security options are set, if applicable (Scored)"
type:manual
remediation:|
? ? ? If SELinux is applicable for your Linux OS, use it. You may have to follow below set of steps:
? ? ? ? ? ? ? 1. Set the SELinux State.
? ? ? ? ? ? ? 2. Set the SELinux Policy.
? ? ? ? ? ? ? 3. Create or import a SELinux policy template for Docker containers.
? ? ? ? ? ? ? 4. Start Docker in daemon mode with SELinux enabled. For example,
? ? ? ? docker daemon --selinux-enabled
? ? ? ? ? ? ? 5. Start your Docker container using the security options. For example,
? ? ? ? docker run --interactive --tty --security-opt label=level:TopSecret centos
? ? ? ? /bin/bash
scored:true
-id:5.3
description:"Ensure Linux Kernel Capabilities are restricted within containers
(Scored)"
type:manual
remediation:|
? ? ? Execute the below command to add needed capabilities:
? ? ? $> docker run --cap-add={"Capability 1","Capability 2"}
? ? ? For example,
? ? ? docker run --interactive --tty --cap-add={"NET_ADMIN","SYS_ADMIN"}
? ? ? centos:latest /bin/bash
scored:true
-id:5.4
description:"Ensure privileged containers are not used (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:Privileged={{ .HostConfig.Privileged }}'
tests:
test_items:
-flag:"Privileged=true"
set:false
remediation:|
? ? ? Do not run container with the --privileged flag.
? ? ? For example, do not start a container as below:
? ? ? docker run --interactive --tty --privileged centos /bin/bash
scored:true
-id:5.5
description:"Ensure sensitive host system directories are not mounted on
containers (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:Volumes={{ .Mounts }}'
tests:
test_items:
-flag:"Source:/ Destination"
set:false
-flag:"Source:/boot Destination"
set:false
-flag:"Source:/dev Destination"
set:false
-flag:"Source:/etc Destination"
set:false
-flag:"Source:/lib Destination"
set:false
-flag:"Source:/proc Destination"
set:false
-flag:"Source:/sys Destination"
set:false
-flag:"Source:/usr Destination"
set:false
remediation:|
? ? ? Do not mount host sensitive directories on containers especially in read-write mode.
scored:true
-id:5.6
description:"Ensure ssh is not run within containers (Scored)"
type:manual
remediation:|
? ? ? Uninstall SSH server from the container and use nsenter or any other commands such as
? ? ? docker exec or docker attach to interact with the container instance.
? ? ? docker exec --interactive --tty $INSTANCE_ID sh
? ? ? OR
? ? ? docker attach $INSTANCE_ID
scored:true
-id:5.7
description:"Ensure privileged ports are not mapped within containers (Scored)"
type:manual
remediation:|
? ? ? Do not map the container ports to privileged host ports when starting a container. Also,
? ? ? ensure that there is no such container to host privileged port mapping declarations in the
? ? ? Dockerfile.
scored:true
-id:5.8
description:"Ensure only needed ports are open on the container (Scored)"
type:manual
remediation:|
? ? ? Fix the Dockerfile of the container image to expose only needed ports by your
? ? ? containerized application. You can also completely ignore the list of ports defined in the
? ? ? Dockerfile by NOT using -P (UPPERCASE) or --publish-all flag when starting the
? ? ? container. Use the -p (lowercase) or --publish flag to explicitly define the ports that you
? ? ? need for a particular container instance.
? ? ? For example,
? ? ? docker run --interactive --tty --publish 5000 --publish 5001 --publish 5002
? ? ? centos /bin/bash
scored:true
-id:5.9
description:"Ensure the host's network namespace is not shared (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:NetworkMode={{ .HostConfig.NetworkMode }}'
tests:
test_items:
-flag:"NetworkMode=host"
set:false
remediation:|
? ? ? Do not pass --net=host option when starting the container.
scored:true
-id:5.10
description:"Ensure memory usage for container is limited (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:Memory={{ .HostConfig.Memory }}'
tests:
test_items:
-flag:"Memory"
compare:
op:gt
value:0
set:true
remediation:|
? ? ? Run the container with only as much memory as required. Always run the container using
? ? ? the --memory argument.
? ? ? For example, you could run a container as below:
? ? ? docker run --interactive --tty --memory 256m centos /bin/bash
? ? ? In the above example, the container is started with a memory limit of 256 MB.
? ? ? Note: Please note that the output of the below command would return values in scientific
? ? ? notation if memory limits are in place.
? ? ? docker inspect --format='{{.Config.Memory}}' 7c5a2d4c7fe0
? ? ? For example, if the memory limit is set to 256 MB for the above container instance, the
? ? ? output of the above command would be 2.68435456e+08 and NOT 256m. You should
? ? ? convert this value using a scientific calculator or programmatic methods.
scored:true
-id:5.11
description:"Ensure CPU priority is set appropriately on the container (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:CpuShares={{ .HostConfig.CpuShares }}'
tests:
test_items:
-flag:"CpuShares"
compare:
op:gt
value:0
set:true
-flag:"CpuShares"
compare:
op:lt
value:1024
set:true
remediation:|
? ? ? Manage the CPU shares between your containers. To do so start the container using the --
? ? ? cpu-shares argument.
? ? ? For example, you could run a container as below:
? ? ? docker run --interactive --tty --cpu-shares 512 centos /bin/bash
? ? ? In the above example, the container is started with CPU shares of 50% of what the other
? ? ? containers use. So, if the other container has CPU shares of 80%, this container will have
? ? ? CPU shares of 40%.
? ? ? Note: 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.
scored:true
-id:5.12
description:"Ensure the container's root filesystem is mounted as read only
(Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:ReadonlyRootfs={{ .HostConfig.ReadonlyRootfs }}'
tests:
test_items:
-flag:"ReadonlyRootfs=false"
set:false
remediation:|
? ? ? Add a --read-only flag at a container's runtime to enforce the container's root filesystem
? ? ? to be mounted as read only.
? ? ? docker run <Run arguments> --read-only <Container Image Name or ID> <Command>
? ? ? Enabling the --read-only option at a container's runtime should be used by administrators
? ? ? to force a container's executable processes to only write container data to explicit storage
? ? ? locations during the container's runtime.
? ? ? Examples of explicit storage locations during a container's runtime include, but not limited
? ? ? to:
? ? ? 1. Use 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 Docker shared-storage volume plugins 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
? ? ? 3. Transmitting container data outside of the docker during the container's runtime
? ? ? for container data to persist container data. Examples include hosted databases,
? ? ? network file shares, and APIs.
scored:true
-id:5.13
description:"Ensure incoming container traffic is binded to a specific host
interface (Scored)"
audit:docker ps --quiet | xargs docker inspect --format '{{ .Id }}:Ports={{ .NetworkSettings.Ports }}'
tests:
test_items:
-flag:"0.0.0.0"
set:false
remediation:|
? ? ? Bind the container port to a specific host interface on the desired host port.
? ? ? For example,
? ? ? docker run --detach --publish 10.2.3.4:49153:80 nginx
? ? ? In the example above, the container port 80 is bound to the host port on 49153 and would
? ? ? accept incoming connection only from 10.2.3.4 external interface.
scored:true
#This test request requires multi-test capabilities
-id:5.14
description:"Ensure 'on-failure' container restart policy is set to '5' (Scored)"
type:manual
remediation:|
? ? ? If a container is desired to be restarted of its own, then, for example, you could start the
? ? ? container as below:
? ? ? docker run --detach --restart=on-failure:5 nginx
scored:true
-id:5.15
description:"Ensure the host's process namespace is not shared (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:PidMode={{ .HostConfig.PidMode }}'
tests:
test_items:
-flag:"PidMode=host"
set:false
remediation:|
? ? ? Do not start a container with --pid=host argument.
? ? ? For example, do not start a container as below:
? ? ? docker run --interactive --tty --pid=host centos /bin/bash
scored:true
-id:5.16
description:"Ensure the host's IPC namespace is not shared (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:IpcMode={{ .HostConfig.IpcMode }}'
tests:
test_items:
-flag:"IpcMode=host"
set:false
remediation:|
? ? ? Do not start a container with --ipc=host argument. For example, do not start a container
? ? ? as below:
? ? ? docker run --interactive --tty --ipc=host centos /bin/bash
scored:true
-id:5.17
description:"Ensure host devices are not directly exposed to containers (Not
Scored)"
type:manual
remediation:|
? ? ? Do not directly expose the host devices to containers. If at all, you need to expose the host
? ? ? devices to containers, use the correct set of permissions:
? ? ? For example, do not start a container as below:
? ? ? docker run --interactive --tty --device=/dev/tty0:/dev/tty0:rwm --
? ? ? device=/dev/temp_sda:/dev/temp_sda:rwm centos bash
? ? ? For example, share the host device with correct permissions:
? ? ? docker run --interactive --tty --device=/dev/tty0:/dev/tty0:rw --
? ? ? device=/dev/temp_sda:/dev/temp_sda:r centos bash
scored:false
-id:5.18
description:"Ensure the default ulimit is overwritten at runtime, only if needed
(Not Scored)"
type:manual
remediation:|
? ? ? Only override the default ulimit settings if needed.
? ? ? For example, to override default ulimit settings start a container as below:
? ? ? docker run --ulimit nofile=1024:1024 --interactive --tty centos /bin/bash
scored:true
-id:5.19
description:"Ensure mount propagation mode is not set to shared (Scored)"
type:manual
remediation:|
? ? ? Do not mount volumes in shared mode propagation.
? ? ? For example, do not start container as below:
? ? ? docker run <Run arguments> --volume=/hostPath:/containerPath:shared
? ? ? <Container Image Name or ID> <Command>
scored:true
-id:5.20
description:"Ensure the host's UTS namespace is not shared (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:UTSMode={{ .HostConfig.UTSMode }}'
tests:
test_items:
-flag:"UTSMode=host"
set:false
remediation:|
? ? ? Do not start a container with --uts=host argument.
? ? ? For example, do not start a container as below:
? ? ? docker run --rm --interactive --tty --uts=host rhel7.2
scored:true
-id:5.21
description:"Ensure the default seccomp profile is not Disabled (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:SecurityOpt={{ .HostConfig.SecurityOpt }}'
tests:
test_items:
-flag:"seccomp:unconfined"
set:false
remediation:|
? ? ? By default, seccomp profiles are enabled. You do not need to do anything unless you want
? ? ? to modify and use the modified seccomp profile.
scored:true
#Revisit
-id:5.22
description:"Ensure docker exec commands are not used with privileged option
(Scored)"
type:manual
remediation:|
? ? ? Do not use --privileged option in docker exec command.
scored:true
#Revisit
-id:5.23
description:"Ensure docker exec commands are not used with user option
(Scored)"
type:manual
remediation:|
? ? ? Do not use --user option in docker exec command.
scored:true
#Revisit: issue with representing empty parameter
-id:5.24
description:"Ensure cgroup usage is confirmed (Scored)"
type:manual
remediation:|
? ? ? Do not use --cgroup-parent option in docker run command unless needed.
scored:true
-id:5.25
description:"Ensure the container is restricted from acquiring additional
privileges (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:SecurityOpt={{ .HostConfig.SecurityOpt }}'
tests:
test_items:
-flag:"no-new-privileges"
set:true
remediation:|
? ? ? For example, you should start your container as below:
? ? ? docker run --rm -it --security-opt=no-new-privileges ubuntu bash
scored:true
#Revisit
-id:5.26
description:"Ensure container health is checked at runtime (Scored)"
type:manual
remediation:|
? ? ? Run the container using --health-cmd and the other parameters.
? ? ? For example,
? ? ? docker run -d --health-cmd='stat /etc/passwd || exit 1' nginx
scored:true
-id:5.27
description:"Ensure docker commands always get the latest version of the
image (Not Scored)"
type:manual
remediation:|
? ? ? Use proper version pinning mechanisms (the latest tag which is assigned by default is still
? ? ? vulnerable to caching attacks) to avoid extracting the cached older versions. Version
? ? ? pinning mechanisms should be used for base images, packages, and entire images too. You
? ? ? can customize version pinning rules as per your requirements.
scored:false
-id:5.28
description:"Ensure PIDs cgroup limit is used (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:PidsLimit={{ .HostConfig.PidsLimit }}'
tests:
test_items:
-flag:"PidsLimit"
compare:
op:gt
value:0
set:true
remediation:|
? ? ? Use --pids-limit flag while launching the container with an appropriate value.
? ? ? For example,
? ? ? docker run -it --pids-limit 100 <Image_ID>
? ? ? In the above example, the number of processes allowed to run at any given time is set to
? ? ? 100. After a limit of 100 concurrently running processes is reached, docker would restrict
? ? ? any new process creation.
scored:true
-id:5.29
description:"Ensure Docker's default bridge docker0 is not used (Not Scored)"
audit:docker network ls --quiet | xargs xargs docker network inspect --format '{{ .Name }}:{{ .Options }}'
tests:
test_items:
-flag:"com.docker.network.bridge.name:docker0"
set:false
remediation:|
? ? ? Follow Docker documentation and setup a user-defined network. Run all the containers in
? ? ? the defined network.
scored:false
#Revisit: issue representing null value
-id:5.30
description:"Ensure the host's user namespaces is not shared (Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:UsernsMode={{ .HostConfig.UsernsMode }}'
type:manual
tests:
test_items:
-flag:"UsernsMode="
set:true
remediation:|
? ? ? Do not share user namespaces between host and containers.
? ? ? For example, do not run a container as below:
? ? ? docker run --rm -it --userns=host ubuntu bash
scored:true
-id:5.31
description:"Ensure the Docker socket is not mounted inside any containers
(Scored)"
audit:docker ps --quiet --all | xargs docker inspect --format '{{ .Id }}:Volumes={{ .Mounts }}' | grep docker.sock
tests:
test_items:
-flag:"docker.sock"
set:false
remediation:|
? ? ? Ensure that no containers mount docker.sock as a volume.
scored:true
-id:6
description:"Docker Security Operations"
checks:
-id:6.1
description:"Perform regular security audits of your host system and containers (Not Scored)"
type:manual
remediation:|
? ? ? Follow your organization's security audit policies and requirements.
scored:false
-id:6.2
description:"Monitor Docker containers usage, performance and metering (Not Scored)"
type:manual
remediation:|
? ? ? Use a software or a container for tracking container usage, reporting performance and
? ? ? metering.
scored:false
-id:6.3
description:"Backup container data (Not Scored)"
type:manual
remediation:|
? ? ? You should follow your organization's policy for data backup. You can take backup of your
? ? ? container data volume using ' --volumes-from ' parameter as below:
? ? ? ? ? ? $> docker run <Run arguments> --volumes-from $INSTANCE_ID -v [host-dir]:[container-
? ? ? ? ? ? dir] <Container Image Name or ID> <Command>
? ? ? For example,
? ? ? ? ? ? docker run --volumes-from 699ee3233b96 -v /mybackup:/backup centos tar cvf
? ? ? ? ? ? ? /backup/backup.tar /exampledatatobackup
scored:false
-id:6.4
description:"Avoid image sprawl (Not Scored)"
type:manual
remediation:|
? ? ? Keep the set of the images that you actually need and establish a workflow to remove old or
? ? ? stale images from the host. Additionally, use features such as pull-by-digest to get specific
? ? ? images from the registry.
? ? ? Additionally, you can follow below set of steps to find out unused images on the system and
? ? ? delete them.
? ? ? Step 1 Make a list of all image IDs that are currently instantiated by executing below
? ? ? command:
? ? ? docker images --quiet | xargs docker inspect --format '{{ .Id }}: Image={{
? ? ? ? ? ? ? .Config.Image }}'
? ? ? Step 2: List all the images present on the system by executing below command:
? ? ? docker images
? ? ? Step 3: Compare the list of image IDs populated from Step 1 and Step 2 and find out images
? ? ? that are currently not being instantiated.
? ? ? Step 4: Decide if you want to keep the images that are not currently in use. If not delete
? ? ? them by executing below command:
? ? ? docker rmi $IMAGE_ID
scored:false
-id:6.5
description:"Avoid container sprawl (Not Scored)"
type:manual
remediation:|
? ? ? Periodically check your container inventory per host and clean up the stopped containers
? ? ? using the below command:
? ? ? docker container prune
scored:false
-id:7
description:"Docker Swarm Configuration"
checks:
-id:7.1
description:"Ensure swarm mode is not Enabled, if not needed (Scored)"
type:manual
remediation:|
? ? ? If swarm mode has been enabled on a system in error, run
? ? ? docker swarm leave
scored:true
-id:7.2
description:"Ensure the minimum number of manager nodes have been created
in a swarm (Scored)"
type:manual
remediation:|
? ? ? If an excessive number of managers is configured, the excess can be demoted as worker
? ? ? using the following command:
? ? ? docker node demote <ID>
? ? ? Where is the node ID value of the manager to be demoted.
scored:true
-id:7.3
description:"Ensure swarm services are binded to a specific host interface
(Scored)"
audit:netstat -lt | grep -i 2377
tests:
test_items:
-flag:"0.0.0.0"
compare:
set:false
remediation:|
? ? ? Remediation of this requires re-initialization of the swarm specifying a specific interface
? ? ? for the --listen-addr parameter.
scored:true
-id:7.4
description:"Ensure data exchanged between containers are encrypted on
different nodes on the overlay network (Scored)"
audit:docker network ls --filter driver=overlay --quiet | xargs docker network inspect --format '{{.Name}} {{ .Options }}'
tests:
test_items:
-flag:"encrypted"
set:true
remediation:|
? ? ? Create overlay network with --opt encrypted flag.
scored:true
-id:7.5
description:"Ensure Docker's secret management commands are used for
managing secrets in a Swarm cluster (Not Scored)"
type:manual
remediation:|
? ? ? Follow docker secret documentation and use it to manage secrets effectively.
scored:true
-id:7.6
description:"Ensure swarm manager is run in auto-lock mode (Scored)"
audit:docker swarm unlock-key
tests:
test_items:
-flag:"no unlock key is set"
set:false
remediation:|
? ? ? If you are initializing swarm, use the below command.
? ? ? docker swarm init --autolock
? ? ? If you want to set --autolock on an existing swarm manager node, use the below
? ? ? command.
? ? ? docker swarm update --autolock
scored:true
-id:7.7
description:"Ensure swarm manager auto-lock key is rotated periodically (Not
Scored)"
type:manual
remediation:|
? ? ? Run the below command to rotate the keys.
? ? ? docker swarm unlock-key --rotate
? ? ? Additionally, to facilitate audit for this recommendation, maintain key rotation records and
? ? ? ensure that you establish a pre-defined frequency for key rotation.
scored:false
-id:7.8
description:"Ensure node certificates are rotated as appropriate (Not Scored)"
type:manual
remediation:|
? ? ? Run the below command to set the desired expiry time.
? ? ? For example,
? ? ? docker swarm update --cert-expiry 48h
scored:false
-id:7.9
description:"Ensure CA certificates are rotated as appropriate (Not Scored)"
type:manual
remediation:|
? ? ? Run the below command to rotate the certificate.
? ? ? docker swarm ca --rotate
scored:false
-id:7.10
description:"Ensure management plane traffic has been separated from data
plane traffic (Not Scored)"
type:manual
remediation:|
? ? ? Initialize Swarm with dedicated interfaces for management and data planes respectively.
? ? ? For example,
? ? ? docker swarm init --advertise-addr=192.168.0.1 --data-path-addr=17.1.0.3
scored:false