inspec 1.20.0 → 1.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -1
- data/docs/resources/docker.md.erb +160 -0
- data/docs/resources/docker_container.md.erb +89 -0
- data/docs/resources/docker_image.md.erb +86 -0
- data/docs/resources/{key_rsa.md → key_rsa.md.erb} +0 -0
- data/docs/resources/{x509_certificate.md → x509_certificate.md.erb} +0 -0
- data/docs/ruby_usage.md +50 -0
- data/inspec.gemspec +1 -1
- data/lib/bundles/inspec-habitat/profile.rb +14 -3
- data/lib/inspec/objects/test.rb +8 -7
- data/lib/inspec/resource.rb +3 -0
- data/lib/inspec/shell.rb +1 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/docker.rb +159 -0
- data/lib/resources/docker_container.rb +97 -0
- data/lib/resources/docker_image.rb +96 -0
- data/lib/resources/http.rb +3 -2
- data/lib/resources/powershell.rb +1 -1
- data/lib/resources/ssh_conf.rb +15 -3
- data/lib/resources/users.rb +31 -31
- metadata +13 -13
- data/examples/inheritance/inspec.lock +0 -11
- data/examples/meta-profile/inspec.lock +0 -18
- data/examples/meta-profile/vendor/11b6287b232c2a689ae87b3ba54897eb9067a749da074b6f3040b6442082dd6a.tar.gz +0 -0
- data/examples/meta-profile/vendor/379757a6ba73c9bc17b37353c1ff5b4eb7dd978a3bd38b29d2dda64f90f16c36.tar.gz +0 -0
- data/examples/meta-profile/vendor/dbb5602f09f58d86f8743dfb44327207e9a23a49ef34f65614f1c1d8cc145f6b.tar.gz +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 765c8898efac5c64dbba0583086f069eea4b521b
|
4
|
+
data.tar.gz: 28d639d2d72be737cb57366790ac1ee572eedc5c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a48f8574446241505bb8678bedc9069931841bee798e8d5dbeb133151e195191cacaa67bfb48441d219d498ed14752f98dea4273120138298df5530545e9b3d3
|
7
|
+
data.tar.gz: c3f91d119061a9695653ee94f50f8c2588b9c6eb08a262578f2caef1b75ac9bef41d290aaa2af51fe9d0e154be0e093aabae23173e1c583fadaa1714d69f7f35
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,42 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v1.21.0](https://github.com/chef/inspec/tree/v1.21.0) (2017-04-24)
|
4
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v1.20.0...v1.21.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- user resource is not fetching groups for windows [\#1400](https://github.com/chef/inspec/issues/1400)
|
9
|
+
- docker resources [\#71](https://github.com/chef/inspec/issues/71)
|
10
|
+
|
11
|
+
**Fixed bugs:**
|
12
|
+
|
13
|
+
- Web references in inspec shell help are wrong [\#1667](https://github.com/chef/inspec/issues/1667)
|
14
|
+
- bugfix: solve warn on uninitialized [\#1694](https://github.com/chef/inspec/pull/1694) ([arlimus](https://github.com/arlimus))
|
15
|
+
|
16
|
+
**Closed issues:**
|
17
|
+
|
18
|
+
- Adding windows domain users to users resource [\#1688](https://github.com/chef/inspec/issues/1688)
|
19
|
+
- stdout matcher has depreciation warnings [\#1685](https://github.com/chef/inspec/issues/1685)
|
20
|
+
- profile upload with dependencies fails uploading to compliance server [\#1670](https://github.com/chef/inspec/issues/1670)
|
21
|
+
- Retrying Inspec Tests [\#1665](https://github.com/chef/inspec/issues/1665)
|
22
|
+
- Add a way to retry a test if failing [\#1404](https://github.com/chef/inspec/issues/1404)
|
23
|
+
- --sudo does not appear to elevate privileges when evaluating local systems. [\#1279](https://github.com/chef/inspec/issues/1279)
|
24
|
+
|
25
|
+
**Merged pull requests:**
|
26
|
+
|
27
|
+
- \[www\] Update www Gemfile.lock [\#1691](https://github.com/chef/inspec/pull/1691) ([adamleff](https://github.com/adamleff))
|
28
|
+
- showing how to shellout in docs [\#1689](https://github.com/chef/inspec/pull/1689) ([rshade](https://github.com/rshade))
|
29
|
+
- \[www\] Fix docs pages for x509\_certificate and key\_rsa [\#1683](https://github.com/chef/inspec/pull/1683) ([adamleff](https://github.com/adamleff))
|
30
|
+
- fix spelling mistake in powershell resource documentation [\#1682](https://github.com/chef/inspec/pull/1682) ([Happycoil](https://github.com/Happycoil))
|
31
|
+
- fetch user groups while building user object [\#1681](https://github.com/chef/inspec/pull/1681) ([Happycoil](https://github.com/Happycoil))
|
32
|
+
- update sslshake to v1.2 [\#1680](https://github.com/chef/inspec/pull/1680) ([arlimus](https://github.com/arlimus))
|
33
|
+
- Fix type-o in control code [\#1676](https://github.com/chef/inspec/pull/1676) ([hannah-radish](https://github.com/hannah-radish))
|
34
|
+
- fix web reference url [\#1669](https://github.com/chef/inspec/pull/1669) ([chris-rock](https://github.com/chris-rock))
|
35
|
+
- fix sshd config help [\#1668](https://github.com/chef/inspec/pull/1668) ([chris-rock](https://github.com/chris-rock))
|
36
|
+
- ER-508 Extended http resource to support no ssl verification [\#1663](https://github.com/chef/inspec/pull/1663) ([ElizabethU](https://github.com/ElizabethU))
|
37
|
+
- Move Habitat sleep time to config file [\#1662](https://github.com/chef/inspec/pull/1662) ([adamleff](https://github.com/adamleff))
|
38
|
+
- Docker resource [\#1566](https://github.com/chef/inspec/pull/1566) ([chris-rock](https://github.com/chris-rock))
|
39
|
+
|
3
40
|
## [v1.20.0](https://github.com/chef/inspec/tree/v1.20.0) (2017-04-13)
|
4
41
|
[Full Changelog](https://github.com/chef/inspec/compare/v1.19.2...v1.20.0)
|
5
42
|
|
@@ -15,6 +52,7 @@
|
|
15
52
|
|
16
53
|
**Merged pull requests:**
|
17
54
|
|
55
|
+
- Release 1.20.0 [\#1657](https://github.com/chef/inspec/pull/1657) ([adamleff](https://github.com/adamleff))
|
18
56
|
- Habitat packages should run as root [\#1656](https://github.com/chef/inspec/pull/1656) ([adamleff](https://github.com/adamleff))
|
19
57
|
- harmonize compliance profiles view with supermarket views [\#1654](https://github.com/chef/inspec/pull/1654) ([chris-rock](https://github.com/chris-rock))
|
20
58
|
- \[www\] Update community page [\#1651](https://github.com/chef/inspec/pull/1651) ([adamleff](https://github.com/adamleff))
|
@@ -466,6 +504,7 @@
|
|
466
504
|
- do not load controls from test directory [\#1327](https://github.com/chef/inspec/pull/1327) ([chris-rock](https://github.com/chris-rock))
|
467
505
|
- Replaced Colors for output [\#1320](https://github.com/chef/inspec/pull/1320) ([hannah-radish](https://github.com/hannah-radish))
|
468
506
|
- Hannah vj/fix tests formatting [\#1319](https://github.com/chef/inspec/pull/1319) ([hannah-radish](https://github.com/hannah-radish))
|
507
|
+
- revert style changes temporarily [\#1317](https://github.com/chef/inspec/pull/1317) ([vjeffrey](https://github.com/vjeffrey))
|
469
508
|
- Updated color palettes, label colors and icons [\#1313](https://github.com/chef/inspec/pull/1313) ([hannah-radish](https://github.com/hannah-radish))
|
470
509
|
- Remove extra `'` in registry key examples [\#1308](https://github.com/chef/inspec/pull/1308) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
|
471
510
|
- also push docker latest tag with each release [\#1307](https://github.com/chef/inspec/pull/1307) ([chris-rock](https://github.com/chris-rock))
|
@@ -486,7 +525,6 @@
|
|
486
525
|
|
487
526
|
**Merged pull requests:**
|
488
527
|
|
489
|
-
- revert style changes temporarily [\#1317](https://github.com/chef/inspec/pull/1317) ([vjeffrey](https://github.com/vjeffrey))
|
490
528
|
- ensure metadata release entry is a string [\#1305](https://github.com/chef/inspec/pull/1305) ([chris-rock](https://github.com/chris-rock))
|
491
529
|
- Fixes resources in the docs [\#1303](https://github.com/chef/inspec/pull/1303) ([burtlo](https://github.com/burtlo))
|
492
530
|
- copy vendored dependencies into cache [\#1291](https://github.com/chef/inspec/pull/1291) ([chris-rock](https://github.com/chris-rock))
|
@@ -0,0 +1,160 @@
|
|
1
|
+
---
|
2
|
+
title: About the docker Resource
|
3
|
+
---
|
4
|
+
|
5
|
+
# docker
|
6
|
+
|
7
|
+
Use the `docker` InSpec audit resource to test configuration data for docker daemon. It is a very comprehensive resource. Please have a look at [docker_container](docker_container) and [docker_image](docker_image), too.
|
8
|
+
|
9
|
+
## Syntax
|
10
|
+
|
11
|
+
A `docker` resource block declares allows you to write test for many containers:
|
12
|
+
|
13
|
+
describe docker.containers do
|
14
|
+
its('images') { should_not include 'u12:latest' }
|
15
|
+
end
|
16
|
+
|
17
|
+
or:
|
18
|
+
|
19
|
+
describe docker.containers.where { name == 'flamboyant_colden' } do
|
20
|
+
it { should be_running }
|
21
|
+
end
|
22
|
+
|
23
|
+
where
|
24
|
+
|
25
|
+
* `.where()` may specify a specific item and value, to which the matchers are compared
|
26
|
+
* `commands`, `ids`, `images`, `labels`, `local_volumes`, `mounts`, `names`, `networks`, `ports`, `sizes` and `'status'` are valid matchers for `containers`
|
27
|
+
|
28
|
+
The `docker` resource block also declares allows you to write test for many images:
|
29
|
+
|
30
|
+
describe docker.images do
|
31
|
+
its('repositories') { should_not include 'inssecure_image' }
|
32
|
+
end
|
33
|
+
|
34
|
+
or if you want to query specific images:
|
35
|
+
|
36
|
+
describe docker.images.where { repository == 'ubuntu' && tag == '12.04' } do
|
37
|
+
it { should_not exist }
|
38
|
+
end
|
39
|
+
|
40
|
+
where
|
41
|
+
|
42
|
+
* `.where()` may specify a specific item and value, to which the matchers are compared
|
43
|
+
* `commands`, `ids`, `images`, `labels`, `local_volumes`, `mounts`, `names`, `networks`, `ports`, `sizes` and `'status'` are valid matchers for `containers`
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
## Matchers
|
48
|
+
|
49
|
+
This InSpec audit resource has the following matchers:
|
50
|
+
|
51
|
+
### containers
|
52
|
+
|
53
|
+
`containers` returns information about containers as returned by [docker ps -a](https://docs.docker.com/engine/reference/commandline/ps/). You can determine specific information about
|
54
|
+
|
55
|
+
describe docker.containers do
|
56
|
+
its('ids') { should include 'sha:71b5df59...442b' }
|
57
|
+
its('commands') { should_not include '/bin/sh' }
|
58
|
+
its('images') { should_not include 'u12:latest' }
|
59
|
+
its('ports') { should include '0.0.0.0:1234->1234/tcp' }
|
60
|
+
its('labels') { should include 'License=GPLv2,Vendor=CentOS' }
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
### images
|
65
|
+
|
66
|
+
`images` returns information about docker image as returned by [docker images](https://docs.docker.com/engine/reference/commandline/images/). You can determine specific information about
|
67
|
+
|
68
|
+
describe docker.images do
|
69
|
+
its('ids') { should include 'sha:12b5df59...442b' }
|
70
|
+
its('repositories') { should_not include 'my_image' }
|
71
|
+
its('tags') { should_not include 'unwanted_tag' }
|
72
|
+
its('sizes') { should_not include "1.41 GB" }
|
73
|
+
end
|
74
|
+
|
75
|
+
### version
|
76
|
+
|
77
|
+
`info` returns the parsed result of [docker version](https://docs.docker.com/engine/reference/commandline/version/)
|
78
|
+
|
79
|
+
describe docker.version do
|
80
|
+
its('Server.Version') { should cmp >= '1.12'}
|
81
|
+
its('Client.Version') { should cmp >= '1.12'}
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
### info
|
86
|
+
|
87
|
+
`info` returns the parsed result of [docker info](https://docs.docker.com/engine/reference/commandline/info/)
|
88
|
+
|
89
|
+
describe docker.info do
|
90
|
+
its('Configuration.Path') { should eq 'value' }
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
### object('id')
|
95
|
+
|
96
|
+
`object` returns low-level information about docker objects. It is calling [docker inspect](https://docs.docker.com/engine/reference/commandline/info/) under the hood.
|
97
|
+
|
98
|
+
describe docker.object(id) do
|
99
|
+
its('Configuration.Path') { should eq 'value' }
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
## Examples
|
104
|
+
|
105
|
+
The following examples show how to use this InSpec audit resource.
|
106
|
+
|
107
|
+
### Return all running containers
|
108
|
+
|
109
|
+
docker.containers.running?.ids.each do |id|
|
110
|
+
describe docker.object(id) do
|
111
|
+
its('State.Health.Status') { should eq 'healthy' }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
### Verify a Docker Server and Client version
|
116
|
+
|
117
|
+
describe docker.version do
|
118
|
+
its('Server.Version') { should cmp >= '1.12'}
|
119
|
+
its('Client.Version') { should cmp >= '1.12'}
|
120
|
+
end
|
121
|
+
|
122
|
+
### Iterate over all containers to verify host coniguration
|
123
|
+
|
124
|
+
docker.containers.ids.each do |id|
|
125
|
+
# call docker inspect for a specific container id
|
126
|
+
describe docker.object(id) do
|
127
|
+
its(%w(HostConfig Privileged)) { should cmp false }
|
128
|
+
its(%w(HostConfig Privileged)) { should_not cmp true }
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
### Iterate over all images to verify the container was built without ADD instruction
|
133
|
+
|
134
|
+
docker.images.ids.each do |id|
|
135
|
+
describe command("docker history #{id}| grep 'ADD'") do
|
136
|
+
its('stdout') { should eq '' }
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
### Verify that health-checks are enabled for a container
|
141
|
+
|
142
|
+
describe docker.object('71b5df59442b') do
|
143
|
+
its(%w(Config Healthcheck)) { should_not eq nil }
|
144
|
+
end
|
145
|
+
|
146
|
+
### Run the DevSec docker baseline profile
|
147
|
+
|
148
|
+
There are two ways to run the `docker-baseline` profile to test Docker via the `docker` resource.
|
149
|
+
|
150
|
+
Clone the profile:
|
151
|
+
|
152
|
+
$ git clone https://github.com/dev-sec/cis-docker-benchmark.git
|
153
|
+
|
154
|
+
and then run:
|
155
|
+
|
156
|
+
$ inspec exec cis-docker-benchmark
|
157
|
+
|
158
|
+
Or execute the profile directly via URL:
|
159
|
+
|
160
|
+
$ inspec exec https://github.com/dev-sec/cis-docker-benchmark
|
@@ -0,0 +1,89 @@
|
|
1
|
+
---
|
2
|
+
title: About the docker_container Resource
|
3
|
+
---
|
4
|
+
|
5
|
+
# docker_container
|
6
|
+
|
7
|
+
Use the `docker_container` InSpec audit resource to test a docker container.
|
8
|
+
|
9
|
+
## Syntax
|
10
|
+
|
11
|
+
A `docker_container` resource block declares the configuration data to be tested:
|
12
|
+
|
13
|
+
describe docker_container('container') do
|
14
|
+
it { should exist }
|
15
|
+
it { should be_running }
|
16
|
+
its('id') { should_not eq '' }
|
17
|
+
its('image') { should eq 'busybox:latest' }
|
18
|
+
its('repo') { should eq 'busybox' }
|
19
|
+
its('tag') { should eq 'latest' }
|
20
|
+
its('ports') { should eq [] }
|
21
|
+
its('command') { should eq 'nc -ll -p 1234 -e /bin/cat' }
|
22
|
+
end
|
23
|
+
|
24
|
+
The container name can also be passed with the `name` argument:
|
25
|
+
|
26
|
+
describe docker_container(name: 'an-echo-server') do
|
27
|
+
it { should exist }
|
28
|
+
it { should be_running }
|
29
|
+
end
|
30
|
+
|
31
|
+
Alternatively, you can pass in the container id:
|
32
|
+
|
33
|
+
describe docker_container(id: '71b5df59442b') do
|
34
|
+
it { should exist }
|
35
|
+
it { should be_running }
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
## Matchers
|
40
|
+
|
41
|
+
This InSpec audit resource has the following matchers:
|
42
|
+
|
43
|
+
### id
|
44
|
+
|
45
|
+
The `id` matcher tests the container id:
|
46
|
+
|
47
|
+
its('id') { should eq 'sha:71b5df59...442b' }
|
48
|
+
|
49
|
+
### repo
|
50
|
+
|
51
|
+
The `repo` matcher tests the value of the image repository:
|
52
|
+
|
53
|
+
its('repo') { should eq 'busybox' }
|
54
|
+
|
55
|
+
### tag
|
56
|
+
|
57
|
+
The `tag` matcher tests the value of the image tag:
|
58
|
+
|
59
|
+
its('tag') { should eq 'latest' }
|
60
|
+
|
61
|
+
### ports
|
62
|
+
|
63
|
+
The `ports` matcher tests the value the docker ports:
|
64
|
+
|
65
|
+
its('ports') { should eq '0.0.0.0:1234->1234/tcp' }
|
66
|
+
|
67
|
+
### command
|
68
|
+
|
69
|
+
The `command` matcher tests the value of the container run command:
|
70
|
+
|
71
|
+
its('command') { should eq 'nc -ll -p 1234 -e /bin/cat' }
|
72
|
+
|
73
|
+
|
74
|
+
## Examples
|
75
|
+
|
76
|
+
The following examples show how to use this InSpec resource.
|
77
|
+
|
78
|
+
### Verify an running container:
|
79
|
+
|
80
|
+
describe docker_container('an-echo-server') do
|
81
|
+
it { should exist }
|
82
|
+
it { should be_running }
|
83
|
+
its('id') { should_not eq '' }
|
84
|
+
its('image') { should eq 'busybox:latest' }
|
85
|
+
its('repo') { should eq 'busybox' }
|
86
|
+
its('tag') { should eq 'latest' }
|
87
|
+
its('ports') { should eq [] }
|
88
|
+
its('command') { should eq 'nc -ll -p 1234 -e /bin/cat' }
|
89
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
---
|
2
|
+
title: About the docker_image Resource
|
3
|
+
---
|
4
|
+
|
5
|
+
# docker_image
|
6
|
+
|
7
|
+
Use the `docker_image` InSpec audit resource to verify a docker image.
|
8
|
+
|
9
|
+
## Syntax
|
10
|
+
|
11
|
+
A `docker_image` resource block declares the image:
|
12
|
+
|
13
|
+
describe docker_image('alpine:latest') do
|
14
|
+
it { should exist }
|
15
|
+
its('id') { should eq 'sha256:4a415e...a526' }
|
16
|
+
its('repo') { should eq 'alpine' }
|
17
|
+
its('tag') { should eq 'latest' }
|
18
|
+
end
|
19
|
+
|
20
|
+
The resource allows you to pass in an image id:
|
21
|
+
|
22
|
+
describe docker_image(id: alpine_id) do
|
23
|
+
...
|
24
|
+
end
|
25
|
+
|
26
|
+
If the tag is missing for an image, `latest` is assumed as default:
|
27
|
+
|
28
|
+
describe docker_image('alpine') do
|
29
|
+
...
|
30
|
+
end
|
31
|
+
|
32
|
+
You can also pass in repository and tag as separate values
|
33
|
+
|
34
|
+
describe docker_image(repo: 'alpine', tag: 'latest') do
|
35
|
+
...
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
## Matchers
|
40
|
+
|
41
|
+
This InSpec audit resource has the following matchers:
|
42
|
+
|
43
|
+
### exist
|
44
|
+
|
45
|
+
The `exist` matcher tests if the image is available on the node:
|
46
|
+
|
47
|
+
it { should exist }
|
48
|
+
|
49
|
+
### id
|
50
|
+
|
51
|
+
The `id` matcher returns the full image id:
|
52
|
+
|
53
|
+
its('id') { should eq 'sha256:4a415e3663882fbc554ee830889c68a33b3585503892cc718a4698e91ef2a526' }
|
54
|
+
|
55
|
+
### image
|
56
|
+
|
57
|
+
The `image` matcher tests the value of the image. It is a combination of `repository/tag`:
|
58
|
+
|
59
|
+
its('image') { should eq 'alpine:latest' }
|
60
|
+
|
61
|
+
### repo
|
62
|
+
|
63
|
+
The `repo` matcher tests the value of the repository name:
|
64
|
+
|
65
|
+
its('repo') { should eq 'alpine' }
|
66
|
+
|
67
|
+
### tag
|
68
|
+
|
69
|
+
The `tag` matcher tests the value of image tag:
|
70
|
+
|
71
|
+
its('tag') { should eq 'latest' }
|
72
|
+
|
73
|
+
|
74
|
+
## Examples
|
75
|
+
|
76
|
+
The following examples show how to use this InSpec `docker_image` resource.
|
77
|
+
|
78
|
+
### Test a docker image
|
79
|
+
|
80
|
+
describe docker_image('alpine:latest') do
|
81
|
+
it { should exist }
|
82
|
+
its('id') { should eq 'sha256:4a415e...a526' }
|
83
|
+
its('image') { should eq 'alpine:latest' }
|
84
|
+
its('repo') { should eq 'alpine' }
|
85
|
+
its('tag') { should eq 'latest' }
|
86
|
+
end
|
File without changes
|
File without changes
|
data/docs/ruby_usage.md
CHANGED
@@ -152,3 +152,53 @@ describe command('ls -al /') do
|
|
152
152
|
its('exit_status') { should eq 0 }
|
153
153
|
end
|
154
154
|
```
|
155
|
+
|
156
|
+
## Shelling out in tests
|
157
|
+
|
158
|
+
When writing tests you can not use standard ruby methods to shellout as it tries to execute those commands locally.
|
159
|
+
However, the `command` resource has a `.stdout` method that will allow you to manipulate the results.
|
160
|
+
Using the above example, you could check the writes on several subdirectories.
|
161
|
+
|
162
|
+
### Example 1:
|
163
|
+
```ruby
|
164
|
+
$ inspec shell
|
165
|
+
Welcome to the interactive InSpec Shell
|
166
|
+
To find out how to use it, type: help
|
167
|
+
|
168
|
+
inspec> output=command('echo test').stdout
|
169
|
+
=> "test\n"
|
170
|
+
inspec> describe command('echo test') do
|
171
|
+
inspec> its('stdout') { should eq output }
|
172
|
+
inspec> end
|
173
|
+
|
174
|
+
Profile: inspec-shell
|
175
|
+
Version: (not specified)
|
176
|
+
|
177
|
+
Command echo
|
178
|
+
✔ test stdout should eq "test\n"
|
179
|
+
|
180
|
+
Test Summary: 1 successful, 0 failures, 0 skipped
|
181
|
+
```
|
182
|
+
|
183
|
+
### Example 2:
|
184
|
+
```ruby
|
185
|
+
$ inspec shell
|
186
|
+
Welcome to the interactive InSpec Shell
|
187
|
+
To find out how to use it, type: help
|
188
|
+
|
189
|
+
inspec> dirs = command('ls -d /home/gordon/git/inspec/docs').stdout.split("\n")
|
190
|
+
=> ["/home/gordon/git/inspec/docs"]
|
191
|
+
inspec> dirs.each do |dir|
|
192
|
+
inspec> describe directory(dir) do
|
193
|
+
inspec> its('mode') { should cmp '0775' }
|
194
|
+
inspec> end
|
195
|
+
inspec> end
|
196
|
+
|
197
|
+
Profile: inspec-shell
|
198
|
+
Version: (not specified)
|
199
|
+
|
200
|
+
File /home/gordon/git/inspec/docs/
|
201
|
+
✔ mode should cmp == "0775"
|
202
|
+
|
203
|
+
Test Summary: 1 successful, 0 failures, 0 skipped
|
204
|
+
```
|
data/inspec.gemspec
CHANGED
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
|
|
37
37
|
spec.add_dependency 'pry', '~> 0'
|
38
38
|
spec.add_dependency 'hashie', '~> 3.4'
|
39
39
|
spec.add_dependency 'mixlib-log'
|
40
|
-
spec.add_dependency 'sslshake', '~> 1.
|
40
|
+
spec.add_dependency 'sslshake', '~> 1.2'
|
41
41
|
spec.add_dependency 'parallel', '~> 1.9'
|
42
42
|
spec.add_dependency 'faraday', '>=0.9.0'
|
43
43
|
spec.add_dependency 'toml', '~> 0.1'
|
@@ -43,6 +43,7 @@ module Habitat
|
|
43
43
|
copy_profile_to_work_dir
|
44
44
|
create_plan
|
45
45
|
create_run_hook
|
46
|
+
create_settings_file
|
46
47
|
create_default_config
|
47
48
|
|
48
49
|
# returns the path to the .hart file in the work directory
|
@@ -152,6 +153,7 @@ module Habitat
|
|
152
153
|
@work_dir ||= Dir.mktmpdir('inspec-habitat-exporter')
|
153
154
|
Dir.mkdir(File.join(@work_dir, 'src'))
|
154
155
|
Dir.mkdir(File.join(@work_dir, 'habitat'))
|
156
|
+
Dir.mkdir(File.join(@work_dir, 'habitat', 'config'))
|
155
157
|
Dir.mkdir(File.join(@work_dir, 'habitat', 'hooks'))
|
156
158
|
Habitat::Log.debug("Generated work directory #{@work_dir}")
|
157
159
|
|
@@ -185,6 +187,12 @@ module Habitat
|
|
185
187
|
File.write(run_hook_file, run_hook_contents)
|
186
188
|
end
|
187
189
|
|
190
|
+
def create_settings_file
|
191
|
+
settings_file = File.join(work_dir, 'habitat', 'config', 'settings.sh')
|
192
|
+
Habitat::Log.info("Generating a settings file at #{settings_file}...")
|
193
|
+
File.write(settings_file, "SLEEP_TIME={{cfg.sleep_time}}\n")
|
194
|
+
end
|
195
|
+
|
188
196
|
def create_default_config
|
189
197
|
default_toml = File.join(work_dir, 'habitat', 'default.toml')
|
190
198
|
Habitat::Log.info("Generating Habitat's default.toml configuration...")
|
@@ -335,7 +343,6 @@ export PATH=${PATH}:$(hab pkg path core/ruby)/bin
|
|
335
343
|
export HOME={{pkg.svc_var_path}}
|
336
344
|
|
337
345
|
PROFILE_IDENT="#{habitat_origin}/#{package_name}"
|
338
|
-
SLEEP_TIME={{cfg.sleep_time}}
|
339
346
|
RESULTS_DIR="{{pkg.svc_var_path}}/inspec_results"
|
340
347
|
RESULTS_FILE="${RESULTS_DIR}/#{package_name}.json"
|
341
348
|
ERROR_FILE="{{pkg.svc_var_path}}/inspec.err"
|
@@ -350,11 +357,15 @@ while true; do
|
|
350
357
|
|
351
358
|
if [ "x${RC}" == "x0" ]; then
|
352
359
|
echo "InSpec run completed successfully."
|
353
|
-
|
354
|
-
echo "InSpec run did NOT complete successfully."
|
360
|
+
elsif [ -s ${ERROR_FILE} ]
|
361
|
+
echo "InSpec run did NOT complete successfully. Error:"
|
355
362
|
cat ${ERROR_FILE}
|
363
|
+
else
|
364
|
+
echo "InSpec run completed successfully, but there were control failures."
|
365
|
+
echo "Check the output at ${RESULTS_FILE} for details."
|
356
366
|
fi
|
357
367
|
|
368
|
+
source {{pkg.svc_config_path}}/settings.sh
|
358
369
|
echo "sleeping for ${SLEEP_TIME} seconds"
|
359
370
|
sleep ${SLEEP_TIME}
|
360
371
|
done
|
data/lib/inspec/objects/test.rb
CHANGED
@@ -66,13 +66,14 @@ module Inspec
|
|
66
66
|
res, xtra = describe_chain
|
67
67
|
itsy = xtra.nil? ? 'it' : 'its(' + xtra.to_s.inspect + ')'
|
68
68
|
naughty = @negated ? '_not' : ''
|
69
|
-
xpect = defined?(@expectation)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
69
|
+
xpect = if !defined?(@expectation)
|
70
|
+
''
|
71
|
+
elsif @expectation.class == Regexp
|
72
|
+
# without this, xpect values like / \/zones\// will not be parsed properly
|
73
|
+
"(#{@expectation.inspect})"
|
74
|
+
elsif xpect != ''
|
75
|
+
' ' + expectation.inspect
|
76
|
+
end
|
76
77
|
format("%sdescribe %s do\n %s { should%s %s%s }\nend",
|
77
78
|
vars, res, itsy, naughty, matcher, xpect)
|
78
79
|
end
|
data/lib/inspec/resource.rb
CHANGED
@@ -82,6 +82,9 @@ require 'resources/command'
|
|
82
82
|
require 'resources/crontab'
|
83
83
|
require 'resources/dh_params'
|
84
84
|
require 'resources/directory'
|
85
|
+
require 'resources/docker'
|
86
|
+
require 'resources/docker_image'
|
87
|
+
require 'resources/docker_container'
|
85
88
|
require 'resources/etc_group'
|
86
89
|
require 'resources/file'
|
87
90
|
require 'resources/gem'
|
data/lib/inspec/shell.rb
CHANGED
data/lib/inspec/version.rb
CHANGED
@@ -0,0 +1,159 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Copyright 2017, Christoph Hartmann
|
4
|
+
#
|
5
|
+
# author: Christoph Hartmann
|
6
|
+
# author: Patrick Muench
|
7
|
+
# author: Dominik Richter
|
8
|
+
|
9
|
+
require 'utils/filter'
|
10
|
+
require 'hashie/mash'
|
11
|
+
|
12
|
+
module Inspec::Resources
|
13
|
+
class DockerContainerFilter
|
14
|
+
# use filtertable for containers
|
15
|
+
filter = FilterTable.create
|
16
|
+
filter.add_accessor(:where)
|
17
|
+
.add_accessor(:entries)
|
18
|
+
.add(:commands, field: 'command')
|
19
|
+
.add(:ids, field: 'id')
|
20
|
+
.add(:images, field: 'image')
|
21
|
+
.add(:labels, field: 'labels')
|
22
|
+
.add(:local_volumes, field: 'localvolumes')
|
23
|
+
.add(:mounts, field: 'mounts')
|
24
|
+
.add(:names, field: 'names')
|
25
|
+
.add(:networks, field: 'networks')
|
26
|
+
.add(:ports, field: 'ports')
|
27
|
+
.add(:running_for, field: 'runningfor')
|
28
|
+
.add(:sizes, field: 'size')
|
29
|
+
.add(:status, field: 'status')
|
30
|
+
.add(:exists?) { |x| !x.entries.empty? }
|
31
|
+
.add(:running?) { |x|
|
32
|
+
x.where { status.downcase.start_with?('up') }
|
33
|
+
}
|
34
|
+
filter.connect(self, :containers)
|
35
|
+
|
36
|
+
attr_reader :containers
|
37
|
+
def initialize(containers)
|
38
|
+
@containers = containers
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class DockerImageFilter
|
43
|
+
filter = FilterTable.create
|
44
|
+
filter.add_accessor(:where)
|
45
|
+
.add_accessor(:entries)
|
46
|
+
.add(:ids, field: 'id')
|
47
|
+
.add(:repositories, field: 'repository')
|
48
|
+
.add(:tags, field: 'tag')
|
49
|
+
.add(:sizes, field: 'size')
|
50
|
+
.add(:digests, field: 'digest')
|
51
|
+
.add(:created, field: 'createdat')
|
52
|
+
.add(:created_since, field: 'createdsize')
|
53
|
+
.add(:exists?) { |x| !x.entries.empty? }
|
54
|
+
filter.connect(self, :images)
|
55
|
+
|
56
|
+
attr_reader :images
|
57
|
+
def initialize(images)
|
58
|
+
@images = images
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# This resource helps to parse information from the docker host
|
63
|
+
# For compatability with Serverspec we also offer the following resouses:
|
64
|
+
# - docker_container
|
65
|
+
# - docker_image
|
66
|
+
class Docker < Inspec.resource(1)
|
67
|
+
name 'docker'
|
68
|
+
|
69
|
+
desc "
|
70
|
+
A resource to retrieve information about docker
|
71
|
+
"
|
72
|
+
|
73
|
+
example "
|
74
|
+
describe docker.containers do
|
75
|
+
its('images') { should_not include 'u12:latest' }
|
76
|
+
end
|
77
|
+
|
78
|
+
describe docker.images do
|
79
|
+
its('repositories') { should_not include 'inssecure_image' }
|
80
|
+
end
|
81
|
+
|
82
|
+
describe docker.version do
|
83
|
+
its('Server.Version') { should cmp >= '1.12'}
|
84
|
+
its('Client.Version') { should cmp >= '1.12'}
|
85
|
+
end
|
86
|
+
|
87
|
+
describe docker.object(id) do
|
88
|
+
its('Configuration.Path') { should eq 'value' }
|
89
|
+
end
|
90
|
+
|
91
|
+
docker.containers.ids.each do |id|
|
92
|
+
# call docker inspect for a specific container id
|
93
|
+
describe docker.object(id) do
|
94
|
+
its(%w(HostConfig Privileged)) { should cmp false }
|
95
|
+
its(%w(HostConfig Privileged)) { should_not cmp true }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
"
|
99
|
+
|
100
|
+
def containers
|
101
|
+
DockerContainerFilter.new(parse_containers)
|
102
|
+
end
|
103
|
+
|
104
|
+
def images
|
105
|
+
DockerImageFilter.new(parse_images)
|
106
|
+
end
|
107
|
+
|
108
|
+
def version
|
109
|
+
return @version if defined?(@version)
|
110
|
+
data = JSON.parse(inspec.command('docker version --format \'{{ json . }}\'').stdout)
|
111
|
+
@version = Hashie::Mash.new(data)
|
112
|
+
end
|
113
|
+
|
114
|
+
def info
|
115
|
+
return @info if defined?(@info)
|
116
|
+
data = JSON.parse(inspec.command('docker info --format \'{{ json . }}\'').stdout)
|
117
|
+
@info = Hashie::Mash.new(data)
|
118
|
+
end
|
119
|
+
|
120
|
+
# returns information about docker objects
|
121
|
+
def object(id)
|
122
|
+
return @inspect if defined?(@inspect)
|
123
|
+
data = JSON.parse(inspec.command("docker inspect #{id}").stdout)
|
124
|
+
data = data[0] if data.is_a?(Array)
|
125
|
+
@inspect = Hashie::Mash.new(data)
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_s
|
129
|
+
'Docker Host'
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def parse_containers
|
135
|
+
raw_containers = inspec.command('docker ps -a --no-trunc --format \'{{ json . }}\'').stdout
|
136
|
+
ps = []
|
137
|
+
# since docker is not outputting valid json, we need to parse each row
|
138
|
+
raw_containers.each_line { |entry|
|
139
|
+
j = JSON.parse(entry)
|
140
|
+
# convert all keys to lower_case to work well with ruby and filter table
|
141
|
+
j = j.map { |k, v|
|
142
|
+
[k.downcase, v]
|
143
|
+
}.to_h
|
144
|
+
ps.push(j)
|
145
|
+
}
|
146
|
+
ps
|
147
|
+
end
|
148
|
+
|
149
|
+
def parse_images
|
150
|
+
# docker does not support the `json .` function here, therefore we need to emulate that behavior.
|
151
|
+
raw_images = inspec.command('docker images -a --no-trunc --format \'{ "id": {{json .ID}}, "repository": {{json .Repository}}, "tag": {{json .Tag}}, "size": {{json .Size}}, "digest": {{json .Digest}}, "createdat": {{json .CreatedAt}}, "createdsize": {{json .CreatedSince}} }\'').stdout
|
152
|
+
c_images = []
|
153
|
+
raw_images.each_line { |entry|
|
154
|
+
c_images.push(JSON.parse(entry))
|
155
|
+
}
|
156
|
+
c_images
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Copyright 2017, Christoph Hartmann
|
4
|
+
#
|
5
|
+
# author: Christoph Hartmann
|
6
|
+
# author: Patrick Muench
|
7
|
+
# author: Dominik Richter
|
8
|
+
|
9
|
+
module Inspec::Resources
|
10
|
+
class DockerContainer < Inspec.resource(1)
|
11
|
+
name 'docker_container'
|
12
|
+
desc ''
|
13
|
+
example "
|
14
|
+
describe docker_container('an-echo-server') do
|
15
|
+
it { should exist }
|
16
|
+
it { should be_running }
|
17
|
+
its('id') { should_not eq '' }
|
18
|
+
its('image') { should eq 'busybox:latest' }
|
19
|
+
its('repo') { should eq 'busybox' }
|
20
|
+
its('tag') { should eq 'latest' }
|
21
|
+
its('ports') { should eq [] }
|
22
|
+
its('command') { should eq 'nc -ll -p 1234 -e /bin/cat' }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe docker_container(id: 'e2c52a183358') do
|
26
|
+
it { should exist }
|
27
|
+
it { should be_running }
|
28
|
+
end
|
29
|
+
"
|
30
|
+
|
31
|
+
def initialize(opts = {})
|
32
|
+
# if a string is provided, we expect it is the name
|
33
|
+
if opts.is_a?(String)
|
34
|
+
@opts = { name: opts }
|
35
|
+
else
|
36
|
+
@opts = opts
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def exist?
|
41
|
+
container_info.exists?
|
42
|
+
end
|
43
|
+
|
44
|
+
# is allways returning the full id
|
45
|
+
def id
|
46
|
+
container_info.ids[0] if container_info.entries.length == 1
|
47
|
+
end
|
48
|
+
|
49
|
+
def running?
|
50
|
+
status.downcase.start_with?('up') if container_info.entries.length == 1
|
51
|
+
end
|
52
|
+
|
53
|
+
def status
|
54
|
+
container_info.status[0] if container_info.entries.length == 1
|
55
|
+
end
|
56
|
+
|
57
|
+
def labels
|
58
|
+
container_info.labels[0] if container_info.entries.length == 1
|
59
|
+
end
|
60
|
+
|
61
|
+
def ports
|
62
|
+
container_info.ports[0] if container_info.entries.length == 1
|
63
|
+
end
|
64
|
+
|
65
|
+
def command
|
66
|
+
if container_info.entries.length == 1
|
67
|
+
cmd = container_info.commands[0]
|
68
|
+
cmd.slice(1, cmd.length - 2)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def image
|
73
|
+
container_info.images[0] if container_info.entries.length == 1
|
74
|
+
end
|
75
|
+
|
76
|
+
def repo
|
77
|
+
image.split(':')[0] unless image.nil?
|
78
|
+
end
|
79
|
+
|
80
|
+
def tag
|
81
|
+
image.split(':')[1] unless image.nil?
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_s
|
85
|
+
name = @opts[:name] || @opts[:id]
|
86
|
+
"Docker Container #{name}"
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def container_info
|
92
|
+
return @info if defined?(@info)
|
93
|
+
opts = @opts
|
94
|
+
@info = inspec.docker.containers.where { names == opts[:name] || (!id.nil? && !opts[:id].nil? && (id == opts[:id] || id.start_with?(opts[:id]))) }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Copyright 2017, Christoph Hartmann
|
4
|
+
#
|
5
|
+
# author: Christoph Hartmann
|
6
|
+
# author: Patrick Muench
|
7
|
+
# author: Dominik Richter
|
8
|
+
|
9
|
+
module Inspec::Resources
|
10
|
+
class DockerImage < Inspec.resource(1)
|
11
|
+
name 'docker_image'
|
12
|
+
desc ''
|
13
|
+
example "
|
14
|
+
describe docker_image('alpine:latest') do
|
15
|
+
it { should exist }
|
16
|
+
its('id') { should_not eq '' }
|
17
|
+
its('image') { should eq 'alpine:latest' }
|
18
|
+
its('repo') { should eq 'alpine' }
|
19
|
+
its('tag') { should eq 'latest' }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe docker_image('alpine:latest') do
|
23
|
+
it { should exist }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe docker_image(id: '4a415e366388') do
|
27
|
+
it { should exist }
|
28
|
+
end
|
29
|
+
"
|
30
|
+
|
31
|
+
def initialize(opts = {})
|
32
|
+
# do sanitizion of input values
|
33
|
+
o = opts.dup
|
34
|
+
o = { image: opts } if opts.is_a?(String)
|
35
|
+
@opts = sanitize_options(o)
|
36
|
+
end
|
37
|
+
|
38
|
+
def exist?
|
39
|
+
image_info.exists?
|
40
|
+
end
|
41
|
+
|
42
|
+
def id
|
43
|
+
image_info.ids[0] if image_info.entries.size == 1
|
44
|
+
end
|
45
|
+
|
46
|
+
def image
|
47
|
+
"#{repo}:#{tag}" if image_info.entries.size == 1
|
48
|
+
end
|
49
|
+
|
50
|
+
def repo
|
51
|
+
image_info.repositories[0] if image_info.entries.size == 1
|
52
|
+
end
|
53
|
+
|
54
|
+
def tag
|
55
|
+
image_info.tags[0] if image_info.entries.size == 1
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_s
|
59
|
+
img = @opts[:image] || @opts[:id]
|
60
|
+
"Docker Image #{img}"
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def sanitize_options(opts)
|
66
|
+
if !opts[:image].nil?
|
67
|
+
if !opts[:image].index(':').nil?
|
68
|
+
repo, tag = opts[:image].split(':')
|
69
|
+
else
|
70
|
+
opts[:repo] = opts[:image]
|
71
|
+
opts[:image] = nil
|
72
|
+
end
|
73
|
+
opts[:repo] ||= repo
|
74
|
+
opts[:tag] ||= tag
|
75
|
+
end
|
76
|
+
|
77
|
+
if !opts[:id].nil?
|
78
|
+
if opts[:id].index(':').nil?
|
79
|
+
opts[:id] = 'sha256:' + opts[:id]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
opts[:tag] ||= 'latest'
|
84
|
+
opts[:image] ||= "#{opts[:repo]}:#{opts[:tag]}" unless opts[:repo].nil?
|
85
|
+
opts
|
86
|
+
end
|
87
|
+
|
88
|
+
def image_info
|
89
|
+
return @info if defined?(@info)
|
90
|
+
opts = @opts
|
91
|
+
@info = inspec.docker.images.where {
|
92
|
+
(repository == opts[:repo] && tag == opts[:tag]) || (!id.nil? && !opts[:id].nil? && (id == opts[:id] || id.start_with?(opts[:id])))
|
93
|
+
}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/resources/http.rb
CHANGED
@@ -25,13 +25,14 @@ module Inspec::Resources
|
|
25
25
|
"
|
26
26
|
|
27
27
|
# rubocop:disable ParameterLists
|
28
|
-
def initialize(url, method: 'GET', params: nil, auth: {}, headers: {}, data: nil)
|
28
|
+
def initialize(url, method: 'GET', params: nil, auth: {}, headers: {}, data: nil, ssl_verify: true)
|
29
29
|
@url = url
|
30
30
|
@method = method
|
31
31
|
@params = params
|
32
32
|
@auth = auth
|
33
33
|
@headers = headers
|
34
34
|
@data = data
|
35
|
+
@ssl_verify = ssl_verify
|
35
36
|
end
|
36
37
|
|
37
38
|
def status
|
@@ -53,7 +54,7 @@ module Inspec::Resources
|
|
53
54
|
private
|
54
55
|
|
55
56
|
def response
|
56
|
-
conn = Faraday.new url: @url, headers: @headers, params: @params
|
57
|
+
conn = Faraday.new url: @url, headers: @headers, params: @params, ssl: { verify: @ssl_verify }
|
57
58
|
|
58
59
|
# set basic authentication
|
59
60
|
conn.basic_auth @auth[:user], @auth[:pass] unless @auth.empty?
|
data/lib/resources/powershell.rb
CHANGED
@@ -10,7 +10,7 @@ module Inspec::Resources
|
|
10
10
|
desc 'Use the powershell InSpec audit resource to test a Windows PowerShell script on the Microsoft Windows platform.'
|
11
11
|
example "
|
12
12
|
script = <<-EOH
|
13
|
-
#
|
13
|
+
# your powershell script
|
14
14
|
EOH
|
15
15
|
|
16
16
|
describe powershell(script) do
|
data/lib/resources/ssh_conf.rb
CHANGED
@@ -9,10 +9,12 @@ require 'utils/simpleconfig'
|
|
9
9
|
module Inspec::Resources
|
10
10
|
class SshConf < Inspec.resource(1)
|
11
11
|
name 'ssh_config'
|
12
|
-
desc 'Use the
|
12
|
+
desc 'Use the `ssh_config` InSpec audit resource to test OpenSSH client configuration data located at `/etc/ssh/ssh_config` on Linux and Unix platforms.'
|
13
13
|
example "
|
14
|
-
describe
|
15
|
-
its('
|
14
|
+
describe ssh_config do
|
15
|
+
its('cipher') { should contain '3des' }
|
16
|
+
its('port') { should eq '22' }
|
17
|
+
its('hostname') { should include('example.com') }
|
16
18
|
end
|
17
19
|
"
|
18
20
|
|
@@ -83,9 +85,19 @@ module Inspec::Resources
|
|
83
85
|
|
84
86
|
class SshdConf < SshConf
|
85
87
|
name 'sshd_config'
|
88
|
+
desc 'Use the sshd_config InSpec audit resource to test configuration data for the Open SSH daemon located at /etc/ssh/sshd_config on Linux and UNIX platforms. sshd---the Open SSH daemon---listens on dedicated ports, starts a daemon for each incoming connection, and then handles encryption, authentication, key exchanges, command execution, and data exchanges.'
|
89
|
+
example "
|
90
|
+
describe sshd_config do
|
91
|
+
its('Protocol') { should eq '2' }
|
92
|
+
end
|
93
|
+
"
|
86
94
|
|
87
95
|
def initialize(path = nil)
|
88
96
|
super(path || '/etc/ssh/sshd_config')
|
89
97
|
end
|
98
|
+
|
99
|
+
def to_s
|
100
|
+
'SSHD Configuration'
|
101
|
+
end
|
90
102
|
end
|
91
103
|
end
|
data/lib/resources/users.rb
CHANGED
@@ -576,42 +576,42 @@ module Inspec::Resources
|
|
576
576
|
def collect_user_details # rubocop:disable Metrics/MethodLength
|
577
577
|
return @users_cache if defined?(@users_cache)
|
578
578
|
script = <<-EOH
|
579
|
-
Function
|
580
|
-
(New-Object
|
579
|
+
Function ConvertTo-SID { Param([byte[]]$BinarySID)
|
580
|
+
(New-Object System.Security.Principal.SecurityIdentifier($BinarySID,0)).Value
|
581
581
|
}
|
582
582
|
|
583
|
-
Function
|
584
|
-
$List
|
585
|
-
Switch
|
586
|
-
($UserFlag
|
587
|
-
($UserFlag
|
588
|
-
($UserFlag
|
589
|
-
($UserFlag
|
590
|
-
($UserFlag
|
591
|
-
($UserFlag
|
592
|
-
($UserFlag
|
593
|
-
($UserFlag
|
594
|
-
($UserFlag
|
595
|
-
($UserFlag
|
596
|
-
($UserFlag
|
597
|
-
($UserFlag
|
598
|
-
($UserFlag
|
599
|
-
($UserFlag
|
600
|
-
($UserFlag
|
601
|
-
($UserFlag
|
602
|
-
($UserFlag
|
603
|
-
($UserFlag
|
604
|
-
($UserFlag
|
605
|
-
($UserFlag
|
606
|
-
($UserFlag
|
607
|
-
($UserFlag
|
583
|
+
Function Convert-UserFlag { Param ($UserFlag)
|
584
|
+
$List = @()
|
585
|
+
Switch ($UserFlag) {
|
586
|
+
($UserFlag -BOR 0x0001) { $List += 'SCRIPT' }
|
587
|
+
($UserFlag -BOR 0x0002) { $List += 'ACCOUNTDISABLE' }
|
588
|
+
($UserFlag -BOR 0x0008) { $List += 'HOMEDIR_REQUIRED' }
|
589
|
+
($UserFlag -BOR 0x0010) { $List += 'LOCKOUT' }
|
590
|
+
($UserFlag -BOR 0x0020) { $List += 'PASSWD_NOTREQD' }
|
591
|
+
($UserFlag -BOR 0x0040) { $List += 'PASSWD_CANT_CHANGE' }
|
592
|
+
($UserFlag -BOR 0x0080) { $List += 'ENCRYPTED_TEXT_PWD_ALLOWED' }
|
593
|
+
($UserFlag -BOR 0x0100) { $List += 'TEMP_DUPLICATE_ACCOUNT' }
|
594
|
+
($UserFlag -BOR 0x0200) { $List += 'NORMAL_ACCOUNT' }
|
595
|
+
($UserFlag -BOR 0x0800) { $List += 'INTERDOMAIN_TRUST_ACCOUNT' }
|
596
|
+
($UserFlag -BOR 0x1000) { $List += 'WORKSTATION_TRUST_ACCOUNT' }
|
597
|
+
($UserFlag -BOR 0x2000) { $List += 'SERVER_TRUST_ACCOUNT' }
|
598
|
+
($UserFlag -BOR 0x10000) { $List += 'DONT_EXPIRE_PASSWORD' }
|
599
|
+
($UserFlag -BOR 0x20000) { $List += 'MNS_LOGON_ACCOUNT' }
|
600
|
+
($UserFlag -BOR 0x40000) { $List += 'SMARTCARD_REQUIRED' }
|
601
|
+
($UserFlag -BOR 0x80000) { $List += 'TRUSTED_FOR_DELEGATION' }
|
602
|
+
($UserFlag -BOR 0x100000) { $List += 'NOT_DELEGATED' }
|
603
|
+
($UserFlag -BOR 0x200000) { $List += 'USE_DES_KEY_ONLY' }
|
604
|
+
($UserFlag -BOR 0x400000) { $List += 'DONT_REQ_PREAUTH' }
|
605
|
+
($UserFlag -BOR 0x800000) { $List += 'PASSWORD_EXPIRED' }
|
606
|
+
($UserFlag -BOR 0x1000000) { $List += 'TRUSTED_TO_AUTH_FOR_DELEGATION' }
|
607
|
+
($UserFlag -BOR 0x04000000) { $List += 'PARTIAL_SECRETS_ACCOUNT' }
|
608
608
|
}
|
609
609
|
$List
|
610
610
|
}
|
611
611
|
|
612
|
-
$Computername =
|
613
|
-
$adsi
|
614
|
-
$adsi.Children | where {$_.SchemaClassName -eq
|
612
|
+
$Computername = $Env:Computername
|
613
|
+
$adsi = [ADSI]"WinNT://$Computername"
|
614
|
+
$adsi.Children | where {$_.SchemaClassName -eq 'user'} | ForEach {
|
615
615
|
New-Object PSObject -property @{
|
616
616
|
uid = ConvertTo-SID -BinarySID $_.ObjectSID[0]
|
617
617
|
username = $_.Name[0]
|
@@ -627,7 +627,7 @@ $adsi.Children | where {$_.SchemaClassName -eq 'user'} | ForEach {
|
|
627
627
|
maxbadpasswords = $_.MaxBadPasswordsAllowed[0]
|
628
628
|
gid = $null
|
629
629
|
group = $null
|
630
|
-
groups = $null
|
630
|
+
groups = @($_.Groups() | Foreach-Object { $_.GetType().InvokeMember('Name', 'GetProperty', $null, $_, $null) })
|
631
631
|
home = $_.HomeDirectory[0]
|
632
632
|
shell = $null
|
633
633
|
domain = $Computername
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.21.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominik Richter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: train
|
@@ -182,14 +182,14 @@ dependencies:
|
|
182
182
|
requirements:
|
183
183
|
- - "~>"
|
184
184
|
- !ruby/object:Gem::Version
|
185
|
-
version: '1.
|
185
|
+
version: '1.2'
|
186
186
|
type: :runtime
|
187
187
|
prerelease: false
|
188
188
|
version_requirements: !ruby/object:Gem::Requirement
|
189
189
|
requirements:
|
190
190
|
- - "~>"
|
191
191
|
- !ruby/object:Gem::Version
|
192
|
-
version: '1.
|
192
|
+
version: '1.2'
|
193
193
|
- !ruby/object:Gem::Dependency
|
194
194
|
name: parallel
|
195
195
|
requirement: !ruby/object:Gem::Requirement
|
@@ -291,7 +291,6 @@ files:
|
|
291
291
|
- docs/migration.md
|
292
292
|
- docs/plugin_kitchen_inspec.html.md
|
293
293
|
- docs/profiles.md
|
294
|
-
- docs/resources.md
|
295
294
|
- docs/resources/apache_conf.md.erb
|
296
295
|
- docs/resources/apt.md.erb
|
297
296
|
- docs/resources/audit_policy.md.erb
|
@@ -306,6 +305,9 @@ files:
|
|
306
305
|
- docs/resources/csv.md.erb
|
307
306
|
- docs/resources/dh_params.md
|
308
307
|
- docs/resources/directory.md.erb
|
308
|
+
- docs/resources/docker.md.erb
|
309
|
+
- docs/resources/docker_container.md.erb
|
310
|
+
- docs/resources/docker_image.md.erb
|
309
311
|
- docs/resources/etc_group.md.erb
|
310
312
|
- docs/resources/etc_passwd.md.erb
|
311
313
|
- docs/resources/etc_shadow.md.erb
|
@@ -323,7 +325,7 @@ files:
|
|
323
325
|
- docs/resources/json.md.erb
|
324
326
|
- docs/resources/kernel_module.md.erb
|
325
327
|
- docs/resources/kernel_parameter.md.erb
|
326
|
-
- docs/resources/key_rsa.md
|
328
|
+
- docs/resources/key_rsa.md.erb
|
327
329
|
- docs/resources/launchd_service.md.erb
|
328
330
|
- docs/resources/limits_conf.md.erb
|
329
331
|
- docs/resources/login_def.md.erb
|
@@ -362,7 +364,7 @@ files:
|
|
362
364
|
- docs/resources/windows_feature.md.erb
|
363
365
|
- docs/resources/windows_task.md.erb
|
364
366
|
- docs/resources/wmi.md.erb
|
365
|
-
- docs/resources/x509_certificate.md
|
367
|
+
- docs/resources/x509_certificate.md.erb
|
366
368
|
- docs/resources/xinetd_conf.md.erb
|
367
369
|
- docs/resources/yaml.md.erb
|
368
370
|
- docs/resources/yum.md.erb
|
@@ -378,7 +380,6 @@ files:
|
|
378
380
|
- examples/README.md
|
379
381
|
- examples/inheritance/README.md
|
380
382
|
- examples/inheritance/controls/example.rb
|
381
|
-
- examples/inheritance/inspec.lock
|
382
383
|
- examples/inheritance/inspec.yml
|
383
384
|
- examples/kitchen-ansible/.kitchen.yml
|
384
385
|
- examples/kitchen-ansible/Gemfile
|
@@ -404,11 +405,7 @@ files:
|
|
404
405
|
- examples/kitchen-puppet/test/integration/default/web_spec.rb
|
405
406
|
- examples/meta-profile/README.md
|
406
407
|
- examples/meta-profile/controls/example.rb
|
407
|
-
- examples/meta-profile/inspec.lock
|
408
408
|
- examples/meta-profile/inspec.yml
|
409
|
-
- examples/meta-profile/vendor/11b6287b232c2a689ae87b3ba54897eb9067a749da074b6f3040b6442082dd6a.tar.gz
|
410
|
-
- examples/meta-profile/vendor/379757a6ba73c9bc17b37353c1ff5b4eb7dd978a3bd38b29d2dda64f90f16c36.tar.gz
|
411
|
-
- examples/meta-profile/vendor/dbb5602f09f58d86f8743dfb44327207e9a23a49ef34f65614f1c1d8cc145f6b.tar.gz
|
412
409
|
- examples/profile-attribute.yml
|
413
410
|
- examples/profile-attribute/README.md
|
414
411
|
- examples/profile-attribute/controls/example.rb
|
@@ -531,6 +528,9 @@ files:
|
|
531
528
|
- lib/resources/csv.rb
|
532
529
|
- lib/resources/dh_params.rb
|
533
530
|
- lib/resources/directory.rb
|
531
|
+
- lib/resources/docker.rb
|
532
|
+
- lib/resources/docker_container.rb
|
533
|
+
- lib/resources/docker_image.rb
|
534
534
|
- lib/resources/etc_group.rb
|
535
535
|
- lib/resources/file.rb
|
536
536
|
- lib/resources/gem.rb
|
@@ -625,7 +625,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
625
625
|
version: '0'
|
626
626
|
requirements: []
|
627
627
|
rubyforge_project:
|
628
|
-
rubygems_version: 2.
|
628
|
+
rubygems_version: 2.6.11
|
629
629
|
signing_key:
|
630
630
|
specification_version: 4
|
631
631
|
summary: Infrastructure and compliance testing.
|
@@ -1,11 +0,0 @@
|
|
1
|
-
---
|
2
|
-
lockfile_version: 1
|
3
|
-
depends:
|
4
|
-
- name: profile
|
5
|
-
resolved_source:
|
6
|
-
path: "/Users/aleff/projects/inspec/examples/profile"
|
7
|
-
version_constraints: ">= 0"
|
8
|
-
- name: profile-attribute
|
9
|
-
resolved_source:
|
10
|
-
path: "/Users/aleff/projects/inspec/examples/profile-attribute"
|
11
|
-
version_constraints: ">= 0"
|
@@ -1,18 +0,0 @@
|
|
1
|
-
---
|
2
|
-
lockfile_version: 1
|
3
|
-
depends:
|
4
|
-
- name: dev-sec/ssh-baseline
|
5
|
-
resolved_source:
|
6
|
-
url: https://github.com/dev-sec/ssh-baseline/archive/master.tar.gz
|
7
|
-
sha256: 379757a6ba73c9bc17b37353c1ff5b4eb7dd978a3bd38b29d2dda64f90f16c36
|
8
|
-
version_constraints: ">= 0"
|
9
|
-
- name: ssl-benchmark
|
10
|
-
resolved_source:
|
11
|
-
url: https://github.com/dev-sec/ssl-benchmark/archive/master.tar.gz
|
12
|
-
sha256: 11b6287b232c2a689ae87b3ba54897eb9067a749da074b6f3040b6442082dd6a
|
13
|
-
version_constraints: ">= 0"
|
14
|
-
- name: windows-patch-benchmark
|
15
|
-
resolved_source:
|
16
|
-
url: https://github.com/chris-rock/windows-patch-benchmark/archive/master.tar.gz
|
17
|
-
sha256: dbb5602f09f58d86f8743dfb44327207e9a23a49ef34f65614f1c1d8cc145f6b
|
18
|
-
version_constraints: ">= 0"
|
Binary file
|
Binary file
|