Skip to content

Commit dc85a1f

Browse files
authored
Merge pull request #4 from dev-sec/chris-rock/docker-resource
externalize reoccurring calls to docker resource
2 parents 5e3fb1f + 122dde1 commit dc85a1f

4 files changed

Lines changed: 111 additions & 121 deletions

File tree

controls/docker_host_os_level1.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,7 @@
150150
desc 'Apart from auditing your regular Linux file system and system calls, audit all Docker related files and directories. Docker daemon runs with \'root\' privileges. Its behavior depends on some key files and directories. docker.service is one such file. The docker.service file might be present if the daemon parameters have been changed by an administrator. It holds various parameters for Docker daemon. It must be audited, if applicable.'
151151
ref 'https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/chap-system_auditing.html'
152152

153-
rule = '-w ' << command('systemctl show -p FragmentPath docker.service').stdout.split('=')[1].delete("\n") << ' -p rwxa -k docker'
154-
153+
rule = '-w ' << docker.path << ' -p rwxa -k docker'
155154
describe auditd_rules do
156155
its(:lines) { should include(rule) }
157156
end
@@ -163,8 +162,7 @@
163162
desc 'Apart from auditing your regular Linux file system and system calls, audit all Docker related files and directories. Docker daemon runs with \'root\' privileges. Its behavior depends on some key files and directories. docker.service is one such file. The docker.service file might be present if the daemon parameters have been changed by an administrator. It holds various parameters for Docker daemon. It must be audited, if applicable.'
164163
ref 'https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_Guide/chap-system_auditing.html'
165164

166-
rule = '-w ' << command('systemctl show -p FragmentPath docker.socket').stdout.split('=')[1].delete("\n") << ' -p rwxa -k docker'
167-
165+
rule = '-w ' << docker.socket << ' -p rwxa -k docker'
168166
describe auditd_rules do
169167
its(:lines) { should include(rule) }
170168
end

controls/docker_level1.rb

Lines changed: 52 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144
desc 'Verify that the \'docker.service\' file ownership and group-ownership are correctly set to \'root\''
145145
ref 'https://docs.docker.com/engine/admin/systemd/'
146146

147-
describe file(command('systemctl show -p FragmentPath docker.service').stdout.split('=')[1].delete("\n")) do
147+
describe file(docker.path) do
148148
it { should exist }
149149
it { should be_file }
150150
it { should be_owned_by 'root' }
@@ -158,7 +158,7 @@
158158
desc 'Verify that the \'docker.service\' file permissions are correctly set to \'644\' or more restrictive'
159159
ref 'https://docs.docker.com/engine/admin/systemd/'
160160

161-
describe file(command('systemctl show -p FragmentPath docker.service').stdout.split('=')[1].delete("\n")) do
161+
describe file(docker.path) do
162162
it { should exist }
163163
it { should be_file }
164164
it { should be_readable.by('owner') }
@@ -179,7 +179,7 @@
179179
ref 'https://github.com/YungSang/fedora-atomic-packer/blob/master/oem/docker.socket'
180180
ref 'https://daviddaeschler.com/2014/12/14/centos-7rhel-7-and-docker-containers-on-boot/'
181181

182-
describe file(command('systemctl show -p FragmentPath docker.socket').stdout.split('=')[1].delete("\n")) do
182+
describe file(docker.socket) do
183183
it { should exist }
184184
it { should be_file }
185185
it { should be_owned_by 'root' }
@@ -195,7 +195,7 @@
195195
ref 'https://github.com/YungSang/fedora-atomic-packer/blob/master/oem/docker.socket'
196196
ref 'https://daviddaeschler.com/2014/12/14/centos-7rhel-7-and-docker-containers-on-boot/'
197197

198-
describe file(command('systemctl show -p FragmentPath docker.service').stdout.split('=')[1].delete("\n")) do
198+
describe file(docker.path) do
199199
it { should exist }
200200
it { should be_file }
201201
it { should be_readable.by('owner') }
@@ -502,11 +502,8 @@
502502
ref 'https://github.com/docker/docker/issues/7906'
503503
ref 'https://www.altiscale.com/blog/making-docker-work-yarn/'
504504

