inspec 0.20.1 → 0.21.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 +45 -2
- data/docs/dsl_inspec.rst +2 -2
- data/docs/resources.rst +9 -9
- data/docs/ruby_usage.rst +145 -0
- data/inspec.gemspec +1 -0
- data/lib/bundles/inspec-compliance/cli.rb +15 -2
- data/lib/inspec/cli.rb +23 -10
- data/lib/inspec/dsl.rb +0 -52
- data/lib/inspec/objects/or_test.rb +1 -0
- data/lib/inspec/objects/test.rb +4 -4
- data/lib/inspec/profile.rb +76 -61
- data/lib/inspec/profile_context.rb +12 -11
- data/lib/inspec/rspec_json_formatter.rb +93 -40
- data/lib/inspec/rule.rb +7 -29
- data/lib/inspec/runner.rb +15 -4
- data/lib/inspec/runner_mock.rb +1 -1
- data/lib/inspec/runner_rspec.rb +26 -24
- data/lib/inspec/version.rb +1 -1
- data/lib/matchers/matchers.rb +3 -3
- data/lib/resources/auditd_rules.rb +2 -2
- data/lib/resources/host.rb +1 -1
- data/lib/resources/interface.rb +1 -1
- data/lib/resources/kernel_parameter.rb +1 -1
- data/lib/resources/mount.rb +2 -1
- data/lib/resources/mysql_session.rb +1 -1
- data/lib/resources/os_env.rb +2 -2
- data/lib/resources/passwd.rb +33 -93
- data/lib/resources/port.rb +47 -3
- data/lib/resources/processes.rb +3 -3
- data/lib/resources/service.rb +33 -1
- data/lib/resources/user.rb +15 -15
- data/lib/utils/base_cli.rb +1 -3
- data/lib/utils/filter.rb +30 -7
- data/test/cookbooks/os_prepare/recipes/_upstart_service_centos.rb +4 -0
- data/test/functional/helper.rb +1 -0
- data/test/functional/inheritance_test.rb +1 -1
- data/test/functional/inspec_compliance_test.rb +4 -3
- data/test/functional/inspec_exec_json_test.rb +122 -0
- data/test/functional/inspec_exec_test.rb +23 -117
- data/test/functional/{inspec_json_test.rb → inspec_json_profile_test.rb} +13 -15
- data/test/functional/inspec_test.rb +15 -2
- data/test/helper.rb +5 -1
- data/test/integration/default/auditd_rules_spec.rb +3 -3
- data/test/integration/default/kernel_parameter_spec.rb +6 -6
- data/test/integration/default/service_spec.rb +4 -0
- data/test/resource/command_test.rb +9 -9
- data/test/resource/dsl_test.rb +1 -1
- data/test/resource/file_test.rb +17 -17
- data/test/unit/control_test.rb +1 -1
- data/test/unit/mock/cmd/hpux-netstat-inet +10 -0
- data/test/unit/mock/cmd/hpux-netstat-inet6 +11 -0
- data/test/unit/mock/profiles/skippy-profile-os/controls/one.rb +1 -1
- data/test/unit/profile_context_test.rb +2 -2
- data/test/unit/profile_test.rb +11 -14
- data/test/unit/resources/passwd_test.rb +13 -14
- data/test/unit/resources/port_test.rb +14 -0
- data/test/unit/resources/processes_test.rb +3 -3
- data/test/unit/resources/service_test.rb +103 -39
- data/test/unit/utils/filter_table_test.rb +35 -3
- metadata +25 -4
data/lib/resources/port.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
# author: Dominik Richter
|
4
4
|
|
5
5
|
require 'utils/parser'
|
6
|
-
|
7
6
|
# Usage:
|
8
7
|
# describe port(80) do
|
9
8
|
# it { should be_listening }
|
@@ -47,6 +46,8 @@ module Inspec::Resources
|
|
47
46
|
@port_manager = FreeBsdPorts.new(inspec)
|
48
47
|
elsif os.solaris?
|
49
48
|
@port_manager = SolarisPorts.new(inspec)
|
49
|
+
elsif os.hpux?
|
50
|
+
@port_manager = HpuxPorts.new(inspec)
|
50
51
|
else
|
51
52
|
return skip_resource 'The `port` resource is not supported on your OS yet.'
|
52
53
|
end
|
@@ -292,7 +293,6 @@ module Inspec::Resources
|
|
292
293
|
# parse each line
|
293
294
|
# 1 - Proto, 2 - Recv-Q, 3 - Send-Q, 4 - Local Address, 5 - Foreign Address, 6 - State, 7 - Inode, 8 - PID/Program name
|
294
295
|
parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)?\s+(\S+)\s+(\S+)\s+(\S+)/.match(line)
|
295
|
-
|
296
296
|
return {} if parsed.nil? || line.match(/^proto/i)
|
297
297
|
|
298
298
|
# parse ip4 and ip6 addresses
|
@@ -408,7 +408,7 @@ module Inspec::Resources
|
|
408
408
|
# parse the content
|
409
409
|
netstat_ports = parse_netstat(cmd.stdout)
|
410
410
|
|
411
|
-
# filter all ports, where we listen
|
411
|
+
# filter all ports, where we `listen`
|
412
412
|
listen = netstat_ports.select { |val|
|
413
413
|
!val['state'].nil? && 'listen'.casecmp(val['state']) == 0
|
414
414
|
}
|
@@ -433,4 +433,48 @@ module Inspec::Resources
|
|
433
433
|
ports
|
434
434
|
end
|
435
435
|
end
|
436
|
+
|
437
|
+
# extracts information from netstat for hpux
|
438
|
+
class HpuxPorts < FreeBsdPorts
|
439
|
+
def info
|
440
|
+
## Can't use 'netstat -an -f inet -f inet6' as the latter -f option overrides the former one and return only inet ports
|
441
|
+
cmd1 = inspec.command('netstat -an -f inet')
|
442
|
+
return nil if cmd1.exit_status.to_i != 0
|
443
|
+
cmd2 = inspec.command('netstat -an -f inet6')
|
444
|
+
return nil if cmd2.exit_status.to_i != 0
|
445
|
+
cmd = cmd1.stdout + cmd2.stdout
|
446
|
+
ports = []
|
447
|
+
# parse all lines
|
448
|
+
cmd.each_line do |line|
|
449
|
+
port_info = parse_netstat_line(line)
|
450
|
+
next unless %w{tcp tcp6 udp udp6}.include?(port_info[:protocol])
|
451
|
+
ports.push(port_info)
|
452
|
+
end
|
453
|
+
# select all ports, where we `listen`
|
454
|
+
ports.select { |val| val if 'listen'.casecmp(val[:state]) == 0 }
|
455
|
+
end
|
456
|
+
|
457
|
+
def parse_netstat_line(line)
|
458
|
+
# parse each line
|
459
|
+
# 1 - Proto, 2 - Recv-Q, 3 - Send-Q, 4 - Local Address, 5 - Foreign Address, 6 - (state)
|
460
|
+
parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)?/.match(line)
|
461
|
+
|
462
|
+
return {} if parsed.nil? || line.match(/^proto/i) || line.match(/^active/i)
|
463
|
+
protocol = parsed[1].downcase
|
464
|
+
state = parsed[6].nil?? ' ' : parsed[6].downcase
|
465
|
+
local_addr = parsed[4]
|
466
|
+
local_addr[local_addr.rindex('.')] = ':'
|
467
|
+
# extract host and port information
|
468
|
+
host, port = parse_net_address(local_addr, protocol)
|
469
|
+
# map data
|
470
|
+
{
|
471
|
+
port: port,
|
472
|
+
address: host,
|
473
|
+
protocol: protocol,
|
474
|
+
state: state,
|
475
|
+
process: nil,
|
476
|
+
pid: nil,
|
477
|
+
}
|
478
|
+
end
|
479
|
+
end
|
436
480
|
end
|
data/lib/resources/processes.rb
CHANGED
data/lib/resources/service.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
# author: Dominik Richter
|
4
4
|
# author: Stephan Renatus
|
5
5
|
# license: All rights reserved
|
6
|
+
require 'hashie'
|
6
7
|
|
7
8
|
module Inspec::Resources
|
8
9
|
class Runlevels < Hash
|
@@ -67,7 +68,7 @@ module Inspec::Resources
|
|
67
68
|
# Ubuntu < 15.04 : upstart
|
68
69
|
#
|
69
70
|
# TODO: extend the logic to detect the running init system, independently of OS
|
70
|
-
class Service < Inspec.resource(1)
|
71
|
+
class Service < Inspec.resource(1) # rubocop:disable ClassLength
|
71
72
|
name 'service'
|
72
73
|
desc 'Use the service InSpec audit resource to test if the named service is installed, running and/or enabled.'
|
73
74
|
example "
|
@@ -75,11 +76,16 @@ module Inspec::Resources
|
|
75
76
|
it { should be_installed }
|
76
77
|
it { should be_enabled }
|
77
78
|
it { should be_running }
|
79
|
+
its('type') { should be 'systemd' }
|
78
80
|
end
|
79
81
|
|
80
82
|
describe service('service_name').runlevels(3, 5) do
|
81
83
|
it { should be_enabled }
|
82
84
|
end
|
85
|
+
|
86
|
+
describe service('service_name').params do
|
87
|
+
its('UnitFileState') { should eq 'enabled' }
|
88
|
+
end
|
83
89
|
"
|
84
90
|
|
85
91
|
attr_reader :service_ctl
|
@@ -163,6 +169,11 @@ module Inspec::Resources
|
|
163
169
|
info[:enabled]
|
164
170
|
end
|
165
171
|
|
172
|
+
def params
|
173
|
+
return {} if info.nil?
|
174
|
+
Hashie::Mash.new(info[:params] || {})
|
175
|
+
end
|
176
|
+
|
166
177
|
# verifies the service is registered
|
167
178
|
def installed?(_name = nil, _version = nil)
|
168
179
|
return false if info.nil?
|
@@ -181,9 +192,29 @@ module Inspec::Resources
|
|
181
192
|
Runlevels.from_hash(self, info[:runlevels], args)
|
182
193
|
end
|
183
194
|
|
195
|
+
# returns the service type from info
|
196
|
+
def type
|
197
|
+
return nil if info.nil?
|
198
|
+
info[:type]
|
199
|
+
end
|
200
|
+
|
201
|
+
# returns the service name from info
|
202
|
+
def name
|
203
|
+
return @service_name if info.nil?
|
204
|
+
info[:name]
|
205
|
+
end
|
206
|
+
|
207
|
+
# returns the service description from info
|
208
|
+
def description
|
209
|
+
return nil if info.nil?
|
210
|
+
info[:description]
|
211
|
+
end
|
212
|
+
|
184
213
|
def to_s
|
185
214
|
"Service #{@service_name}"
|
186
215
|
end
|
216
|
+
|
217
|
+
private :info
|
187
218
|
end
|
188
219
|
|
189
220
|
class ServiceManager
|
@@ -229,6 +260,7 @@ module Inspec::Resources
|
|
229
260
|
running: running,
|
230
261
|
enabled: enabled,
|
231
262
|
type: 'systemd',
|
263
|
+
params: params,
|
232
264
|
}
|
233
265
|
end
|
234
266
|
end
|
data/lib/resources/user.rb
CHANGED
@@ -6,15 +6,15 @@
|
|
6
6
|
#
|
7
7
|
# describe user('root') do
|
8
8
|
# it { should exist }
|
9
|
-
# its(
|
10
|
-
# its(
|
11
|
-
# its(
|
12
|
-
# its(
|
13
|
-
# its(
|
14
|
-
# its(
|
15
|
-
# its(
|
16
|
-
# its(
|
17
|
-
# its(
|
9
|
+
# its('uid') { should eq 0 }
|
10
|
+
# its('gid') { should eq 0 }
|
11
|
+
# its('group') { should eq 'root' }
|
12
|
+
# its('groups') { should eq ['root', 'wheel']}
|
13
|
+
# its('home') { should eq '/root' }
|
14
|
+
# its('shell') { should eq '/bin/bash' }
|
15
|
+
# its('mindays') { should eq 0 }
|
16
|
+
# its('maxdays') { should eq 99 }
|
17
|
+
# its('warndays') { should eq 5 }
|
18
18
|
# end
|
19
19
|
#
|
20
20
|
# The following Serverspec matchers are deprecated in favor for direct value access
|
@@ -24,8 +24,8 @@
|
|
24
24
|
# it { should have_uid 0 }
|
25
25
|
# it { should have_home_directory '/root' }
|
26
26
|
# it { should have_login_shell '/bin/bash' }
|
27
|
-
# its(
|
28
|
-
# its(
|
27
|
+
# its('minimum_days_between_password_change') { should eq 0 }
|
28
|
+
# its('maximum_days_between_password_change') { should eq 99 }
|
29
29
|
# end
|
30
30
|
|
31
31
|
# ServerSpec tests that are not supported:
|
@@ -119,13 +119,13 @@ module Inspec::Resources
|
|
119
119
|
|
120
120
|
# implement 'mindays' method to be compatible with serverspec
|
121
121
|
def minimum_days_between_password_change
|
122
|
-
deprecated('minimum_days_between_password_change', "Please use
|
122
|
+
deprecated('minimum_days_between_password_change', "Please use: its('mindays')")
|
123
123
|
mindays
|
124
124
|
end
|
125
125
|
|
126
126
|
# implement 'maxdays' method to be compatible with serverspec
|
127
127
|
def maximum_days_between_password_change
|
128
|
-
deprecated('maximum_days_between_password_change', "Please use
|
128
|
+
deprecated('maximum_days_between_password_change', "Please use: its('maxdays')")
|
129
129
|
maxdays
|
130
130
|
end
|
131
131
|
|
@@ -137,12 +137,12 @@ module Inspec::Resources
|
|
137
137
|
end
|
138
138
|
|
139
139
|
def has_home_directory?(compare_home)
|
140
|
-
deprecated('has_home_directory?', "Please use
|
140
|
+
deprecated('has_home_directory?', "Please use: its('home')")
|
141
141
|
home == compare_home
|
142
142
|
end
|
143
143
|
|
144
144
|
def has_login_shell?(compare_shell)
|
145
|
-
deprecated('has_login_shell?', "Please use
|
145
|
+
deprecated('has_login_shell?', "Please use: its('shell')")
|
146
146
|
shell == compare_shell
|
147
147
|
end
|
148
148
|
|
data/lib/utils/base_cli.rb
CHANGED
@@ -45,8 +45,6 @@ module Inspec
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def self.exec_options
|
48
|
-
option :id, type: :string,
|
49
|
-
desc: 'Attach a profile ID to all test results'
|
50
48
|
target_options
|
51
49
|
profile_options
|
52
50
|
option :controls, type: :array,
|
@@ -68,7 +66,7 @@ module Inspec
|
|
68
66
|
runner = Inspec::Runner.new(o)
|
69
67
|
targets.each { |target| runner.add_target(target, opts) }
|
70
68
|
exit runner.run
|
71
|
-
rescue RuntimeError => e
|
69
|
+
rescue RuntimeError, Train::UserError => e
|
72
70
|
$stderr.puts e.message
|
73
71
|
exit 1
|
74
72
|
end
|
data/lib/utils/filter.rb
CHANGED
@@ -95,15 +95,38 @@ module FilterTable
|
|
95
95
|
|
96
96
|
private
|
97
97
|
|
98
|
+
def matches_float(x, y)
|
99
|
+
return false if x.nil?
|
100
|
+
return false if !x.is_a?(Float) && (x =~ /\A[-+]?(\d+\.?\d*|\.\d+)\z/).nil?
|
101
|
+
x.to_f == y
|
102
|
+
end
|
103
|
+
|
104
|
+
def matches_int(x, y)
|
105
|
+
return false if x.nil?
|
106
|
+
return false if !x.is_a?(Integer) && (x =~ /\A[-+]?\d+\z/).nil?
|
107
|
+
x.to_i == y
|
108
|
+
end
|
109
|
+
|
110
|
+
def matches_regex(x, y)
|
111
|
+
return x == y if x.is_a?(Regexp)
|
112
|
+
!x.to_s.match(y).nil?
|
113
|
+
end
|
114
|
+
|
115
|
+
def matches(x, y)
|
116
|
+
x === y # rubocop:disable Style/CaseEquality
|
117
|
+
end
|
118
|
+
|
98
119
|
def filter_lines(table, field, condition)
|
120
|
+
m = case condition
|
121
|
+
when Float then method(:matches_float)
|
122
|
+
when Integer then method(:matches_int)
|
123
|
+
when Regexp then method(:matches_regex)
|
124
|
+
else method(:matches)
|
125
|
+
end
|
126
|
+
|
99
127
|
table.find_all do |line|
|
100
128
|
next unless line.key?(field)
|
101
|
-
|
102
|
-
when condition
|
103
|
-
true
|
104
|
-
else
|
105
|
-
false
|
106
|
-
end
|
129
|
+
m.call(line[field], condition)
|
107
130
|
end
|
108
131
|
end
|
109
132
|
end
|
@@ -134,7 +157,7 @@ module FilterTable
|
|
134
157
|
fields.each do |method, field_name|
|
135
158
|
block = blocks[method]
|
136
159
|
define_method method.to_sym do |condition = Show, &cond_block|
|
137
|
-
return block.call(self) unless block.nil?
|
160
|
+
return block.call(self, condition) unless block.nil?
|
138
161
|
return where(nil).get_fields(field_name) if condition == Show && !block_given?
|
139
162
|
where({ field_name => condition }, &cond_block)
|
140
163
|
end
|
data/test/functional/helper.rb
CHANGED
@@ -20,6 +20,7 @@ module FunctionalHelper
|
|
20
20
|
let(:examples_path) { File.join(repo_path, 'examples') }
|
21
21
|
|
22
22
|
let(:example_profile) { File.join(examples_path, 'profile') }
|
23
|
+
let(:example_control) { File.join(example_profile, 'controls', 'example.rb') }
|
23
24
|
let(:inheritance_profile) { File.join(examples_path, 'profile') }
|
24
25
|
|
25
26
|
let(:dst) {
|
@@ -37,7 +37,8 @@ describe 'inspec compliance' do
|
|
37
37
|
|
38
38
|
it 'inspec compliance profiles without authentication' do
|
39
39
|
out = inspec('compliance profile')
|
40
|
-
out.
|
40
|
+
out.stdout.must_include 'You need to login first with `inspec compliance login`'
|
41
|
+
out.exit_status.must_equal 0
|
41
42
|
end
|
42
43
|
|
43
44
|
it 'try to upload a profile without directory' do
|
@@ -48,8 +49,8 @@ describe 'inspec compliance' do
|
|
48
49
|
|
49
50
|
it 'try to upload a profile a non-existing path' do
|
50
51
|
out = inspec('compliance upload /path/to/dir')
|
51
|
-
out.stdout.must_include '
|
52
|
-
out.exit_status.must_equal
|
52
|
+
out.stdout.must_include 'You need to login first with `inspec compliance login`'
|
53
|
+
out.exit_status.must_equal 0
|
53
54
|
end
|
54
55
|
|
55
56
|
it 'logout' do
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Dominik Richter
|
3
|
+
# author: Christoph Hartmann
|
4
|
+
|
5
|
+
require 'functional/helper'
|
6
|
+
|
7
|
+
describe 'inspec exec with json formatter' do
|
8
|
+
include FunctionalHelper
|
9
|
+
|
10
|
+
it 'can execute a simple file with the json formatter' do
|
11
|
+
out = inspec('exec ' + example_control + ' --format json')
|
12
|
+
out.stderr.must_equal ''
|
13
|
+
out.exit_status.must_equal 0
|
14
|
+
JSON.load(out.stdout).must_be_kind_of Hash
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'can execute the profile with the json formatter' do
|
18
|
+
out = inspec('exec ' + example_profile + ' --format json')
|
19
|
+
out.stderr.must_equal ''
|
20
|
+
out.exit_status.must_equal 0
|
21
|
+
JSON.load(out.stdout).must_be_kind_of Hash
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'execute a profile with json formatting' do
|
25
|
+
let(:json) { JSON.load(inspec('exec ' + example_profile + ' --format json').stdout) }
|
26
|
+
let(:profile) { json['profiles']['profile'] }
|
27
|
+
let(:controls) { profile['controls'] }
|
28
|
+
let(:ex1) { controls['tmp-1.0'] }
|
29
|
+
let(:ex2) {
|
30
|
+
k = controls.keys.find { |x| x =~ /generated/ }
|
31
|
+
controls[k]
|
32
|
+
}
|
33
|
+
let(:ex3) { profile['controls']['gordon-1.0'] }
|
34
|
+
let(:check_result) {
|
35
|
+
ex3['results'].find { |x| x['resource'] == 'gordon_config' }
|
36
|
+
}
|
37
|
+
|
38
|
+
it 'has all the metadata' do
|
39
|
+
actual = profile.dup
|
40
|
+
key = actual.delete('controls').keys
|
41
|
+
.find { |x| x =~ /generated from example.rb/ }
|
42
|
+
|
43
|
+
actual.must_equal({
|
44
|
+
"name" => "profile",
|
45
|
+
"title" => "InSpec Example Profile",
|
46
|
+
"maintainer" => "Chef Software, Inc.",
|
47
|
+
"copyright" => "Chef Software, Inc.",
|
48
|
+
"copyright_email" => "support@chef.io",
|
49
|
+
"license" => "Apache 2 license",
|
50
|
+
"summary" => "Demonstrates the use of InSpec Compliance Profile",
|
51
|
+
"version" => "1.0.0",
|
52
|
+
"supports" => [{"os-family" => "unix"}],
|
53
|
+
"groups" => {
|
54
|
+
"controls/meta.rb" => {"title"=>"SSH Server Configuration", "controls"=>["ssh-1"]},
|
55
|
+
"controls/example.rb" => {"title"=>"/tmp profile", "controls"=>["tmp-1.0", key]},
|
56
|
+
"controls/gordon.rb" => {"title"=>"Gordon Config Checks", "controls"=>["gordon-1.0"]},
|
57
|
+
},
|
58
|
+
})
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'must have 4 controls' do
|
62
|
+
controls.length.must_equal 4
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'has an id for every control' do
|
66
|
+
controls.keys.find(&:nil?).must_be :nil?
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'has no missing checks' do
|
70
|
+
json['other_checks'].must_equal([])
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'has results for every control' do
|
74
|
+
ex1['results'].length.must_equal 1
|
75
|
+
ex2['results'].length.must_equal 1
|
76
|
+
ex3['results'].length.must_equal 2
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'has the right result for tmp-1.0' do
|
80
|
+
actual = ex1.dup
|
81
|
+
|
82
|
+
src = actual.delete('source_location')
|
83
|
+
src[0].must_match %r{examples/profile/controls/example.rb$}
|
84
|
+
src[1].must_equal 8
|
85
|
+
|
86
|
+
result = actual.delete('results')[0]
|
87
|
+
result.wont_be :nil?
|
88
|
+
result['status'].must_equal 'passed'
|
89
|
+
result['code_desc'].must_equal 'File /tmp should be directory'
|
90
|
+
result['run_time'].wont_be :nil?
|
91
|
+
result['start_time'].wont_be :nil?
|
92
|
+
|
93
|
+
actual.must_equal({
|
94
|
+
"title" => "Create /tmp directory",
|
95
|
+
"desc" => "An optional description...",
|
96
|
+
"impact" => 0.7,
|
97
|
+
"refs" => [
|
98
|
+
{
|
99
|
+
"url" => "http://...",
|
100
|
+
"ref" => "Document A-12"
|
101
|
+
}
|
102
|
+
],
|
103
|
+
"tags" => {
|
104
|
+
"data" => "temp data",
|
105
|
+
"security" => nil
|
106
|
+
},
|
107
|
+
"code" => "control \"tmp-1.0\" do # A unique ID for this control\n impact 0.7 # The criticality, if this control fails.\n title \"Create /tmp directory\" # A human-readable title\n desc \"An optional description...\" # Describe why this is needed\n tag data: \"temp data\" # A tag allows you to associate key information\n tag \"security\" # to the test\n ref \"Document A-12\", url: 'http://...' # Additional references\n\n describe file('/tmp') do # The actual test\n it { should be_directory }\n end\nend\n",
|
108
|
+
})
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe 'with a profile that is not supported on this OS/platform' do
|
113
|
+
let(:out) { inspec('exec ' + File.join(profile_path, 'skippy-profile-os') + ' --format json') }
|
114
|
+
let(:json) { JSON.load(out.stdout) }
|
115
|
+
|
116
|
+
# TODO: failure handling in json formatters...
|
117
|
+
|
118
|
+
it 'never runs the actual resource' do
|
119
|
+
File.exist?('/tmp/inspec_test_DONT_CREATE').must_equal false
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|