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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e175f1b4f521dfa8107012a2ce9887a71af34717
4
- data.tar.gz: 9c14b1a99c50557cdefa23076f3926c1dabe5192
3
+ metadata.gz: a68bde2c8c3272f13f8f2953742130866e0a8384
4
+ data.tar.gz: ce752f86311f19345c39d1ae1a3884194700164d
5
5
  SHA512:
6
- metadata.gz: e29e205b839e1de3732c2395a280b9c3b1c21fb450dbf01a9cf6db306aaa60ebb3ae8915f5cb8da6ce09e63a11be3553de5c9c8de63640379d3c3fc04b51cc49
7
- data.tar.gz: ef28f083bc1b0bd7aea60d9bc4fd15b1a0878f7b5130abd567d45535cd8ee01ad7cfb3d318bcf94d2d51b40275f9e3ae100535452e8f3d21b4b29d153c896388
6
+ metadata.gz: 4271a1f24111f22d6044ff3e0892e16ccbd32b9cdcc942afe1d10490225594f8aaff71c1a41b98fdc347d65612fcd254295a1f90c3941a73c54d4c4b029e3c72
7
+ data.tar.gz: 6c2e5e7c839b3e641a435570e00ee48c839f1ed9bf84220505a2eee1be2dc97719d58b851205cd9b8e52e38383b0debbe86628cfcda95507b490b49de59767d3
@@ -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
@@ -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 compliance exec profile` - runs a Chef Compliance profile
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
- # list available profiles via Chef Compliance
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
- # upload a profile to chef Compliance
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
- # run a profile from Chef Compliance locally
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
- # Logout from Chef Compliance
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.map do |owner, ps|
26
- { org: ps['owner_id'], name: owner }
27
- end.flatten
25
+ mapped_profiles = profiles.values.to_a.flatten
28
26
  else
29
- mapped_profiles = profiles.map do |owner, ps|
30
- ps.keys.map do |name|
31
- { org: owner, name: name }
32
- end
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[:org]}/#{p[:name]}" == profile }
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' --dctoken or --usertoken='TOKEN'", 'Log in to an Automate SERVER'
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
- if !options['dctoken'].nil? || !options['usertoken'].nil?
77
- msg = login_automate_config(url, options['user'], options['dctoken'], options['usertoken'], options['ent'], options['insecure'])
78
- else
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
- puts '', msg
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[:org]}/#{profile[:name]}")
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 = %r{^#{@config['server']}/owners/(?<owner>[^/]+)/compliance/(?<id>[^/]+)/tar$}.match(@target)
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
@@ -294,6 +294,7 @@ pkg_origin=#{habitat_origin}
294
294
  pkg_source="nosuchfile.tar.gz"
295
295
  pkg_deps=(chef/inspec)
296
296
  pkg_build_deps=()
297
+ pkg_svc_user=root
297
298
  EOL
298
299
 
299
300
  plan += "pkg_license='#{profile.metadata.params[:license]}'\n\n" if profile.metadata.params[:license]
@@ -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
@@ -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'
@@ -4,5 +4,5 @@
4
4
  # author: Christoph Hartmann
5
5
 
6
6
  module Inspec
7
- VERSION = '1.19.2'.freeze
7
+ VERSION = '1.20.0'.freeze
8
8
  end
@@ -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]
@@ -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, proto = 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
@@ -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
  }
@@ -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.19.2
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-07 00:00:00.000000000 Z
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