505-
ids = command('docker ps --format "{{.ID}}"').stdout.split
506-
ids.each do |id|
507-
raw = command("docker inspect #{id}").stdout
508-
info = json('').parse(raw)
509-
describe info[0] do
505+
docker.ps.each do |id|
506+
describe docker.inspect(id) do
510507
its(%w(Config User)) { should eq attrs['CONTAINER_USER'] }
511508
its(%w(Config User)) { should_not eq nil }
512509
end
@@ -550,11 +547,8 @@
550547
ref 'http://man7.org/linux/man-pages/man7/capabilities.7.html'
551548
ref 'https://github.com/docker/docker/blob/master/oci/defaults_linux.go#L64-L79'
552549

553-
ids = command('docker ps --format "{{.ID}}"').stdout.split
554-
ids.each do |id|
555-
raw = command("docker inspect #{id}").stdout
556-
info = json('').parse(raw)
557-
describe info[0] do
550+
docker.ps.each do |id|
551+
describe docker.inspect(id) do
558552
its(%w(HostConfig CapDrop)) { should include(/all/) }
559553
its(%w(HostConfig CapDrop)) { should_not eq nil }
560554
its(%w(HostConfig CapAdd)) { should eq attrs['CONTAINER_CAPADD'] }
@@ -568,11 +562,8 @@
568562
desc 'Using the --privileged flag gives all Linux Kernel Capabilities to the container thus overwriting the --cap-add and --cap-drop flags. Ensure that it is not used.'
569563
ref 'https://docs.docker.com/engine/reference/commandline/cli/'
570564

571-
ids = command('docker ps --format "{{.ID}}"').stdout.split
572-
ids.each do |id|
573-
raw = command("docker inspect #{id}").stdout
574-
info = json('').parse(raw)
575-
describe info[0] do
565+
docker.ps.each do |id|
566+
describe docker.inspect(id) do
576567
its(%w(HostConfig Privileged)) { should eq false }
577568
its(%w(HostConfig Privileged)) { should_not eq true }
578569
end
@@ -585,11 +576,9 @@
585576
desc 'Sensitive host system directories such as \'/, /boot, /dev, /etc, /lib, /proc, /sys, /usr\' should not be allowed to be mounted as container volumes especially in read-write mode.'
586577
ref 'https://docs.docker.com/engine/userguide/containers/dockervolumes/'
587578

588-
ids = command('docker ps --format "{{.ID}}"').stdout.split
589-
ids.each do |id|
590-
raw = command("docker inspect #{id}").stdout
591-
info = json('').parse(raw)
592-
info[0]['Mounts'].each do |mounts|
579+
docker.ps.each do |id|
580+
info = docker.inspect(id)
581+
info['Mounts'].each do |mounts|
593582
describe mounts['Source'] do
594583
it { should_not eq '/' }
595584
it { should_not match(/\/boot/) }
@@ -610,8 +599,7 @@
610599
desc 'SSH server should not be running within the container. You should SSH into the Docker host, and use nsenter tool to enter a container from a remote host.'
611600
ref 'https://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/'
612601

613-
ids = command('docker ps --format "{{.ID}}"').stdout.split
614-
ids.each do |id|
602+
docker.ps.each do |id|
615603
execute_command = 'docker exec ' << id << ' ps -e'
616604
describe command(execute_command) do
617605
its('stdout') { should_not match(/ssh/) }
@@ -626,13 +614,11 @@
626614
ref 'https://docs.docker.com/engine/userguide/networking/default_network/binding/'
627615
ref 'https://www.adayinthelifeof.nl/2012/03/12/why-putting-ssh-on-another-port-than-22-is-bad-idea/'
628616

