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.
@@ -0,0 +1,80 @@
1
+ # encoding: utf-8
2
+ # author: Dominik Richter
3
+ # author: Christoph Hartmann
4
+
5
+ require 'functional/helper'
6
+
7
+ describe 'inspec archive' do
8
+ include FunctionalHelper
9
+
10
+ it 'archive is successful' do
11
+ out = inspec('archive ' + example_profile + ' --overwrite')
12
+ out.exit_status.must_equal 0
13
+ out.stdout.must_match /Generate archive [^ ]*profile.tar.gz/
14
+ out.stdout.must_include 'Finished archive generation.'
15
+ end
16
+
17
+ it 'archives to output file' do
18
+ out = inspec('archive ' + example_profile + ' --output ' + dst.path)
19
+ out.stderr.must_equal ''
20
+ out.stdout.must_include 'Generate archive '+dst.path
21
+ out.stdout.must_include 'Finished archive generation.'
22
+ out.exit_status.must_equal 0
23
+ File.exist?(dst.path).must_equal true
24
+ end
25
+
26
+ it 'auto-archives when no --output is given' do
27
+ auto_dst = File.join(repo_path, 'profile.tar.gz')
28
+ out = inspec('archive ' + example_profile + ' --overwrite')
29
+ out.stderr.must_equal ''
30
+ out.stdout.must_include 'Generate archive '+auto_dst
31
+ out.stdout.must_include 'Finished archive generation.'
32
+ out.exit_status.must_equal 0
33
+ File.exist?(auto_dst).must_equal true
34
+ end
35
+
36
+ it 'archive on invalid archive' do
37
+ out = inspec('archive /proc --output ' + dst.path)
38
+ # out.stdout.must_equal '' => we have partial stdout output right now
39
+ out.stderr.must_include "Don't understand inspec profile in \"/proc\""
40
+ out.exit_status.must_equal 1
41
+ File.exist?(dst.path).must_equal false
42
+ end
43
+
44
+ it 'archive wont overwrite existing files' do
45
+ x = rand.to_s
46
+ File.write(dst.path, x)
47
+ out = inspec('archive ' + example_profile + ' --output ' + dst.path)
48
+ out.stderr.must_equal '' # uh...
49
+ out.stdout.must_include "Archive #{dst.path} exists already. Use --overwrite."
50
+ out.exit_status.must_equal 1
51
+ File.read(dst.path).must_equal x
52
+ end
53
+
54
+ it 'archive will overwrite files if necessary' do
55
+ x = rand.to_s
56
+ File.write(dst.path, x)
57
+ out = inspec('archive ' + example_profile + ' --output ' + dst.path + ' --overwrite')
58
+ out.stderr.must_equal ''
59
+ out.stdout.must_include 'Generate archive '+dst.path
60
+ out.exit_status.must_equal 0
61
+ File.read(dst.path).wont_equal x
62
+ end
63
+
64
+ it 'creates valid tar.gz archives' do
65
+ out = inspec('archive ' + example_profile + ' --output ' + dst.path + ' --tar')
66
+ out.stderr.must_equal ''
67
+ out.stdout.must_include 'Generate archive '+dst.path
68
+ out.exit_status.must_equal 0
69
+ t = Zlib::GzipReader.open(dst.path)
70
+ Gem::Package::TarReader.new(t).entries.map(&:header).map(&:name).must_include 'inspec.yml'
71
+ end
72
+
73
+ it 'creates valid zip archives' do
74
+ out = inspec('archive ' + example_profile + ' --output ' + dst.path + ' --zip')
75
+ out.stderr.must_equal ''
76
+ out.stdout.must_include 'Generate archive '+dst.path
77
+ out.exit_status.must_equal 0
78
+ Zip::File.new(dst.path).entries.map(&:name).must_include 'inspec.yml'
79
+ end
80
+ end
@@ -0,0 +1,141 @@
1
+ # encoding: utf-8
2
+ # author: Dominik Richter
3
+ # author: Christoph Hartmann
4
+
5
+ require 'functional/helper'
6
+
7
+ describe 'inspec exec' do
8
+ include FunctionalHelper
9
+
10
+ it 'can execute the profile' do
11
+ out = inspec('exec ' + example_profile)
12
+ out.stderr.must_equal ''
13
+ out.exit_status.must_equal 0
14
+ out.stdout.must_match /^Pending: /
15
+ out.stdout.must_include '4 examples, 0 failures, 1 pending'
16
+ end
17
+
18
+ it 'executes only specified controls' do
19
+ out = inspec('exec ' + example_profile + ' --controls tmp-1.0')
20
+ out.stderr.must_equal ''
21
+ out.exit_status.must_equal 0
22
+ out.stdout.must_include '1 example, 0 failures'
23
+ end
24
+
25
+ it 'can execute the profile with the json formatter' do
26
+ out = inspec('exec ' + example_profile + ' --format json')
27
+ out.stderr.must_equal ''
28
+ out.exit_status.must_equal 0
29
+ JSON.load(out.stdout).must_be_kind_of Hash
30
+ end
31
+
32
+ describe 'execute a profile with json formatting' do
33
+ let(:json) { JSON.load(inspec('exec ' + example_profile + ' --format json').stdout) }
34
+ let(:examples) { json['examples'] }
35
+ let(:ex1) { examples.find{|x| x['id'] == 'tmp-1.0'} }
36
+ let(:ex2) { examples.find{|x| x['id'] =~ /generated/} }
37
+ let(:ex3) { examples.find{|x| x['id'] == 'gordon-1.0'} }
38
+
39
+ it 'must have 4 examples' do
40
+ json['examples'].length.must_equal 4
41
+ end
42
+
43
+ it 'id in json' do
44
+ examples.find { |ex| !ex.key? 'id' }.must_be :nil?
45
+ end
46
+
47
+ it 'impact in json' do
48
+ ex1['impact'].must_equal 0.7
49
+ ex2['impact'].must_be :nil?
50
+ end
51
+
52
+ it 'status in json' do
53
+ ex1['status'].must_equal 'passed'
54
+ ex3['status'].must_equal 'pending'
55
+ end
56
+
57
+ it 'pending message in json' do
58
+ ex1['pending_message'].must_be :nil?
59
+ ex3['pending_message'].must_equal 'Not yet implemented'
60
+ end
61
+ end
62
+
63
+ describe 'execute a profile with fulljson formatting' do
64
+ let(:json) { JSON.load(inspec('exec ' + example_profile + ' --format fulljson').stdout) }
65
+ let(:examples) { json['examples'] }
66
+ let(:metadata) { json['profiles'][0] }
67
+ let(:ex1) { examples.find{|x| x['id'] == 'tmp-1.0'} }
68
+ let(:ex2) { examples.find{|x| x['id'] =~ /generated/} }
69
+ let(:ex3) { examples.find{|x| x['id'] == 'gordon-1.0'} }
70
+
71
+ it 'has all the metadata' do
72
+ metadata.must_equal({
73
+ "name" => "profile",
74
+ "title" => "InSpec Example Profile",
75
+ "maintainer" => "Chef Software, Inc.",
76
+ "copyright" => "Chef Software, Inc.",
77
+ "copyright_email" => "support@chef.io",
78
+ "license" => "Apache 2 license",
79
+ "summary" => "Demonstrates the use of InSpec Compliance Profile",
80
+ "version" => "1.0.0",
81
+ "supports" => [{"os-family" => "unix"}]
82
+ })
83
+ end
84
+
85
+ it 'must have 4 examples' do
86
+ json['examples'].length.must_equal 4
87
+ end
88
+
89
+ it 'id in json' do
90
+ examples.find { |ex| !ex.key? 'id' }.must_be :nil?
91
+ end
92
+
93
+ it 'title in json' do
94
+ ex3['title'].must_equal 'Verify the version number of Gordon'
95
+ end
96
+
97
+ it 'desc in json' do
98
+ ex3['desc'].must_equal 'An optional description...'
99
+ end
100
+
101
+ it 'code in json' do
102
+ ex3['code'].wont_be :nil?
103
+ end
104
+
105
+ it 'code_desc in json' do
106
+ ex3['code_desc'].wont_be :nil?
107
+ end
108
+
109
+ it 'impact in json' do
110
+ ex1['impact'].must_equal 0.7
111
+ ex2['impact'].must_be :nil?
112
+ end
113
+
114
+ it 'status in json' do
115
+ ex1['status'].must_equal 'passed'
116
+ ex3['status'].must_equal 'pending'
117
+ end
118
+
119
+ it 'ref in json' do
120
+ ex1['ref'].must_match %r{examples/profile/controls/example.rb$}
121
+ end
122
+
123
+ it 'ref_line in json' do
124
+ ex1['ref_line'].must_equal 14
125
+ end
126
+
127
+ it 'run_time in json' do
128
+ ex1['run_time'].wont_be :nil?
129
+ end
130
+
131
+ it 'start_time in json' do
132
+ ex1['start_time'].wont_be :nil?
133
+ end
134
+
135
+ it 'pending message in json' do
136
+ ex1['pending'].must_be :nil?
137
+ ex3['pending'].must_equal "Can't find file \"/tmp/gordon/config.yaml\""
138
+ end
139
+ end
140
+
141
+ end
@@ -0,0 +1,104 @@
1
+ # encoding: utf-8
2
+ # author: Dominik Richter
3
+ # author: Christoph Hartmann
4
+
5
+ require 'functional/helper'
6
+
7
+ describe 'inspec json' do
8
+ include FunctionalHelper
9
+
10
+ it 'read the profile json' do
11
+ out = inspec('json ' + example_profile)
12
+ out.stderr.must_equal ''
13
+ out.exit_status.must_equal 0
14
+ s = out.stdout
15
+ JSON.load(s).must_be_kind_of Hash
16
+ end
17
+
18
+ describe 'json profile data' do
19
+ let(:json) { JSON.load(inspec('json ' + example_profile).stdout) }
20
+
21
+ it 'has a name' do
22
+ json['name'].must_equal 'profile'
23
+ end
24
+
25
+ it 'has a title' do
26
+ json['title'].must_equal 'InSpec Example Profile'
27
+ end
28
+
29
+ it 'has a summary' do
30
+ json['summary'].must_equal 'Demonstrates the use of InSpec Compliance Profile'
31
+ end
32
+
33
+ it 'has a version' do
34
+ json['version'].must_equal '1.0.0'
35
+ end
36
+
37
+ it 'has a maintainer' do
38
+ json['maintainer'].must_equal 'Chef Software, Inc.'
39
+ end
40
+
41
+ it 'has a copyright' do
42
+ json['copyright'].must_equal 'Chef Software, Inc.'
43
+ end
44
+
45
+ it 'has rules' do
46
+ json['rules'].length.must_equal 3 # TODO: flatten out or search deeper!
47
+ end
48
+
49
+ describe 'a rule' do
50
+ let(:rule) { json['rules']['controls/example.rb']['rules']['tmp-1.0'] }
51
+
52
+ it 'has a title' do
53
+ rule['title'].must_equal 'Create /tmp directory'
54
+ end
55
+
56
+ it 'has a description' do
57
+ rule['desc'].must_equal 'An optional description...'
58
+ end
59
+
60
+ it 'has an impact' do
61
+ rule['impact'].must_equal 0.7
62
+ end
63
+
64
+ it 'has a ref' do
65
+ rule['refs'].must_equal([{'ref' => 'Document A-12', 'url' => 'http://...'}])
66
+ end
67
+
68
+ it 'has a source location' do
69
+ loc = File.join(example_profile, '/controls/example.rb')
70
+ rule['source_location'].must_equal [loc, 8]
71
+ end
72
+
73
+ it 'has a the source code' do
74
+ rule['code'].must_match /\Acontrol \"tmp-1.0\" do.*end\n\Z/m
75
+ end
76
+ end
77
+ end
78
+
79
+ describe 'filter with --controls' do
80
+ let(:out) { inspec('json ' + example_profile + ' --controls tmp-1.0') }
81
+
82
+ it 'still succeeds' do
83
+ out.stderr.must_equal ''
84
+ out.exit_status.must_equal 0
85
+ end
86
+
87
+ it 'only has one control included' do
88
+ json = JSON.load(out.stdout)
89
+ grps = json['rules']
90
+ grps.keys.must_equal ['controls/example.rb']
91
+ rules = grps.values[0]['rules']
92
+ rules.keys.must_equal ['tmp-1.0']
93
+ end
94
+ end
95
+
96
+ it 'writes json to file' do
97
+ out = inspec('json ' + example_profile + ' --output ' + dst.path)
98
+ out.stderr.must_equal ''
99
+ out.exit_status.must_equal 0
100
+ hm = JSON.load(File.read(dst.path))
101
+ hm['name'].must_equal 'profile'
102
+ hm['rules'].length.must_equal 3 # TODO: flatten out or search deeper!
103
+ end
104
+ end
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+ # author: Dominik Richter
3
+ # author: Christoph Hartmann
4
+
5
+ require 'functional/helper'
6
+
7
+ describe 'command tests' do
8
+ include FunctionalHelper
9
+
10
+ describe 'detect' do
11
+ it 'runs well on all nodes' do
12
+ out = inspec('detect')
13
+ out.stderr.must_equal ''
14
+ out.exit_status.must_equal 0
15
+ j = JSON.load(out.stdout)
16
+ j.keys.must_include 'name'
17
+ j.keys.must_include 'family'
18
+ j.keys.must_include 'arch'
19
+ j.keys.must_include 'release'
20
+ end
21
+ end
22
+
23
+ describe 'version' do
24
+ it 'provides the version number on stdout' do
25
+ out = inspec('version')
26
+ out.stderr.must_equal ''
27
+ out.exit_status.must_equal 0
28
+ out.stdout.must_equal Inspec::VERSION+"\n"
29
+ end
30
+ end
31
+
32
+ describe 'shell' do
33
+ it 'provides a help command' do
34
+ out = CMD.run_command("echo \"help\nexit\" | #{exec_inspec} shell")
35
+ out.exit_status.must_equal 0
36
+ out.stdout.must_include 'Available commands:'
37
+ out.stdout.must_include 'You are currently running on:'
38
+ end
39
+
40
+ it 'exposes all resources' do
41
+ out = CMD.run_command("echo \"os\nexit\" | #{exec_inspec} shell")
42
+ out.exit_status.must_equal 0
43
+ out.stdout.must_match /^=> .*Operating.* .*System.* .*Detection.*$/
44
+ end
45
+ end
46
+
47
+ describe 'check' do
48
+ it 'verifies that a profile is ok' do
49
+ out = inspec('check ' + example_profile)
50
+ out.stdout.must_match /Valid.*true/
51
+ out.exit_status.must_equal 0
52
+ end
53
+ end
54
+ end
@@ -91,7 +91,7 @@ describe Inspec::ProfileContext do
91
91
  it 'supports empty describe calls' do
