inspec 4.16.0 → 4.17.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/inspec.rb +0 -1
- data/lib/inspec/backend.rb +7 -0
- data/lib/inspec/base_cli.rb +2 -0
- data/lib/inspec/cli.rb +3 -10
- data/lib/inspec/config.rb +3 -4
- data/lib/inspec/control_eval_context.rb +5 -3
- data/lib/inspec/dsl.rb +24 -1
- data/lib/inspec/errors.rb +0 -26
- data/lib/inspec/file_provider.rb +33 -43
- data/lib/inspec/formatters/base.rb +1 -0
- data/lib/inspec/impact.rb +2 -0
- data/lib/inspec/input.rb +410 -0
- data/lib/inspec/input_registry.rb +10 -1
- data/lib/inspec/objects.rb +3 -1
- data/lib/inspec/objects/input.rb +5 -387
- data/lib/inspec/objects/tag.rb +1 -1
- data/lib/inspec/plugin/v1/plugin_types/resource.rb +16 -5
- data/lib/inspec/plugin/v2/activator.rb +4 -8
- data/lib/inspec/plugin/v2/loader.rb +19 -3
- data/lib/inspec/profile.rb +1 -1
- data/lib/inspec/profile_context.rb +1 -1
- data/lib/inspec/reporters/json.rb +70 -88
- data/lib/inspec/resource.rb +1 -0
- data/lib/inspec/resources.rb +9 -2
- data/lib/inspec/resources/aide_conf.rb +4 -0
- data/lib/inspec/resources/apt.rb +19 -19
- data/lib/inspec/resources/etc_fstab.rb +4 -0
- data/lib/inspec/resources/etc_hosts.rb +4 -0
- data/lib/inspec/resources/firewalld.rb +4 -0
- data/lib/inspec/resources/json.rb +10 -3
- data/lib/inspec/resources/mssql_session.rb +1 -1
- data/lib/inspec/resources/platform.rb +18 -13
- data/lib/inspec/resources/postfix_conf.rb +6 -2
- data/lib/inspec/resources/security_identifier.rb +4 -0
- data/lib/inspec/resources/sys_info.rb +65 -4
- data/lib/inspec/resources/user.rb +1 -0
- data/lib/inspec/rule.rb +68 -6
- data/lib/inspec/runner.rb +6 -1
- data/lib/inspec/runner_rspec.rb +1 -0
- data/lib/inspec/shell.rb +8 -1
- data/lib/inspec/utils/pkey_reader.rb +1 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/matchers/matchers.rb +2 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/functional/help_test.rb +23 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/functional/helper.rb +62 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/functional/install_test.rb +368 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/functional/list_test.rb +101 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/functional/search_test.rb +129 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/functional/uninstall_test.rb +63 -0
- data/lib/plugins/inspec-plugin-manager-cli/test/functional/update_test.rb +84 -0
- metadata +11 -3
- data/lib/plugins/inspec-plugin-manager-cli/test/functional/inspec-plugin_test.rb +0 -845
@@ -93,10 +93,17 @@ module Inspec::Resources
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def load_raw_from_command(command)
|
96
|
-
|
97
|
-
raise Inspec::Exceptions::ResourceSkipped, "No output from command: #{command}" if command_output.nil? || command_output.empty?
|
96
|
+
result = inspec.command(command)
|
98
97
|
|
99
|
-
|
98
|
+
return result.stdout unless result.stdout.empty?
|
99
|
+
|
100
|
+
msg = if result.stderr.empty?
|
101
|
+
"No JSON output, STDERR was empty"
|
102
|
+
else
|
103
|
+
"No JSON output, STDERR:\n #{result.stderr}"
|
104
|
+
end
|
105
|
+
|
106
|
+
raise Inspec::Exceptions::ResourceFailed, msg
|
100
107
|
end
|
101
108
|
|
102
109
|
# for resources the subclass JsonConfig, this allows specification of the resource
|
@@ -53,7 +53,7 @@ module Inspec::Resources
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def query(q) # rubocop:disable Metrics/PerceivedComplexity
|
56
|
-
escaped_query = q.gsub(/\\/, '\\\\').gsub(/"/, '
|
56
|
+
escaped_query = q.gsub(/\\/, '\\\\').gsub(/"/, '""').gsub(/\$/, '\\$')
|
57
57
|
# surpress 'x rows affected' in SQLCMD with 'set nocount on;'
|
58
58
|
cmd_string = "sqlcmd -Q \"set nocount on; #{escaped_query}\" -W -w 1024 -s ','"
|
59
59
|
cmd_string += " -U '#{@user}' -P '#{@password}'" unless @user.nil? || @password.nil?
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "inspec/resource"
|
2
|
+
|
1
3
|
module Inspec::Resources
|
2
4
|
class PlatformResource < Inspec.resource(1)
|
3
5
|
name "platform"
|
@@ -67,19 +69,22 @@ module Inspec::Resources
|
|
67
69
|
return true if supports.nil? || supports.empty?
|
68
70
|
|
69
71
|
status = true
|
70
|
-
supports.each do |
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
72
|
+
supports.each do |support|
|
73
|
+
support.each do |k, v|
|
74
|
+
status =
|
75
|
+
case k
|
76
|
+
when :os_family, :"os-family", :platform_family, :"platform-family" then
|
77
|
+
in_family?(v)
|
78
|
+
when :os, :platform then
|
79
|
+
platform?(v)
|
80
|
+
when :os_name, :"os-name", :platform_name, :"platform-name" then
|
81
|
+
name == v
|
82
|
+
when :release then
|
83
|
+
check_release(v)
|
84
|
+
else
|
85
|
+
false
|
86
|
+
end
|
87
|
+
|
83
88
|
break if status == false
|
84
89
|
end
|
85
90
|
return true if status == true
|
@@ -11,7 +11,7 @@ module Inspec::Resources
|
|
11
11
|
def initialize(*opts)
|
12
12
|
@params = {}
|
13
13
|
if opts.length == 1
|
14
|
-
@raw_content = load_raw_content(opts)
|
14
|
+
@raw_content = load_raw_content(opts[0])
|
15
15
|
else
|
16
16
|
@raw_content = load_raw_content("/etc/postfix/main.cf")
|
17
17
|
end
|
@@ -22,10 +22,14 @@ module Inspec::Resources
|
|
22
22
|
SimpleConfig.new(content).params
|
23
23
|
end
|
24
24
|
|
25
|
+
def to_s
|
26
|
+
"Postfix Mail Transfer Agent"
|
27
|
+
end
|
28
|
+
|
25
29
|
private
|
26
30
|
|
27
31
|
def resource_base_name
|
28
|
-
"
|
32
|
+
"Postfix Config"
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
@@ -13,20 +13,77 @@ module Inspec::Resources
|
|
13
13
|
describe sys_info do
|
14
14
|
its('hostname') { should eq 'example.com' }
|
15
15
|
end
|
16
|
+
|
17
|
+
describe sys_info do
|
18
|
+
its('fqdn') { should eq 'user.example.com' }
|
19
|
+
end
|
20
|
+
|
16
21
|
EXAMPLE
|
17
22
|
|
23
|
+
%w{ domain fqdn ip_address short }.each do |opt|
|
24
|
+
define_method(opt.to_sym) do
|
25
|
+
hostname(opt)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
18
29
|
# returns the hostname of the local system
|
19
|
-
def hostname
|
30
|
+
def hostname(opt = nil)
|
20
31
|
os = inspec.os
|
21
|
-
if os.linux?
|
22
|
-
|
32
|
+
if os.linux?
|
33
|
+
linux_hostname(opt)
|
34
|
+
elsif os.darwin?
|
35
|
+
mac_hostname(opt)
|
23
36
|
elsif os.windows?
|
24
|
-
|
37
|
+
if !opt.nil?
|
38
|
+
skip_resource "The `sys_info.hostname` resource is not supported with that option on your OS."
|
39
|
+
else
|
40
|
+
inspec.powershell("$env:computername").stdout.chomp
|
41
|
+
end
|
25
42
|
else
|
26
43
|
skip_resource "The `sys_info.hostname` resource is not supported on your OS yet."
|
27
44
|
end
|
28
45
|
end
|
29
46
|
|
47
|
+
def linux_hostname(opt = nil)
|
48
|
+
if !opt.nil?
|
49
|
+
opt = case opt
|
50
|
+
when "f", "long", "fqdn", "full"
|
51
|
+
" -f"
|
52
|
+
when "d", "domain"
|
53
|
+
" -d"
|
54
|
+
when "i", "ip_address"
|
55
|
+
" -I"
|
56
|
+
when "s", "short"
|
57
|
+
" -s"
|
58
|
+
else
|
59
|
+
"ERROR"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
if opt == "ERROR"
|
63
|
+
skip_resource "The `sys_info.hostname` resource is not supported with that option on your OS."
|
64
|
+
else
|
65
|
+
inspec.command("hostname#{opt}").stdout.chomp
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def mac_hostname(opt = nil)
|
70
|
+
if !opt.nil?
|
71
|
+
opt = case opt
|
72
|
+
when "f", "long", "fqdn", "full"
|
73
|
+
" -f"
|
74
|
+
when "s", "short"
|
75
|
+
" -s"
|
76
|
+
else
|
77
|
+
"ERROR"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
if opt == "ERROR"
|
81
|
+
skip_resource "The `sys_info.hostname` resource is not supported with that option on your OS."
|
82
|
+
else
|
83
|
+
inspec.command("hostname#{opt}").stdout.chomp
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
30
87
|
# returns the Manufacturer of the local system
|
31
88
|
def manufacturer
|
32
89
|
os = inspec.os
|
@@ -54,5 +111,9 @@ module Inspec::Resources
|
|
54
111
|
skip_resource "The `sys_info.model` resource is not supported on your OS yet."
|
55
112
|
end
|
56
113
|
end
|
114
|
+
|
115
|
+
def to_s
|
116
|
+
"System Information"
|
117
|
+
end
|
57
118
|
end
|
58
119
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "inspec/resources/users"
|
data/lib/inspec/rule.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
# copyright: 2015, Dominik Richter
|
2
2
|
|
3
3
|
require "method_source"
|
4
|
+
require "date"
|
4
5
|
require "inspec/describe"
|
5
6
|
require "inspec/expect"
|
6
7
|
require "inspec/resource"
|
7
8
|
require "inspec/resources/os"
|
9
|
+
require "inspec/input_registry"
|
8
10
|
|
9
11
|
module Inspec
|
10
12
|
class Rule
|
@@ -28,6 +30,7 @@ module Inspec
|
|
28
30
|
@resource_dsl
|
29
31
|
end
|
30
32
|
|
33
|
+
attr_reader :__waiver_data
|
31
34
|
def initialize(id, profile_id, opts, &block)
|
32
35
|
@impact = nil
|
33
36
|
@title = nil
|
@@ -42,7 +45,7 @@ module Inspec
|
|
42
45
|
@__rule_id = id
|
43
46
|
@__profile_id = profile_id
|
44
47
|
@__checks = []
|
45
|
-
@__skip_rule = {}
|
48
|
+
@__skip_rule = {} # { result: true, message: "Why", type: [:only_if, :waiver] }
|
46
49
|
@__merge_count = 0
|
47
50
|
@__merge_changes = []
|
48
51
|
@__skip_only_if_eval = opts[:skip_only_if_eval]
|
@@ -52,6 +55,11 @@ module Inspec
|
|
52
55
|
|
53
56
|
begin
|
54
57
|
instance_eval(&block)
|
58
|
+
|
59
|
+
# By applying waivers *after* the instance eval, we assure that
|
60
|
+
# waivers have higher precedence than only_if.
|
61
|
+
__apply_waivers
|
62
|
+
|
55
63
|
rescue StandardError => e
|
56
64
|
# We've encountered an exception while trying to eval the code inside the
|
57
65
|
# control block. We need to prevent the exception from bubbling up, and
|
@@ -141,6 +149,7 @@ module Inspec
|
|
141
149
|
return if @__skip_only_if_eval == true
|
142
150
|
|
143
151
|
@__skip_rule[:result] ||= !yield
|
152
|
+
@__skip_rule[:type] = :only_if
|
144
153
|
@__skip_rule[:message] = message
|
145
154
|
end
|
146
155
|
|
@@ -193,9 +202,9 @@ module Inspec
|
|
193
202
|
rule.instance_variable_get(:@__skip_rule)
|
194
203
|
end
|
195
204
|
|
196
|
-
def self.set_skip_rule(rule, value, message = nil)
|
205
|
+
def self.set_skip_rule(rule, value, message = nil, type = :only_if)
|
197
206
|
rule.instance_variable_set(:@__skip_rule,
|
198
|
-
{ result: value, message: message })
|
207
|
+
{ result: value, message: message, type: type })
|
199
208
|
end
|
200
209
|
|
201
210
|
def self.merge_count(rule)
|
@@ -206,14 +215,16 @@ module Inspec
|
|
206
215
|
rule.instance_variable_get(:@__merge_changes)
|
207
216
|
end
|
208
217
|
|
218
|
+
# If a rule is marked to be skipped, this
|
219
|
+
# creates a dummay array of "checks" with a skip outcome
|
209
220
|
def self.prepare_checks(rule)
|
210
221
|
skip_check = skip_status(rule)
|
211
222
|
return checks(rule) unless skip_check[:result].eql?(true)
|
212
223
|
|
213
224
|
if skip_check[:message]
|
214
|
-
msg = "Skipped control due to
|
225
|
+
msg = "Skipped control due to #{skip_check[:type]} condition: #{skip_check[:message]}"
|
215
226
|
else
|
216
|
-
msg = "Skipped control due to
|
227
|
+
msg = "Skipped control due to #{skip_check[:type]} condition."
|
217
228
|
end
|
218
229
|
|
219
230
|
# TODO: we use os as the carrier here, but should consider
|
@@ -251,7 +262,8 @@ module Inspec
|
|
251
262
|
skip_check = skip_status(src)
|
252
263
|
sr = skip_check[:result]
|
253
264
|
msg = skip_check[:message]
|
254
|
-
|
265
|
+
skip_type = skip_check[:type]
|
266
|
+
set_skip_rule(dst, sr, msg, skip_type) unless sr.nil?
|
255
267
|
|
256
268
|
# Save merge history
|
257
269
|
dst.instance_variable_set(:@__merge_count, merge_count(dst) + 1)
|
@@ -267,6 +279,56 @@ module Inspec
|
|
267
279
|
@__checks.push([describe_or_expect, values, block])
|
268
280
|
end
|
269
281
|
|
282
|
+
# Look for an input with a matching ID, and if found, apply waiver
|
283
|
+
# skipping logic. Basically, if we have a current waiver, and it says
|
284
|
+
# to skip, we'll replace all the checks with a dummy check (same as
|
285
|
+
# only_if mechanism)
|
286
|
+
# Double underscore: not intended to be called as part of the DSL
|
287
|
+
def __apply_waivers
|
288
|
+
input_name = @__rule_id # TODO: control ID slugging
|
289
|
+
registry = Inspec::InputRegistry.instance
|
290
|
+
input = registry.inputs_by_profile.dig(@__profile_id, input_name)
|
291
|
+
return unless input
|
292
|
+
|
293
|
+
# An InSpec Input is a datastructure that tracks a profile parameter
|
294
|
+
# over time. Its value can be set by many sources, and it keeps a
|
295
|
+
# log of each "set" event so that when it is collapsed to a value,
|
296
|
+
# it can determine the correct (highest priority) value.
|
297
|
+
# Store in an instance variable for.. later reading???
|
298
|
+
@__waiver_data = input.value
|
299
|
+
__waiver_data["skipped_due_to_waiver"] = false
|
300
|
+
__waiver_data["message"] = ""
|
301
|
+
|
302
|
+
# Waivers should have a hash value with keys possibly including skip and
|
303
|
+
# expiration_date. We only care here if it has a skip key and it
|
304
|
+
# is yes-like, since all non-skipped waiver operations are handled
|
305
|
+
# during reporting phase.
|
306
|
+
return unless __waiver_data.key?("skip") && __waiver_data["skip"]
|
307
|
+
|
308
|
+
# OK, the intent is to skip. Does it have an expiration date, and
|
309
|
+
# if so, is it in the future?
|
310
|
+
expiry = __waiver_data["expiration_date"]
|
311
|
+
if expiry
|
312
|
+
if expiry.is_a?(Date)
|
313
|
+
# It appears that yaml.rb automagically parses dates for us
|
314
|
+
if expiry < Date.today # If the waiver expired, return - no skip applied
|
315
|
+
__waiver_data["message"] = "Waiver expired on #{expiry}, evaluating control normally"
|
316
|
+
return
|
317
|
+
end
|
318
|
+
else
|
319
|
+
ui = Inspec::UI.new
|
320
|
+
ui.error("Unable to parse waiver expiration date '#{expiry}' for control #{@__rule_id}")
|
321
|
+
ui.exit(:usage_error)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# OK, apply a skip.
|
326
|
+
@__skip_rule[:result] = true
|
327
|
+
@__skip_rule[:type] = :waiver
|
328
|
+
@__skip_rule[:message] = __waiver_data["justification"]
|
329
|
+
__waiver_data["skipped_due_to_waiver"] = true
|
330
|
+
end
|
331
|
+
|
270
332
|
#
|
271
333
|
# Takes a block and returns a block that will run the given block
|
272
334
|
# with access to the resource_dsl of the current class. This is to
|
data/lib/inspec/runner.rb
CHANGED
@@ -9,7 +9,6 @@ require "inspec/metadata"
|
|
9
9
|
require "inspec/config"
|
10
10
|
require "inspec/dependencies/cache"
|
11
11
|
require "inspec/dist"
|
12
|
-
require "inspec/resources"
|
13
12
|
require "inspec/reporters"
|
14
13
|
require "inspec/runner_rspec"
|
15
14
|
# spec requirements
|
@@ -57,6 +56,12 @@ module Inspec
|
|
57
56
|
RunnerRspec.new(@conf)
|
58
57
|
end
|
59
58
|
|
59
|
+
if @conf[:waiver_file]
|
60
|
+
waivers = @conf.delete(:waiver_file)
|
61
|
+
@conf[:input_file] ||= []
|
62
|
+
@conf[:input_file].concat waivers
|
63
|
+
end
|
64
|
+
|
60
65
|
# About reading inputs:
|
61
66
|
# @conf gets passed around a lot, eventually to
|
62
67
|
# Inspec::InputRegistry.register_external_inputs.
|
data/lib/inspec/runner_rspec.rb
CHANGED
@@ -171,6 +171,7 @@ module Inspec
|
|
171
171
|
metadata[:descriptions] = rule.descriptions
|
172
172
|
metadata[:code] = rule.instance_variable_get(:@__code)
|
173
173
|
metadata[:source_location] = rule.instance_variable_get(:@__source_location)
|
174
|
+
metadata[:waiver_data] = rule.__waiver_data
|
174
175
|
end
|
175
176
|
end
|
176
177
|
end
|
data/lib/inspec/shell.rb
CHANGED
@@ -112,6 +112,7 @@ module Inspec
|
|
112
112
|
#{print_target_info}
|
113
113
|
EOF
|
114
114
|
elsif topic == "resources"
|
115
|
+
require "inspec/resources"
|
115
116
|
resources.sort.each do |resource|
|
116
117
|
puts " - #{resource}"
|
117
118
|
end
|
@@ -134,7 +135,13 @@ module Inspec
|
|
134
135
|
info += "https://www.inspec.io/docs/reference/resources/#{topic}\n\n"
|
135
136
|
puts info
|
136
137
|
else
|
137
|
-
|
138
|
+
begin
|
139
|
+
require "inspec/resources/#{topic}"
|
140
|
+
help topic
|
141
|
+
rescue LoadError
|
142
|
+
# TODO: stderr!
|
143
|
+
puts "The resource #{topic} does not exist. For a list of valid resources, type: help resources"
|
144
|
+
end
|
138
145
|
end
|
139
146
|
end
|
140
147
|
|
data/lib/inspec/version.rb
CHANGED