629-
ids = command('docker ps --format "{{.ID}}"').stdout.split
630-
ids.each do |id|
631-
raw = command("docker inspect #{id}").stdout
632-
info = json('').parse(raw)
633-
ports = info[0]['NetworkSettings']['Ports'].keys
617+
docker.ps.each do |id|
618+
info = docker.inspect(id)
619+
ports = info['NetworkSettings']['Ports'].keys
634620
ports.each do |item|
635-
info[0]['NetworkSettings']['Ports'][item].each do |hostport|
621+
info['NetworkSettings']['Ports'][item].each do |hostport|
636622
describe hostport['HostPort'].to_i.between?(1, 1024) do
637623
it { should eq false }
638624
end
@@ -655,11 +641,8 @@
655641
ref 'https://docs.docker.com/engine/userguide/networking/dockernetworks/'
656642
ref 'https://github.com/docker/docker/issues/6401'
657643

658-
ids = command('docker ps --format "{{.ID}}"').stdout.split
659-
ids.each do |id|
660-
raw = command("docker inspect #{id}").stdout
661-
info = json('').parse(raw)
662-
describe info[0] do
644+
docker.ps.each do |id|
645+
describe docker.inspect(id) do
663646
its(%w(HostConfig NetworkMode)) { should_not eq 'host' }
664647
end
665648
end
@@ -673,11 +656,8 @@
673656
ref 'https://docs.docker.com/engine/reference/commandline/cli/#run'
674657
ref 'https://docs.docker.com/v1.8/articles/runmetrics/'
675658

676-
ids = command('docker ps --format "{{.ID}}"').stdout.split
677-
ids.each do |id|
678-
raw = command("docker inspect #{id}").stdout
679-
info = json('').parse(raw)
680-
describe info[0] do
659+
docker.ps.each do |id|
660+
describe docker.inspect(id) do
681661
its(%w(HostConfig Memory)) { should_not eq 0 }
682662
end
683663
end
@@ -691,11 +671,8 @@
691671
ref 'https://docs.docker.com/engine/reference/commandline/cli/#run'
692672
ref 'https://docs.docker.com/v1.8/articles/runmetrics/'
693673

694-
ids = command('docker ps --format "{{.ID}}"').stdout.split
695-
ids.each do |id|
696-
raw = command("docker inspect #{id}").stdout
697-
info = json('').parse(raw)
698-
describe info[0] do
674+
docker.ps.each do |id|
675+
describe docker.inspect(id) do
699676
its(%w(HostConfig CpuShares)) { should_not eq 0 }
700677
its(%w(HostConfig CpuShares)) { should_not eq 1024 }
701678
end
@@ -708,11 +685,8 @@
708685
desc 'The container\'s root file system should be treated as a \'golden image\' and any writes to the root filesystem should be avoided. You should explicitly define a container volume for writing.'
709686
ref 'https://docs.docker.com/engine/reference/commandline/cli/#run'
710687

711-
ids = command('docker ps --format "{{.ID}}"').stdout.split
712-
ids.each do |id|
713-
raw = command("docker inspect #{id}").stdout
714-
info = json('').parse(raw)
715-
describe info[0] do
688+
docker.ps.each do |id|
689+
describe docker.inspect(id) do
716690
its(%w(HostConfig ReadonlyRootfs)) { should eq true }
717691
end
718692
end
@@ -724,13 +698,11 @@
724698
desc 'By default, Docker containers can make connections to the outside world, but the outside world cannot connect to containers. Each outgoing connection will appear to originate from one of the host machine\'s own IP addresses. Only allow container services to be contacted through a specific external interface on the host machine.'
725699
ref 'https://docs.docker.com/engine/userguide/networking/default_network/binding/'
726700

727-
ids = command('docker ps --format "{{.ID}}"').stdout.split
728-
ids.each do |id|
729-
raw = command("docker inspect #{id}").stdout
730-
info = json('').parse(raw)
731-
ports = info[0]['NetworkSettings']['Ports'].keys
701+
docker.ps.each do |id|
702+
info = docker.inspect(id)
703+
ports = info['NetworkSettings']['Ports'].keys
732704
ports.each do |item|
733-
info[0]['NetworkSettings']['Ports'][item].each do |hostip|
705+
info['NetworkSettings']['Ports'][item].each do |hostip|
734706
describe hostip['HostIp'] do
735707
it { should_not eq '0.0.0.0' }
736708
end
@@ -745,15 +717,13 @@
745717
desc 'Using the \'--restart\' flag in \'docker run\' 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.'
746718
ref 'https://docs.docker.com/engine/reference/commandline/cli/#restart-policies'
747719