92
92
  load('describe').must_output ''
93
93
  profile.rules.keys.length.must_equal 1
94
- profile.rules.keys[0].must_match /^\(generated from unknown:1 [0-9a-f]+\)$/
94
+ profile.rules.keys[0].must_match /^\(generated from \(eval\):1 [0-9a-f]+\)$/
95
95
  profile.rules.values[0].must_be_kind_of Inspec::Rule
96
96
  end
97
97
 
@@ -99,7 +99,7 @@ describe Inspec::ProfileContext do
99
99
  load('describe true do; it { should_eq true }; end')
100
100
  .must_output ''
101
101
  profile.rules.keys.length.must_equal 1
102
- profile.rules.keys[0].must_match /^\(generated from unknown:1 [0-9a-f]+\)$/
102
+ profile.rules.keys[0].must_match /^\(generated from \(eval\):1 [0-9a-f]+\)$/
103
103
  profile.rules.values[0].must_be_kind_of Inspec::Rule
104
104
  end
105
105
 
@@ -108,7 +108,7 @@ describe Inspec::ProfileContext do
108
108
  .must_output ''
109
109
  profile.rules.keys.length.must_equal 3
110
110
  [0, 1, 2].each do |i|
111
- profile.rules.keys[i].must_match /^\(generated from unknown:2 [0-9a-f]+\)$/
111
+ profile.rules.keys[i].must_match /^\(generated from \(eval\):2 [0-9a-f]+\)$/
112
112
  profile.rules.values[i].must_be_kind_of Inspec::Rule
