inspec-core 2.3.5 → 2.3.10

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -8
  3. data/lib/bundles/inspec-compliance/api.rb +3 -353
  4. data/lib/bundles/inspec-compliance/configuration.rb +3 -102
  5. data/lib/bundles/inspec-compliance/http.rb +3 -115
  6. data/lib/bundles/inspec-compliance/support.rb +3 -35
  7. data/lib/bundles/inspec-compliance/target.rb +3 -142
  8. data/lib/inspec/base_cli.rb +4 -1
  9. data/lib/inspec/cli.rb +1 -1
  10. data/lib/inspec/control_eval_context.rb +2 -2
  11. data/lib/inspec/version.rb +1 -1
  12. data/lib/matchers/matchers.rb +3 -3
  13. data/lib/{bundles → plugins}/inspec-compliance/README.md +0 -0
  14. data/lib/plugins/inspec-compliance/lib/inspec-compliance.rb +12 -0
  15. data/lib/plugins/inspec-compliance/lib/inspec-compliance/api.rb +358 -0
  16. data/lib/plugins/inspec-compliance/lib/inspec-compliance/api/login.rb +192 -0
  17. data/lib/plugins/inspec-compliance/lib/inspec-compliance/cli.rb +266 -0
  18. data/lib/plugins/inspec-compliance/lib/inspec-compliance/configuration.rb +103 -0
  19. data/lib/plugins/inspec-compliance/lib/inspec-compliance/http.rb +116 -0
  20. data/lib/{bundles → plugins/inspec-compliance/lib}/inspec-compliance/images/cc-token.png +0 -0
  21. data/lib/plugins/inspec-compliance/lib/inspec-compliance/support.rb +36 -0
  22. data/lib/plugins/inspec-compliance/lib/inspec-compliance/target.rb +143 -0
  23. data/lib/plugins/inspec-compliance/test/functional/inspec_compliance_test.rb +43 -0
  24. data/lib/{bundles → plugins}/inspec-compliance/test/integration/default/cli.rb +0 -0
  25. data/lib/plugins/inspec-compliance/test/unit/api/login_test.rb +190 -0
  26. data/lib/plugins/inspec-compliance/test/unit/api_test.rb +385 -0
  27. data/lib/plugins/inspec-compliance/test/unit/target_test.rb +155 -0
  28. data/lib/resources/processes.rb +19 -3
  29. metadata +17 -10
  30. data/lib/bundles/inspec-compliance.rb +0 -16
  31. data/lib/bundles/inspec-compliance/.kitchen.yml +0 -20
  32. data/lib/bundles/inspec-compliance/api/login.rb +0 -193
  33. data/lib/bundles/inspec-compliance/bootstrap.sh +0 -41
  34. data/lib/bundles/inspec-compliance/cli.rb +0 -276
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dda2c82e4eee5fbc41c0963a8b767d3afb617b55c80b84a81334bef2d086dba5
4
- data.tar.gz: 1c9b9b15341380af7150cadb89b56ee0f86711880325a78c3adb6cce348ed800
3
+ metadata.gz: 8c5e7615776b52330a209b35ca344d1bdb85a04f78903152edd67fa94d81700e
4
+ data.tar.gz: e6042ee4e8ede90034c06762b2dd2ab6135d0eeeef505ffccc138b0df566f5f9
5
5
  SHA512:
6
- metadata.gz: 629f0ac2f1d7fe9996c6e24a61b6652e7d82cd71dd630c6893c6d7975ccc4e9db4aa4eff964a2eff54f25b5b7480fddcbc542c19daa0a29ef849d38ec63c8de7
7
- data.tar.gz: ade62e212feeb71e1ae89e4c3aa9151c99f1baa548b1819549d1cfe30409ee178f0ae9eafe19522d55f2f9c6d2d051cf1796f36567408001e5b45dba4e288b61
6
+ metadata.gz: 22bf4eed15b0f3b8ab6eb0ff13b7901bbe468c956d0a9c7615fcbce1e20e4974b4af823744106ed77db6d6fd40d31ae143a707edb8a94ae1d6aaf40bd1acc707
7
+ data.tar.gz: 5ff797572d8637e1e1d7a6939e4c95d2b33bdc5e4577f0db0677c85a850d536d7d1677ba28e9112473ebe60ca01f7aa4d0a3d05821a090630667f42b2d687f89
@@ -1,20 +1,34 @@
1
1
  # Change Log