748-
ids = command('docker ps --format "{{.ID}}"').stdout.split
749-
ids.each do |id|
750-
raw = command("docker inspect #{id}").stdout
751-
info = json('').parse(raw)
752-
only_if { info[0]['HostConfig']['RestartPolicy']['Name'] != 'no' }
753-
describe info[0] do
720+
docker.ps.each do |id|
721+
info = docker.inspect(id)
722+
only_if { info['HostConfig']['RestartPolicy']['Name'] != 'no' }
723+
describe info do
754724
its(%w(HostConfig RestartPolicy Name)) { should eq 'on-failure' }
755725
end
756-
describe info[0] do
726+
describe info do
757727
its(%w(HostConfig RestartPolicy MaximumRetryCount)) { should eq 5 }
758728
end
759729
end
@@ -766,11 +736,8 @@
766736
ref 'https://docs.docker.com/engine/reference/run/#pid-settings'
767737
ref 'http://man7.org/linux/man-pages/man7/pid_namespaces.7.html'
768738

769-
ids = command('docker ps --format "{{.ID}}"').stdout.split
770-
ids.each do |id|
771-
raw = command("docker inspect #{id}").stdout
772-
info = json('').parse(raw)
773-
describe info[0] do
739+
docker.ps.each do |id|
740+
describe docker.inspect(id) do
774741
its(%w(HostConfig PidMode)) { should_not eq 'host' }
775742
end
776743
end
@@ -783,11 +750,8 @@
783750
ref 'https://docs.docker.com/engine/reference/run/#ipc-settings'
784751
ref 'http://man7.org/linux/man-pages/man7/pid_namespaces.7.html'
785752

786-
ids = command('docker ps --format "{{.ID}}"').stdout.split
787-
ids.each do |id|
788-
raw = command("docker inspect #{id}").stdout
789-
info = json('').parse(raw)
790-
describe info[0] do
753+
docker.ps.each do |id|
754+
describe docker.inspect(id) do
791755
its(%w(HostConfig IpcMode)) { should_not eq 'host' }
792756
end
793757
end
@@ -799,11 +763,8 @@
799763
desc 'Host devices can be directly exposed to containers at runtime. Do not directly expose host devices to containers especially for containers that are not trusted.'
800764
ref 'https://docs.docker.com/engine/reference/commandline/cli/#run'
801765

802-
ids = command('docker ps --format "{{.ID}}"').stdout.split
803-
ids.each do |id|
804-
raw = command("docker inspect #{id}").stdout
805-
info = json('').parse(raw)
806-
describe info[0] do
766+
docker.ps.each do |id|
767+
describe docker.inspect(id) do
807768
its(%w(HostConfig Devices)) { should be_empty }
808769
end
809770
end
@@ -815,11 +776,8 @@
815776
desc 'The default ulimit is set at the Docker daemon level. However, you may override the default ulimit setting, if needed, during container runtime.'
816777
ref 'https://docs.docker.com/engine/reference/commandline/cli/#setting-ulimits-in-a-container'
817778

818-
ids = command('docker ps --format "{{.ID}}"').stdout.split
819-
ids.each do |id|
820-
raw = command("docker inspect #{id}").stdout
821-
info = json('').parse(raw)
822-
describe info[0] do
779+
docker.ps.each do |id|
780+
describe docker.inspect(id) do
823781
its(%w(HostConfig Ulimits)) { should eq nil }
824782
end
825783
end
@@ -833,8 +791,7 @@
833791
ref 'https://docs.docker.com/engine/reference/run/'
834792
ref 'https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt'
835793