113
113
  end
114
114
  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: 0.16.3
4
+ version: 0.16.4
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-03-23 00:00:00.000000000 Z
11
+ date: 2016-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: r-train
@@ -208,11 +208,9 @@ files:
208
208
  - examples/profile/README.md
209
209
  - examples/profile/controls/example.rb
210
210
  - examples/profile/controls/gordon.rb
211
+ - examples/profile/controls/meta.rb
211
212
  - examples/profile/inspec.yml
212
213
  - examples/profile/libraries/gordon_config.rb
213
- - examples/resource/controls/tiny.rb
214
- - examples/resource/inspec.yml
215
- - examples/resource/libraries/tiny.rb
216
214
  - inspec.gemspec
217
215
  - lib/bundles/README.md
218
216
  - lib/bundles/inspec-compliance.rb
@@ -360,7 +358,12 @@ files:
360
358
  - test/cookbooks/os_prepare/templates/default/sv-default-svlog-run.erb
361
359
  - test/docker_run.rb
362
360
  - test/docker_test.rb
363
- - test/functional/command_test.rb
361
+ - test/functional/helper.rb
362
+ - test/functional/inheritance_test.rb
363
+ - test/functional/inspec_archive_test.rb
364
+ - test/functional/inspec_exec_test.rb
365
+ - test/functional/inspec_json_test.rb
366
+ - test/functional/inspec_test.rb
364
367
  - test/helper.rb
365
368
  - test/integration/default/_debug_spec.rb
366
369
  - test/integration/default/apache_conf_spec.rb
@@ -617,7 +620,12 @@ test_files:
617
620
  - test/cookbooks/os_prepare/templates/default/sv-default-svlog-run.erb
618
621
  - test/docker_run.rb
619
622
  - test/docker_test.rb
620
- - test/functional/command_test.rb
623
+ - test/functional/helper.rb
624
+ - test/functional/inheritance_test.rb
625
+ - test/functional/inspec_archive_test.rb
626
+ - test/functional/inspec_exec_test.rb
627
+ - test/functional/inspec_json_test.rb
628
+ - test/functional/inspec_test.rb
621
629
  - test/helper.rb
622
630
  - test/integration/default/_debug_spec.rb
623
631
  - test/integration/default/apache_conf_spec.rb