2
2
  <!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
3
- <!-- latest_release 2.3.5 -->
4
- ## [v2.3.5](https://github.com/inspec/inspec/tree/v2.3.5) (2018-09-28)
3
+ <!-- latest_release 2.3.10 -->
4
+ ## [v2.3.10](https://github.com/inspec/inspec/tree/v2.3.10) (2018-10-04)
5
5
 
6
- #### Bug Fixes
7
- - Update plugin gem install code [#3453](https://github.com/inspec/inspec/pull/3453) ([jquick](https://github.com/jquick))
6
+ #### Enhancements
7
+ - Move compliance to v2 plugin [#3423](https://github.com/inspec/inspec/pull/3423) ([jquick](https://github.com/jquick))
8
8
  <!-- latest_release -->
9
9
 
10
- <!-- release_rollup since=2.3.4 -->
11
- ### Changes since 2.3.4 release
10
+ <!-- release_rollup since=2.3.5 -->
11
+ ### Changes since 2.3.5 release
12
12
 
13
13
  #### Bug Fixes
14
- - Update plugin gem install code [#3453](https://github.com/inspec/inspec/pull/3453) ([jquick](https://github.com/jquick)) <!-- 2.3.5 -->
14
+ - Fix distinct_exit cli desc to reflect reality [#3463](https://github.com/inspec/inspec/pull/3463) ([teknofire](https://github.com/teknofire)) <!-- 2.3.8 -->
15
+
16
+ #### Merged Pull Requests
17
+ - Fix `attribute` with empty hash regression [#3454](https://github.com/inspec/inspec/pull/3454) ([jerryaldrichiii](https://github.com/jerryaldrichiii)) <!-- 2.3.7 -->
18
+
19
+ #### Enhancements
20
+ - Move compliance to v2 plugin [#3423](https://github.com/inspec/inspec/pull/3423) ([jquick](https://github.com/jquick)) <!-- 2.3.10 -->
21
+ - Support finding larger processes on Busybox [#3446](https://github.com/inspec/inspec/pull/3446) ([RoboticCheese](https://github.com/RoboticCheese)) <!-- 2.3.9 -->
22
+ - Modify `cmp` matcher output to use `.inspect` [#3450](https://github.com/inspec/inspec/pull/3450) ([jerryaldrichiii](https://github.com/jerryaldrichiii)) <!-- 2.3.6 -->
15
23
  <!-- release_rollup -->
16
24
 
17
25
  <!-- latest_stable_release -->
26
+ ## [v2.3.5](https://github.com/inspec/inspec/tree/v2.3.5) (2018-10-01)
27
+
28
+ #### Bug Fixes
29
+ - Update plugin gem install code [#3453](https://github.com/inspec/inspec/pull/3453) ([jquick](https://github.com/jquick))
30
+ <!-- latest_stable_release -->
31
+
18
32
  ## [v2.3.4](https://github.com/inspec/inspec/tree/v2.3.4) (2018-09-28)
19
33
 
20
34
  #### New Features
@@ -37,7 +51,6 @@
37
51
  - RFC inspec style guide [#3356](https://github.com/inspec/inspec/pull/3356) ([arlimus](https://github.com/arlimus))
38
52
  - Pin postgresql to a lower cookbook version [#3449](https://github.com/inspec/inspec/pull/3449) ([jquick](https://github.com/jquick))
39
53
  - Plugins: Example CLI Plugin, a Resource Lister [#3421](https://github.com/inspec/inspec/pull/3421) ([clintoncwolfe](https://github.com/clintoncwolfe))
40
- <!-- latest_stable_release -->
41
54
 
42
55
  ## [v2.2.112](https://github.com/inspec/inspec/tree/v2.2.112) (2018-09-19)
43
56
 
@@ -1,354 +1,4 @@
1
- # encoding: utf-8
2
- # author: Christoph Hartmann
3
- # author: Dominik Richter
1
+ # This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
2
+ # TODO: Remove in inspec 4.0
4
3
 
5
- require 'net/http'
6
- require 'uri'
7
- require 'json'
8
-
9
- require_relative 'api/login'
10
-
11
- module Compliance
12
- class ServerConfigurationMissing < StandardError; end
13
-
14
- # API Implementation does not hold any state by itself,
15
- # everything will be stored in local Configuration store
16
- class API
17
- extend Compliance::API::Login
18
-
19
- # return all compliance profiles available for the user
20
- # the user is either specified in the options hash or by default
21
- # the username of the account is used that is logged in
22
- def self.profiles(config, profile_filter = nil) # rubocop:disable PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/MethodLength
23
- owner = config['owner'] || config['user']
24
-
25
- # Chef Compliance
26
- if is_compliance_server?(config)
27
- url = "#{config['server']}/user/compliance"
28
- # Chef Automate2
29
- elsif is_automate2_server?(config)
30
- url = "#{config['server']}/compliance/profiles/search"
31
- # Chef Automate
32
- elsif is_automate_server?(config)
33
- url = "#{config['server']}/profiles/#{owner}"
34
- else
35
- raise ServerConfigurationMissing
36
- end
37
-
38
- headers = get_headers(config)
39
- if profile_filter
40
- _owner, id, ver = profile_split(profile_filter)
41
- else
42
- id, ver = nil
43
- end
44
-
45
- if is_automate2_server?(config)
46
- body = { owner: owner, name: id }.to_json
47
- response = Compliance::HTTP.post_with_headers(url, headers, body, config['insecure'])
48
- else
49
- response = Compliance::HTTP.get(url, headers, config['insecure'])
50
- end
51
- data = response.body
52
- response_code = response.code
53
- case response_code
54
- when '200'
55
- msg = 'success'
56
- profiles = JSON.parse(data)
57
- # iterate over profiles
58
- if is_compliance_server?(config)
59
- mapped_profiles = []
60
- profiles.values.each { |org|
61
- mapped_profiles += org.values
62
- }
63
- # Chef Automate pre 0.8.0
64
- elsif is_automate_server_pre_080?(config)
65
- mapped_profiles = profiles.values.flatten
66
- elsif is_automate2_server?(config)
67
- mapped_profiles = []
68
- profiles['profiles'].each { |p|
69
- mapped_profiles << p
70
- }
71
- else
72
- mapped_profiles = profiles.map { |e|
73
- e['owner_id'] = owner
74
- e
75
- }
76
- end
77
- # filter by name and version if they were specified in profile_filter
78
- mapped_profiles.select! do |p|
79
- (!ver || p['version'] == ver) && (!id || p['name'] == id)
80
- end
81
- return msg, mapped_profiles
82
- when '401'
83
- msg = '401 Unauthorized. Please check your token.'
84
- return msg, []
85
- else
86
- msg = "An unexpected error occurred (HTTP #{response_code}): #{response.message}"
87
- return msg, []
88
- end
89
- end
90
-
91
- # return the server api version
92
- # NB this method does not use Compliance::Configuration to allow for using
93
- # it before we know the version (e.g. oidc or not)
94
- def self.version(config)
95
- url = config['server']
96
- insecure = config['insecure']
97
-
98
- raise ServerConfigurationMissing if url.nil?
99
-
100
- headers = get_headers(config)
101
- response = Compliance::HTTP.get(url+'/version', headers, insecure)
102
- return {} if response.code == '404'
103
-
104
- data = response.body
105
- return {} if data.nil? || data.empty?
106
-
107
- parsed = JSON.parse(data)
108
- return {} unless parsed.key?('version') && !parsed['version'].empty?
109
-
110
- parsed
111
- end
112
-
113
- # verifies that a profile exists
114
- def self.exist?(config, profile)
115
- _msg, profiles = Compliance::API.profiles(config, profile)
116
- !profiles.empty?
117
- end
118
-
119
- def self.upload(config, owner, profile_name, archive_path)
120
- # Chef Compliance
121
- if is_compliance_server?(config)
122
- url = "#{config['server']}/owners/#{owner}/compliance/#{profile_name}/tar"
123
- # Chef Automate pre 0.8.0
124
- elsif is_automate_server_pre_080?(config)
125
- url = "#{config['server']}/#{owner}"
126
- elsif is_automate2_server?(config)
127
- url = "#{config['server']}/compliance/profiles?owner=#{owner}"
128
- # Chef Automate
129
- else
130
- url = "#{config['server']}/profiles/#{owner}"
131
- end
132
-
133
- headers = get_headers(config)
134
- if is_automate2_server?(config)
135
- res = Compliance::HTTP.post_multipart_file(url, headers, archive_path, config['insecure'])
136
- else
137
- res = Compliance::HTTP.post_file(url, headers, archive_path, config['insecure'])
138
- end
139
-
140
- [res.is_a?(Net::HTTPSuccess), res.body]
141
- end
142
-
143
- # Use username and refresh_token to get an API access token
144
- def self.get_token_via_refresh_token(url, refresh_token, insecure)
145
- uri = URI.parse("#{url}/login")
146
- req = Net::HTTP::Post.new(uri.path)
147
- req.body = { token: refresh_token }.to_json
148
- access_token = nil
149
- response = Compliance::HTTP.send_request(uri, req, insecure)
150
- data = response.body
151
- if response.code == '200'
152
- begin
153
- tokendata = JSON.parse(data)
154
- access_token = tokendata['access_token']
155
- msg = 'Successfully fetched API access token'
156
- success = true
157
- rescue JSON::ParserError => e
158
- success = false
159
- msg = e.message
160
- end
161
- else
162
- success = false
163
- msg = "Failed to authenticate to #{url} \n\
164
- Response code: #{response.code}\n Body: #{response.body}"
165
- end
166
-
167
- [success, msg, access_token]
168
- end
169
-
170
- # Use username and password to get an API access token
171
- def self.get_token_via_password(url, username, password, insecure)
172
- uri = URI.parse("#{url}/login")
173
- req = Net::HTTP::Post.new(uri.path)
174
- req.body = { userid: username, password: password }.to_json
175
- access_token = nil
176
- response = Compliance::HTTP.send_request(uri, req, insecure)
177
- data = response.body
178
- if response.code == '200'
179
- access_token = data
180
- msg = 'Successfully fetched an API access token valid for 12 hours'
181
- success = true
182
- else
183
- success = false
184
- msg = "Failed to authenticate to #{url} \n\
185
- Response code: #{response.code}\n Body: #{response.body}"
186
- end
187
-
188
- [success, msg, access_token]
189
- end
190
-
191
- def self.get_headers(config)
192
- token = get_token(config)
193
- if is_automate_server?(config) || is_automate2_server?(config)
194
- headers = { 'chef-delivery-enterprise' => config['automate']['ent'] }
195
- if config['automate']['token_type'] == 'dctoken'
196
- headers['x-data-collector-token'] = token
197
- else
198
- headers['chef-delivery-user'] = config['user']
199
- headers['chef-delivery-token'] = token
200
- end
201
- else
202
- headers = { 'Authorization' => "Bearer #{token}" }
203
- end
204
- headers
205
- end
206
-
207
- def self.get_token(config)
208
- return config['token'] unless config['refresh_token']
209
- _success, _msg, token = get_token_via_refresh_token(config['server'], config['refresh_token'], config['insecure'])
210
- token
211
- end
212
-
213
- def self.target_url(config, profile)
214
- owner, id, ver = profile_split(profile)
215
-
216
- return "#{config['server']}/compliance/profiles/tar" if is_automate2_server?(config)
217
- return "#{config['server']}/owners/#{owner}/compliance/#{id}/tar" unless is_automate_server?(config)
218
-
219
- if ver.nil?
220
- "#{config['server']}/profiles/#{owner}/#{id}/tar"
221
- else
222
- "#{config['server']}/profiles/#{owner}/#{id}/version/#{ver}/tar"
223
- end
224
- end
225
-
226
- def self.profile_split(profile)
227
- owner, id = profile.split('/')
228
- id, version = id.split('#')
229
- [owner, id, version]
230
- end
231
-
232
- # returns a parsed url for `admin/profile` or `compliance://admin/profile`
233
- def self.sanitize_profile_name(profile)
234
- if URI(profile).scheme == 'compliance'
235
- uri = URI(profile)
236
- else
237
- uri = URI("compliance://#{profile}")
238
- end
239
- uri.to_s.sub(%r{^compliance:\/\/}, '')
240
- end
241
-
242
- def self.is_compliance_server?(config)
243
- config['server_type'] == 'compliance'
244
- end
245
-
246
- def self.is_automate_server_pre_080?(config)
247
- # Automate versions before 0.8.x do not have a valid version in the config
248
- return false unless config['server_type'] == 'automate'
249
- server_version_from_config(config).nil?
250
- end
251
-
252
- def self.is_automate_server_080_and_later?(config)
253
- # Automate versions 0.8.x and later will have a "version" key in the config
254
- # that is properly parsed out via server_version_from_config below
255
- return false unless config['server_type'] == 'automate'
256
- !server_version_from_config(config).nil?
257
- end
258
-
259
- def self.is_automate2_server?(config)
260
- config['server_type'] == 'automate2'
261
- end
262
-
263
- def self.is_automate_server?(config)
264
- config['server_type'] == 'automate'
265
- end
266
-
267
- def self.server_version_from_config(config)
268
- # Automate versions 0.8.x and later will have a "version" key in the config
269
- # that looks like: "version":{"api":"compliance","version":"0.8.24"}
270
- return nil unless config.key?('version')
271
- return nil unless config['version'].is_a?(Hash)
272
- config['version']['version']
273
- end
274
-
275
- def self.determine_server_type(url, insecure)
276
- if target_is_automate2_server?(url, insecure)
277
- :automate2
278
- elsif target_is_automate_server?(url, insecure)
279
- :automate
280
- elsif target_is_compliance_server?(url, insecure)
281
- :compliance
282
- else
283
- Inspec::Log.debug('Could not determine server type using known endpoints')
284
- nil
285
- end
286
- end
287
-
288
- def self.target_is_automate2_server?(url, insecure)
289
- automate_endpoint = '/dex/auth'
290
- response = Compliance::HTTP.get(url + automate_endpoint, nil, insecure)
291
- if response.code == '400'
292
- Inspec::Log.debug(
293
- "Received 400 from #{url}#{automate_endpoint} - " \
294
- 'assuming target is a Chef Automate2 instance',
295
- )
296
- true
297
- else
298
- false
299
- end
300
- end
301
-
302
- def self.target_is_automate_server?(url, insecure)
303
- automate_endpoint = '/compliance/version'
304
- response = Compliance::HTTP.get(url + automate_endpoint, nil, insecure)
305
- case response.code
306
- when '401'
307
- Inspec::Log.debug(
308
- "Received 401 from #{url}#{automate_endpoint} - " \
309
- 'assuming target is a Chef Automate instance',
310
- )
311
- true
312
- when '200'
313
- # Chef Automate currently returns 401 for `/compliance/version` but some
314
- # versions of OpsWorks Chef Automate return 200 and a Chef Manage page
315
- # when unauthenticated requests are received.
316
- if response.body.include?('Are You Looking For the Chef Server?')
317
- Inspec::Log.debug(
318
- "Received 200 from #{url}#{automate_endpoint} - " \
319
- 'assuming target is an OpsWorks Chef Automate instance',
320
- )
321
- true
322
- else
323
- Inspec::Log.debug(
324
- "Received 200 from #{url}#{automate_endpoint} " \
325
- 'but did not receive the Chef Manage page - ' \
326
- 'assuming target is not a Chef Automate instance',
327
- )
328
- false
329
- end
330
- else
331
- Inspec::Log.debug(
332
- "Received unexpected status code #{response.code} " \
333
- "from #{url}#{automate_endpoint} - " \
334
- 'assuming target is not a Chef Automate instance',
335
- )
336
- false
337
- end
338
- end
339
-
340
- def self.target_is_compliance_server?(url, insecure)
341
- # All versions of Chef Compliance return 200 for `/api/version`
342
- compliance_endpoint = '/api/version'
343
-
344
- response = Compliance::HTTP.get(url + compliance_endpoint, nil, insecure)
345
- return false unless response.code == '200'
346
-
347
- Inspec::Log.debug(
348
- "Received 200 from #{url}#{compliance_endpoint} - " \
349
- 'assuming target is a Compliance server',
350
- )
351
- true
352
- end
353
- end
354
- end
4
+ require 'plugins/inspec-compliance/lib/inspec-compliance/api'
@@ -1,103 +1,4 @@
1
- # encoding: utf-8
2
- # author: Christoph Hartmann
3
- # author: Dominik Richter
1
+ # This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
2
+ # TODO: Remove in inspec 4.0
4
3
 
5
- module Compliance
6
- # stores configuration on local filesystem
7
- class Configuration
8
- def initialize
9
- @config_path = File.join(Dir.home, '.inspec', 'compliance')
10
- # ensure the directory is available
11
- unless File.directory?(@config_path)
12
- FileUtils.mkdir_p(@config_path)
13
- end
14
- # set config file path
15
- @config_file = File.join(@config_path, '/config.json')
16
- @config = {}
17
-
18
- # load the data
19
- get
20
- end
21
-
22
- # direct access to config
23
- def [](key)
24
- @config[key]
25
- end
26
-
27
- def []=(key, value)
28
- @config[key] = value
29
- end
30
-
31
- def key?(key)
32
- @config.key?(key)
33
- end
34
-
35
- def clean
36
- @config = {}
37
- end
38
-
39
- # return the json data
40
- def get
41
- if File.exist?(@config_file)
42
- file = File.read(@config_file)
43
- @config = JSON.parse(file)
44
- end
45
- @config
46
- end
47
-
48
- # stores a hash to json
49
- def store
50
- File.open(@config_file, 'w') do |f|
51
- f.chmod(0600)
52
- f.write(@config.to_json)
53
- end
54
- end
55
-
56
- # deletes data
57
- def destroy
58
- if File.exist?(@config_file)
59
- File.delete(@config_file)
60
- else
61
- true
62
- end
63
- end
64
-
65
- # return if the (stored) api version does not support a certain feature
66
- def supported?(feature)
67
- sup = version_with_support(feature)
68
-
69
- # we do not know the version, therefore we do not know if its possible to use the feature
70
- return if self['version'].nil? || self['version']['version'].nil?
71
-
72
- if sup.is_a?(Array)
73
- Gem::Version.new(self['version']['version']) >= sup[0] &&
74
- Gem::Version.new(self['version']['version']) < sup[1]
75
- else
76
- Gem::Version.new(self['version']['version']) >= sup
77
- end
78
- end
79
-
80
- # exit 1 if the version of compliance that we're working with doesn't support odic
81
- def legacy_check!(feature)
82
- return if supported?(feature)
83
-
84
- puts "This feature (#{feature}) is not available for legacy installations."
85
- puts 'Please upgrade to a recent version of Chef Compliance.'
86
- exit 1
87
- end
88
-
89
- private
90
-
91
- # for a feature, returns either:
92
- # - a version v0: v supports v0 iff v0 <= v
93
- # - an array [v0, v1] of two versions: v supports [v0, v1] iff v0 <= v < v1
94
- def version_with_support(feature)
95
- case feature.to_sym
96
- when :oidc
97
- Gem::Version.new('0.16.19')
98
- else
99
- Gem::Version.new('0.0.0')
100
- end
101
- end
102
- end
103
- end
4
+ require 'plugins/inspec-compliance/lib/inspec-compliance/configuration'