inspec 0.16.3 → 0.16.4

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.
@@ -1,3 +0,0 @@
1
- describe tiny do
2
- require 'pry'; binding.pry
3
- end
@@ -1,10 +0,0 @@
1
- name: resource
2
- title: InSpec Example Resources
3
- maintainer: Chef Software, Inc.
4
- copyright: Chef Software, Inc.
5
- copyright_email: support@chef.io
6
- license: Apache 2 license
7
- summary: Demonstrates the use of InSpec custom resources
8
- version: 1.0.0
9
- supports:
10
- - linux
@@ -1,3 +0,0 @@
1
- class Tiny < Inspec.resource(1)
2
- name 'tiny'
3
- end
@@ -1,390 +0,0 @@
1
- # encoding: utf-8
2
- # author: Dominik Richter
3
- # author: Christoph Hartmann
4
-
5
- require 'helper'
6
- require 'minitest/hell'
7
- class Minitest::Test
8
- parallelize_me!
9
- end
10
-
11
- describe 'Inspec::InspecCLI' do
12
- let(:repo_path) { File.expand_path(File.join( __FILE__, '..', '..', '..')) }
13
- let(:exec_inspec) { File.join(repo_path, 'bin', 'inspec') }
14
- let(:profile_path) { File.join(repo_path, 'test', 'unit', 'mock', 'profiles') }
15
- let(:examples_path) { File.join(repo_path, 'examples') }
16
- let(:dst) {
17
- # create a temporary path, but we only want an auto-clean helper
18
- # so remove the file and give back the path
19
- res = Tempfile.new('inspec-shred')
20
- FileUtils.rm(res.path)
21
- TMP_CACHE[res.path] = res
22
- }
23
-
24
- def inspec(commandline)
25
- CMD.run_command("#{exec_inspec} #{commandline}")
26
- end
27
-
28
- describe 'detect' do
29
- it 'runs well on all nodes' do
30
- out = inspec('detect')
31
- out.stderr.must_equal ''
32
- out.exit_status.must_equal 0
33
- j = JSON.load(out.stdout)
34
- j.keys.must_include 'name'
35
- j.keys.must_include 'family'
36
- j.keys.must_include 'arch'
37
- j.keys.must_include 'release'
38
- end
39
- end
40
-
41
- describe 'version' do
42
- it 'provides the version number on stdout' do
43
- out = inspec('version')
44
- out.stderr.must_equal ''
45
- out.exit_status.must_equal 0
46
- out.stdout.must_equal Inspec::VERSION+"\n"
47
- end
48
- end
49
-
50
- describe 'shell' do
51
- it 'provides a help command' do
52
- out = CMD.run_command("echo \"help\nexit\" | #{exec_inspec} shell")
53
- out.exit_status.must_equal 0
54
- out.stdout.must_include 'Available commands:'
55
- out.stdout.must_include 'You are currently running on:'
56
- end
57
-
58
- it 'exposes all resources' do
59
- out = CMD.run_command("echo \"os\nexit\" | #{exec_inspec} shell")
60
- out.exit_status.must_equal 0
61
- out.stdout.must_match /^=> .*Operating.* .*System.* .*Detection.*$/
62
- end
63
- end
64
-
65
- describe 'example profile' do
66
- let(:path) { File.join(examples_path, 'profile') }
67
-
68
- it 'check is successful' do
69
- out = inspec('check ' + path)
70
- out.stdout.must_match /Valid.*true/
71
- out.exit_status.must_equal 0
72
- end
73
-
74
- it 'archive is successful' do
75
- out = inspec('archive ' + path + ' --overwrite')
76
- out.exit_status.must_equal 0
77
- out.stdout.must_match /Generate archive [^ ]*profile.tar.gz/
78
- out.stdout.must_include 'Finished archive generation.'
79
- end
80
-
81
- it 'archives to output file' do
82
- out = inspec('archive ' + path + ' --output ' + dst.path)
83
- out.stderr.must_equal ''
84
- out.stdout.must_include 'Generate archive '+dst.path
85
- out.stdout.must_include 'Finished archive generation.'
86
- out.exit_status.must_equal 0
87
- File.exist?(dst.path).must_equal true
88
- end
89
-
90
- it 'auto-archives when no --output is given' do
91
- auto_dst = File.join(repo_path, 'profile.tar.gz')
92
- out = inspec('archive ' + path + ' --overwrite')
93
- out.stderr.must_equal ''
94
- out.stdout.must_include 'Generate archive '+auto_dst
95
- out.stdout.must_include 'Finished archive generation.'
96
- out.exit_status.must_equal 0
97
- File.exist?(auto_dst).must_equal true
98
- end
99
-
100
- it 'archive on invalid archive' do
101
- out = inspec('archive /proc --output ' + dst.path)
102
- # out.stdout.must_equal '' => we have partial stdout output right now
103
- out.stderr.must_include "Don't understand inspec profile in \"/proc\""
104
- out.exit_status.must_equal 1
105
- File.exist?(dst.path).must_equal false
106
- end
107
-
108
- it 'archive wont overwrite existing files' do
109
- x = rand.to_s
110
- File.write(dst.path, x)
111
- out = inspec('archive ' + path + ' --output ' + dst.path)
112
- out.stderr.must_equal '' # uh...
113
- out.stdout.must_include "Archive #{dst.path} exists already. Use --overwrite."
114
- out.exit_status.must_equal 1
115
- File.read(dst.path).must_equal x
116
- end
117
-
118
- it 'archive will overwrite files if necessary' do
119
- x = rand.to_s
120
- File.write(dst.path, x)
121
- out = inspec('archive ' + path + ' --output ' + dst.path + ' --overwrite')
122
- out.stderr.must_equal ''
123
- out.stdout.must_include 'Generate archive '+dst.path
124
- out.exit_status.must_equal 0
125
- File.read(dst.path).wont_equal x
126
- end
127
-
128
- it 'creates valid tar.gz archives' do
129
- out = inspec('archive ' + path + ' --output ' + dst.path + ' --tar')
130
- out.stderr.must_equal ''
131
- out.stdout.must_include 'Generate archive '+dst.path
132
- out.exit_status.must_equal 0
133
- t = Zlib::GzipReader.open(dst.path)
134
- Gem::Package::TarReader.new(t).entries.map(&:header).map(&:name).must_include 'inspec.yml'
135
- end
136
-
137
- it 'creates valid zip archives' do
138
- out = inspec('archive ' + path + ' --output ' + dst.path + ' --zip')
139
- out.stderr.must_equal ''
140
- out.stdout.must_include 'Generate archive '+dst.path
141
- out.exit_status.must_equal 0
142
- Zip::File.new(dst.path).entries.map(&:name).must_include 'inspec.yml'
143
- end
144
-
145
- it 'read the profile json' do
146
- out = inspec('json ' + path)
147
- out.stderr.must_equal ''
148
- out.exit_status.must_equal 0
149
- s = out.stdout
150
- JSON.load(s).must_be_kind_of Hash
151
- end
152
-
153
- describe 'json profile data' do
154
- let(:json) { JSON.load(inspec('json '+path).stdout) }
155
-
156
- it 'has a name' do
157
- json['name'].must_equal 'profile'
158
- end
159
-
160
- it 'has a title' do
161
- json['title'].must_equal 'InSpec Example Profile'
162
- end
163
-
164
- it 'has a summary' do
165
- json['summary'].must_equal 'Demonstrates the use of InSpec Compliance Profile'
166
- end
167
-
168
- it 'has a version' do
169
- json['version'].must_equal '1.0.0'
170
- end
171
-
172
- it 'has a maintainer' do
173
- json['maintainer'].must_equal 'Chef Software, Inc.'
174
- end
175
-
176
- it 'has a copyright' do
177
- json['copyright'].must_equal 'Chef Software, Inc.'
178
- end
179
-
180
- it 'has rules' do
181
- json['rules'].length.must_equal 2 # TODO: flatten out or search deeper!
182
- end
183
-
184
- describe 'a rule' do
185
- let(:rule) { json['rules']['controls/example.rb']['rules']['tmp-1.0'] }
186
-
187
- it 'has a title' do
188
- rule['title'].must_equal 'Create /tmp directory'
189
- end
190
-
191
- it 'has a description' do
192
- rule['desc'].must_equal 'An optional description...'
193
- end
194
-
195
- it 'has an impact' do
196
- rule['impact'].must_equal 0.7
197
- end
198
-
199
- it 'has a ref' do
200
- rule['refs'].must_equal([{'ref' => 'Document A-12', 'url' => 'http://...'}])
201
- end
202
-
203
- it 'has a source location' do
204
- loc = File.join(path, '/controls/example.rb')
205
- rule['source_location'].must_equal [loc, 8]
206
- end
207
-
208
- it 'has a the source code' do
209
- rule['code'].must_match /\Acontrol \"tmp-1.0\" do.*end\n\Z/m
210
- end
211
- end
212
- end
213
-
214
- it 'writes json to file' do
215
- out = inspec('json ' + path + ' --output ' + dst.path)
216
- out.stderr.must_equal ''
217
- out.exit_status.must_equal 0
218
- hm = JSON.load(File.read(dst.path))
219
- hm['name'].must_equal 'profile'
220
- hm['rules'].length.must_equal 2 # TODO: flatten out or search deeper!
221
- end
222
-
223
- it 'can execute the profile' do
224
- out = inspec('exec ' + path)
225
- out.stderr.must_equal ''
226
- out.exit_status.must_equal 0
227
- out.stdout.must_match /^Pending: /
228
- out.stdout.must_include '3 examples, 0 failures, 1 pending'
229
- end
230
-
231
- it 'can execute the profile with the json formatter' do
232
- out = inspec('exec ' + path + ' --format json')
233
- out.stderr.must_equal ''
234
- out.exit_status.must_equal 0
235
- JSON.load(out.stdout).must_be_kind_of Hash
236
- end
237
-
238
- describe 'execute a profile with json formatting' do
239
- let(:json) { JSON.load(inspec('exec ' + path + ' --format json').stdout) }
240
- let(:examples) { json['examples'] }
241
- let(:ex1) { examples.find{|x| x['id'] == 'tmp-1.0'} }
242
- let(:ex2) { examples.find{|x| x['id'] =~ /generated/} }
243
- let(:ex3) { examples.find{|x| x['id'] == 'gordon-1.0'} }
244
-
245
- it 'must have 3 examples' do
246
- json['examples'].length.must_equal 3
247
- end
248
-
249
- it 'id in json' do
250
- examples.find { |ex| !ex.key? 'id' }.must_be :nil?
251
- end
252
-
253
- it 'impact in json' do
254
- ex1['impact'].must_equal 0.7
255
- ex2['impact'].must_be :nil?
256
- end
257
-
258
- it 'status in json' do
259
- ex1['status'].must_equal 'passed'
260
- ex3['status'].must_equal 'pending'
261
- end
262
-
263
- it 'pending message in json' do
264
- ex1['pending_message'].must_be :nil?
265
- ex3['pending_message'].must_equal 'Not yet implemented'
266
- end
267
- end
268
-
269
- describe 'execute a profile with fulljson formatting' do
270
- let(:json) { JSON.load(inspec('exec ' + path + ' --format fulljson').stdout) }
271
- let(:examples) { json['examples'] }
272
- let(:metadata) { json['profiles'][0] }
273
- let(:ex1) { examples.find{|x| x['id'] == 'tmp-1.0'} }
274
- let(:ex2) { examples.find{|x| x['id'] =~ /generated/} }
275
- let(:ex3) { examples.find{|x| x['id'] == 'gordon-1.0'} }
276
-
277
- it 'has all the metadata' do
278
- metadata.must_equal({
279
- "name" => "profile",
280
- "title" => "InSpec Example Profile",
281
- "maintainer" => "Chef Software, Inc.",
282
- "copyright" => "Chef Software, Inc.",
283
- "copyright_email" => "support@chef.io",
284
- "license" => "Apache 2 license",
285
- "summary" => "Demonstrates the use of InSpec Compliance Profile",
286
- "version" => "1.0.0",
287
- "supports" => [{"os-family" => "linux"}]
288
- })
289
- end
290
-
291
- it 'must have 3 examples' do
292
- json['examples'].length.must_equal 3
293
- end
294
-
295
- it 'id in json' do
296
- examples.find { |ex| !ex.key? 'id' }.must_be :nil?
297
- end
298
-
299
- it 'title in json' do
300
- ex3['title'].must_equal 'Verify the version number of Gordon'
301
- end
302
-
303
- it 'desc in json' do
304
- ex3['desc'].must_equal 'An optional description...'
305
- end
306
-
307
- it 'code in json' do
308
- ex3['code'].wont_be :nil?
309
- end
310
-
311
- it 'code_desc in json' do
312
- ex3['code_desc'].wont_be :nil?
313
- end
314
-
315
- it 'impact in json' do
316
- ex1['impact'].must_equal 0.7
317
- ex2['impact'].must_be :nil?
318
- end
319
-
320
- it 'status in json' do
321
- ex1['status'].must_equal 'passed'
322
- ex3['status'].must_equal 'pending'
323
- end
324
-
325
- it 'ref in json' do
326
- ex1['ref'].must_match %r{examples/profile/controls/example.rb$}
327
- end
328
-
329
- it 'ref_line in json' do
330
- ex1['ref_line'].must_equal 14
331
- end
332
-
333
- it 'run_time in json' do
334
- ex1['run_time'].wont_be :nil?
335
- end
336
-
337
- it 'start_time in json' do
338
- ex1['start_time'].wont_be :nil?
339
- end
340
-
341
- it 'pending message in json' do
342
- ex1['pending'].must_be :nil?
343
- ex3['pending'].must_equal "Can't find file \"/etc/gordon/config.yaml\""
344
- end
345
- end
346
- end
347
-
348
- describe 'example inheritance profile' do
349
- let(:path) { File.join(examples_path, 'inheritance') }
350
-
351
- [
352
- 'archive %s --overwrite',
353
- 'check %s',
354
- 'json %s',
355
- ].each do |cmd|
356
- it cmd[/^\w/] + ' fails without --profiles-path' do
357
- out = inspec(format(cmd, path))
358
- out.stderr.must_include 'You must supply a --profiles-path to inherit'
359
- # out.stdout.must_equal '' => we still get partial output
360
- out.exit_status.must_equal 1
361
- end
362
- end
363
-
364
- it 'check succeeds with --profiles-path' do
365
- out = inspec('check ' + path + ' --profiles-path ' + examples_path)
366
- out.stderr.must_equal ''
367
- out.stdout.must_match /Valid.*true/
368
- out.exit_status.must_equal 0
369
- end
370
-
371
- it 'archive is successful with --profiles-path' do
372
- out = inspec('archive ' + path + ' --output ' + dst.path + ' --profiles-path ' + examples_path)
373
- out.stderr.must_equal ''
374
- out.stdout.must_include 'Generate archive '+dst.path
375
- out.stdout.must_include 'Finished archive generation.'
376
- out.exit_status.must_equal 0
377
- File.exist?(dst.path).must_equal true
378
- end
379
-
380
- it 'read the profile json with --profiles-path' do
381
- out = inspec('json ' + path + ' --profiles-path '+examples_path)
382
- out.stderr.must_equal ''
383
- out.exit_status.must_equal 0
384
- s = out.stdout
385
- hm = JSON.load(s)
386
- hm['name'].must_equal 'inheritance'
387
- hm['rules'].length.must_equal 1 # TODO: flatten out or search deeper!
388
- end
389
- end
390
- end