inspec 1.19.2 → 1.20.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 +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
|
![Chef Compliance Token](images/cc-token.png)
|
@@ -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
|