inspec 1.27.0 → 1.28.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 +25 -0
- data/docs/resources/host.md.erb +4 -4
- data/docs/resources/iis_app.md.erb +126 -0
- data/docs/resources/virtualization.md.erb +71 -0
- data/examples/inheritance/inspec.lock +11 -0
- data/examples/meta-profile/inspec.lock +18 -0
- data/examples/meta-profile/vendor/0e6d170415e120af5f1dda113f96f7e0d156e49f82706ac41d13da00599f9b25.tar.gz +0 -0
- data/examples/meta-profile/vendor/403580959915ea24bc176b9ebdc555aeda5e2c957604b48d5f32b43554423582.tar.gz +0 -0
- data/examples/meta-profile/vendor/d08d3cc35debff04e708147cdd07739876c5d1c8357afb5e58adfaad92dd650f.tar.gz +0 -0
- data/lib/bundles/inspec-compliance/api.rb +13 -2
- data/lib/bundles/inspec-compliance/configuration.rb +4 -0
- data/lib/fetchers/url.rb +2 -0
- data/lib/inspec/archive/tar.rb +1 -1
- data/lib/inspec/base_cli.rb +19 -2
- data/lib/inspec/file_provider.rb +29 -2
- data/lib/inspec/plugins/resource.rb +1 -1
- data/lib/inspec/profile.rb +2 -2
- data/lib/inspec/resource.rb +2 -0
- data/lib/inspec/rspec_json_formatter.rb +9 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/auditd_rules.rb +1 -0
- data/lib/resources/host.rb +97 -27
- data/lib/resources/iis_app.rb +103 -0
- data/lib/resources/service.rb +2 -0
- data/lib/resources/virtualization.rb +252 -0
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0d407da61108e3110902410c9250bb1aa65727d
|
4
|
+
data.tar.gz: '08e3dfe5818627298ae9fada47ebdb20295be3d3'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00b4a96e07c8b54024b756c1abfe4fe0334d16817177ae538902ddb76cc9e21fbd604a473c41fc3538b2a26491872f8ae30c02af82cf913c430238fe526a07d9
|
7
|
+
data.tar.gz: a020a8a48d76d26da019ea92ad298b9e1c70d5a22dc8d3f691457201649d5108c85fb49ff90f37d1112f6b5710db2c5296a20d09ab9512fc5281a68535ba218a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,30 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v1.28.0](https://github.com/chef/inspec/tree/v1.28.0) (2017-06-15)
|
4
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v1.27.0...v1.28.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- Add support for CoreOS to the service resource [\#1928](https://github.com/chef/inspec/pull/1928) ([rarenerd](https://github.com/rarenerd))
|
9
|
+
- Host resource ping method should return stdout [\#1927](https://github.com/chef/inspec/pull/1927) ([justincmoy](https://github.com/justincmoy))
|
10
|
+
- Add TCP reachability support on Linux for host resource [\#1915](https://github.com/chef/inspec/pull/1915) ([adamleff](https://github.com/adamleff))
|
11
|
+
- Adds support for iis\_app InSpec testing [\#1905](https://github.com/chef/inspec/pull/1905) ([EasyAsABC123](https://github.com/EasyAsABC123))
|
12
|
+
- Add support for virtualization resource [\#1803](https://github.com/chef/inspec/pull/1803) ([tkak](https://github.com/tkak))
|
13
|
+
|
14
|
+
**Fixed bugs:**
|
15
|
+
|
16
|
+
- Error when listing compliance profiles against Automate pre 0.8 [\#1921](https://github.com/chef/inspec/issues/1921)
|
17
|
+
- Unexpected `nil` authentication with `inspec exec -t` and WinRM [\#1901](https://github.com/chef/inspec/issues/1901)
|
18
|
+
- inspec exec with --json-config option having multiple node information [\#1897](https://github.com/chef/inspec/issues/1897)
|
19
|
+
- describe package failing in newer version [\#1797](https://github.com/chef/inspec/issues/1797)
|
20
|
+
- Fix detection of Automate pre-0.8.x in Compliance::API [\#1922](https://github.com/chef/inspec/pull/1922) ([adamleff](https://github.com/adamleff))
|
21
|
+
- bugfix: reading tgz files with binread [\#1920](https://github.com/chef/inspec/pull/1920) ([arlimus](https://github.com/arlimus))
|
22
|
+
- fix intermitten functional vendor test failures [\#1919](https://github.com/chef/inspec/pull/1919) ([arlimus](https://github.com/arlimus))
|
23
|
+
- enforce option values where needed [\#1918](https://github.com/chef/inspec/pull/1918) ([arlimus](https://github.com/arlimus))
|
24
|
+
- inspec archive for tgz files on windows [\#1907](https://github.com/chef/inspec/pull/1907) ([arlimus](https://github.com/arlimus))
|
25
|
+
- reading binary profile data on windows [\#1906](https://github.com/chef/inspec/pull/1906) ([arlimus](https://github.com/arlimus))
|
26
|
+
- remove duplicate message in describe.one blocks [\#1896](https://github.com/chef/inspec/pull/1896) ([arlimus](https://github.com/arlimus))
|
27
|
+
|
3
28
|
## [v1.27.0](https://github.com/chef/inspec/tree/v1.27.0) (2017-06-06)
|
4
29
|
[Full Changelog](https://github.com/chef/inspec/compare/v1.26.0...v1.27.0)
|
5
30
|
|
data/docs/resources/host.md.erb
CHANGED
@@ -12,7 +12,7 @@ A `host` resource block declares a host name, and then (depending on what is to
|
|
12
12
|
|
13
13
|
.. code-block:: ruby
|
14
14
|
|
15
|
-
describe host('example.com', port: 80,
|
15
|
+
describe host('example.com', port: 80, protocol: 'tcp') do
|
16
16
|
it { should be_reachable }
|
17
17
|
end
|
18
18
|
|
@@ -21,7 +21,7 @@ where
|
|
21
21
|
* `host()` must specify a host name and may specify a port number and/or a protocol
|
22
22
|
* `'example.com'` is the host name
|
23
23
|
* `port:` is the port number
|
24
|
-
* `
|
24
|
+
* `protocol: 'name'` is the Internet protocol: TCP (`protocol: 'tcp'`), UDP (`protocol: 'udp'` or ICMP (`protocol: 'icmp'`))
|
25
25
|
* `be_reachable` is a valid matcher for this resource
|
26
26
|
|
27
27
|
|
@@ -73,13 +73,13 @@ The following examples show how to use this InSpec audit resource.
|
|
73
73
|
|
74
74
|
### Verify host name is reachable over a specific protocol and port number
|
75
75
|
|
76
|
-
describe host('example.com', port:
|
76
|
+
describe host('example.com', port: 80, protocol: 'tcp') do
|
77
77
|
it { should be_reachable }
|
78
78
|
end
|
79
79
|
|
80
80
|
### Verify that a specific IP address can be resolved
|
81
81
|
|
82
|
-
describe host('example.com'
|
82
|
+
describe host('example.com') do
|
83
83
|
it { should be_resolvable }
|
84
84
|
its('ipaddress') { should include '192.168.1.1' }
|
85
85
|
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
---
|
2
|
+
title: About the iis_app Resource
|
3
|
+
---
|
4
|
+
|
5
|
+
# iis_app
|
6
|
+
|
7
|
+
Use the `iis_app` InSpec audit resource to test the state of IIS on Windows Server 2012 (and later).
|
8
|
+
|
9
|
+
## Syntax
|
10
|
+
|
11
|
+
An `iis_app` resource block declares details about the named site:
|
12
|
+
|
13
|
+
describe iis_app('application_path', 'site_name') do
|
14
|
+
it { should exist }
|
15
|
+
it { should have_application_pool('application_pool') }
|
16
|
+
it { should have_protocols('protocol') }
|
17
|
+
it { should have_site_name('site') }
|
18
|
+
it { should have_physical_path('physical_path') }
|
19
|
+
it { should have_path('application_path') }
|
20
|
+
end
|
21
|
+
|
22
|
+
where
|
23
|
+
|
24
|
+
* `'application_path'` is the path to the application, such as `'/myapp'`
|
25
|
+
* `'site_name'` is the name of the site, such as `'Default Web Site'`
|
26
|
+
* `('application_pool')` is the name of the application pool in which the site's root application is run, such as `'DefaultAppPool'`
|
27
|
+
* `('protocols')` is a binding for the site, such as `'http'`. A site may have multiple bindings; therefore, use a `have_protocol` matcher for each site protocol to be tested
|
28
|
+
* `('physical_path') is the physical path to the application, such as `'C:\\inetpub\\wwwroot\\myapp'`
|
29
|
+
|
30
|
+
For example:
|
31
|
+
|
32
|
+
describe iis_app('/myapp', 'Default Web Site') do
|
33
|
+
it { should exist }
|
34
|
+
it { should have_application_pool('MyAppPool') }
|
35
|
+
it { should have_protocols('http') }
|
36
|
+
it { should have_site_name('Default Web Site') }
|
37
|
+
it { should have_physical_path('C:\\inetpub\\wwwroot\\myapp') }
|
38
|
+
it { should have_path('\\My Application') }
|
39
|
+
end
|
40
|
+
|
41
|
+
## Matchers
|
42
|
+
|
43
|
+
This InSpec audit resource has the following matchers:
|
44
|
+
|
45
|
+
### cmp
|
46
|
+
|
47
|
+
<%= partial "/shared/matcher_cmp" %>
|
48
|
+
|
49
|
+
### eq
|
50
|
+
|
51
|
+
<%= partial "/shared/matcher_eq" %>
|
52
|
+
|
53
|
+
### exist
|
54
|
+
|
55
|
+
The `exist` matcher tests if the site exists:
|
56
|
+
|
57
|
+
it { should exist }
|
58
|
+
|
59
|
+
### have\_application\_pool
|
60
|
+
|
61
|
+
The `have_application_pool` matcher tests if the named application pool exists for the web application:
|
62
|
+
|
63
|
+
it { should have_application_pool('DefaultAppPool') }
|
64
|
+
|
65
|
+
### have_protocol
|
66
|
+
|
67
|
+
The `have_protocol` matcher tests if the specified protocol exists for the web application:
|
68
|
+
|
69
|
+
it { should have_protocol('http') }
|
70
|
+
|
71
|
+
or:
|
72
|
+
|
73
|
+
it { should have_protocol('https') }
|
74
|
+
|
75
|
+
A web application may have multiple bindings; use a `have_protocol` matcher for each unique web application binding to be tested.
|
76
|
+
|
77
|
+
##### Protocol Attributes
|
78
|
+
|
79
|
+
The `have_protocol` matcher can also test attributes that are defined for a web application enabledProtocols.
|
80
|
+
|
81
|
+
it { should have_protocol('http') }
|
82
|
+
|
83
|
+
For example, testing a site that doesn't have https enabled:
|
84
|
+
|
85
|
+
it { should_not have_protocol('https') }
|
86
|
+
it { should have_protocol('http') }
|
87
|
+
|
88
|
+
Testing a web application with https enabled and http enabled:
|
89
|
+
|
90
|
+
it { should have_protocol('https') }
|
91
|
+
it { should have_protocol('http') }
|
92
|
+
|
93
|
+
### have_physical_path
|
94
|
+
|
95
|
+
The `have_physical_path` matcher tests if the named path is defined for the web application:
|
96
|
+
|
97
|
+
it { should have_physical_path('C:\\inetpub\\wwwroot') }
|
98
|
+
|
99
|
+
### include
|
100
|
+
|
101
|
+
<%= partial "/shared/matcher_include" %>
|
102
|
+
|
103
|
+
### match
|
104
|
+
|
105
|
+
<%= partial "/shared/matcher_match" %>
|
106
|
+
|
107
|
+
## Examples
|
108
|
+
|
109
|
+
The following examples show how to use this InSpec audit resource.
|
110
|
+
|
111
|
+
### Test a default IIS web application
|
112
|
+
|
113
|
+
describe iis_app('Default Web Site') do
|
114
|
+
it { should exist }
|
115
|
+
it { should be_running }
|
116
|
+
it { should have_app_pool('DefaultAppPool') }
|
117
|
+
it { should have_binding('http *:80:') }
|
118
|
+
it { should have_path('%SystemDrive%\\inetpub\\wwwroot') }
|
119
|
+
end
|
120
|
+
|
121
|
+
### Test if IIS service is running
|
122
|
+
|
123
|
+
describe service('W3SVC') do
|
124
|
+
it { should be_installed }
|
125
|
+
it { should be_running }
|
126
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
---
|
2
|
+
title: About the virtualization Resource
|
3
|
+
---
|
4
|
+
|
5
|
+
# virtualization
|
6
|
+
|
7
|
+
Use the `virtualization` InSpec audit resource to test the virtualization platform on which the system is running.
|
8
|
+
|
9
|
+
## Syntax
|
10
|
+
|
11
|
+
An `virtualization` resource block declares the virtualization platform that should be tested:
|
12
|
+
|
13
|
+
describe virtualization do
|
14
|
+
its('system') { should MATCHER 'value' }
|
15
|
+
end
|
16
|
+
|
17
|
+
where
|
18
|
+
|
19
|
+
* `('system')` is the name of the system information of the virtualization platform (e.g. docker, lxc, vbox, kvm, etc)
|
20
|
+
* `MATCHER` is a valid matcher for this resource
|
21
|
+
* `'value'` is the value to be tested
|
22
|
+
|
23
|
+
## Matchers
|
24
|
+
|
25
|
+
This InSpec audit resource has the following matchers:
|
26
|
+
|
27
|
+
### be
|
28
|
+
|
29
|
+
<%= partial "/shared/matcher_be" %>
|
30
|
+
|
31
|
+
### cmp
|
32
|
+
|
33
|
+
<%= partial "/shared/matcher_cmp" %>
|
34
|
+
|
35
|
+
### eq
|
36
|
+
|
37
|
+
<%= partial "/shared/matcher_eq" %>
|
38
|
+
|
39
|
+
### include
|
40
|
+
|
41
|
+
<%= partial "/shared/matcher_include" %>
|
42
|
+
|
43
|
+
### match
|
44
|
+
|
45
|
+
<%= partial "/shared/matcher_match" %>
|
46
|
+
|
47
|
+
## Examples
|
48
|
+
|
49
|
+
The following examples show how to use this InSpec audit resource.
|
50
|
+
|
51
|
+
### Test for Docker
|
52
|
+
|
53
|
+
describe virtualization do
|
54
|
+
its('system') { should eq 'docker' }
|
55
|
+
end
|
56
|
+
|
57
|
+
### Test for VirtualBox
|
58
|
+
|
59
|
+
describe virtualization do
|
60
|
+
its('system') { should eq 'vbox' }
|
61
|
+
its('role') { should eq 'guest' }
|
62
|
+
end
|
63
|
+
|
64
|
+
### Detect the virtualization platform
|
65
|
+
|
66
|
+
if virtualization.system == 'vbox'
|
67
|
+
describe package('name') do
|
68
|
+
it { should be_installed }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
@@ -0,0 +1,11 @@
|
|
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"
|
@@ -0,0 +1,18 @@
|
|
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: 403580959915ea24bc176b9ebdc555aeda5e2c957604b48d5f32b43554423582
|
8
|
+
version_constraints: ">= 0"
|
9
|
+
- name: ssl-baseline
|
10
|
+
resolved_source:
|
11
|
+
url: https://github.com/dev-sec/ssl-baseline/archive/master.tar.gz
|
12
|
+
sha256: 0e6d170415e120af5f1dda113f96f7e0d156e49f82706ac41d13da00599f9b25
|
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: d08d3cc35debff04e708147cdd07739876c5d1c8357afb5e58adfaad92dd650f
|
18
|
+
version_constraints: ">= 0"
|
Binary file
|
Binary file
|
Binary file
|
@@ -204,11 +204,22 @@ module Compliance
|
|
204
204
|
end
|
205
205
|
|
206
206
|
def self.is_automate_server_pre_080?(config)
|
207
|
-
|
207
|
+
# Automate versions before 0.8.x may have a "version" key in the config.
|
208
|
+
# Unless it's a hash that also contains a "version" key, it came from
|
209
|
+
# an Automate server that is pre-0.8.x.
|
210
|
+
return false unless config['server_type'] == 'automate'
|
211
|
+
return true unless config.key?('version')
|
212
|
+
return true unless config['version'].is_a?(Hash)
|
213
|
+
config['version']['version'].nil?
|
208
214
|
end
|
209
215
|
|
210
216
|
def self.is_automate_server_080_and_later?(config)
|
211
|
-
|
217
|
+
# Automate versions 0.8.x and later will have a "version" key in the config
|
218
|
+
# that looks like: "version":{"api":"compliance","version":"0.8.24"}
|
219
|
+
return false unless config['server_type'] == 'automate'
|
220
|
+
return false unless config.key?('version')
|
221
|
+
return false unless config['version'].is_a?(Hash)
|
222
|
+
!config['version']['version'].nil?
|
212
223
|
end
|
213
224
|
|
214
225
|
def self.is_automate_server?(config)
|
data/lib/fetchers/url.rb
CHANGED
data/lib/inspec/archive/tar.rb
CHANGED
data/lib/inspec/base_cli.rb
CHANGED
@@ -19,7 +19,7 @@ module Inspec
|
|
19
19
|
desc: 'Specify the login port for a remote scan.'
|
20
20
|
option :user, type: :string,
|
21
21
|
desc: 'The login user for a remote scan.'
|
22
|
-
option :password, type: :string,
|
22
|
+
option :password, type: :string, lazy_default: -1,
|
23
23
|
desc: 'Login password for a remote scan, if required.'
|
24
24
|
option :key_files, aliases: :i, type: :array,
|
25
25
|
desc: 'Login key or certificate file for a remote scan.'
|
@@ -27,7 +27,7 @@ module Inspec
|
|
27
27
|
desc: 'Login path to use when connecting to the target (WinRM).'
|
28
28
|
option :sudo, type: :boolean,
|
29
29
|
desc: 'Run scans with sudo. Only activates on Unix and non-root user.'
|
30
|
-
option :sudo_password, type: :string,
|
30
|
+
option :sudo_password, type: :string, lazy_default: -1,
|
31
31
|
desc: 'Specify a sudo password, if it is required.'
|
32
32
|
option :sudo_options, type: :string,
|
33
33
|
desc: 'Additional sudo options for a remote scan.'
|
@@ -100,6 +100,23 @@ module Inspec
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def opts
|
103
|
+
o = merged_opts
|
104
|
+
|
105
|
+
# Due to limitations in Thor it is not possible to set an argument to be
|
106
|
+
# both optional and its value to be mandatory. E.g. the user supplying
|
107
|
+
# the --password argument is optional and not always required, but
|
108
|
+
# whenever it is used, it requires a value. Handle options that were
|
109
|
+
# defined above and require a value here:
|
110
|
+
%w{password sudo-password}.each do |v|
|
111
|
+
id = v.tr('-', '_').to_sym
|
112
|
+
next unless o[id] == -1
|
113
|
+
raise ArgumentError, "Please provide a value for --#{v}. For example: --#{v}=hello."
|
114
|
+
end
|
115
|
+
|
116
|
+
o
|
117
|
+
end
|
118
|
+
|
119
|
+
def merged_opts
|
103
120
|
# argv overrides json
|
104
121
|
Thor::CoreExt::HashWithIndifferentAccess.new(options_json.merge(options))
|
105
122
|
end
|
data/lib/inspec/file_provider.rb
CHANGED
@@ -24,12 +24,29 @@ module Inspec
|
|
24
24
|
def initialize(_path)
|
25
25
|
end
|
26
26
|
|
27
|
+
# List all files that are offered.
|
28
|
+
#
|
29
|
+
# @return [Array[String]] list of file paths that are included
|
30
|
+
def files
|
31
|
+
raise "Fetcher #{self} does not implement `files()`. This is required."
|
32
|
+
end
|
33
|
+
|
34
|
+
# Read the contents of a file. This will typically refer to a text
|
35
|
+
# file reading a string.
|
36
|
+
#
|
37
|
+
# @param _file [String] path of the file to be read
|
38
|
+
# @return [String] contents of the file described
|
27
39
|
def read(_file)
|
28
40
|
raise "#{self} does not implement `read(...)`. This is required."
|
29
41
|
end
|
30
42
|
|
31
|
-
|
32
|
-
|
43
|
+
# Provide a method for reading binary contents from a file.
|
44
|
+
# It will default to #read if not defined. For most streams that implement
|
45
|
+
# it, it will be the same. For some special cases, it will add change the
|
46
|
+
# way in which encoding of the returned data structure is handled.
|
47
|
+
# Does not work with alias nor alias_method.
|
48
|
+
def binread(file)
|
49
|
+
read(file)
|
33
50
|
end
|
34
51
|
|
35
52
|
def relative_provider
|
@@ -65,6 +82,12 @@ module Inspec
|
|
65
82
|
return nil unless File.file?(file)
|
66
83
|
File.read(file)
|
67
84
|
end
|
85
|
+
|
86
|
+
def binread(file)
|
87
|
+
return nil unless files.include?(file)
|
88
|
+
return nil unless File.file?(file)
|
89
|
+
File.binread(file)
|
90
|
+
end
|
68
91
|
end
|
69
92
|
|
70
93
|
class ZipProvider < FileProvider
|
@@ -163,6 +186,10 @@ module Inspec
|
|
163
186
|
parent.read(abs_path(file))
|
164
187
|
end
|
165
188
|
|
189
|
+
def binread(file)
|
190
|
+
parent.binread(abs_path(file))
|
191
|
+
end
|
192
|
+
|
166
193
|
private
|
167
194
|
|
168
195
|
def get_prefix(fs)
|
data/lib/inspec/profile.rb
CHANGED
@@ -37,7 +37,7 @@ module Inspec
|
|
37
37
|
cache = file_provider.files.find_all do |entry|
|
38
38
|
entry.start_with?('vendor')
|
39
39
|
end
|
40
|
-
content = Hash[cache.map { |x| [x, file_provider.
|
40
|
+
content = Hash[cache.map { |x| [x, file_provider.binread(x)] }]
|
41
41
|
keys = content.keys
|
42
42
|
keys.each do |key|
|
43
43
|
next if content[key].nil?
|
@@ -47,7 +47,7 @@ module Inspec
|
|
47
47
|
|
48
48
|
FileUtils.mkdir_p tar.dirname.to_s
|
49
49
|
Inspec::Log.debug "Copy #{tar} to cache directory"
|
50
|
-
File.
|
50
|
+
File.binwrite(tar.to_s, content[key])
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
data/lib/inspec/resource.rb
CHANGED
@@ -96,6 +96,7 @@ require 'resources/groups'
|
|
96
96
|
require 'resources/grub_conf'
|
97
97
|
require 'resources/host'
|
98
98
|
require 'resources/http'
|
99
|
+
require 'resources/iis_app'
|
99
100
|
require 'resources/iis_site'
|
100
101
|
require 'resources/inetd_conf'
|
101
102
|
require 'resources/interface'
|
@@ -138,6 +139,7 @@ require 'resources/ssh_conf'
|
|
138
139
|
require 'resources/sys_info'
|
139
140
|
require 'resources/users'
|
140
141
|
require 'resources/vbscript'
|
142
|
+
require 'resources/virtualization'
|
141
143
|
require 'resources/windows_feature'
|
142
144
|
require 'resources/windows_task'
|
143
145
|
require 'resources/xinetd'
|
@@ -52,7 +52,7 @@ class InspecRspecMiniJson < RSpec::Core::Formatters::JsonFormatter
|
|
52
52
|
format_example(example).tap do |hash|
|
53
53
|
e = example.exception
|
54
54
|
next unless e
|
55
|
-
hash[:message] = e
|
55
|
+
hash[:message] = exception_message(e)
|
56
56
|
|
57
57
|
next if e.is_a? RSpec::Expectations::ExpectationNotMetError
|
58
58
|
hash[:exception] = e.class.name
|
@@ -63,6 +63,14 @@ class InspecRspecMiniJson < RSpec::Core::Formatters::JsonFormatter
|
|
63
63
|
|
64
64
|
private
|
65
65
|
|
66
|
+
def exception_message(exception)
|
67
|
+
if exception.is_a?(RSpec::Core::MultipleExceptionError)
|
68
|
+
exception.all_exceptions.map(&:message).uniq.join("\n\n")
|
69
|
+
else
|
70
|
+
exception.message
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
66
74
|
def format_example(example)
|
67
75
|
if !example.metadata[:description_args].empty? && example.metadata[:skip]
|
68
76
|
# For skipped profiles, rspec returns in full_description the skip_message as well. We don't want
|
data/lib/inspec/version.rb
CHANGED
data/lib/resources/host.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
# end
|
11
11
|
#
|
12
12
|
# To verify a hostname with protocol and port
|
13
|
-
# describe host('example.com', port:
|
13
|
+
# describe host('example.com', port: 443, protocol: 'tcp') do
|
14
14
|
# it { should be_reachable }
|
15
15
|
# end
|
16
16
|
#
|
@@ -33,17 +33,26 @@ module Inspec::Resources
|
|
33
33
|
it { should be_reachable }
|
34
34
|
end
|
35
35
|
|
36
|
-
describe host('example.com', port: '80') do
|
36
|
+
describe host('example.com', port: '80', protocol: 'tcp') do
|
37
37
|
it { should be_reachable }
|
38
38
|
end
|
39
39
|
"
|
40
40
|
|
41
|
+
attr_reader :hostname, :port, :protocol
|
42
|
+
|
41
43
|
def initialize(hostname, params = {})
|
42
44
|
@hostname = hostname
|
43
|
-
@port = params[:port]
|
44
|
-
@proto = params[:proto] || nil
|
45
|
+
@port = params[:port]
|
45
46
|
|
46
|
-
|
47
|
+
if params[:proto]
|
48
|
+
warn '[DEPRECATION] The `proto` parameter is deprecated. Use `protocol` instead.'
|
49
|
+
@protocol = params[:proto]
|
50
|
+
else
|
51
|
+
@protocol = params.fetch(:protocol, 'icmp')
|
52
|
+
end
|
53
|
+
|
54
|
+
return skip_resource 'Invalid protocol: only `tcp` and `icmp` protocols are support for the `host` resource.' unless
|
55
|
+
%w{icmp tcp}.include?(@protocol)
|
47
56
|
|
48
57
|
@host_provider = nil
|
49
58
|
if inspec.os.linux?
|
@@ -55,6 +64,16 @@ module Inspec::Resources
|
|
55
64
|
else
|
56
65
|
return skip_resource 'The `host` resource is not supported on your OS yet.'
|
57
66
|
end
|
67
|
+
|
68
|
+
missing_requirements = @host_provider.missing_requirements(protocol)
|
69
|
+
unless missing_requirements.empty?
|
70
|
+
return skip_resource "The following requirements are not met for this resource: #{missing_requirements.join(', ')}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def proto
|
75
|
+
warn '[DEPRECATION] The `proto` method is deprecated. Use `protocol` instead.'
|
76
|
+
protocol
|
58
77
|
end
|
59
78
|
|
60
79
|
# if we get the IP address, the host is resolvable
|
@@ -63,9 +82,25 @@ module Inspec::Resources
|
|
63
82
|
resolve.nil? || resolve.empty? ? false : true
|
64
83
|
end
|
65
84
|
|
66
|
-
def reachable?
|
67
|
-
|
68
|
-
ping.
|
85
|
+
def reachable?
|
86
|
+
# ping checks do not require port or protocol
|
87
|
+
return ping.fetch(:success, false) if protocol == 'icmp'
|
88
|
+
|
89
|
+
# if either port or protocol are specified but not both, we cannot proceed.
|
90
|
+
if port.nil? || protocol.nil?
|
91
|
+
raise "Protocol required with port. Use `host` resource with host('#{hostname}', port: 1234, proto: 'tcp') parameters." if port.nil? || protocol.nil?
|
92
|
+
end
|
93
|
+
|
94
|
+
# perform the protocol-specific reachability test
|
95
|
+
ping.fetch(:success, false)
|
96
|
+
end
|
97
|
+
|
98
|
+
def connection
|
99
|
+
ping[:connection]
|
100
|
+
end
|
101
|
+
|
102
|
+
def socket
|
103
|
+
ping[:socket]
|
69
104
|
end
|
70
105
|
|
71
106
|
# returns all A records of the IP address, will return an array
|
@@ -74,19 +109,21 @@ module Inspec::Resources
|
|
74
109
|
end
|
75
110
|
|
76
111
|
def to_s
|
77
|
-
"Host #{
|
112
|
+
"Host #{hostname}"
|
78
113
|
end
|
79
114
|
|
80
115
|
private
|
81
116
|
|
82
117
|
def ping
|
83
118
|
return @ping_cache if defined?(@ping_cache)
|
84
|
-
|
119
|
+
return {} if @host_provider.nil?
|
120
|
+
|
121
|
+
@ping_cache = @host_provider.ping(hostname, port, protocol)
|
85
122
|
end
|
86
123
|
|
87
124
|
def resolve
|
88
125
|
return @ip_cache if defined?(@ip_cache)
|
89
|
-
@ip_cache = @host_provider.resolve(
|
126
|
+
@ip_cache = @host_provider.resolve(hostname) if !@host_provider.nil?
|
90
127
|
end
|
91
128
|
end
|
92
129
|
|
@@ -95,16 +132,37 @@ module Inspec::Resources
|
|
95
132
|
def initialize(inspec)
|
96
133
|
@inspec = inspec
|
97
134
|
end
|
135
|
+
|
136
|
+
def missing_requirements(_protocol)
|
137
|
+
# each provider can return an array of missing requirements that can
|
138
|
+
# be enumerated in a skip_resource message
|
139
|
+
[]
|
140
|
+
end
|
98
141
|
end
|
99
142
|
|
100
143
|
class DarwinHostProvider < HostProvider
|
101
|
-
def
|
102
|
-
|
144
|
+
def missing_requirements(protocol)
|
145
|
+
missing = []
|
146
|
+
|
147
|
+
if protocol == 'tcp'
|
148
|
+
missing << 'netcat must be installed' unless inspec.command('nc').exist?
|
149
|
+
end
|
150
|
+
|
151
|
+
missing
|
152
|
+
end
|
153
|
+
|
154
|
+
def ping(hostname, port, protocol)
|
155
|
+
if protocol == 'tcp'
|
103
156
|
resp = inspec.command("nc -vz -G 1 #{hostname} #{port}")
|
104
157
|
else
|
105
158
|
resp = inspec.command("ping -W 1 -c 1 #{hostname}")
|
106
159
|
end
|
107
|
-
|
160
|
+
|
161
|
+
{
|
162
|
+
success: resp.exit_status.to_i.zero?,
|
163
|
+
connection: resp.stderr,
|
164
|
+
socket: resp.stdout,
|
165
|
+
}
|
108
166
|
end
|
109
167
|
|
110
168
|
def resolve(hostname)
|
@@ -121,12 +179,29 @@ module Inspec::Resources
|
|
121
179
|
end
|
122
180
|
|
123
181
|
class LinuxHostProvider < HostProvider
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
182
|
+
def missing_requirements(protocol)
|
183
|
+
missing = []
|
184
|
+
|
185
|
+
if protocol == 'tcp'
|
186
|
+
missing << 'netcat must be installed' unless inspec.command('nc').exist?
|
187
|
+
end
|
188
|
+
|
189
|
+
missing
|
190
|
+
end
|
191
|
+
|
192
|
+
def ping(hostname, port, protocol)
|
193
|
+
if protocol == 'tcp'
|
194
|
+
resp = inspec.command("echo | nc -v -w 1 #{hostname} #{port}")
|
195
|
+
else
|
196
|
+
# fall back to ping, but we can only test ICMP packages with ping
|
197
|
+
resp = inspec.command("ping -w 1 -c 1 #{hostname}")
|
198
|
+
end
|
199
|
+
|
200
|
+
{
|
201
|
+
success: resp.exit_status.to_i.zero?,
|
202
|
+
connection: resp.stderr,
|
203
|
+
socket: resp.stdout,
|
204
|
+
}
|
130
205
|
end
|
131
206
|
|
132
207
|
def resolve(hostname)
|
@@ -156,15 +231,10 @@ module Inspec::Resources
|
|
156
231
|
begin
|
157
232
|
ping = JSON.parse(cmd.stdout)
|
158
233
|
rescue JSON::ParserError => _e
|
159
|
-
return
|
234
|
+
return {}
|
160
235
|
end
|
161
236
|
|
162
|
-
|
163
|
-
if port.nil?
|
164
|
-
ping['PingSucceeded']
|
165
|
-
else
|
166
|
-
ping['TcpTestSucceeded']
|
167
|
-
end
|
237
|
+
{ success: port.nil? ? ping['PingSucceeded'] : ping['TcpTestSucceeded'] }
|
168
238
|
end
|
169
239
|
|
170
240
|
def resolve(hostname)
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
# check for web applications in IIS
|
4
|
+
# Note: this is only supported in windows 2012 and later
|
5
|
+
module Inspec::Resources
|
6
|
+
class IisApp < Inspec.resource(1)
|
7
|
+
name 'iis_app'
|
8
|
+
desc 'Tests IIS application configuration on windows. Supported in server 2012+ only'
|
9
|
+
example "
|
10
|
+
describe iis_app('/myapp', 'Default Web Site') do
|
11
|
+
it { should exist }
|
12
|
+
it { should have_application_pool('MyAppPool') }
|
13
|
+
it { should have_protocols('http') }
|
14
|
+
it { should have_site_name('Default Web Site') }
|
15
|
+
it { should have_physical_path('C:\\inetpub\\wwwroot\\myapp') }
|
16
|
+
it { should have_path('\\My Application') }
|
17
|
+
end
|
18
|
+
"
|
19
|
+
|
20
|
+
def initialize(path, site_name)
|
21
|
+
@path = path
|
22
|
+
@site_name = site_name
|
23
|
+
@cache = nil
|
24
|
+
@inspec = inspec
|
25
|
+
|
26
|
+
# verify that this resource is only supported on Windows
|
27
|
+
return skip_resource 'The `iis_app` resource is not supported on your OS.' unless inspec.os.windows?
|
28
|
+
end
|
29
|
+
|
30
|
+
def application_pool
|
31
|
+
iis_app[:application_pool]
|
32
|
+
end
|
33
|
+
|
34
|
+
def protocols
|
35
|
+
iis_app[:protocols]
|
36
|
+
end
|
37
|
+
|
38
|
+
def site_name
|
39
|
+
iis_app[:site_name]
|
40
|
+
end
|
41
|
+
|
42
|
+
def path
|
43
|
+
iis_app[:path]
|
44
|
+
end
|
45
|
+
|
46
|
+
def physical_path
|
47
|
+
iis_app[:physical_path]
|
48
|
+
end
|
49
|
+
|
50
|
+
def exists?
|
51
|
+
!iis_app[:path].empty?
|
52
|
+
end
|
53
|
+
|
54
|
+
def has_site_name?(site_name)
|
55
|
+
iis_app[:site_name] == site_name
|
56
|
+
end
|
57
|
+
|
58
|
+
def has_application_pool?(application_pool)
|
59
|
+
iis_app[:application_pool] == application_pool
|
60
|
+
end
|
61
|
+
|
62
|
+
def has_path?(path)
|
63
|
+
iis_app[:path] == path
|
64
|
+
end
|
65
|
+
|
66
|
+
def has_physical_path?(physical_path)
|
67
|
+
iis_app[:physical_path] == physical_path
|
68
|
+
end
|
69
|
+
|
70
|
+
def has_protocol?(protocol)
|
71
|
+
iis_app[:protocols].include?(protocol)
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_s
|
75
|
+
"iis_app '#{@site_name}#{@path}'"
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def iis_app
|
81
|
+
return @cache unless @cache.nil?
|
82
|
+
command = "Import-Module WebAdministration; Get-WebApplication -Name '#{@path}' -Site '#{@site_name}' | Select-Object * | ConvertTo-Json"
|
83
|
+
cmd = @inspec.command(command)
|
84
|
+
|
85
|
+
begin
|
86
|
+
app = JSON.parse(cmd.stdout)
|
87
|
+
rescue JSON::ParserError => _e
|
88
|
+
return {}
|
89
|
+
end
|
90
|
+
|
91
|
+
# map our values to a hash table
|
92
|
+
info = {
|
93
|
+
site_name: @site_name,
|
94
|
+
path: @path,
|
95
|
+
application_pool: app['applicationPool'],
|
96
|
+
physical_path: app['PhysicalPath'],
|
97
|
+
protocols: app['enabledProtocols'],
|
98
|
+
}
|
99
|
+
|
100
|
+
@cache = info unless info.nil?
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/resources/service.rb
CHANGED
@@ -151,6 +151,8 @@ module Inspec::Resources
|
|
151
151
|
BSDInit.new(inspec, service_ctl)
|
152
152
|
elsif %w{arch}.include?(platform)
|
153
153
|
Systemd.new(inspec, service_ctl)
|
154
|
+
elsif %w{coreos}.include?(platform)
|
155
|
+
Systemd.new(inspec, service_ctl)
|
154
156
|
elsif %w{suse opensuse}.include?(platform)
|
155
157
|
if os[:release].to_i >= 12
|
156
158
|
Systemd.new(inspec, service_ctl)
|
@@ -0,0 +1,252 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Takaaki Furukawa
|
3
|
+
|
4
|
+
require 'hashie/mash'
|
5
|
+
|
6
|
+
module Inspec::Resources
|
7
|
+
class Virtualization < Inspec.resource(1) # rubocop:disable Metrics/ClassLength
|
8
|
+
name 'virtualization'
|
9
|
+
desc 'Use the virtualization InSpec audit resource to test the virtualization platform on which the system is running'
|
10
|
+
example "
|
11
|
+
describe virtualization do
|
12
|
+
its('system') { should eq 'docker' }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe virtualization do
|
16
|
+
its('role') { should eq 'guest' }
|
17
|
+
end
|
18
|
+
|
19
|
+
control 'test' do
|
20
|
+
describe file('/var/tmp/foo') do
|
21
|
+
it { should be_file }
|
22
|
+
end
|
23
|
+
only_if { virtualization.system == 'docker' }
|
24
|
+
end
|
25
|
+
"
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
unless inspec.os.linux?
|
29
|
+
skip_resource 'The `virtualization` resource is not supported on your OS yet.'
|
30
|
+
else
|
31
|
+
collect_data_linux
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# add helper methods for easy access of properties
|
36
|
+
# allows users to use virtualization.role, virtualization.system
|
37
|
+
%w{role system}.each do |property|
|
38
|
+
define_method(property.to_sym) do
|
39
|
+
@virtualization_data[property.to_sym]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def params
|
44
|
+
collect_data_linux
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
'Virtualization Detection'
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def lxc_version_exists?
|
54
|
+
inspec.command('lxc-version').exist?
|
55
|
+
end
|
56
|
+
|
57
|
+
def docker_exists?
|
58
|
+
inspec.command('docker').exist?
|
59
|
+
end
|
60
|
+
|
61
|
+
def nova_exists?
|
62
|
+
inspec.command('nova').exist?
|
63
|
+
end
|
64
|
+
|
65
|
+
# Detect Xen
|
66
|
+
# /proc/xen is an empty dir for EL6 + Linode Guests + Paravirt EC2 instances
|
67
|
+
# Notes:
|
68
|
+
# - cpuid of guests, if we could get it, would also be a clue
|
69
|
+
# - may be able to determine if under paravirt from /dev/xen/evtchn (See OHAI-253)
|
70
|
+
# - Additional edge cases likely should not change the above assumptions
|
71
|
+
# but rather be additive - btm
|
72
|
+
def detect_xen
|
73
|
+
return false unless inspec.file('/proc/xen').exist?
|
74
|
+
@virtualization_data[:system] = 'xen'
|
75
|
+
@virtualization_data[:role] = 'guest'
|
76
|
+
|
77
|
+
# This file should exist on most Xen systems, normally empty for guests
|
78
|
+
if inspec.file('/proc/xen/capabilities').exist? &&
|
79
|
+
inspec.file('/proc/xen/capabilities').content =~ /control_d/i # rubocop:disable Style/MultilineOperationIndentation
|
80
|
+
@virtualization_data[:role] = 'host'
|
81
|
+
end
|
82
|
+
true
|
83
|
+
end
|
84
|
+
|
85
|
+
# Detect Virtualbox from kernel module
|
86
|
+
def detect_virtualbox
|
87
|
+
return false unless inspec.file('/proc/modules').exist?
|
88
|
+
modules = inspec.file('/proc/modules').content
|
89
|
+
if modules =~ /^vboxdrv/
|
90
|
+
Inspec::Log.debug('Plugin Virtualization: /proc/modules contains vboxdrv. Detecting as vbox host')
|
91
|
+
@virtualization_data[:system] = 'vbox'
|
92
|
+
@virtualization_data[:role] = 'host'
|
93
|
+
elsif modules =~ /^vboxguest/
|
94
|
+
Inspec::Log.debug('Plugin Virtualization: /proc/modules contains vboxguest. Detecting as vbox guest')
|
95
|
+
@virtualization_data[:system] = 'vbox'
|
96
|
+
@virtualization_data[:role] = 'guest'
|
97
|
+
else
|
98
|
+
return false
|
99
|
+
end
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
# if nova binary is present we're on an openstack host
|
104
|
+
def detect_openstack
|
105
|
+
return false unless nova_exists?
|
106
|
+
@virtualization_data[:system] = 'openstack'
|
107
|
+
@virtualization_data[:role] = 'host'
|
108
|
+
true
|
109
|
+
end
|
110
|
+
|
111
|
+
# Detect paravirt KVM/QEMU from cpuinfo, report as KVM
|
112
|
+
def detect_kvm_from_cpuinfo
|
113
|
+
return false unless inspec.file('/proc/cpuinfo').content =~ /QEMU Virtual CPU|Common KVM processor|Common 32-bit KVM processor/
|
114
|
+
@virtualization_data[:system] = 'kvm'
|
115
|
+
@virtualization_data[:role] = 'guest'
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
119
|
+
# Detect KVM systems via /sys
|
120
|
+
# guests will have the hypervisor cpu feature that hosts don't have
|
121
|
+
def detect_kvm_from_sys
|
122
|
+
return false unless inspec.file('/sys/devices/virtual/misc/kvm').exist?
|
123
|
+
if inspec.file('/proc/cpuinfo').content =~ /hypervisor/
|
124
|
+
@virtualization_data[:system] = 'kvm'
|
125
|
+
@virtualization_data[:role] = 'guest'
|
126
|
+
else
|
127
|
+
@virtualization_data[:system] = 'kvm'
|
128
|
+
@virtualization_data[:role] = 'host'
|
129
|
+
end
|
130
|
+
true
|
131
|
+
end
|
132
|
+
|
133
|
+
# Detect OpenVZ / Virtuozzo.
|
134
|
+
# http://wiki.openvz.org/BC_proc_entries
|
135
|
+
def detect_openvz
|
136
|
+
if inspec.file('/proc/bc/0').exist?
|
137
|
+
@virtualization_data[:system] = 'openvz'
|
138
|
+
@virtualization_data[:role] = 'host'
|
139
|
+
elsif inspec.file('/proc/vz').exist?
|
140
|
+
@virtualization_data[:system] = 'openvz'
|
141
|
+
@virtualization_data[:role] = 'guest'
|
142
|
+
else
|
143
|
+
return false
|
144
|
+
end
|
145
|
+
true
|
146
|
+
end
|
147
|
+
|
148
|
+
# Detect Parallels virtual machine from pci devices
|
149
|
+
def detect_parallels
|
150
|
+
return false unless inspec.file('/proc/bus/pci/devices').content =~ /1ab84000/
|
151
|
+
@virtualization_data[:system] = 'parallels'
|
152
|
+
@virtualization_data[:role] = 'guest'
|
153
|
+
true
|
154
|
+
end
|
155
|
+
|
156
|
+
# Detect Linux-VServer
|
157
|
+
def detect_linux_vserver
|
158
|
+
return false unless inspec.file('/proc/self/status').exist?
|
159
|
+
proc_self_status = inspec.file('/proc/self/status').content
|
160
|
+
vxid = proc_self_status.match(/^(s_context|VxID):\s*(\d+)$/)
|
161
|
+
return false unless vxid && vxid[2]
|
162
|
+
@virtualization_data[:system] = 'linux-vserver'
|
163
|
+
if vxid[2] == '0'
|
164
|
+
@virtualization_data[:role] = 'host'
|
165
|
+
else
|
166
|
+
@virtualization_data[:role] = 'guest'
|
167
|
+
end
|
168
|
+
true
|
169
|
+
end
|
170
|
+
|
171
|
+
# Detect LXC/Docker
|
172
|
+
#
|
173
|
+
# /proc/self/cgroup will look like this inside a docker container:
|
174
|
+
# <index #>:<subsystem>:/lxc/<hexadecimal container id>
|
175
|
+
#
|
176
|
+
# /proc/self/cgroup could have a name including alpha/digit/dashes
|
177
|
+
# <index #>:<subsystem>:/lxc/<named container id>
|
178
|
+
#
|
179
|
+
# /proc/self/cgroup could have a non-lxc cgroup name indicating other uses
|
180
|
+
# of cgroups. This is probably not LXC/Docker.
|
181
|
+
# <index #>:<subsystem>:/Charlie
|
182
|
+
#
|
183
|
+
# A host which supports cgroups, and has capacity to host lxc containers,
|
184
|
+
# will show the subsystems and root (/) namespace.
|
185
|
+
# <index #>:<subsystem>:/
|
186
|
+
#
|
187
|
+
# Full notes, https://tickets.opscode.com/browse/OHAI-551
|
188
|
+
# Kernel docs, https://www.kernel.org/doc/Documentation/cgroups
|
189
|
+
def detect_lxc_docker
|
190
|
+
return false unless inspec.file('/proc/self/cgroup').exist?
|
191
|
+
cgroup_content = inspec.file('/proc/self/cgroup').content
|
192
|
+
if cgroup_content =~ %r{^\d+:[^:]+:/(lxc|docker)/.+$} ||
|
193
|
+
cgroup_content =~ %r{^\d+:[^:]+:/[^/]+/(lxc|docker)-.+$} # rubocop:disable Style/MultilineOperationIndentation
|
194
|
+
@virtualization_data[:system] = $1 # rubocop:disable Style/PerlBackrefs
|
195
|
+
@virtualization_data[:role] = 'guest'
|
196
|
+
elsif lxc_version_exists? && cgroup_content =~ %r{\d:[^:]+:/$}
|
197
|
+
# lxc-version shouldn't be installed by default
|
198
|
+
# Even so, it is likely we are on an LXC capable host that is not being used as such
|
199
|
+
# So we're cautious here to not overwrite other existing values (OHAI-573)
|
200
|
+
unless @virtualization_data[:system] && @virtualization_data[:role]
|
201
|
+
@virtualization_data[:system] = 'lxc'
|
202
|
+
@virtualization_data[:role] = 'host'
|
203
|
+
end
|
204
|
+
else
|
205
|
+
return false
|
206
|
+
end
|
207
|
+
true
|
208
|
+
end
|
209
|
+
|
210
|
+
def detect_docker
|
211
|
+
return false unless inspec.file('/.dockerenv').exist? || inspec.file('/.dockerinit').exist?
|
212
|
+
@virtualization_data[:system] = 'docker'
|
213
|
+
@virtualization_data[:role] = 'guest'
|
214
|
+
true
|
215
|
+
end
|
216
|
+
|
217
|
+
# Detect LXD
|
218
|
+
# See https://github.com/lxc/lxd/blob/master/doc/dev-lxd.md
|
219
|
+
def detect_lxd
|
220
|
+
if inspec.file('/dev/lxd/sock').exist?
|
221
|
+
@virtualization_data[:system] = 'lxd'
|
222
|
+
@virtualization_data[:role] = 'guest'
|
223
|
+
elsif inspec.file('/var/lib/lxd/devlxd').exist?
|
224
|
+
@virtualization_data[:system] = 'lxd'
|
225
|
+
@virtualization_data[:role] = 'host'
|
226
|
+
else
|
227
|
+
return false
|
228
|
+
end
|
229
|
+
true
|
230
|
+
end
|
231
|
+
|
232
|
+
def collect_data_linux # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
233
|
+
# cache data in an instance var to avoid doing multiple detections for a single test
|
234
|
+
@virtualization_data ||= Hashie::Mash.new
|
235
|
+
return unless @virtualization_data.empty?
|
236
|
+
|
237
|
+
# each detect method will return true if it matched and was successfully
|
238
|
+
# able to populate @virtualization_data with stuff.
|
239
|
+
return if detect_xen
|
240
|
+
return if detect_virtualbox
|
241
|
+
return if detect_openstack
|
242
|
+
return if detect_kvm_from_cpuinfo
|
243
|
+
return if detect_kvm_from_sys
|
244
|
+
return if detect_openvz
|
245
|
+
return if detect_parallels
|
246
|
+
return if detect_linux_vserver
|
247
|
+
return if detect_lxc_docker
|
248
|
+
return if detect_docker
|
249
|
+
return if detect_lxd
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
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.28.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-06-
|
11
|
+
date: 2017-06-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: train
|
@@ -305,6 +305,7 @@ files:
|
|
305
305
|
- docs/migration.md
|
306
306
|
- docs/plugin_kitchen_inspec.md
|
307
307
|
- docs/profiles.md
|
308
|
+
- docs/resources.md
|
308
309
|
- docs/resources/apache_conf.md.erb
|
309
310
|
- docs/resources/apt.md.erb
|
310
311
|
- docs/resources/audit_policy.md.erb
|
@@ -331,6 +332,7 @@ files:
|
|
331
332
|
- docs/resources/grub_conf.md.erb
|
332
333
|
- docs/resources/host.md.erb
|
333
334
|
- docs/resources/http.md.erb
|
335
|
+
- docs/resources/iis_app.md.erb
|
334
336
|
- docs/resources/iis_site.md.erb
|
335
337
|
- docs/resources/inetd_conf.md.erb
|
336
338
|
- docs/resources/ini.md.erb
|
@@ -377,6 +379,7 @@ files:
|
|
377
379
|
- docs/resources/user.md.erb
|
378
380
|
- docs/resources/users.md.erb
|
379
381
|
- docs/resources/vbscript.md.erb
|
382
|
+
- docs/resources/virtualization.md.erb
|
380
383
|
- docs/resources/windows_feature.md.erb
|
381
384
|
- docs/resources/windows_task.md.erb
|
382
385
|
- docs/resources/wmi.md.erb
|
@@ -396,6 +399,7 @@ files:
|
|
396
399
|
- examples/README.md
|
397
400
|
- examples/inheritance/README.md
|
398
401
|
- examples/inheritance/controls/example.rb
|
402
|
+
- examples/inheritance/inspec.lock
|
399
403
|
- examples/inheritance/inspec.yml
|
400
404
|
- examples/kitchen-ansible/.kitchen.yml
|
401
405
|
- examples/kitchen-ansible/Gemfile
|
@@ -421,7 +425,11 @@ files:
|
|
421
425
|
- examples/kitchen-puppet/test/integration/default/web_spec.rb
|
422
426
|
- examples/meta-profile/README.md
|
423
427
|
- examples/meta-profile/controls/example.rb
|
428
|
+
- examples/meta-profile/inspec.lock
|
424
429
|
- examples/meta-profile/inspec.yml
|
430
|
+
- examples/meta-profile/vendor/0e6d170415e120af5f1dda113f96f7e0d156e49f82706ac41d13da00599f9b25.tar.gz
|
431
|
+
- examples/meta-profile/vendor/403580959915ea24bc176b9ebdc555aeda5e2c957604b48d5f32b43554423582.tar.gz
|
432
|
+
- examples/meta-profile/vendor/d08d3cc35debff04e708147cdd07739876c5d1c8357afb5e58adfaad92dd650f.tar.gz
|
425
433
|
- examples/profile-attribute.yml
|
426
434
|
- examples/profile-attribute/README.md
|
427
435
|
- examples/profile-attribute/controls/example.rb
|
@@ -558,6 +566,7 @@ files:
|
|
558
566
|
- lib/resources/grub_conf.rb
|
559
567
|
- lib/resources/host.rb
|
560
568
|
- lib/resources/http.rb
|
569
|
+
- lib/resources/iis_app.rb
|
561
570
|
- lib/resources/iis_site.rb
|
562
571
|
- lib/resources/inetd_conf.rb
|
563
572
|
- lib/resources/ini.rb
|
@@ -601,6 +610,7 @@ files:
|
|
601
610
|
- lib/resources/sys_info.rb
|
602
611
|
- lib/resources/users.rb
|
603
612
|
- lib/resources/vbscript.rb
|
613
|
+
- lib/resources/virtualization.rb
|
604
614
|
- lib/resources/windows_feature.rb
|
605
615
|
- lib/resources/windows_task.rb
|
606
616
|
- lib/resources/wmi.rb
|