inspec 1.6.0 → 1.7.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 +34 -2
- data/Rakefile +2 -2
- data/examples/meta-profile/inspec.yml +2 -2
- data/lib/bundles/inspec-compliance/api.rb +33 -11
- data/lib/bundles/inspec-compliance/cli.rb +73 -12
- data/lib/bundles/inspec-compliance/http.rb +8 -13
- data/lib/bundles/inspec-compliance/target.rb +17 -6
- data/lib/fetchers/url.rb +14 -2
- data/lib/inspec/base_cli.rb +30 -1
- data/lib/inspec/cli.rb +5 -30
- data/lib/inspec/dependencies/lockfile.rb +7 -2
- data/lib/inspec/profile.rb +8 -7
- data/lib/inspec/rspec_json_formatter.rb +106 -88
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/processes.rb +4 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a69a3a78ee7d17ad89e5d13c6445346393e1e1a1
|
4
|
+
data.tar.gz: 03059ff1d249a73bc2f49bdfbac8f162eb3ee3ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c71b46c3f283a84725615ebcdab4d8b0e58e301a7bd53ba0903a4abbd7e0d54af271b2d24dc21d1cafcbade09ced2ee5b1a4cc2af55594d47d925b9b39e13e46
|
7
|
+
data.tar.gz: db25eac456c658775d97fa388e68b7d1e8a39562615cfdaf5d76647d9045c5b4a4ab914f2a12d3321e4e44261f02eaa0ef8ea0017dc667663b98677323cb8cac
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,39 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [1.
|
4
|
-
[Full Changelog](https://github.com/chef/inspec/compare/v1.
|
3
|
+
## [1.7.0](https://github.com/chef/inspec/tree/1.7.0) (2016-12-02)
|
4
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v1.6.0...1.7.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- inspec compliance profiles should support automate as a backend [\#1295](https://github.com/chef/inspec/issues/1295)
|
9
|
+
- this is killing my eyes!!!!!!!!! [\#951](https://github.com/chef/inspec/issues/951)
|
10
|
+
- Show process name during inspec output [\#1329](https://github.com/chef/inspec/pull/1329) ([jcastillocano](https://github.com/jcastillocano))
|
11
|
+
|
12
|
+
**Fixed bugs:**
|
13
|
+
|
14
|
+
- inspec.lock not loaded from tarball profiles [\#1322](https://github.com/chef/inspec/issues/1322)
|
15
|
+
- InSpec tries to re-fetch profiles even if lockfile exists [\#1316](https://github.com/chef/inspec/issues/1316)
|
16
|
+
- fix docker release script [\#1328](https://github.com/chef/inspec/pull/1328) ([chris-rock](https://github.com/chris-rock))
|
17
|
+
- Provide inspec.lock for archives as well [\#1323](https://github.com/chef/inspec/pull/1323) ([alexpop](https://github.com/alexpop))
|
18
|
+
- inspec check and json to use vendored dependencies [\#1321](https://github.com/chef/inspec/pull/1321) ([alexpop](https://github.com/alexpop))
|
19
|
+
|
20
|
+
**Closed issues:**
|
21
|
+
|
22
|
+
- RegExp in processes resource can't match long-run process [\#1332](https://github.com/chef/inspec/issues/1332)
|
23
|
+
- inspec archive vendoring [\#1325](https://github.com/chef/inspec/issues/1325)
|
24
|
+
- inspec compliance upload of a meta-profile [\#1294](https://github.com/chef/inspec/issues/1294)
|
25
|
+
|
26
|
+
**Merged pull requests:**
|
27
|
+
|
28
|
+
- improve functional tests for vendored profiles [\#1337](https://github.com/chef/inspec/pull/1337) ([chris-rock](https://github.com/chris-rock))
|
29
|
+
- Adds junit to the inspec help exec [\#1336](https://github.com/chef/inspec/pull/1336) ([burtlo](https://github.com/burtlo))
|
30
|
+
- Vendor profile when uploading to chef-compliance [\#1334](https://github.com/chef/inspec/pull/1334) ([vjeffrey](https://github.com/vjeffrey))
|
31
|
+
- fix bug: RegExp in processes resource can't match long-run process \#1332 [\#1333](https://github.com/chef/inspec/pull/1333) ([Wing924](https://github.com/Wing924))
|
32
|
+
- clean up rspec\_json\_formatter [\#1314](https://github.com/chef/inspec/pull/1314) ([vjeffrey](https://github.com/vjeffrey))
|
33
|
+
- enable inspec compliance cli support automate [\#1297](https://github.com/chef/inspec/pull/1297) ([vjeffrey](https://github.com/vjeffrey))
|
34
|
+
|
35
|
+
## [v1.6.0](https://github.com/chef/inspec/tree/v1.6.0) (2016-11-28)
|
36
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v1.5.0...v1.6.0)
|
5
37
|
|
6
38
|
**Fixed bugs:**
|
7
39
|
|
data/Rakefile
CHANGED
@@ -163,8 +163,8 @@ task :release_docker do
|
|
163
163
|
cmd = "rm *.gem; gem build *gemspec && "\
|
164
164
|
"mv *.gem inspec.gem && "\
|
165
165
|
"docker build -t chef/inspec:#{version} . && "\
|
166
|
-
"docker push chef/inspec:#{version}"
|
167
|
-
"docker tag chef/inspec:#{version} chef/inspec:latest"
|
166
|
+
"docker push chef/inspec:#{version} && "\
|
167
|
+
"docker tag chef/inspec:#{version} chef/inspec:latest &&"\
|
168
168
|
"docker push chef/inspec:latest"
|
169
169
|
puts "--> #{cmd}"
|
170
170
|
sh('sh', '-c', cmd)
|
@@ -8,6 +8,6 @@ summary: InSpec Profile that is only consuming dependencies
|
|
8
8
|
version: 0.2.0
|
9
9
|
depends:
|
10
10
|
- name: hardening/ssh-hardening # defaults to supermarket
|
11
|
-
-
|
11
|
+
- url: https://github.com/dev-sec/ssl-benchmark
|
12
12
|
- name: windows-patch-benchmark
|
13
|
-
|
13
|
+
url: https://github.com/chris-rock/windows-patch-benchmark
|
@@ -8,12 +8,12 @@ require 'uri'
|
|
8
8
|
module Compliance
|
9
9
|
# API Implementation does not hold any state by itself,
|
10
10
|
# everything will be stored in local Configuration store
|
11
|
-
class API
|
11
|
+
class API # rubocop:disable Metrics/ClassLength
|
12
12
|
# return all compliance profiles available for the user
|
13
13
|
def self.profiles(config)
|
14
|
-
url = "#{config['server']}/user/compliance"
|
15
|
-
|
16
|
-
response = Compliance::HTTP.get(url,
|
14
|
+
config['server_type'] == 'automate' ? url = "#{config['server']}/#{config['user']}" : url = "#{config['server']}/user/compliance"
|
15
|
+
headers = get_headers(config)
|
16
|
+
response = Compliance::HTTP.get(url, headers, config['insecure'])
|
17
17
|
data = response.body
|
18
18
|
response_code = response.code
|
19
19
|
case response_code
|
@@ -21,11 +21,17 @@ module Compliance
|
|
21
21
|
msg = 'success'
|
22
22
|
profiles = JSON.parse(data)
|
23
23
|
# iterate over profiles
|
24
|
-
|
25
|
-
|
26
|
-
{ org:
|
27
|
-
end
|
28
|
-
|
24
|
+
if config['server_type'] == 'automate'
|
25
|
+
mapped_profiles = profiles.map do |owner, ps|
|
26
|
+
{ org: ps['owner_id'], name: owner }
|
27
|
+
end.flatten
|
28
|
+
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
|
34
|
+
end
|
29
35
|
return msg, mapped_profiles
|
30
36
|
when '401'
|
31
37
|
msg = '401 Unauthorized. Please check your token.'
|
@@ -69,8 +75,9 @@ Please login using `inspec compliance login https://compliance.test --user admin
|
|
69
75
|
|
70
76
|
def self.upload(config, owner, profile_name, archive_path)
|
71
77
|
# upload the tar to Chef Compliance
|
72
|
-
url = "#{config['server']}/owners/#{owner}/compliance/#{profile_name}/tar"
|
73
|
-
|
78
|
+
config['server_type'] == 'automate' ? url = "#{config['server']}/#{config['user']}" : url = "#{config['server']}/owners/#{owner}/compliance/#{profile_name}/tar"
|
79
|
+
headers = get_headers(config)
|
80
|
+
res = Compliance::HTTP.post_file(url, headers, archive_path, config['insecure'])
|
74
81
|
[res.is_a?(Net::HTTPSuccess), res.body]
|
75
82
|
end
|
76
83
|
|
@@ -121,5 +128,20 @@ Please login using `inspec compliance login https://compliance.test --user admin
|
|
121
128
|
|
122
129
|
[success, msg, access_token]
|
123
130
|
end
|
131
|
+
|
132
|
+
def self.get_headers(config)
|
133
|
+
if config['server_type'] == 'automate'
|
134
|
+
headers = { 'chef-delivery-enterprise' => config['automate']['ent'] }
|
135
|
+
if config['automate']['token_type'] == 'dctoken'
|
136
|
+
headers['x-data-collector-token'] = config['token']
|
137
|
+
else
|
138
|
+
headers['chef-delivery-user'] = config['user']
|
139
|
+
headers['chef-delivery-token'] = config['token']
|
140
|
+
end
|
141
|
+
else
|
142
|
+
headers = { 'Authorization' => "Bearer #{config['token']}" }
|
143
|
+
end
|
144
|
+
headers
|
145
|
+
end
|
124
146
|
end
|
125
147
|
end
|
@@ -36,6 +36,7 @@ module Compliance
|
|
36
36
|
|
37
37
|
options['server'] = server
|
38
38
|
url = options['server'] + options['apipath']
|
39
|
+
|
39
40
|
if !options['user'].nil? && !options['password'].nil?
|
40
41
|
# username / password
|
41
42
|
_success, msg = login_username_password(url, options['user'], options['password'], options['insecure'])
|
@@ -56,6 +57,35 @@ module Compliance
|
|
56
57
|
puts '', msg
|
57
58
|
end
|
58
59
|
|
60
|
+
desc "login_automate SERVER --user='USER' --ent='ENT' --dctoken or --usertoken='TOKEN'", 'Log in to an Automate SERVER'
|
61
|
+
option :dctoken, type: :string,
|
62
|
+
desc: 'Data Collector token'
|
63
|
+
option :usertoken, type: :string,
|
64
|
+
desc: 'Automate user token'
|
65
|
+
option :user, type: :string,
|
66
|
+
desc: 'Automate username'
|
67
|
+
option :ent, type: :string,
|
68
|
+
desc: 'Enterprise for Chef Automate reporting'
|
69
|
+
option :insecure, aliases: :k, type: :boolean,
|
70
|
+
desc: 'Explicitly allows InSpec to perform "insecure" SSL connections and transfers'
|
71
|
+
def login_automate(server) # rubocop:disable Metrics/AbcSize
|
72
|
+
options['server'] = server
|
73
|
+
url = options['server'] + '/compliance/profiles'
|
74
|
+
|
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
|
85
|
+
end
|
86
|
+
puts '', msg
|
87
|
+
end
|
88
|
+
|
59
89
|
desc 'profiles', 'list all available profiles in Chef Compliance'
|
60
90
|
def profiles
|
61
91
|
config = Compliance::Configuration.new
|
@@ -79,10 +109,8 @@ module Compliance
|
|
79
109
|
def exec(*tests)
|
80
110
|
config = Compliance::Configuration.new
|
81
111
|
return if !loggedin(config)
|
82
|
-
|
83
112
|
# iterate over tests and add compliance scheme
|
84
113
|
tests = tests.map { |t| 'compliance://' + t }
|
85
|
-
|
86
114
|
# execute profile from inspec exec implementation
|
87
115
|
diagnose
|
88
116
|
run_tests(tests, opts)
|
@@ -100,6 +128,8 @@ module Compliance
|
|
100
128
|
exit 1
|
101
129
|
end
|
102
130
|
|
131
|
+
vendor_deps(path, options) if File.directory?(path)
|
132
|
+
|
103
133
|
o = options.dup
|
104
134
|
configure_logger(o)
|
105
135
|
# check the profile, we only allow to upload valid profiles
|
@@ -144,7 +174,6 @@ module Compliance
|
|
144
174
|
# if it is a directory, tar it to tmp directory
|
145
175
|
if File.directory?(path)
|
146
176
|
archive_path = Dir::Tmpname.create([profile_name, '.tar.gz']) {}
|
147
|
-
# archive_path = file.path
|
148
177
|
puts "Generate temporary profile archive at #{archive_path}"
|
149
178
|
profile.archive({ output: archive_path, ignore_errors: false, overwrite: true })
|
150
179
|
else
|
@@ -154,7 +183,8 @@ module Compliance
|
|
154
183
|
puts "Start upload to #{owner}/#{profile_name}"
|
155
184
|
pname = ERB::Util.url_encode(profile_name)
|
156
185
|
|
157
|
-
|
186
|
+
config['server_type'] == 'automate' ? upload_msg = 'Uploading to Chef Automate' : upload_msg = 'Uploading to Chef Compliance'
|
187
|
+
puts upload_msg
|
158
188
|
success, msg = Compliance::API.upload(config, owner, pname, archive_path)
|
159
189
|
|
160
190
|
if success
|
@@ -169,24 +199,27 @@ module Compliance
|
|
169
199
|
desc 'version', 'displays the version of the Chef Compliance server'
|
170
200
|
def version
|
171
201
|
config = Compliance::Configuration.new
|
172
|
-
|
173
|
-
|
174
|
-
puts "Chef Compliance version: #{info['version']}"
|
202
|
+
if config['server_type'] == 'automate'
|
203
|
+
puts 'Version not available when logged in with Automate.'
|
175
204
|
else
|
176
|
-
|
177
|
-
|
205
|
+
info = Compliance::API.version(config['server'], config['insecure'])
|
206
|
+
if !info.nil? && info['version']
|
207
|
+
puts "Chef Compliance version: #{info['version']}"
|
208
|
+
else
|
209
|
+
puts 'Could not determine server version.'
|
210
|
+
exit 1
|
211
|
+
end
|
178
212
|
end
|
179
213
|
end
|
180
214
|
|
181
215
|
desc 'logout', 'user logout from Chef Compliance'
|
182
216
|
def logout
|
183
217
|
config = Compliance::Configuration.new
|
184
|
-
unless config.supported?(:oidc) || config['token'].nil?
|
218
|
+
unless config.supported?(:oidc) || config['token'].nil? || config['server_type'] == 'automate'
|
185
219
|
config = Compliance::Configuration.new
|
186
220
|
url = "#{config['server']}/logout"
|
187
221
|
Compliance::API.post(url, config['token'], config['insecure'], !config.supported?(:oidc))
|
188
222
|
end
|
189
|
-
|
190
223
|
success = config.destroy
|
191
224
|
|
192
225
|
if success
|
@@ -198,6 +231,32 @@ module Compliance
|
|
198
231
|
|
199
232
|
private
|
200
233
|
|
234
|
+
def login_automate_config(url, user, dctoken, usertoken, ent, insecure) # rubocop:disable Metrics/ParameterLists
|
235
|
+
config = Compliance::Configuration.new
|
236
|
+
config['user'] = user
|
237
|
+
config['server'] = url
|
238
|
+
config['automate'] = {}
|
239
|
+
config['automate']['ent'] = ent
|
240
|
+
config['server_type'] = 'automate'
|
241
|
+
config['insecure'] = insecure
|
242
|
+
|
243
|
+
# determine token method being used
|
244
|
+
if !dctoken.nil?
|
245
|
+
config['token'] = dctoken
|
246
|
+
token_type = 'dctoken'
|
247
|
+
token_msg = 'data collector token'
|
248
|
+
else
|
249
|
+
config['token'] = usertoken
|
250
|
+
token_type = 'usertoken'
|
251
|
+
token_msg = 'automate user token'
|
252
|
+
end
|
253
|
+
|
254
|
+
config['automate']['token_type'] = token_type
|
255
|
+
config.store
|
256
|
+
msg = "Stored configuration for Chef Automate: '#{url}' with user: '#{user}', ent: '#{ent}' and your #{token_msg}"
|
257
|
+
msg
|
258
|
+
end
|
259
|
+
|
201
260
|
def login_refreshtoken(url, options)
|
202
261
|
success, msg, access_token = Compliance::API.get_token_via_refresh_token(url, options['refresh_token'], options['insecure'])
|
203
262
|
if success
|
@@ -206,6 +265,7 @@ module Compliance
|
|
206
265
|
config['token'] = access_token
|
207
266
|
config['insecure'] = options['insecure']
|
208
267
|
config['version'] = Compliance::API.version(url, options['insecure'])
|
268
|
+
config['server_type'] = 'compliance'
|
209
269
|
config.store
|
210
270
|
end
|
211
271
|
|
@@ -221,6 +281,7 @@ module Compliance
|
|
221
281
|
config['token'] = api_token
|
222
282
|
config['insecure'] = insecure
|
223
283
|
config['version'] = Compliance::API.version(url, insecure)
|
284
|
+
config['server_type'] = 'compliance'
|
224
285
|
config.store
|
225
286
|
success = true
|
226
287
|
end
|
@@ -267,7 +328,7 @@ module Compliance
|
|
267
328
|
|
268
329
|
def loggedin(config)
|
269
330
|
serverknown = !config['server'].nil?
|
270
|
-
puts 'You need to login first with `inspec compliance login`' if !serverknown
|
331
|
+
puts 'You need to login first with `inspec compliance login` or `inspec compliance login_automate`' if !serverknown
|
271
332
|
serverknown
|
272
333
|
end
|
273
334
|
end
|
@@ -9,16 +9,13 @@ module Compliance
|
|
9
9
|
# implements a simple http abstraction on top of Net::HTTP
|
10
10
|
class HTTP
|
11
11
|
# generic get requires
|
12
|
-
def self.get(url,
|
12
|
+
def self.get(url, headers = nil, insecure)
|
13
13
|
uri = URI.parse(url)
|
14
14
|
req = Net::HTTP::Get.new(uri.path)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
req.basic_auth(token, '')
|
20
|
-
else
|
21
|
-
req['Authorization'] = "Bearer #{token}"
|
15
|
+
if !headers.nil?
|
16
|
+
headers.each do |key, value|
|
17
|
+
req.add_field(key, value)
|
18
|
+
end
|
22
19
|
end
|
23
20
|
send_request(uri, req, insecure)
|
24
21
|
end
|
@@ -39,7 +36,7 @@ module Compliance
|
|
39
36
|
end
|
40
37
|
|
41
38
|
# post a file
|
42
|
-
def self.post_file(url,
|
39
|
+
def self.post_file(url, headers, file_path, insecure)
|
43
40
|
uri = URI.parse(url)
|
44
41
|
fail "Unable to parse URL: #{url}" if uri.nil? || uri.host.nil?
|
45
42
|
http = Net::HTTP.new(uri.host, uri.port)
|
@@ -49,10 +46,8 @@ module Compliance
|
|
49
46
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if insecure
|
50
47
|
|
51
48
|
req = Net::HTTP::Post.new(uri.path)
|
52
|
-
|
53
|
-
req.
|
54
|
-
else
|
55
|
-
req['Authorization'] = "Bearer #{token}"
|
49
|
+
headers.each do |key, value|
|
50
|
+
req.add_field(key, value)
|
56
51
|
end
|
57
52
|
|
58
53
|
req.body_stream=File.open(file_path, 'rb')
|
@@ -13,8 +13,7 @@ module Compliance
|
|
13
13
|
class Fetcher < Fetchers::Url
|
14
14
|
name 'compliance'
|
15
15
|
priority 500
|
16
|
-
|
17
|
-
def self.resolve(target)
|
16
|
+
def self.resolve(target) # rubocop:disable PerceivedComplexity
|
18
17
|
uri = if target.is_a?(String) && URI(target).scheme == 'compliance'
|
19
18
|
URI(target)
|
20
19
|
elsif target.respond_to?(:key?) && target.key?(:compliance)
|
@@ -26,14 +25,21 @@ module Compliance
|
|
26
25
|
# check if we have a compliance token
|
27
26
|
config = Compliance::Configuration.new
|
28
27
|
if config['token'].nil?
|
28
|
+
if config['server_type'] == 'automate'
|
29
|
+
server = 'automate'
|
30
|
+
msg = 'inspec compliance login_automate https://your_automate_server --user USER --ent ENT --dctoken DCTOKEN or --usertoken USERTOKEN'
|
31
|
+
else
|
32
|
+
server = 'compliance'
|
33
|
+
msg = "inspec compliance login https://your_compliance_server --user admin --insecure --token 'PASTE TOKEN HERE' "
|
34
|
+
end
|
29
35
|
fail Inspec::FetcherFailure, <<EOF
|
30
36
|
|
31
|
-
Cannot fetch #{uri} because your
|
37
|
+
Cannot fetch #{uri} because your #{server} token has not been
|
32
38
|
configured.
|
33
39
|
|
34
40
|
Please login using
|
35
41
|
|
36
|
-
|
42
|
+
#{msg}
|
37
43
|
EOF
|
38
44
|
end
|
39
45
|
|
@@ -48,8 +54,13 @@ EOF
|
|
48
54
|
end
|
49
55
|
|
50
56
|
def self.target_url(profile, config)
|
51
|
-
|
52
|
-
|
57
|
+
if config['server_type'] == 'automate'
|
58
|
+
target = "#{config['server']}/#{profile}/tar"
|
59
|
+
else
|
60
|
+
owner, id = profile.split('/')
|
61
|
+
target = "#{config['server']}/owners/#{owner}/compliance/#{id}/tar"
|
62
|
+
end
|
63
|
+
target
|
53
64
|
end
|
54
65
|
|
55
66
|
#
|
data/lib/fetchers/url.rb
CHANGED
@@ -8,7 +8,7 @@ require 'tempfile'
|
|
8
8
|
require 'open-uri'
|
9
9
|
|
10
10
|
module Fetchers
|
11
|
-
class Url < Inspec.fetcher(1)
|
11
|
+
class Url < Inspec.fetcher(1) # rubocop:disable Metrics/ClassLength
|
12
12
|
MIME_TYPES = {
|
13
13
|
'application/x-zip-compressed' => '.zip',
|
14
14
|
'application/zip' => '.zip',
|
@@ -126,7 +126,19 @@ module Fetchers
|
|
126
126
|
Inspec::Log.debug("Fetching URL: #{@target}")
|
127
127
|
http_opts = {}
|
128
128
|
http_opts['ssl_verify_mode'.to_sym] = OpenSSL::SSL::VERIFY_NONE if @insecure
|
129
|
-
|
129
|
+
if @config
|
130
|
+
if @config['server_type'] == 'automate'
|
131
|
+
http_opts['chef-delivery-enterprise'] = @config['automate']['ent']
|
132
|
+
if @config['automate']['token_type'] == 'dctoken'
|
133
|
+
http_opts['x-data-collector-token'] = @config['token']
|
134
|
+
else
|
135
|
+
http_opts['chef-delivery-user'] = @config['user']
|
136
|
+
http_opts['chef-delivery-token'] = @config['token']
|
137
|
+
end
|
138
|
+
elsif @token
|
139
|
+
http_opts['Authorization'] = "Bearer #{@token}"
|
140
|
+
end
|
141
|
+
end
|
130
142
|
remote = open(@target, http_opts)
|
131
143
|
@archive_type = file_type_from_remote(remote) # side effect :(
|
132
144
|
archive = Tempfile.new(['inspec-dl-', @archive_type])
|
data/lib/inspec/base_cli.rb
CHANGED
@@ -57,7 +57,7 @@ module Inspec
|
|
57
57
|
option :controls, type: :array,
|
58
58
|
desc: 'A list of controls to run. Ignore all other tests.'
|
59
59
|
option :format, type: :string,
|
60
|
-
desc: 'Which formatter to use: cli, progress, documentation, json, json-min'
|
60
|
+
desc: 'Which formatter to use: cli, progress, documentation, json, json-min, junit'
|
61
61
|
option :color, type: :boolean, default: true,
|
62
62
|
desc: 'Use colors in output.'
|
63
63
|
option :attrs, type: :array,
|
@@ -146,6 +146,35 @@ module Inspec
|
|
146
146
|
end
|
147
147
|
end
|
148
148
|
|
149
|
+
def vendor_deps(path, opts)
|
150
|
+
path.nil? ? path = Pathname.new(Dir.pwd) : path = Pathname.new(path)
|
151
|
+
cache_path = path.join('vendor')
|
152
|
+
inspec_lock = path.join('inspec.lock')
|
153
|
+
|
154
|
+
if (cache_path.exist? || inspec_lock.exist?) && !opts[:overwrite]
|
155
|
+
puts 'Profile is already vendored. Use --overwrite.'
|
156
|
+
return false
|
157
|
+
end
|
158
|
+
|
159
|
+
# remove existing
|
160
|
+
FileUtils.rm_rf(cache_path) if cache_path.exist?
|
161
|
+
File.delete(inspec_lock) if inspec_lock.exist?
|
162
|
+
|
163
|
+
puts "Vendor dependencies of #{path} into #{cache_path}"
|
164
|
+
opts[:logger] = Logger.new(STDOUT)
|
165
|
+
opts[:logger].level = get_log_level(opts.log_level)
|
166
|
+
opts[:cache] = Inspec::Cache.new(cache_path.to_s)
|
167
|
+
opts[:backend] = Inspec::Backend.create(target: 'mock://')
|
168
|
+
configure_logger(opts)
|
169
|
+
|
170
|
+
# vendor dependencies and generate lockfile
|
171
|
+
profile = Inspec::Profile.for_target(path.to_s, opts)
|
172
|
+
lockfile = profile.generate_lockfile
|
173
|
+
File.write(inspec_lock, lockfile.to_yaml)
|
174
|
+
rescue StandardError => e
|
175
|
+
pretty_handle_exception(e)
|
176
|
+
end
|
177
|
+
|
149
178
|
def configure_logger(o)
|
150
179
|
#
|
151
180
|
# TODO(ssd): This is a big gross, but this configures the
|
data/lib/inspec/cli.rb
CHANGED
@@ -33,6 +33,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
33
33
|
def json(target)
|
34
34
|
diagnose
|
35
35
|
o = opts.dup
|
36
|
+
configure_logger(o)
|
36
37
|
o[:ignore_supports] = true
|
37
38
|
o[:backend] = Inspec::Backend.create(target: 'mock://')
|
38
39
|
|
@@ -59,7 +60,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
59
60
|
def check(path) # rubocop:disable Metrics/AbcSize
|
60
61
|
diagnose
|
61
62
|
o = opts.dup
|
62
|
-
|
63
|
+
configure_logger(o)
|
63
64
|
o[:ignore_supports] = true # we check for integrity only
|
64
65
|
o[:backend] = Inspec::Backend.create(target: 'mock://')
|
65
66
|
|
@@ -108,35 +109,9 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
108
109
|
desc 'vendor PATH', 'Download all dependencies and generate a lockfile in a `vendor` directory'
|
109
110
|
option :overwrite, type: :boolean, default: false,
|
110
111
|
desc: 'Overwrite existing vendored dependencies and lockfile.'
|
111
|
-
def vendor(path = nil)
|
112
|
+
def vendor(path = nil)
|
112
113
|
o = opts.dup
|
113
|
-
|
114
|
-
path.nil? ? path = Pathname.new(Dir.pwd) : path = Pathname.new(path)
|
115
|
-
cache_path = path.join('vendor')
|
116
|
-
inspec_lock = path.join('inspec.lock')
|
117
|
-
|
118
|
-
if (cache_path.exist? || inspec_lock.exist?) && !opts[:overwrite]
|
119
|
-
puts 'Profile is already vendored. Use --overwrite.'
|
120
|
-
return false
|
121
|
-
end
|
122
|
-
|
123
|
-
# remove existing
|
124
|
-
FileUtils.rm_rf(cache_path) if cache_path.exist?
|
125
|
-
File.delete(inspec_lock) if inspec_lock.exist?
|
126
|
-
|
127
|
-
puts "Vendor dependencies of #{path} into #{cache_path}"
|
128
|
-
o[:logger] = Logger.new(STDOUT)
|
129
|
-
o[:logger].level = get_log_level(o.log_level)
|
130
|
-
o[:cache] = Inspec::Cache.new(cache_path.to_s)
|
131
|
-
o[:backend] = Inspec::Backend.create(target: 'mock://')
|
132
|
-
configure_logger(o)
|
133
|
-
|
134
|
-
# vendor dependencies and generate lockfile
|
135
|
-
profile = Inspec::Profile.for_target(path.to_s, o)
|
136
|
-
lockfile = profile.generate_lockfile
|
137
|
-
File.write(inspec_lock, lockfile.to_yaml)
|
138
|
-
rescue StandardError => e
|
139
|
-
pretty_handle_exception(e)
|
114
|
+
vendor_deps(path, o)
|
140
115
|
end
|
141
116
|
|
142
117
|
desc 'archive PATH', 'archive a profile to tar.gz (default) or zip'
|
@@ -211,7 +186,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
211
186
|
option :command, aliases: :c,
|
212
187
|
desc: 'A single command string to run instead of launching the shell'
|
213
188
|
option :format, type: :string, default: nil, hide: true,
|
214
|
-
desc: 'Which formatter to use: cli, progress, documentation, json, json-min'
|
189
|
+
desc: 'Which formatter to use: cli, progress, documentation, json, json-min, junit'
|
215
190
|
def shell_func
|
216
191
|
diagnose
|
217
192
|
o = opts.dup
|
@@ -15,14 +15,19 @@ module Inspec
|
|
15
15
|
new(lockfile_content)
|
16
16
|
end
|
17
17
|
|
18
|
-
def self.
|
19
|
-
parsed_content = YAML.load(
|
18
|
+
def self.from_content(content)
|
19
|
+
parsed_content = YAML.load(content)
|
20
20
|
version = parsed_content['lockfile_version']
|
21
21
|
fail "No lockfile_version set in #{path}!" if version.nil?
|
22
22
|
validate_lockfile_version!(version.to_i)
|
23
23
|
new(parsed_content)
|
24
24
|
end
|
25
25
|
|
26
|
+
def self.from_file(path)
|
27
|
+
content = File.read(path)
|
28
|
+
from_content(content)
|
29
|
+
end
|
30
|
+
|
26
31
|
def self.validate_lockfile_version!(version)
|
27
32
|
if version < MINIMUM_SUPPORTED_VERSION
|
28
33
|
fail <<EOF
|
data/lib/inspec/profile.rb
CHANGED
@@ -21,10 +21,9 @@ module Inspec
|
|
21
21
|
class Profile # rubocop:disable Metrics/ClassLength
|
22
22
|
extend Forwardable
|
23
23
|
|
24
|
-
def self.resolve_target(target, cache
|
25
|
-
|
26
|
-
Inspec::
|
27
|
-
Inspec::CachedFetcher.new(target, cache || Cache.new)
|
24
|
+
def self.resolve_target(target, cache)
|
25
|
+
Inspec::Log.debug "Resolve #{target} into cache #{cache.path}"
|
26
|
+
Inspec::CachedFetcher.new(target, cache)
|
28
27
|
end
|
29
28
|
|
30
29
|
# Check if the profile contains a vendored cache, move content into global cache
|
@@ -65,11 +64,13 @@ module Inspec
|
|
65
64
|
end
|
66
65
|
|
67
66
|
def self.for_fetcher(fetcher, opts)
|
67
|
+
opts[:cache] = opts[:cache] || Cache.new
|
68
68
|
path, writable = fetcher.fetch
|
69
69
|
for_path(path, opts.merge(target: fetcher.target, writable: writable))
|
70
70
|
end
|
71
71
|
|
72
72
|
def self.for_target(target, opts = {})
|
73
|
+
opts[:cache] = opts[:cache] || Cache.new
|
73
74
|
fetcher = resolve_target(target, opts[:cache])
|
74
75
|
for_fetcher(fetcher, opts)
|
75
76
|
end
|
@@ -205,7 +206,7 @@ module Inspec
|
|
205
206
|
res
|
206
207
|
end
|
207
208
|
|
208
|
-
# Check if the profile is
|
209
|
+
# Check if the profile is internally well-structured. The logger will be
|
209
210
|
# used to print information on errors and warnings which are found.
|
210
211
|
#
|
211
212
|
# @return [Boolean] true if no errors were found, false otherwise
|
@@ -342,7 +343,7 @@ module Inspec
|
|
342
343
|
end
|
343
344
|
|
344
345
|
def lockfile_exists?
|
345
|
-
|
346
|
+
@source_reader.target.files.include?('inspec.lock')
|
346
347
|
end
|
347
348
|
|
348
349
|
def lockfile_path
|
@@ -360,7 +361,7 @@ module Inspec
|
|
360
361
|
|
361
362
|
def lockfile
|
362
363
|
@lockfile ||= if lockfile_exists?
|
363
|
-
Inspec::Lockfile.
|
364
|
+
Inspec::Lockfile.from_content(@source_reader.target.read('inspec.lock'))
|
364
365
|
else
|
365
366
|
generate_lockfile
|
366
367
|
end
|
@@ -280,13 +280,7 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
280
280
|
MULTI_TEST_CONTROL_SUMMARY_MAX_LEN = 60
|
281
281
|
|
282
282
|
def initialize(*args)
|
283
|
-
@colors = COLORS
|
284
|
-
@indicators = INDICATORS
|
285
|
-
|
286
|
-
@format = '%color%indicator%id%summary'
|
287
283
|
@current_control = nil
|
288
|
-
@current_profile = nil
|
289
|
-
@missing_controls = []
|
290
284
|
@anonymous_tests = []
|
291
285
|
@control_tests = []
|
292
286
|
@profile_printed = false
|
@@ -294,12 +288,12 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
294
288
|
end
|
295
289
|
|
296
290
|
def close(_notification) # rubocop:disable Metrics/AbcSize
|
297
|
-
flush_current_control
|
291
|
+
flush_current_control(@current_control)
|
298
292
|
output.puts('') unless @current_control.nil?
|
299
|
-
print_tests
|
293
|
+
print_tests(@anonymous_tests)
|
300
294
|
output.puts('')
|
301
295
|
|
302
|
-
print_profiles_info if !@profile_printed
|
296
|
+
print_profiles_info(@current_control) if !@profile_printed
|
303
297
|
controls_res = controls_summary
|
304
298
|
tests_res = tests_summary
|
305
299
|
|
@@ -318,6 +312,31 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
318
312
|
|
319
313
|
private
|
320
314
|
|
315
|
+
# Formats example; calls example2control, gets a 'status_type', and calls
|
316
|
+
# flush current_control; returns control data
|
317
|
+
def format_example(example)
|
318
|
+
data = super(example)
|
319
|
+
control = example2control(data, @profiles_info) || {}
|
320
|
+
control[:id] = data[:id]
|
321
|
+
control[:profile_id] = data[:profile_id]
|
322
|
+
|
323
|
+
data[:status_type] = status_type(data, control)
|
324
|
+
dump_one_example(data, control)
|
325
|
+
|
326
|
+
@current_control ||= control
|
327
|
+
if !control[:id].nil?
|
328
|
+
if @current_control[:id] != control[:id]
|
329
|
+
flush_current_control(@current_control)
|
330
|
+
@current_control = control
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
data
|
335
|
+
end
|
336
|
+
|
337
|
+
# Determines 'status_type' (critical, major, minor) of control given
|
338
|
+
# status (failed/passed/skipped) and impact value (0.0 - 1.0).
|
339
|
+
# Called from format_example, sets the 'status_type' for each 'example'
|
321
340
|
def status_type(data, control)
|
322
341
|
status = data[:status]
|
323
342
|
return status if status != 'failed' || control[:impact].nil?
|
@@ -330,12 +349,45 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
330
349
|
end
|
331
350
|
end
|
332
351
|
|
333
|
-
|
352
|
+
# TODO: does a lot of stuff!
|
353
|
+
# Called from format_example and close
|
354
|
+
def flush_current_control(current_control)
|
355
|
+
return if current_control.nil?
|
356
|
+
|
357
|
+
profile = @profiles_info.find { |i| i[:id] == current_control[:profile_id] }
|
358
|
+
print_current_profile(profile) if !@profile_printed
|
359
|
+
|
360
|
+
fails, skips, passes, summary_indicator = current_control_infos(current_control)
|
361
|
+
summary = current_control_summary(fails, skips, current_control)
|
362
|
+
|
363
|
+
control_id = current_control[:id].to_s
|
364
|
+
control_id += ': '
|
365
|
+
if control_id.start_with? '(generated from '
|
366
|
+
@anonymous_tests.push(current_control)
|
367
|
+
else
|
368
|
+
@control_tests.push(current_control)
|
369
|
+
print_line(
|
370
|
+
color: COLORS[summary_indicator] || '',
|
371
|
+
indicator: INDICATORS[summary_indicator] || INDICATORS['unknown'],
|
372
|
+
summary: format_lines(summary, INDICATORS['empty']),
|
373
|
+
id: control_id,
|
374
|
+
profile: current_control[:profile_id],
|
375
|
+
)
|
376
|
+
|
377
|
+
print_results(fails + skips + passes)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
############# Current control methods #############
|
382
|
+
|
383
|
+
# Takes current_control (called from flush_current_control) and returns
|
384
|
+
# fails, skips, passes.
|
385
|
+
def current_control_infos(current_control)
|
334
386
|
summary_status = STATUS_TYPES['unknown']
|
335
387
|
skips = []
|
336
388
|
fails = []
|
337
389
|
passes = []
|
338
|
-
|
390
|
+
current_control[:results].each do |r|
|
339
391
|
i = STATUS_TYPES[r[:status_type]]
|
340
392
|
summary_status = i if i > summary_status
|
341
393
|
fails.push(r) if i > 0
|
@@ -345,9 +397,11 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
345
397
|
[fails, skips, passes, STATUS_TYPES.key(summary_status)]
|
346
398
|
end
|
347
399
|
|
348
|
-
|
349
|
-
|
350
|
-
|
400
|
+
# Determine title for control given current_control.
|
401
|
+
# Called from current_control_summary.
|
402
|
+
def current_control_title(current_control)
|
403
|
+
title = current_control[:title]
|
404
|
+
res = current_control[:results]
|
351
405
|
if title
|
352
406
|
title
|
353
407
|
elsif res.length == 1
|
@@ -368,9 +422,10 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
368
422
|
end
|
369
423
|
end
|
370
424
|
|
371
|
-
|
372
|
-
|
373
|
-
|
425
|
+
# Return summary of current_control, called from flush_current_control
|
426
|
+
def current_control_summary(fails, skips, current_control)
|
427
|
+
title = current_control_title(current_control)
|
428
|
+
res = current_control[:results]
|
374
429
|
suffix =
|
375
430
|
if res.length == 1
|
376
431
|
# Single test - be nice and just print the exception message if the test
|
@@ -389,27 +444,34 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
389
444
|
end
|
390
445
|
end
|
391
446
|
|
447
|
+
############# Print results and lines methods #############
|
448
|
+
|
449
|
+
# Formats the line (called from print_line)
|
392
450
|
def format_line(fields)
|
393
|
-
|
451
|
+
format = '%color%indicator%id%summary'
|
452
|
+
format.gsub(/%\w+/) do |x|
|
394
453
|
term = x[1..-1]
|
395
454
|
fields.key?(term.to_sym) ? fields[term.to_sym].to_s : x
|
396
|
-
end +
|
455
|
+
end + COLORS['reset']
|
397
456
|
end
|
398
457
|
|
458
|
+
# Prints line; used to print results
|
399
459
|
def print_line(fields)
|
400
460
|
output.puts(format_line(fields))
|
401
461
|
end
|
402
462
|
|
463
|
+
# Helps formatting summary lines (called from within print_line arguments)
|
403
464
|
def format_lines(lines, indentation)
|
404
465
|
lines.gsub(/\n/, "\n" + indentation)
|
405
466
|
end
|
406
467
|
|
468
|
+
# Sorts through results, calls print_line (called from flush_current_control)
|
407
469
|
def print_results(all)
|
408
470
|
all.each do |x|
|
409
471
|
test_status = x[:status_type]
|
410
|
-
test_color =
|
411
|
-
indicator =
|
412
|
-
indicator =
|
472
|
+
test_color = COLORS[test_status]
|
473
|
+
indicator = INDICATORS[x[:status]]
|
474
|
+
indicator = INDICATORS['empty'] if indicator.nil?
|
413
475
|
if x[:message]
|
414
476
|
msg = x[:code_desc] + "\n" + x[:message]
|
415
477
|
else
|
@@ -417,15 +479,16 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
417
479
|
end
|
418
480
|
print_line(
|
419
481
|
color: test_color,
|
420
|
-
indicator:
|
421
|
-
summary: format_lines(msg,
|
482
|
+
indicator: INDICATORS['small'] + indicator,
|
483
|
+
summary: format_lines(msg, INDICATORS['empty']),
|
422
484
|
id: nil, profile: nil
|
423
485
|
)
|
424
486
|
end
|
425
487
|
end
|
426
488
|
|
427
|
-
|
428
|
-
|
489
|
+
# Prints anonymous describe blocks; called from close method
|
490
|
+
def print_tests(anonymous_tests) # rubocop:disable Metrics/AbcSize
|
491
|
+
anonymous_tests.each do |control|
|
429
492
|
control_result = control[:results]
|
430
493
|
title = control_result[0][:code_desc].split[0..1].join(' ')
|
431
494
|
puts ' ' + title
|
@@ -443,9 +506,9 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
443
506
|
end
|
444
507
|
status_indicator = test[:status_type]
|
445
508
|
print_line(
|
446
|
-
color:
|
447
|
-
indicator:
|
448
|
-
summary: format_lines(test_result,
|
509
|
+
color: COLORS[status_indicator] || '',
|
510
|
+
indicator: INDICATORS['small'] + INDICATORS[status_indicator] || INDICATORS['unknown'],
|
511
|
+
summary: format_lines(test_result, INDICATORS['empty']),
|
449
512
|
id: control_id,
|
450
513
|
profile: control[:profile_id],
|
451
514
|
)
|
@@ -453,57 +516,33 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
453
516
|
end
|
454
517
|
end
|
455
518
|
|
456
|
-
|
457
|
-
return if @current_control.nil?
|
458
|
-
|
459
|
-
@current_profile = @profiles_info.find { |i| i[:id] == @current_control[:profile_id] }
|
460
|
-
print_current_profile if !@profile_printed
|
461
|
-
|
462
|
-
fails, skips, passes, summary_indicator = current_control_infos
|
463
|
-
summary = current_control_summary(fails, skips)
|
464
|
-
|
465
|
-
control_id = @current_control[:id].to_s
|
466
|
-
control_id += ': '
|
467
|
-
if control_id.start_with? '(generated from '
|
468
|
-
@anonymous_tests.push(@current_control)
|
469
|
-
else
|
470
|
-
@control_tests.push(@current_control)
|
471
|
-
print_line(
|
472
|
-
color: @colors[summary_indicator] || '',
|
473
|
-
indicator: @indicators[summary_indicator] || @indicators['unknown'],
|
474
|
-
summary: format_lines(summary, @indicators['empty']),
|
475
|
-
id: control_id,
|
476
|
-
profile: @current_control[:profile_id],
|
477
|
-
)
|
478
|
-
|
479
|
-
print_results(fails + skips + passes)
|
480
|
-
end
|
481
|
-
end
|
519
|
+
############# Print profile info methods #############
|
482
520
|
|
483
|
-
|
521
|
+
# Prints target information; called from print_current_profile
|
522
|
+
def print_target
|
484
523
|
return if @backend.nil?
|
485
524
|
connection = @backend.backend
|
486
525
|
return unless connection.respond_to?(:uri)
|
487
|
-
output.puts(
|
526
|
+
output.puts('Target: ' + connection.uri + "\n\n")
|
488
527
|
end
|
489
528
|
|
490
|
-
|
529
|
+
# Prints blank info is no current_control is defined
|
530
|
+
# Called from print_current_profile and close
|
531
|
+
def print_profiles_info(current_control)
|
491
532
|
@profiles_info.each do |profile|
|
492
533
|
next if profile[:already_printed]
|
493
|
-
|
494
|
-
next unless print_current_profile
|
534
|
+
next unless print_current_profile(profile)
|
495
535
|
print_line(
|
496
|
-
color: '', indicator:
|
536
|
+
color: '', indicator: INDICATORS['empty'], id: '', profile: '',
|
497
537
|
summary: 'No tests executed.'
|
498
|
-
) if
|
538
|
+
) if current_control.nil?
|
499
539
|
output.puts('')
|
500
540
|
end
|
501
541
|
end
|
502
542
|
|
503
|
-
def print_current_profile
|
504
|
-
profile = @current_profile
|
543
|
+
def print_current_profile(profile)
|
505
544
|
if profile.nil?
|
506
|
-
print_profiles_info
|
545
|
+
print_profiles_info(@current_control)
|
507
546
|
@profile_printed = true
|
508
547
|
return true
|
509
548
|
end
|
@@ -511,7 +550,7 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
511
550
|
profile[:already_printed] = true
|
512
551
|
|
513
552
|
if profile[:name].nil?
|
514
|
-
print_target
|
553
|
+
print_target
|
515
554
|
@profile_printed = true
|
516
555
|
return true
|
517
556
|
end
|
@@ -523,31 +562,10 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
523
562
|
end
|
524
563
|
|
525
564
|
output.puts 'Version: ' + (profile[:version] || 'unknown')
|
526
|
-
print_target
|
527
|
-
output.puts
|
565
|
+
print_target
|
528
566
|
@profile_printed = true
|
529
567
|
true
|
530
568
|
end
|
531
|
-
|
532
|
-
def format_example(example)
|
533
|
-
data = super(example)
|
534
|
-
control = example2control(data, @profiles_info) || {}
|
535
|
-
control[:id] = data[:id]
|
536
|
-
control[:profile_id] = data[:profile_id]
|
537
|
-
|
538
|
-
data[:status_type] = status_type(data, control)
|
539
|
-
dump_one_example(data, control)
|
540
|
-
|
541
|
-
@current_control ||= control
|
542
|
-
if control[:id].nil?
|
543
|
-
@missing_controls.push(data)
|
544
|
-
elsif @current_control[:id] != control[:id]
|
545
|
-
flush_current_control
|
546
|
-
@current_control = control
|
547
|
-
end
|
548
|
-
|
549
|
-
data
|
550
|
-
end
|
551
569
|
end
|
552
570
|
|
553
571
|
class InspecRspecJUnit < RSpecJUnitFormatter
|
data/lib/inspec/version.rb
CHANGED
data/lib/resources/processes.rb
CHANGED
@@ -21,9 +21,10 @@ module Inspec::Resources
|
|
21
21
|
:states
|
22
22
|
|
23
23
|
def initialize(grep)
|
24
|
+
@grep = grep
|
24
25
|
# turn into a regexp if it isn't one yet
|
25
26
|
if grep.class == String
|
26
|
-
grep = '(/[^/]*)*'+grep if grep[0] != '/'
|
27
|
+
grep = '(/[^/]*)*' + grep if grep[0] != '/'
|
27
28
|
grep = Regexp.new('^' + grep + '(\s|$)')
|
28
29
|
end
|
29
30
|
all_cmds = ps_axo
|
@@ -38,7 +39,7 @@ module Inspec::Resources
|
|
38
39
|
end
|
39
40
|
|
40
41
|
def to_s
|
41
|
-
|
42
|
+
"Processes #{@grep.class == String ? @grep : @grep.inspect}"
|
42
43
|
end
|
43
44
|
|
44
45
|
private
|
@@ -48,7 +49,7 @@ module Inspec::Resources
|
|
48
49
|
|
49
50
|
if os.linux?
|
50
51
|
command = 'ps axo label,pid,pcpu,pmem,vsz,rss,tty,stat,start,time,user:32,command'
|
51
|
-
regex = /^([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+(
|
52
|
+
regex = /^([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+(\w{3} \d{2}|\d{2}:\d{2}:\d{2})\s+([^ ]+)\s+([^ ]+)\s+(.*)$/
|
52
53
|
else
|
53
54
|
command = 'ps axo pid,pcpu,pmem,vsz,rss,tty,stat,start,time,user,command'
|
54
55
|
regex = /^\s*([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+(.*)$/
|
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.7.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: 2016-
|
11
|
+
date: 2016-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: train
|