inspec 0.32.0 → 0.33.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 +46 -2
- data/Gemfile +2 -1
- data/README.md +1 -1
- data/docs/dsl_inspec.rst +21 -0
- data/docs/resources.rst +3 -3
- data/docs/ruby_usage.rst +1 -1
- data/inspec.gemspec +1 -1
- data/lib/bundles/inspec-compliance/http.rb +2 -0
- data/lib/inspec/base_cli.rb +1 -1
- data/lib/inspec/control_eval_context.rb +145 -0
- data/lib/inspec/dependencies/dependency_set.rb +21 -6
- data/lib/inspec/dependencies/requirement.rb +13 -6
- data/lib/inspec/dependencies/resolver.rb +2 -2
- data/lib/inspec/dsl.rb +3 -32
- data/lib/inspec/dsl_shared.rb +25 -0
- data/lib/inspec/library_eval_context.rb +47 -0
- data/lib/inspec/plugins/resource.rb +63 -63
- data/lib/inspec/profile.rb +61 -31
- data/lib/inspec/profile_context.rb +48 -140
- data/lib/inspec/resource.rb +13 -7
- data/lib/inspec/rspec_json_formatter.rb +37 -6
- data/lib/inspec/rule.rb +4 -0
- data/lib/inspec/runner.rb +86 -86
- data/lib/inspec/version.rb +1 -1
- data/lib/matchers/matchers.rb +1 -1
- data/lib/resources/apache_conf.rb +1 -1
- data/lib/resources/mysql.rb +1 -1
- data/lib/resources/powershell.rb +3 -7
- data/lib/resources/service.rb +3 -3
- data/lib/resources/vbscript.rb +17 -1
- metadata +7 -4
@@ -23,9 +23,9 @@ module Inspec
|
|
23
23
|
# implementation of the fetcher being used.
|
24
24
|
#
|
25
25
|
class Resolver
|
26
|
-
def self.resolve(dependencies, vendor_index, working_dir)
|
26
|
+
def self.resolve(dependencies, vendor_index, working_dir, backend)
|
27
27
|
reqs = dependencies.map do |dep|
|
28
|
-
req = Inspec::Requirement.from_metadata(dep, vendor_index, cwd: working_dir)
|
28
|
+
req = Inspec::Requirement.from_metadata(dep, vendor_index, cwd: working_dir, backend: backend)
|
29
29
|
req || fail("Cannot initialize dependency: #{req}")
|
30
30
|
end
|
31
31
|
new.resolve(reqs)
|
data/lib/inspec/dsl.rb
CHANGED
@@ -18,19 +18,6 @@ module Inspec::DSL
|
|
18
18
|
alias require_rules require_controls
|
19
19
|
alias include_rules include_controls
|
20
20
|
|
21
|
-
def self.rule_from_check(m, a, b)
|
22
|
-
if a.is_a?(Array) && !a.empty? &&
|
23
|
-
a[0].respond_to?(:resource_skipped) &&
|
24
|
-
!a[0].resource_skipped.nil?
|
25
|
-
::Inspec::Rule.__send__(m, *a) do
|
26
|
-
it a[0].resource_skipped
|
27
|
-
end
|
28
|
-
else
|
29
|
-
# execute the method
|
30
|
-
::Inspec::Rule.__send__(m, *a, &b)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
21
|
def self.load_spec_files_for_profile(bind_context, opts, &block)
|
35
22
|
dependencies = opts[:dependencies]
|
36
23
|
profile_id = opts[:profile_id]
|
@@ -43,25 +30,21 @@ of #{bind_context.profile_name}.
|
|
43
30
|
|
44
31
|
Dependencies available from this context are:
|
45
32
|
|
46
|
-
|
33
|
+
#{dependencies.list.keys.join("\n ")}
|
47
34
|
EOF
|
48
35
|
end
|
49
36
|
|
50
|
-
context =
|
51
|
-
|
37
|
+
context = dep_entry.profile.runner_context
|
52
38
|
# if we don't want all the rules, then just make 1 pass to get all rule_IDs
|
53
39
|
# that we want to keep from the original
|
54
40
|
filter_included_controls(context, dep_entry.profile, &block) if !opts[:include_all]
|
55
|
-
|
56
41
|
# interpret the block and skip/modify as required
|
57
42
|
context.load(block) if block_given?
|
58
|
-
|
59
43
|
bind_context.add_subcontext(context)
|
60
44
|
end
|
61
45
|
|
62
46
|
def self.filter_included_controls(context, profile, &block)
|
63
|
-
|
64
|
-
include_ctx = Inspec::ProfileContext.for_profile(profile, mock)
|
47
|
+
include_ctx = profile.runner_context
|
65
48
|
include_ctx.load(block) if block_given?
|
66
49
|
# remove all rules that were not registered
|
67
50
|
context.rules.keys.each do |id|
|
@@ -70,16 +53,4 @@ EOF
|
|
70
53
|
end
|
71
54
|
end
|
72
55
|
end
|
73
|
-
|
74
|
-
def self.load_profile_context(profile, backend)
|
75
|
-
ctx = Inspec::ProfileContext.for_profile(profile, backend)
|
76
|
-
profile.libraries.each do |path, content|
|
77
|
-
ctx.load(content.to_s, path, 1)
|
78
|
-
ctx.reload_dsl
|
79
|
-
end
|
80
|
-
profile.tests.each do |path, content|
|
81
|
-
ctx.load(content.to_s, path, 1)
|
82
|
-
end
|
83
|
-
ctx
|
84
|
-
end
|
85
56
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Inspec
|
3
|
+
#
|
4
|
+
# Contains methods we would like in multiple DSL
|
5
|
+
#
|
6
|
+
module DSL
|
7
|
+
module RequireOverride
|
8
|
+
# Save the toplevel require method to load all ruby dependencies.
|
9
|
+
# It is used whenever the `require 'lib'` is not in libraries.
|
10
|
+
alias __ruby_require require
|
11
|
+
|
12
|
+
def require(path)
|
13
|
+
rbpath = path + '.rb'
|
14
|
+
return __ruby_require(path) if !@require_loader.exists?(rbpath)
|
15
|
+
return false if @require_loader.loaded?(rbpath)
|
16
|
+
|
17
|
+
# This is equivalent to calling `require 'lib'` with lib on disk.
|
18
|
+
# We cannot rely on libraries residing on disk however.
|
19
|
+
# TODO: Sandboxing.
|
20
|
+
content, path, line = @require_loader.load(rbpath)
|
21
|
+
eval(content, TOPLEVEL_BINDING, path, line) # rubocop:disable Lint/Eval
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Steven Danna
|
3
|
+
# author: Victoria Jeffrey
|
4
|
+
require 'inspec/plugins/resource'
|
5
|
+
require 'inspec/dsl_shared'
|
6
|
+
|
7
|
+
module Inspec
|
8
|
+
#
|
9
|
+
# LibaryEvalContext constructs an instance of an anonymous class
|
10
|
+
# that library files will be instance_exec'd against.
|
11
|
+
#
|
12
|
+
# The anonymous class ensures that `Inspec.resource(1)` will return
|
13
|
+
# an anonymouse class that is suitable as the parent class of an
|
14
|
+
# inspec resource. The class returned will have the resource
|
15
|
+
# registry used by all dsl methods bound to the resource registry
|
16
|
+
# passed into the #create constructor.
|
17
|
+
#
|
18
|
+
#
|
19
|
+
class LibraryEvalContext
|
20
|
+
def self.create(registry, require_loader)
|
21
|
+
c = Class.new do
|
22
|
+
extend Inspec::ResourceDSL
|
23
|
+
include Inspec::ResourceBehaviors
|
24
|
+
define_singleton_method :__resource_registry do
|
25
|
+
registry
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
c2 = Class.new do
|
30
|
+
define_singleton_method :resource do |version|
|
31
|
+
Inspec.validate_resource_dsl_version!(version)
|
32
|
+
c
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
c3 = Class.new do
|
37
|
+
include Inspec::DSL::RequireOverride
|
38
|
+
def initialize(require_loader) # rubocop:disable Lint/NestedMethodDefinition
|
39
|
+
@require_loader = require_loader
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
c3.const_set(:Inspec, c2)
|
44
|
+
c3.new(require_loader)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -3,83 +3,83 @@
|
|
3
3
|
# author: Christoph Hartmann
|
4
4
|
|
5
5
|
module Inspec
|
6
|
-
module
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@name = name
|
11
|
-
Inspec::Plugins::Resource.__register(name, self)
|
12
|
-
end
|
6
|
+
module ResourceBehaviors
|
7
|
+
def to_s
|
8
|
+
@__resource_name__
|
9
|
+
end
|
13
10
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
# Overwrite inspect to provide better output to RSpec results.
|
12
|
+
#
|
13
|
+
# @return [String] full name of the resource
|
14
|
+
def inspect
|
15
|
+
to_s
|
16
|
+
end
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
module ResourceDSL
|
20
|
+
def name(name = nil)
|
21
|
+
return if name.nil?
|
22
|
+
@name = name
|
23
|
+
__register(name, self)
|
24
|
+
end
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
include Inspec::Plugins::ResourceCommon
|
29
|
-
def initialize(backend, name, *args)
|
30
|
-
# attach the backend to this instance
|
31
|
-
@__backend_runner__ = backend
|
32
|
-
@__resource_name__ = name
|
33
|
-
# call the resource initializer
|
34
|
-
super(*args)
|
35
|
-
end
|
26
|
+
def desc(description = nil)
|
27
|
+
return if description.nil?
|
28
|
+
__resource_registry[@name].desc(description)
|
29
|
+
end
|
36
30
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
31
|
+
def example(example = nil)
|
32
|
+
return if example.nil?
|
33
|
+
__resource_registry[@name].example(example)
|
34
|
+
end
|
41
35
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
36
|
+
def __resource_registry
|
37
|
+
Inspec::Resource.registry
|
38
|
+
end
|
46
39
|
|
47
|
-
|
48
|
-
|
49
|
-
|
40
|
+
def __register(name, obj)
|
41
|
+
# rubocop:disable Lint/NestedMethodDefinition
|
42
|
+
cl = Class.new(obj) do
|
43
|
+
def initialize(backend, name, *args)
|
44
|
+
# attach the backend to this instance
|
45
|
+
@__backend_runner__ = backend
|
46
|
+
@__resource_name__ = name
|
47
|
+
# call the resource initializer
|
48
|
+
super(*args)
|
50
49
|
end
|
51
|
-
# rubocop:enable Lint/NestedMethodDefinition
|
52
50
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
51
|
+
def self.desc(description = nil)
|
52
|
+
return @description if description.nil?
|
53
|
+
@description = description
|
54
|
+
end
|
58
55
|
|
59
|
-
|
60
|
-
|
56
|
+
def self.example(example = nil)
|
57
|
+
return @example if example.nil?
|
58
|
+
@example = example
|
59
|
+
end
|
61
60
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
61
|
+
def resource_skipped
|
62
|
+
@resource_skipped
|
63
|
+
end
|
66
64
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
def inspect
|
71
|
-
to_s
|
72
|
-
end
|
73
|
-
end
|
65
|
+
def skip_resource(message)
|
66
|
+
@resource_skipped = message
|
67
|
+
end
|
74
68
|
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
def inspec
|
70
|
+
@__backend_runner__
|
71
|
+
end
|
78
72
|
end
|
79
73
|
|
80
|
-
|
81
|
-
|
82
|
-
|
74
|
+
# rubocop:enable Lint/NestedMethodDefinition
|
75
|
+
__resource_registry[name] = cl
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module Plugins
|
80
|
+
class Resource
|
81
|
+
extend Inspec::ResourceDSL
|
82
|
+
include Inspec::ResourceBehaviors
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
data/lib/inspec/profile.rb
CHANGED
@@ -8,6 +8,9 @@ require 'inspec/polyfill'
|
|
8
8
|
require 'inspec/fetcher'
|
9
9
|
require 'inspec/source_reader'
|
10
10
|
require 'inspec/metadata'
|
11
|
+
require 'inspec/backend'
|
12
|
+
require 'inspec/rule'
|
13
|
+
require 'inspec/profile_context'
|
11
14
|
require 'inspec/dependencies/lockfile'
|
12
15
|
require 'inspec/dependencies/dependency_set'
|
13
16
|
|
@@ -15,9 +18,8 @@ module Inspec
|
|
15
18
|
class Profile # rubocop:disable Metrics/ClassLength
|
16
19
|
extend Forwardable
|
17
20
|
|
18
|
-
def self.resolve_target(target
|
21
|
+
def self.resolve_target(target)
|
19
22
|
# Fetchers retrieve file contents
|
20
|
-
opts[:target] = target
|
21
23
|
fetcher = Inspec::Fetcher.resolve(target)
|
22
24
|
if fetcher.nil?
|
23
25
|
fail("Could not fetch inspec profile in #{target.inspect}.")
|
@@ -32,8 +34,8 @@ module Inspec
|
|
32
34
|
reader
|
33
35
|
end
|
34
36
|
|
35
|
-
def self.for_target(target, opts)
|
36
|
-
new(resolve_target(target, opts
|
37
|
+
def self.for_target(target, opts = {})
|
38
|
+
new(resolve_target(target), opts.merge(target: target))
|
37
39
|
end
|
38
40
|
|
39
41
|
attr_reader :source_reader
|
@@ -48,9 +50,14 @@ module Inspec
|
|
48
50
|
@target = @options.delete(:target)
|
49
51
|
@logger = @options[:logger] || Logger.new(nil)
|
50
52
|
@source_reader = source_reader
|
53
|
+
if options[:dependencies]
|
54
|
+
@locked_dependencies = options[:dependencies]
|
55
|
+
end
|
56
|
+
@controls = options[:controls] || []
|
51
57
|
@profile_id = @options[:id]
|
52
|
-
@
|
58
|
+
@backend = @options[:backend] || Inspec::Backend.create(options)
|
53
59
|
Metadata.finalize(@source_reader.metadata, @profile_id)
|
60
|
+
@runner_context = @options[:profile_context] || Inspec::ProfileContext.for_profile(self, @backend)
|
54
61
|
end
|
55
62
|
|
56
63
|
def name
|
@@ -61,6 +68,46 @@ module Inspec
|
|
61
68
|
@params ||= load_params
|
62
69
|
end
|
63
70
|
|
71
|
+
def collect_tests(include_list = @controls)
|
72
|
+
if !@tests_collected
|
73
|
+
locked_dependencies.each(&:collect_tests)
|
74
|
+
|
75
|
+
tests.each do |path, content|
|
76
|
+
next if content.nil? || content.empty?
|
77
|
+
abs_path = source_reader.target.abs_path(path)
|
78
|
+
@runner_context.load_control_file(content, abs_path, nil)
|
79
|
+
end
|
80
|
+
@tests_collected = true
|
81
|
+
end
|
82
|
+
filter_controls(@runner_context.all_rules, include_list)
|
83
|
+
end
|
84
|
+
|
85
|
+
def filter_controls(controls_array, include_list)
|
86
|
+
return controls_array if include_list.nil? || include_list.empty?
|
87
|
+
controls_array.select do |c|
|
88
|
+
id = ::Inspec::Rule.rule_id(c)
|
89
|
+
include_list.include?(id)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def load_libraries
|
94
|
+
locked_dependencies.each do |d|
|
95
|
+
c = d.load_libraries
|
96
|
+
@runner_context.add_resources(c)
|
97
|
+
end
|
98
|
+
|
99
|
+
libs = libraries.map do |path, content|
|
100
|
+
[content, path]
|
101
|
+
end
|
102
|
+
|
103
|
+
@runner_context.load_libraries(libs)
|
104
|
+
@runner_context
|
105
|
+
end
|
106
|
+
|
107
|
+
def to_s
|
108
|
+
"Inspec::Profile<#{name}>"
|
109
|
+
end
|
110
|
+
|
64
111
|
def info
|
65
112
|
res = params.dup
|
66
113
|
# add information about the controls
|
@@ -249,11 +296,15 @@ module Inspec
|
|
249
296
|
# @return [Inspec::Lockfile]
|
250
297
|
#
|
251
298
|
def generate_lockfile(vendor_path = nil)
|
252
|
-
res = Inspec::DependencySet.new(cwd, vendor_path)
|
299
|
+
res = Inspec::DependencySet.new(cwd, vendor_path, nil, @backend)
|
253
300
|
res.vendor(metadata.dependencies)
|
254
301
|
Inspec::Lockfile.from_dependency_set(res)
|
255
302
|
end
|
256
303
|
|
304
|
+
def load_dependencies
|
305
|
+
Inspec::DependencySet.from_lockfile(lockfile, cwd, nil, @backend)
|
306
|
+
end
|
307
|
+
|
257
308
|
private
|
258
309
|
|
259
310
|
# Create an archive name for this profile and an additional options
|
@@ -282,34 +333,17 @@ module Inspec
|
|
282
333
|
params
|
283
334
|
end
|
284
335
|
|
285
|
-
#
|
286
|
-
# Returns a new runner for the current profile.
|
287
|
-
#
|
288
|
-
# @params [Symbol] The type of backend to use when constructing a
|
289
|
-
# new runner.
|
290
|
-
# @returns [Inspec::Runner]
|
291
|
-
#
|
292
|
-
def runner_for_profile(backend = :mock)
|
293
|
-
opts = @options.dup
|
294
|
-
opts[:ignore_supports] = true
|
295
|
-
r = Runner.new(id: @profile_id,
|
296
|
-
backend: backend,
|
297
|
-
test_collector: opts.delete(:test_collector))
|
298
|
-
r.add_profile(self, opts)
|
299
|
-
r
|
300
|
-
end
|
301
|
-
|
302
336
|
def load_checks_params(params)
|
337
|
+
load_libraries
|
338
|
+
tests = collect_tests
|
303
339
|
params[:controls] = controls = {}
|
304
340
|
params[:groups] = groups = {}
|
305
341
|
prefix = @source_reader.target.prefix || ''
|
306
|
-
|
307
|
-
runner = @runner_context || runner_for_profile
|
308
|
-
runner.all_rules.each do |rule|
|
342
|
+
tests.each do |rule|
|
309
343
|
f = load_rule_filepath(prefix, rule)
|
310
344
|
load_rule(rule, f, controls, groups)
|
311
345
|
end
|
312
|
-
params[:attributes] =
|
346
|
+
params[:attributes] = @runner_context.attributes
|
313
347
|
params
|
314
348
|
end
|
315
349
|
|
@@ -338,9 +372,5 @@ module Inspec
|
|
338
372
|
}
|
339
373
|
groups[file][:controls].push(id)
|
340
374
|
end
|
341
|
-
|
342
|
-
def load_dependencies
|
343
|
-
Inspec::DependencySet.from_lockfile(lockfile, cwd, nil)
|
344
|
-
end
|
345
375
|
end
|
346
376
|
end
|