836-
ids = command('docker ps --format "{{.ID}}"').stdout.split
837-
ids.each do |id|
794+
docker.ps.each do |id|
838795
raw = command("docker inspect --format '{{range $mnt := .Mounts}} {{json $mnt.Propagation}} {{end}}' #{id}").stdout
839796
describe raw.delete("\n").delete('\"').delete(' ') do
840797
it { should_not eq 'shared' }
@@ -849,11 +806,8 @@
849806
ref 'https://docs.docker.com/engine/reference/run/'
850807
ref 'http://man7.org/linux/man-pages/man7/pid_namespaces.7.html'
851808

852-
ids = command('docker ps --format "{{.ID}}"').stdout.split
853-
ids.each do |id|
854-
raw = command("docker inspect #{id}").stdout
855-
info = json('').parse(raw)
856-
describe info[0] do
809+
docker.ps.each do |id|
810+
describe docker.inspect(id) do
857811
its(%w(HostConfig UTSMode)) { should_not eq 'host' }
858812
end
859813
end
@@ -870,11 +824,8 @@
870824
ref 'https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt'
871825
ref 'https://github.com/docker/docker/pull/17034'
872826

873-
ids = command('docker ps --format "{{.ID}}"').stdout.split
874-
ids.each do |id|
875-
raw = command("docker inspect #{id}").stdout
876-
info = json('').parse(raw)
877-
describe info[0] do
827+
docker.ps.each do |id|
828+
describe docker.inspect(id) do
878829
its(%w(HostConfig SecurityOpt)) { should include(/seccomp/) }
879830
its(%w(HostConfig SecurityOpt)) { should_not include(/seccomp[=|:]unconfined/) }
880831
end
@@ -888,11 +839,8 @@
888839
ref 'https://docs.docker.com/engine/reference/run/#specifying-custom-cgroups'
889840
ref 'https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Resource_Management_Guide/ch01.html'
890841

891-
ids = command('docker ps --format "{{.ID}}"').stdout.split
892-
ids.each do |id|
893-
raw = command("docker inspect #{id}").stdout
894-
info = json('').parse(raw)
895-
describe info[0] do
842+
docker.ps.each do |id|
843+
describe docker.inspect(id) do
896844
its(%w(HostConfig CgroupParent)) { should be_empty }
897845
end
898846
end
@@ -908,11 +856,8 @@
908856
ref 'https://lwn.net/Articles/475678/'
909857
ref 'https://lwn.net/Articles/475362/'
910858

911-
ids = command('docker ps --format "{{.ID}}"').stdout.split
912-
ids.each do |id|
913-
raw = command("docker inspect #{id}").stdout
914-
info = json('').parse(raw)
915-
describe info[0] do
859+
docker.ps.each do |id|
860+
describe docker.inspect(id) do
916861
its(%w(HostConfig SecurityOpt)) { should include(/no-new-privileges/) }
917862
end
918863
end

controls/docker_level2.rb

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,8 @@
145145
ref 'http://wiki.apparmor.net/index.php/Main_Page'
146146

147147
only_if { os[:family] == ('ubuntu' || 'debian') }
148-
ids = command('docker ps --format "{{.ID}}"').stdout.split
149-
ids.each do |id|
150-
raw = command("docker inspect #{id}").stdout
151-
info = json('').parse(raw)
152-
describe info[0] do
148+
docker.ps.each do |id|
149+
describe docker.inspect(id) do
153150
its(['AppArmorProfile']) { should include(attrs['APP_ARMOR_PROFILE']) }
154151
its(['AppArmorProfile']) { should_not eq nil }
155152
end
@@ -171,11 +168,8 @@
171168
its(['selinux-enabled']) { should eq(true) }
172169
end
173170

174-
ids = command('docker ps --format "{{.ID}}"').stdout.split
175-
ids.each do |id|
176-
raw = command("docker inspect #{id}").stdout
177-
info = json('').parse(raw)
178-
describe info[0] do
171+
docker.ps.each do |id|
172+
describe docker.inspect(id) do
179173
its(%w(HostConfig SecurityOpt)) { should_not eq nil }
180174
its(%w(HostConfig SecurityOpt)) { should include(attrs['SELINUX_PROFILE']) }
181175
end

0 commit comments

Comments
 (0)