inspec 1.19.2 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -1
- data/docs/resources/rabbitmq_config.md.erb +55 -0
- data/inspec.gemspec +2 -1
- data/lib/bundles/inspec-compliance/README.md +44 -15
- data/lib/bundles/inspec-compliance/api.rb +7 -9
- data/lib/bundles/inspec-compliance/cli.rb +33 -14
- data/lib/bundles/inspec-compliance/target.rb +6 -1
- data/lib/bundles/inspec-habitat/profile.rb +1 -0
- data/lib/inspec/profile.rb +1 -1
- data/lib/inspec/resource.rb +1 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/gem.rb +4 -1
- data/lib/resources/host.rb +28 -4
- data/lib/resources/rabbitmq_conf.rb +53 -0
- data/lib/resources/ssl.rb +1 -1
- data/lib/resources/sys_info.rb +1 -1
- data/lib/utils/erlang_parser.rb +192 -0
- metadata +21 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a68bde2c8c3272f13f8f2953742130866e0a8384
|
4
|
+
data.tar.gz: ce752f86311f19345c39d1ae1a3884194700164d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4271a1f24111f22d6044ff3e0892e16ccbd32b9cdcc942afe1d10490225594f8aaff71c1a41b98fdc347d65612fcd254295a1f90c3941a73c54d4c4b029e3c72
|
7
|
+
data.tar.gz: 6c2e5e7c839b3e641a435570e00ee48c839f1ed9bf84220505a2eee1be2dc97719d58b851205cd9b8e52e38383b0debbe86628cfcda95507b490b49de59767d3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v1.20.0](https://github.com/chef/inspec/tree/v1.20.0) (2017-04-13)
|
4
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v1.19.2...v1.20.0)
|
5
|
+
|
6
|
+
**Fixed bugs:**
|
7
|
+
|
8
|
+
- gem resource :chef symbol isn't valid on Windows [\#1645](https://github.com/chef/inspec/issues/1645)
|
9
|
+
|
10
|
+
**Closed issues:**
|
11
|
+
|
12
|
+
- List on-tap hard to use [\#1644](https://github.com/chef/inspec/issues/1644)
|
13
|
+
- inspec vendor meta profiles fails when dependency profile is in Automate asset store [\#1632](https://github.com/chef/inspec/issues/1632)
|
14
|
+
- cannot upload meta profile to Automate [\#1631](https://github.com/chef/inspec/issues/1631)
|
15
|
+
|
16
|
+
**Merged pull requests:**
|
17
|
+
|
18
|
+
- Habitat packages should run as root [\#1656](https://github.com/chef/inspec/pull/1656) ([adamleff](https://github.com/adamleff))
|
19
|
+
- harmonize compliance profiles view with supermarket views [\#1654](https://github.com/chef/inspec/pull/1654) ([chris-rock](https://github.com/chris-rock))
|
20
|
+
- \[www\] Update community page [\#1651](https://github.com/chef/inspec/pull/1651) ([adamleff](https://github.com/adamleff))
|
21
|
+
- Fix gem resource on Windows [\#1650](https://github.com/chef/inspec/pull/1650) ([adamleff](https://github.com/adamleff))
|
22
|
+
- add support for hostname detection on macOS [\#1648](https://github.com/chef/inspec/pull/1648) ([chris-rock](https://github.com/chris-rock))
|
23
|
+
- allow Automate profile dependencies [\#1647](https://github.com/chef/inspec/pull/1647) ([jeremymv2](https://github.com/jeremymv2))
|
24
|
+
- pass options hash sans target key [\#1646](https://github.com/chef/inspec/pull/1646) ([jeremymv2](https://github.com/jeremymv2))
|
25
|
+
- add `rabbitmq\_config` resource [\#1639](https://github.com/chef/inspec/pull/1639) ([arlimus](https://github.com/arlimus))
|
26
|
+
- \[www\] Adding a website acceptance environment [\#1634](https://github.com/chef/inspec/pull/1634) ([adamleff](https://github.com/adamleff))
|
27
|
+
- Adding SNI utilization to ssl resource [\#1624](https://github.com/chef/inspec/pull/1624) ([supergicko](https://github.com/supergicko))
|
28
|
+
- Add OSX support for host resource [\#1608](https://github.com/chef/inspec/pull/1608) ([RyanJarv](https://github.com/RyanJarv))
|
29
|
+
|
3
30
|
## [v1.19.2](https://github.com/chef/inspec/tree/v1.19.2) (2017-04-07)
|
4
31
|
[Full Changelog](https://github.com/chef/inspec/compare/v1.19.1...v1.19.2)
|
5
32
|
|
@@ -13,6 +40,7 @@
|
|
13
40
|
|
14
41
|
**Merged pull requests:**
|
15
42
|
|
43
|
+
- Release 1.19.2 patch release [\#1638](https://github.com/chef/inspec/pull/1638) ([adamleff](https://github.com/adamleff))
|
16
44
|
- Fix and document registry issues [\#1635](https://github.com/chef/inspec/pull/1635) ([chris-rock](https://github.com/chris-rock))
|
17
45
|
- \[www\] Add warning to the http resource documentation [\#1623](https://github.com/chef/inspec/pull/1623) ([adamleff](https://github.com/adamleff))
|
18
46
|
|
@@ -438,7 +466,6 @@
|
|
438
466
|
- do not load controls from test directory [\#1327](https://github.com/chef/inspec/pull/1327) ([chris-rock](https://github.com/chris-rock))
|
439
467
|
- Replaced Colors for output [\#1320](https://github.com/chef/inspec/pull/1320) ([hannah-radish](https://github.com/hannah-radish))
|
440
468
|
- Hannah vj/fix tests formatting [\#1319](https://github.com/chef/inspec/pull/1319) ([hannah-radish](https://github.com/hannah-radish))
|
441
|
-
- revert style changes temporarily [\#1317](https://github.com/chef/inspec/pull/1317) ([vjeffrey](https://github.com/vjeffrey))
|
442
469
|
- Updated color palettes, label colors and icons [\#1313](https://github.com/chef/inspec/pull/1313) ([hannah-radish](https://github.com/hannah-radish))
|
443
470
|
- Remove extra `'` in registry key examples [\#1308](https://github.com/chef/inspec/pull/1308) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
|
444
471
|
- also push docker latest tag with each release [\#1307](https://github.com/chef/inspec/pull/1307) ([chris-rock](https://github.com/chris-rock))
|
@@ -459,6 +486,7 @@
|
|
459
486
|
|
460
487
|
**Merged pull requests:**
|
461
488
|
|
489
|
+
- revert style changes temporarily [\#1317](https://github.com/chef/inspec/pull/1317) ([vjeffrey](https://github.com/vjeffrey))
|
462
490
|
- ensure metadata release entry is a string [\#1305](https://github.com/chef/inspec/pull/1305) ([chris-rock](https://github.com/chris-rock))
|
463
491
|
- Fixes resources in the docs [\#1303](https://github.com/chef/inspec/pull/1303) ([burtlo](https://github.com/burtlo))
|
464
492
|
- copy vendored dependencies into cache [\#1291](https://github.com/chef/inspec/pull/1291) ([chris-rock](https://github.com/chris-rock))
|
@@ -0,0 +1,55 @@
|
|
1
|
+
---
|
2
|
+
title: About the rabbitmq_config Resource
|
3
|
+
---
|
4
|
+
|
5
|
+
# rabbitmq_config
|
6
|
+
|
7
|
+
Use the `rabbitmq_config` InSpec audit resource to test configuration data for the RabbitMQ daemon located at `/etc/rabbitmq/rabbitmq.config` on Linux and Unix platforms.
|
8
|
+
|
9
|
+
## Syntax
|
10
|
+
|
11
|
+
A `rabbitmq_config` resource block declares the RabbitMQ configuration data to be tested:
|
12
|
+
|
13
|
+
describe rabbitmq_config.params('rabbit', 'ssl_listeners') do
|
14
|
+
it { should cmp 5671 }
|
15
|
+
end
|
16
|
+
|
17
|
+
where
|
18
|
+
|
19
|
+
* `params` is the list of parameters configured in the RabbitMQ config file
|
20
|
+
* `{ should cmp 5671 }` tests the value of `rabbit.ssl_listeners` as read from `rabbitmq.config` versus the value declared in the test
|
21
|
+
|
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 the list of TCP listeners
|
52
|
+
|
53
|
+
describe rabbitmq_config.params('rabbit', 'tcp_listeners') do
|
54
|
+
it { should eq [5672] }
|
55
|
+
end
|
data/inspec.gemspec
CHANGED
@@ -37,9 +37,10 @@ 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.1'
|
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'
|
44
44
|
spec.add_dependency 'addressable', '~> 2.4'
|
45
|
+
spec.add_dependency 'parslet', '~> 1.5'
|
45
46
|
end
|
@@ -9,8 +9,9 @@ This extensions offers the following features:
|
|
9
9
|
To use the CLI, this InSpec add-on adds the following commands:
|
10
10
|
|
11
11
|
* `$ inspec compliance login` - authentication of the API token against Chef Compliance
|
12
|
+
* `$ inspec compliance login_automate` - authentication of the API token against Chef Automate
|
12
13
|
* `$ inspec compliance profiles` - list all available Chef Compliance profiles
|
13
|
-
* `$ inspec
|
14
|
+
* `$ inspec exec compliance://profile` - runs a Chef Compliance profile
|
14
15
|
* `$ inspec compliance upload path/to/local/profile` - uploads a local profile to Chef Compliance
|
15
16
|
* `$ inspec compliance logout` - logout of Chef Compliance
|
16
17
|
|
@@ -19,8 +20,37 @@ Compliance profiles can be executed in two mays:
|
|
19
20
|
- via compliance exec: `inspec compliance exec profile`
|
20
21
|
- via compliance scheme: `inspec exec compliance://profile`
|
21
22
|
|
23
|
+
|
22
24
|
## Usage
|
23
25
|
|
26
|
+
### Command options
|
27
|
+
|
28
|
+
```
|
29
|
+
$ inspec compliance
|
30
|
+
Commands:
|
31
|
+
inspec compliance download PROFILE # downloads a profile from Chef Compliance
|
32
|
+
inspec compliance exec PROFILE # executes a Chef Compliance profile
|
33
|
+
inspec compliance help [COMMAND] # Describe subcommands or one specific subcommand
|
34
|
+
inspec compliance login SERVER # Log in to a Chef Compliance SERVER
|
35
|
+
inspec compliance login_automate SERVER # Log in to an Automate SERVER
|
36
|
+
inspec compliance logout # user logout from Chef Compliance
|
37
|
+
inspec compliance profiles # list all available profiles in Chef Compliance
|
38
|
+
inspec compliance upload PATH # uploads a local profile to Chef Compliance
|
39
|
+
inspec compliance version # displays the version of the Chef Compliance server
|
40
|
+
```
|
41
|
+
|
42
|
+
### Login with Chef Automate
|
43
|
+
|
44
|
+
You need a Chef Automate server up and running. Compliance features need to [be activated](https://docs.chef.io/install_chef_automate.html#compliance), too.
|
45
|
+
|
46
|
+
Now, you need a user token. You can retrieve that via [UI](https://docs.chef.io/api_delivery.html) or [CLI](https://docs.chef.io/ctl_delivery.html#delivery-token).
|
47
|
+
|
48
|
+
```
|
49
|
+
inspec compliance login_automate https://automate.compliance.test --insecure --user 'admin' --ent 'brewinc' --usertoken 'zuop..._KzE'
|
50
|
+
```
|
51
|
+
|
52
|
+
### Login with Chef Compliance
|
53
|
+
|
24
54
|
Before you start using the compliance plugin, you need a running [Chef Compliance](https://www.chef.io/compliance/) server. Please login and gather the access token:
|
25
55
|
|
26
56
|

|
@@ -28,24 +58,17 @@ Before you start using the compliance plugin, you need a running [Chef Complianc
|
|
28
58
|
You can choose the access token (`--token`) or the refresh token (`--refresh_token`)
|
29
59
|
|
30
60
|
```
|
31
|
-
$ inspec compliance
|
32
|
-
Commands:
|
33
|
-
inspec compliance exec PROFILE # executes a Chef Compliance profile
|
34
|
-
inspec compliance help [COMMAND] # Describe subcommands or one specific subcommand
|
35
|
-
inspec compliance login SERVER # Log in to a Chef Compliance SERVER
|
36
|
-
inspec compliance logout # user logout from Chef Compliance
|
37
|
-
inspec compliance profiles # list all available profiles in Chef Compliance
|
38
|
-
inspec compliance upload PATH # uploads a local profile to Chef Compliance
|
39
|
-
inspec compliance version # displays the version of the Chef Compliance server
|
40
|
-
|
41
61
|
# login to chef compliance server
|
42
62
|
$ inspec compliance login https://compliance.test --user admin --insecure --token '...'
|
43
63
|
|
44
64
|
# display the chef compliance server version
|
45
65
|
$ inspec compliance version
|
46
66
|
Chef Compliance version: 1.0.11
|
67
|
+
```
|
68
|
+
|
69
|
+
### List available profiles via Chef Compliance / Automate
|
47
70
|
|
48
|
-
|
71
|
+
```
|
49
72
|
$ inspec compliance profiles
|
50
73
|
Available profiles:
|
51
74
|
-------------------
|
@@ -65,8 +88,11 @@ Available profiles:
|
|
65
88
|
* cis/cis-ubuntu12.04lts-level2
|
66
89
|
* cis/cis-ubuntu14.04lts-level1
|
67
90
|
* cis/cis-ubuntu14.04lts-level2
|
91
|
+
```
|
92
|
+
|
93
|
+
### Upload a profile to Chef Compliance / Automate
|
68
94
|
|
69
|
-
|
95
|
+
```
|
70
96
|
$ inspec compliance version
|
71
97
|
Chef Compliance version: 1.0.11
|
72
98
|
➜ inspec git:(chris-rock/cc-error-not-loggedin) ✗ b inspec compliance upload examples/profile
|
@@ -103,8 +129,11 @@ Available profiles:
|
|
103
129
|
* cis/cis-ubuntu12.04lts-level2
|
104
130
|
* cis/cis-ubuntu14.04lts-level1
|
105
131
|
* cis/cis-ubuntu14.04lts-level2
|
132
|
+
```
|
133
|
+
|
134
|
+
### Run a profile from Chef Compliance / Automate on Workstation
|
106
135
|
|
107
|
-
|
136
|
+
```
|
108
137
|
$ inspec exec compliance://admin/profile
|
109
138
|
.*...
|
110
139
|
|
@@ -119,7 +148,7 @@ Finished in 0.02862 seconds (files took 0.62628 seconds to load)
|
|
119
148
|
5 examples, 0 failures, 1 pending
|
120
149
|
```
|
121
150
|
|
122
|
-
|
151
|
+
### To Logout from Chef Compliance
|
123
152
|
|
124
153
|
```
|
125
154
|
$ inspec compliance logout
|
@@ -22,16 +22,14 @@ module Compliance
|
|
22
22
|
profiles = JSON.parse(data)
|
23
23
|
# iterate over profiles
|
24
24
|
if config['server_type'] == 'automate'
|
25
|
-
mapped_profiles = profiles.
|
26
|
-
{ org: ps['owner_id'], name: owner }
|
27
|
-
end.flatten
|
25
|
+
mapped_profiles = profiles.values.to_a.flatten
|
28
26
|
else
|
29
|
-
mapped_profiles =
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end.flatten
|
27
|
+
mapped_profiles = []
|
28
|
+
profiles.values.each { |org|
|
29
|
+
mapped_profiles += org.values
|
30
|
+
}
|
34
31
|
end
|
32
|
+
|
35
33
|
return msg, mapped_profiles
|
36
34
|
when '401'
|
37
35
|
msg = '401 Unauthorized. Please check your token.'
|
@@ -66,7 +64,7 @@ Please login using `inspec compliance login https://compliance.test --user admin
|
|
66
64
|
def self.exist?(config, profile)
|
67
65
|
_msg, profiles = Compliance::API.profiles(config)
|
68
66
|
if !profiles.empty?
|
69
|
-
index = profiles.index { |p| "#{p[
|
67
|
+
index = profiles.index { |p| "#{p['owner_id']}/#{p['name']}" == profile }
|
70
68
|
!index.nil? && index >= 0
|
71
69
|
else
|
72
70
|
false
|
@@ -57,7 +57,14 @@ module Compliance
|
|
57
57
|
puts '', msg
|
58
58
|
end
|
59
59
|
|
60
|
-
desc "login_automate SERVER --user='USER' --ent='ENT' --
|
60
|
+
desc "login_automate SERVER --insecure --user='USER' --ent='ENT' --usertoken='TOKEN'", 'Log in to an Automate SERVER'
|
61
|
+
long_desc <<-LONGDESC
|
62
|
+
`login_automate` allows you to use InSpec with Chef Automate
|
63
|
+
|
64
|
+
You need to a user-token for communication with Chef Automate. More
|
65
|
+
information about token retrieval for Automate is available at:
|
66
|
+
https://docs.chef.io/api_delivery.html
|
67
|
+
LONGDESC
|
61
68
|
option :dctoken, type: :string,
|
62
69
|
desc: 'Data Collector token'
|
63
70
|
option :usertoken, type: :string,
|
@@ -72,31 +79,32 @@ module Compliance
|
|
72
79
|
options['server'] = server
|
73
80
|
url = options['server'] + '/compliance/profiles'
|
74
81
|
|
75
|
-
if url && !options['user'].nil? && !options['ent'].nil?
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
puts "Please specify a token using --dctoken='DATA_COLLECTOR_TOKEN' or --usertoken='AUTOMATE_TOKEN' "
|
80
|
-
exit 1
|
81
|
-
end
|
82
|
-
else
|
83
|
-
puts "Please login to your automate instance using 'inspec compliance login_automate SERVER --user AUTOMATE_USER --ent AUTOMATE_ENT --dctoken DC_TOKEN or --usertoken USER_TOKEN' "
|
84
|
-
exit 1
|
82
|
+
if url && !options['user'].nil? && !options['ent'].nil? && (!options['dctoken'].nil? || !options['usertoken'].nil?)
|
83
|
+
msg = login_automate_config(url, options['user'], options['dctoken'], options['usertoken'], options['ent'], options['insecure'])
|
84
|
+
puts '', msg
|
85
|
+
exit 0
|
85
86
|
end
|
86
|
-
|
87
|
+
|
88
|
+
# parameters are missing if we reach here
|
89
|
+
puts 'Please specify an user using `--user \'USER\'`' if options['user'].nil?
|
90
|
+
puts 'Please specify an enterprise using `--ent \'cd\'`' if options['ent'].nil?
|
91
|
+
puts 'Please specify a token using `--usertoken=\'AUTOMATE_TOKEN\'`' if options['usertoken'].nil? && options['dctoken'].nil?
|
92
|
+
exit 1
|
87
93
|
end
|
88
94
|
|
89
95
|
desc 'profiles', 'list all available profiles in Chef Compliance'
|
96
|
+
|
90
97
|
def profiles
|
91
98
|
config = Compliance::Configuration.new
|
92
99
|
return if !loggedin(config)
|
93
100
|
|
94
101
|
msg, profiles = Compliance::API.profiles(config)
|
102
|
+
profiles.sort_by! { |hsh| hsh['title'] }
|
95
103
|
if !profiles.empty?
|
96
104
|
# iterate over profiles
|
97
105
|
headline('Available profiles:')
|
98
106
|
profiles.each { |profile|
|
99
|
-
li("#{profile[
|
107
|
+
li("#{profile['title']} #{mark_text(profile['owner_id'] + '/' + profile['name'])}")
|
100
108
|
}
|
101
109
|
else
|
102
110
|
puts msg, 'Could not find any profiles'
|
@@ -110,7 +118,7 @@ module Compliance
|
|
110
118
|
config = Compliance::Configuration.new
|
111
119
|
return if !loggedin(config)
|
112
120
|
# iterate over tests and add compliance scheme
|
113
|
-
tests = tests.map { |t| 'compliance://' + t }
|
121
|
+
tests = tests.map { |t| 'compliance://' + sanitize_profile_name(t) }
|
114
122
|
# execute profile from inspec exec implementation
|
115
123
|
diagnose
|
116
124
|
run_tests(tests, opts)
|
@@ -126,6 +134,7 @@ module Compliance
|
|
126
134
|
config = Compliance::Configuration.new
|
127
135
|
return if !loggedin(config)
|
128
136
|
|
137
|
+
profile_name = sanitize_profile_name(profile_name)
|
129
138
|
if Compliance::API.exist?(config, profile_name)
|
130
139
|
puts "Downloading `#{profile_name}`"
|
131
140
|
|
@@ -260,6 +269,16 @@ module Compliance
|
|
260
269
|
|
261
270
|
private
|
262
271
|
|
272
|
+
# returns a parsed url for `admin/profile` or `compliance://admin/profile`
|
273
|
+
def sanitize_profile_name(profile)
|
274
|
+
if URI(profile).scheme == 'compliance'
|
275
|
+
uri = URI(profile)
|
276
|
+
else
|
277
|
+
uri = URI("compliance://#{profile}")
|
278
|
+
end
|
279
|
+
uri.host + uri.path
|
280
|
+
end
|
281
|
+
|
263
282
|
def login_automate_config(url, user, dctoken, usertoken, ent, insecure) # rubocop:disable Metrics/ParameterLists
|
264
283
|
config = Compliance::Configuration.new
|
265
284
|
config['user'] = user
|
@@ -79,8 +79,13 @@ EOF
|
|
79
79
|
|
80
80
|
private
|
81
81
|
|
82
|
+
# determine the owner_id and the profile name from the url
|
82
83
|
def compliance_profile_name
|
83
|
-
m =
|
84
|
+
m = if @config['server_type'] == 'automate'
|
85
|
+
%r{^#{@config['server']}/(?<owner>[^/]+)/(?<id>[^/]+)/tar$}
|
86
|
+
else
|
87
|
+
%r{^#{@config['server']}/owners/(?<owner>[^/]+)/compliance/(?<id>[^/]+)/tar$}
|
88
|
+
end.match(@target)
|
84
89
|
"#{m[:owner]}/#{m[:id]}"
|
85
90
|
end
|
86
91
|
end
|
data/lib/inspec/profile.rb
CHANGED
@@ -89,7 +89,7 @@ module Inspec
|
|
89
89
|
@writable = options[:writable] || false
|
90
90
|
@profile_id = options[:id]
|
91
91
|
@cache = options[:cache] || Cache.new
|
92
|
-
@backend = options[:backend] || Inspec::Backend.create(options)
|
92
|
+
@backend = options[:backend] || Inspec::Backend.create(options.select { |k, _| k != 'target' })
|
93
93
|
@attr_values = options[:attributes]
|
94
94
|
@source_reader = source_reader
|
95
95
|
@tests_collected = false
|
data/lib/inspec/resource.rb
CHANGED
@@ -120,6 +120,7 @@ require 'resources/postgres_conf'
|
|
120
120
|
require 'resources/postgres_session'
|
121
121
|
require 'resources/powershell'
|
122
122
|
require 'resources/processes'
|
123
|
+
require 'resources/rabbitmq_conf'
|
123
124
|
require 'resources/registry_key'
|
124
125
|
require 'resources/security_policy'
|
125
126
|
require 'resources/service'
|
data/lib/inspec/version.rb
CHANGED
data/lib/resources/gem.rb
CHANGED
@@ -23,7 +23,7 @@ module Inspec::Resources
|
|
23
23
|
'gem'
|
24
24
|
when :chef
|
25
25
|
if inspec.os.windows?
|
26
|
-
'c:\opscode\chef\embedded\bin\gem'
|
26
|
+
'c:\opscode\chef\embedded\bin\gem.bat'
|
27
27
|
else
|
28
28
|
'/opt/chef/embedded/bin/gem'
|
29
29
|
end
|
@@ -32,6 +32,7 @@ module Inspec::Resources
|
|
32
32
|
else
|
33
33
|
gem_binary
|
34
34
|
end
|
35
|
+
skip_resource 'Unable to retrieve gem information' if info.empty?
|
35
36
|
end
|
36
37
|
|
37
38
|
def info
|
@@ -47,6 +48,8 @@ module Inspec::Resources
|
|
47
48
|
# extract package name and version
|
48
49
|
# parses data like winrm (1.3.4, 1.3.3)
|
49
50
|
params = /^\s*([^\(]*?)\s*\((.*?)\)\s*$/.match(cmd.stdout.chomp)
|
51
|
+
return {} if params.nil?
|
52
|
+
|
50
53
|
versions = params[2].split(',')
|
51
54
|
@info[:name] = params[1]
|
52
55
|
@info[:version] = versions[0]
|
data/lib/resources/host.rb
CHANGED
@@ -43,11 +43,15 @@ module Inspec::Resources
|
|
43
43
|
@port = params[:port] || nil
|
44
44
|
@proto = params[:proto] || nil
|
45
45
|
|
46
|
+
return skip_resource 'The UDP protocol for the `host` resource is not supported yet.' if @proto == 'udp'
|
47
|
+
|
46
48
|
@host_provider = nil
|
47
49
|
if inspec.os.linux?
|
48
50
|
@host_provider = LinuxHostProvider.new(inspec)
|
49
51
|
elsif inspec.os.windows?
|
50
52
|
@host_provider = WindowsHostProvider.new(inspec)
|
53
|
+
elsif inspec.os.darwin?
|
54
|
+
@host_provider = DarwinHostProvider.new(inspec)
|
51
55
|
else
|
52
56
|
return skip_resource 'The `host` resource is not supported on your OS yet.'
|
53
57
|
end
|
@@ -93,6 +97,29 @@ module Inspec::Resources
|
|
93
97
|
end
|
94
98
|
end
|
95
99
|
|
100
|
+
class DarwinHostProvider < HostProvider
|
101
|
+
def ping(hostname, port = nil, proto = nil)
|
102
|
+
if proto == 'tcp'
|
103
|
+
resp = inspec.command("nc -vz -G 1 #{hostname} #{port}")
|
104
|
+
else
|
105
|
+
resp = inspec.command("ping -W 1 -c 1 #{hostname}")
|
106
|
+
end
|
107
|
+
resp.exit_status.to_i != 0 ? false : true
|
108
|
+
end
|
109
|
+
|
110
|
+
def resolve(hostname)
|
111
|
+
# Resolve IPv6 address first, if that fails try IPv4 to match Linux behaivor
|
112
|
+
cmd = inspec.command("host -t AAAA #{hostname}")
|
113
|
+
if cmd.exit_status.to_i != 0
|
114
|
+
cmd = inspec.command("host -t A #{hostname}")
|
115
|
+
end
|
116
|
+
return nil if cmd.exit_status.to_i != 0
|
117
|
+
|
118
|
+
resolve = /^.* has IPv\d address\s+(?<ip>\S+)\s*$/.match(cmd.stdout.chomp)
|
119
|
+
[resolve[1]] if resolve
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
96
123
|
class LinuxHostProvider < HostProvider
|
97
124
|
# ping is difficult to achieve, since we are not sure
|
98
125
|
def ping(hostname, _port = nil, _proto = nil)
|
@@ -118,10 +145,7 @@ module Inspec::Resources
|
|
118
145
|
# @see http://blogs.technet.com/b/josebda/archive/2015/04/18/windows-powershell-equivalents-for-common-networking-commands-ipconfig-ping-nslookup.aspx
|
119
146
|
# @see http://blogs.technet.com/b/heyscriptingguy/archive/2014/03/19/creating-a-port-scanner-with-windows-powershell.aspx
|
120
147
|
class WindowsHostProvider < HostProvider
|
121
|
-
def ping(hostname, port = nil,
|
122
|
-
# TODO: abort if we cannot run it via udp
|
123
|
-
return nil if proto == 'udp'
|
124
|
-
|
148
|
+
def ping(hostname, port = nil, _proto = nil)
|
125
149
|
# ICMP: Test-NetConnection www.microsoft.com
|
126
150
|
# TCP and port: Test-NetConnection -ComputerName www.microsoft.com -RemotePort 80
|
127
151
|
request = "Test-NetConnection -ComputerName #{hostname}"
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Dominik Richter
|
3
|
+
# author: Christoph Hartmann
|
4
|
+
|
5
|
+
require 'utils/erlang_parser'
|
6
|
+
|
7
|
+
module Inspec::Resources
|
8
|
+
class RabbitmqConf < Inspec.resource(1)
|
9
|
+
name 'rabbitmq_config'
|
10
|
+
desc 'Use the rabbitmq_config InSpec resource to test configuration data '\
|
11
|
+
'for the RabbitMQ service located in /etc/rabbitmq/rabbitmq.config on '\
|
12
|
+
'Linux and UNIX platforms.'
|
13
|
+
example "
|
14
|
+
describe rabbitmq_config.params('rabbit', 'ssl_listeners') do
|
15
|
+
it { should cmp 5671 }
|
16
|
+
end
|
17
|
+
"
|
18
|
+
|
19
|
+
def initialize(conf_path = nil)
|
20
|
+
@conf_path = conf_path || '/etc/rabbitmq/rabbitmq.config'
|
21
|
+
end
|
22
|
+
|
23
|
+
def params(*opts)
|
24
|
+
opts.inject(read_params) do |res, nxt|
|
25
|
+
res.respond_to?(:key) ? res[nxt] : nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
"rabbitmq_config #{@conf_path}"
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def read_content
|
36
|
+
return @content if defined?(@content)
|
37
|
+
file = inspec.file(@conf_path)
|
38
|
+
if !file.file?
|
39
|
+
return skip_resource "Can't find file \"#{@conf_path}\""
|
40
|
+
end
|
41
|
+
|
42
|
+
@content = file.content
|
43
|
+
end
|
44
|
+
|
45
|
+
def read_params
|
46
|
+
return @params if defined?(@params)
|
47
|
+
return @params = {} if read_content.nil?
|
48
|
+
@params = ErlangConfigFile.parse(read_content)
|
49
|
+
rescue Parslet::ParseFailed
|
50
|
+
raise "Cannot parse RabbitMQ config: \"#{read_content}\""
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/resources/ssl.rb
CHANGED
@@ -71,7 +71,7 @@ class SSL < Inspec.resource(1)
|
|
71
71
|
res = Parallel.map(groups, in_threads: 8) do |proto, e|
|
72
72
|
[proto, SSLShake.hello(x.resource.host, port: x.resource.port,
|
73
73
|
protocol: proto, ciphers: e.map(&:cipher),
|
74
|
-
timeout: x.resource.timeout, retries: x.resource.retries)]
|
74
|
+
timeout: x.resource.timeout, retries: x.resource.retries, servername: x.resource.host)]
|
75
75
|
end
|
76
76
|
Hash[res]
|
77
77
|
}
|
data/lib/resources/sys_info.rb
CHANGED
@@ -14,7 +14,7 @@ module Inspec::Resources
|
|
14
14
|
# returns the hostname of the local system
|
15
15
|
def hostname
|
16
16
|
os = inspec.os
|
17
|
-
if os.linux?
|
17
|
+
if os.linux? || os.darwin?
|
18
18
|
inspec.command('hostname').stdout.chomp
|
19
19
|
elsif os.windows?
|
20
20
|
inspec.powershell('$env:computername').stdout.chomp
|
@@ -0,0 +1,192 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Dominik Richter
|
3
|
+
# author: Christoph Hartmann
|
4
|
+
|
5
|
+
require 'parslet'
|
6
|
+
|
7
|
+
class ErlangParser < Parslet::Parser
|
8
|
+
root :outermost
|
9
|
+
# only designed for rabbitmq config files for now:
|
10
|
+
rule(:outermost) { filler? >> array.maybe >> dot.maybe }
|
11
|
+
|
12
|
+
rule(:exp) {
|
13
|
+
(tuple | array | binary | string | bool | identifier | float | integer) >> filler?
|
14
|
+
}
|
15
|
+
|
16
|
+
rule(:array) {
|
17
|
+
str('[') >> filler? >> (
|
18
|
+
exp.repeat(1) >>
|
19
|
+
(comma >> exp).repeat
|
20
|
+
).maybe.as(:array) >> str(']') >> filler?
|
21
|
+
}
|
22
|
+
|
23
|
+
rule(:tuple) {
|
24
|
+
str('{') >> filler? >> (
|
25
|
+
exp.repeat(1) >> filler? >>
|
26
|
+
(comma >> exp).repeat
|
27
|
+
).maybe.as(:tuple) >> str('}') >> filler?
|
28
|
+
}
|
29
|
+
|
30
|
+
rule(:filler?) { space.repeat }
|
31
|
+
rule(:space) { match('\s+') | match["\n"] | comment }
|
32
|
+
|
33
|
+
rule(:comment) { str('%') >> (match["\n\r"].absent? >> any).repeat }
|
34
|
+
rule(:comma) { str(',') >> filler? }
|
35
|
+
rule(:dot) { str('.') >> filler? }
|
36
|
+
rule(:bool) { str('true').as(:bool) | str('false').as(:bool) }
|
37
|
+
|
38
|
+
rule(:identifier) {
|
39
|
+
(match('[a-zA-Z]') >> match('[a-zA-Z0-9_]').repeat).as(:identifier) >> filler?
|
40
|
+
}
|
41
|
+
|
42
|
+
rule(:float) {
|
43
|
+
(
|
44
|
+
integer >> (
|
45
|
+
str('.') >> match('[0-9]').repeat(1) |
|
46
|
+
str('e') >> match('[0-9]').repeat(1)
|
47
|
+
).as(:e)
|
48
|
+
).as(:float) >> filler?
|
49
|
+
}
|
50
|
+
|
51
|
+
rule(:integer) {
|
52
|
+
((str('+') | str('-')).maybe >> match('[0-9]').repeat(1)).as(:integer) >> filler?
|
53
|
+
}
|
54
|
+
|
55
|
+
rule(:string) { stringS | stringD }
|
56
|
+
|
57
|
+
rule(:stringS) {
|
58
|
+
str("'") >> (
|
59
|
+
str('\\') >> any | str("'").absent? >> any
|
60
|
+
).repeat.as(:string) >> str("'") >> filler?
|
61
|
+
}
|
62
|
+
|
63
|
+
rule(:stringD) {
|
64
|
+
str('"') >> (
|
65
|
+
str('\\') >> any | str('"').absent? >> any
|
66
|
+
).repeat.as(:string) >> str('"') >> filler?
|
67
|
+
}
|
68
|
+
|
69
|
+
rule(:binary_item) {
|
70
|
+
(string | integer) >>
|
71
|
+
(str(':') >> integer).maybe.as(:size) >>
|
72
|
+
(str('/') >> identifier).maybe.as(:type) >>
|
73
|
+
filler?
|
74
|
+
}
|
75
|
+
|
76
|
+
rule(:binary) {
|
77
|
+
str('<<') >> filler? >> (
|
78
|
+
binary_item.repeat(1) >>
|
79
|
+
(comma >> binary_item).repeat
|
80
|
+
).maybe.as(:binary) >> str('>>') >> filler?
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
class ErlangBitstream
|
85
|
+
def initialize
|
86
|
+
@data = [] # a stream of 8-bit numbers
|
87
|
+
@cur_bits = '' # a string of binary bits 10010010...
|
88
|
+
end
|
89
|
+
|
90
|
+
TYPES = {
|
91
|
+
'integer' => 8,
|
92
|
+
'float' => 8*8,
|
93
|
+
'utf8' => 8,
|
94
|
+
'utf16' => 8*2,
|
95
|
+
'utf32' => 8*4,
|
96
|
+
}.freeze
|
97
|
+
|
98
|
+
def bit_size(size, type)
|
99
|
+
raise 'Cannot specify size and type at the same time.' if !type.nil? && !size.nil?
|
100
|
+
return (size || 8).to_i if type.nil?
|
101
|
+
TYPES[type] || raise("Cannot handle binary-stream type #{type}")
|
102
|
+
end
|
103
|
+
|
104
|
+
def add(i)
|
105
|
+
if i[:integer].nil? && i[:string].nil?
|
106
|
+
raise 'No data provided, internal error for binary-stream processing!'
|
107
|
+
end
|
108
|
+
s = bit_size(i[:size], i[:type])
|
109
|
+
unless i[:string].nil?
|
110
|
+
str2int(i[:string].to_s, i[:type]).map { |e| add_bits(int2bits(e, 8)) }
|
111
|
+
else
|
112
|
+
add_int(i[:integer], s)
|
113
|
+
end
|
114
|
+
rescue RuntimeError => e
|
115
|
+
raise 'Error processing Erlang bit string '\
|
116
|
+
"'#{i[:string] || i[:integer]}:#{i[:size]}/#{i[:type]}'. #{e.message}"
|
117
|
+
end
|
118
|
+
|
119
|
+
def str2int(s, type)
|
120
|
+
case type
|
121
|
+
when 'utf8' then s.encode('utf-8').unpack('C*')
|
122
|
+
when 'utf16' then s.encode('utf-16').unpack('C*').drop(2)
|
123
|
+
when 'utf32' then s.encode('utf-32').unpack('C*').drop(4)
|
124
|
+
when 'integer', 'float' then raise "Cannot handle bit string as type #{type}"
|
125
|
+
else s.split('').map { |x| x.ord & 0xff }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def int2bits(i, len)
|
130
|
+
format("%0#{len}b", i)
|
131
|
+
end
|
132
|
+
|
133
|
+
def add_int(v, size)
|
134
|
+
x = v.to_i & (2**size - 1) # only get the bits specified in size
|
135
|
+
add_bits(int2bits(x, size))
|
136
|
+
end
|
137
|
+
|
138
|
+
def add_bits(s)
|
139
|
+
b = (@cur_bits + s).scan(/.{1,8}/)
|
140
|
+
@data += b[0..-2].map { |x| x.to_i(2) }
|
141
|
+
@cur_bits = b.last
|
142
|
+
end
|
143
|
+
|
144
|
+
def value(encoding = 'utf-8')
|
145
|
+
# fill in the rest
|
146
|
+
rest = '0' * (8 - @cur_bits.length) + @cur_bits
|
147
|
+
arr = @data + [rest.to_i(2)]
|
148
|
+
s = arr.pack('C*')
|
149
|
+
s.force_encoding(encoding) unless encoding.nil?
|
150
|
+
s
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
class ErlangTransform < Parslet::Transform
|
155
|
+
class Tuple < Array; end
|
156
|
+
class Identifier < String; end
|
157
|
+
|
158
|
+
def self.assemble_binary(seq)
|
159
|
+
b = ErlangBitstream.new
|
160
|
+
seq.each { |i| b.add(i) }
|
161
|
+
b.value
|
162
|
+
end
|
163
|
+
|
164
|
+
rule(string: simple(:x)) { x.to_s }
|
165
|
+
rule(string: []) { '' }
|
166
|
+
rule(integer: simple(:x)) { x.to_i }
|
167
|
+
rule(float: { integer: simple(:a), e: simple(:b) }) { (a+b).to_f }
|
168
|
+
rule(bool: 'true') { true }
|
169
|
+
rule(bool: 'false') { false }
|
170
|
+
rule(binary: subtree(:x)) { x.nil? ? '' : ErlangTransform.assemble_binary(x) }
|
171
|
+
rule(identifier: simple(:x)) { Identifier.new(x.to_s) }
|
172
|
+
rule(array: subtree(:x)) { Array(x) }
|
173
|
+
rule(tuple: subtree(:x)) {
|
174
|
+
x.nil? ? Tuple.new : Tuple.new(x)
|
175
|
+
}
|
176
|
+
end
|
177
|
+
|
178
|
+
class ErlangConfigFile
|
179
|
+
def self.parse(content)
|
180
|
+
lex = ErlangParser.new.parse(content)
|
181
|
+
tree = ErlangTransform.new.apply(lex)
|
182
|
+
turn_to_hash(tree)
|
183
|
+
end
|
184
|
+
|
185
|
+
def self.turn_to_hash(t)
|
186
|
+
if t.is_a?(Array) && t.all? { |x| x.class == ErlangTransform::Tuple && x.length == 2 }
|
187
|
+
Hash[t.map { |i| [i[0], turn_to_hash(i[1])] }]
|
188
|
+
else
|
189
|
+
t
|
190
|
+
end
|
191
|
+
end
|
192
|
+
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.20.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-13 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.1'
|
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.1'
|
193
193
|
- !ruby/object:Gem::Dependency
|
194
194
|
name: parallel
|
195
195
|
requirement: !ruby/object:Gem::Requirement
|
@@ -246,6 +246,20 @@ dependencies:
|
|
246
246
|
- - "~>"
|
247
247
|
- !ruby/object:Gem::Version
|
248
248
|
version: '2.4'
|
249
|
+
- !ruby/object:Gem::Dependency
|
250
|
+
name: parslet
|
251
|
+
requirement: !ruby/object:Gem::Requirement
|
252
|
+
requirements:
|
253
|
+
- - "~>"
|
254
|
+
- !ruby/object:Gem::Version
|
255
|
+
version: '1.5'
|
256
|
+
type: :runtime
|
257
|
+
prerelease: false
|
258
|
+
version_requirements: !ruby/object:Gem::Requirement
|
259
|
+
requirements:
|
260
|
+
- - "~>"
|
261
|
+
- !ruby/object:Gem::Version
|
262
|
+
version: '1.5'
|
249
263
|
description: InSpec provides a framework for creating end-to-end infrastructure tests.
|
250
264
|
You can use it for integration or even compliance testing. Create fully portable
|
251
265
|
test profiles and use them in your workflow to ensure stability and security. Integrate
|
@@ -330,6 +344,7 @@ files:
|
|
330
344
|
- docs/resources/postgres_session.md.erb
|
331
345
|
- docs/resources/powershell.md.erb
|
332
346
|
- docs/resources/processes.md.erb
|
347
|
+
- docs/resources/rabbitmq_config.md.erb
|
333
348
|
- docs/resources/registry_key.md.erb
|
334
349
|
- docs/resources/runit_service.md.erb
|
335
350
|
- docs/resources/security_policy.md.erb
|
@@ -555,6 +570,7 @@ files:
|
|
555
570
|
- lib/resources/postgres_session.rb
|
556
571
|
- lib/resources/powershell.rb
|
557
572
|
- lib/resources/processes.rb
|
573
|
+
- lib/resources/rabbitmq_conf.rb
|
558
574
|
- lib/resources/registry_key.rb
|
559
575
|
- lib/resources/security_policy.rb
|
560
576
|
- lib/resources/service.rb
|
@@ -577,6 +593,7 @@ files:
|
|
577
593
|
- lib/source_readers/inspec.rb
|
578
594
|
- lib/utils/command_wrapper.rb
|
579
595
|
- lib/utils/convert.rb
|
596
|
+
- lib/utils/erlang_parser.rb
|
580
597
|
- lib/utils/filter.rb
|
581
598
|
- lib/utils/filter_array.rb
|
582
599
|
- lib/utils/find_files.rb
|