inspec 1.48.0 → 1.49.2
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/.rubocop.yml +4 -0
- data/CHANGELOG.md +40 -16
- data/Rakefile +1 -1
- data/docs/resources/bond.md.erb +6 -1
- data/docs/resources/mysql_session.md.erb +24 -12
- data/docs/resources/passwd.md.erb +1 -1
- data/docs/resources/xml.md.erb +7 -2
- data/docs/shell.md +22 -0
- data/inspec.gemspec +1 -1
- data/lib/bundles/inspec-artifact/cli.rb +0 -2
- data/lib/bundles/inspec-compliance/api.rb +58 -3
- data/lib/bundles/inspec-compliance/cli.rb +1 -1
- data/lib/bundles/inspec-habitat/profile.rb +1 -1
- data/lib/fetchers/url.rb +1 -1
- data/lib/inspec/base_cli.rb +3 -1
- data/lib/inspec/cli.rb +11 -1
- data/lib/inspec/control_eval_context.rb +13 -2
- data/lib/inspec/dependencies/lockfile.rb +0 -2
- data/lib/inspec/dsl_shared.rb +8 -0
- data/lib/inspec/library_eval_context.rb +12 -1
- data/lib/inspec/metadata.rb +13 -44
- data/lib/inspec/objects/attribute.rb +1 -1
- data/lib/inspec/plugins/resource.rb +18 -2
- data/lib/inspec/profile.rb +17 -11
- data/lib/inspec/profile_context.rb +9 -3
- data/lib/inspec/profile_vendor.rb +1 -1
- data/lib/inspec/resource.rb +5 -0
- data/lib/inspec/rspec_json_formatter.rb +3 -3
- data/lib/inspec/rule.rb +1 -1
- data/lib/inspec/runner.rb +13 -5
- data/lib/inspec/schema.rb +1 -1
- data/lib/inspec/shell.rb +1 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/aide_conf.rb +0 -2
- data/lib/resources/apache_conf.rb +9 -2
- data/lib/resources/auditd.rb +0 -1
- data/lib/resources/auditd_rules.rb +0 -2
- data/lib/resources/bond.rb +4 -0
- data/lib/resources/crontab.rb +1 -1
- data/lib/resources/docker.rb +1 -1
- data/lib/resources/elasticsearch.rb +1 -1
- data/lib/resources/file.rb +2 -0
- data/lib/resources/groups.rb +29 -5
- data/lib/resources/grub_conf.rb +1 -1
- data/lib/resources/os.rb +8 -20
- data/lib/resources/package.rb +20 -21
- data/lib/resources/platform.rb +112 -0
- data/lib/resources/port.rb +1 -1
- data/lib/resources/processes.rb +1 -1
- data/lib/resources/registry_key.rb +1 -1
- data/lib/resources/service.rb +1 -1
- data/lib/resources/virtualization.rb +1 -1
- data/lib/resources/x509_certificate.rb +1 -1
- data/lib/resources/xml.rb +1 -0
- metadata +5 -10
@@ -13,7 +13,7 @@ module Inspec
|
|
13
13
|
# as the basic DSL of the control files (describe, control, title,
|
14
14
|
# etc).
|
15
15
|
#
|
16
|
-
class ControlEvalContext
|
16
|
+
class ControlEvalContext
|
17
17
|
# Create the context for controls. This includes all components of the DSL,
|
18
18
|
# including matchers and resources.
|
19
19
|
#
|
@@ -117,10 +117,21 @@ module Inspec
|
|
117
117
|
end
|
118
118
|
|
119
119
|
define_method :register_control do |control, &block|
|
120
|
-
if @skip_file
|
120
|
+
if @skip_file
|
121
121
|
::Inspec::Rule.set_skip_rule(control, true)
|
122
122
|
end
|
123
123
|
|
124
|
+
unless profile_context_owner.profile_supports_platform?
|
125
|
+
platform = inspec.platform
|
126
|
+
msg = "Profile #{profile_context_owner.profile_id} is not supported on platform #{platform.name}/#{platform.release}."
|
127
|
+
::Inspec::Rule.set_skip_rule(control, msg)
|
128
|
+
end
|
129
|
+
|
130
|
+
unless profile_context_owner.profile_supports_inspec_version?
|
131
|
+
msg = "Profile #{profile_context_owner.profile_id} is not supported on InSpec version (#{Inspec::VERSION})."
|
132
|
+
::Inspec::Rule.set_skip_rule(control, msg)
|
133
|
+
end
|
134
|
+
|
124
135
|
profile_context_owner.register_rule(control, &block) unless control.nil?
|
125
136
|
end
|
126
137
|
|
@@ -28,7 +28,6 @@ module Inspec
|
|
28
28
|
from_content(content)
|
29
29
|
end
|
30
30
|
|
31
|
-
# rubocop:disable Style/GuardClause
|
32
31
|
def self.validate_lockfile_version!(version)
|
33
32
|
if version < MINIMUM_SUPPORTED_VERSION
|
34
33
|
raise <<~EOF
|
@@ -49,7 +48,6 @@ module Inspec
|
|
49
48
|
EOF
|
50
49
|
end
|
51
50
|
end
|
52
|
-
# rubocop:enable Style/GuardClause
|
53
51
|
|
54
52
|
attr_reader :version, :deps
|
55
53
|
def initialize(lockfile_content_hash)
|
data/lib/inspec/dsl_shared.rb
CHANGED
@@ -18,6 +18,14 @@ module Inspec
|
|
18
18
|
# We cannot rely on libraries residing on disk however.
|
19
19
|
# TODO: Sandboxing.
|
20
20
|
content, path, line = @require_loader.load(rbpath)
|
21
|
+
|
22
|
+
# If we are in the realm of libraries and the LibraryEvalContext
|
23
|
+
# we should have access to the __inspec_binding, which is a Binding
|
24
|
+
# context that provides the correct plane to evaluate all required files to.
|
25
|
+
# It will ensure that embedded calls to `require` still call this
|
26
|
+
# method and get loaded from their correct paths.
|
27
|
+
return __inspec_binding.eval(content, path, line) if defined?(__inspec_binding)
|
28
|
+
|
21
29
|
eval(content, TOPLEVEL_BINDING, path, line) # rubocop:disable Security/Eval
|
22
30
|
end
|
23
31
|
end
|
@@ -37,11 +37,22 @@ module Inspec
|
|
37
37
|
include Inspec::DSL::RequireOverride
|
38
38
|
def initialize(require_loader)
|
39
39
|
@require_loader = require_loader
|
40
|
+
@inspec_binding = nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def __inspec_binding
|
44
|
+
@inspec_binding
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
43
48
|
c3.const_set(:Inspec, c2)
|
44
|
-
c3.new(require_loader)
|
49
|
+
res = c3.new(require_loader)
|
50
|
+
|
51
|
+
# Provide the local binding for this context which is necessary for
|
52
|
+
# calls to `require` to create all dependent objects in the correct
|
53
|
+
# context.
|
54
|
+
res.instance_variable_set('@inspec_binding', res.instance_eval('binding'))
|
55
|
+
res
|
45
56
|
end
|
46
57
|
end
|
47
58
|
end
|
data/lib/inspec/metadata.rb
CHANGED
@@ -14,7 +14,7 @@ module Inspec
|
|
14
14
|
# A Metadata object may be created and finalized with invalid data.
|
15
15
|
# This allows the check CLI command to analyse the issues.
|
16
16
|
# Use valid? to determine if the metadata is coherent.
|
17
|
-
class Metadata
|
17
|
+
class Metadata
|
18
18
|
attr_reader :ref
|
19
19
|
attr_accessor :params, :content
|
20
20
|
def initialize(ref, logger = nil)
|
@@ -36,6 +36,7 @@ module Inspec
|
|
36
36
|
summary
|
37
37
|
description
|
38
38
|
version
|
39
|
+
inspec_version
|
39
40
|
}.each do |name|
|
40
41
|
define_method name.to_sym do |arg|
|
41
42
|
params[name.to_sym] = arg
|
@@ -52,38 +53,16 @@ module Inspec
|
|
52
53
|
# already.
|
53
54
|
end
|
54
55
|
|
55
|
-
def is_supported?(os, entry)
|
56
|
-
name = entry[:'os-name'] || entry[:os]
|
57
|
-
family = entry[:'os-family']
|
58
|
-
release = entry[:release]
|
59
|
-
|
60
|
-
# return true if the backend matches the supported OS's
|
61
|
-
# fields act as masks, i.e. any value configured for os-name, os-family,
|
62
|
-
# or release must be met by the backend; any field that is nil acts as
|
63
|
-
# a glob expression i.e. is true
|
64
|
-
|
65
|
-
# os name is both saved in :family and :name, so check both
|
66
|
-
name_ok = name.nil? ||
|
67
|
-
os[:name] == name || os[:family] == name
|
68
|
-
|
69
|
-
family_check = family.to_s + '?'
|
70
|
-
family_ok = family.nil? || os[:family] == family ||
|
71
|
-
(
|
72
|
-
os.respond_to?(family_check) &&
|
73
|
-
# this call will return true if the family matches
|
74
|
-
os.method(family_check).call
|
75
|
-
)
|
76
|
-
|
77
|
-
# ensure we do have a string if we have a non-nil value eg. 16.06
|
78
|
-
release_ok = release.nil? || os[:release] == release
|
79
|
-
|
80
|
-
# we want to make sure that all matchers are true
|
81
|
-
name_ok && family_ok && release_ok
|
82
|
-
end
|
83
|
-
|
84
56
|
def inspec_requirement
|
85
|
-
|
86
|
-
|
57
|
+
inspec_in_supports = params[:supports].find { |x| !x[:inspec].nil? }
|
58
|
+
if inspec_in_supports
|
59
|
+
Inspec::Log.warn '[DEPRECATED] The use of inspec.yml `supports:inspec` is deprecated and will be removed in InSpec 2.0. Please use `inspec_version` instead.'
|
60
|
+
Gem::Requirement.create(inspec_in_supports[:inspec])
|
61
|
+
else
|
62
|
+
# using Gem::Requirement here to allow nil values which
|
63
|
+
# translate to [">= 0"]
|
64
|
+
Gem::Requirement.create(params[:inspec_version])
|
65
|
+
end
|
87
66
|
end
|
88
67
|
|
89
68
|
def supports_runtime?
|
@@ -91,18 +70,8 @@ module Inspec
|
|
91
70
|
inspec_requirement.satisfied_by?(running)
|
92
71
|
end
|
93
72
|
|
94
|
-
def
|
95
|
-
|
96
|
-
# constraints on the supported backend; it is equivalent to putting
|
97
|
-
# all fields into accept-all mode
|
98
|
-
return true if params[:supports].empty?
|
99
|
-
|
100
|
-
found = params[:supports].find do |entry|
|
101
|
-
is_supported?(backend.os, entry)
|
102
|
-
end
|
103
|
-
|
104
|
-
# finally, if we found a supported entry, we are good to go
|
105
|
-
!found.nil?
|
73
|
+
def supports_platform?(backend)
|
74
|
+
backend.platform.supported?(params[:supports])
|
106
75
|
end
|
107
76
|
|
108
77
|
# return all warn and errors
|
@@ -28,6 +28,12 @@ module Inspec
|
|
28
28
|
__resource_registry[@name].desc(description)
|
29
29
|
end
|
30
30
|
|
31
|
+
def supports(criteria = nil)
|
32
|
+
return if criteria.nil?
|
33
|
+
Inspec::Resource.supports[@name] ||= []
|
34
|
+
Inspec::Resource.supports[@name].push(criteria)
|
35
|
+
end
|
36
|
+
|
31
37
|
def example(example = nil)
|
32
38
|
return if example.nil?
|
33
39
|
__resource_registry[@name].example(example)
|
@@ -37,18 +43,22 @@ module Inspec
|
|
37
43
|
Inspec::Resource.registry
|
38
44
|
end
|
39
45
|
|
40
|
-
def __register(name, obj) # rubocop:disable Metrics/MethodLength
|
41
|
-
cl = Class.new(obj) do
|
46
|
+
def __register(name, obj) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
47
|
+
cl = Class.new(obj) do # rubocop:disable Metrics/BlockLength
|
42
48
|
attr_reader :resource_exception_message
|
43
49
|
|
44
50
|
def initialize(backend, name, *args)
|
45
51
|
@resource_skipped = false
|
46
52
|
@resource_failed = false
|
53
|
+
@supports = Inspec::Resource.supports[name]
|
47
54
|
|
48
55
|
# attach the backend to this instance
|
49
56
|
@__backend_runner__ = backend
|
50
57
|
@__resource_name__ = name
|
51
58
|
|
59
|
+
# check resource supports
|
60
|
+
check_supports unless @supports.nil?
|
61
|
+
|
52
62
|
# call the resource initializer
|
53
63
|
begin
|
54
64
|
super(*args)
|
@@ -69,6 +79,12 @@ module Inspec
|
|
69
79
|
@example = example
|
70
80
|
end
|
71
81
|
|
82
|
+
def check_supports
|
83
|
+
status = inspec.platform.supported?(@supports)
|
84
|
+
skip_msg = "Resource #{@__resource_name__.capitalize} is not supported on platform #{inspec.platform.name}/#{inspec.platform.release}."
|
85
|
+
skip_resource(skip_msg) unless status
|
86
|
+
end
|
87
|
+
|
72
88
|
def skip_resource(message)
|
73
89
|
@resource_skipped = true
|
74
90
|
@resource_exception_message = message
|
data/lib/inspec/profile.rb
CHANGED
@@ -21,7 +21,7 @@ require 'inspec/dependencies/lockfile'
|
|
21
21
|
require 'inspec/dependencies/dependency_set'
|
22
22
|
|
23
23
|
module Inspec
|
24
|
-
class Profile
|
24
|
+
class Profile
|
25
25
|
extend Forwardable
|
26
26
|
|
27
27
|
def self.resolve_target(target, cache)
|
@@ -43,7 +43,7 @@ module Inspec
|
|
43
43
|
next if content[key].nil?
|
44
44
|
# remove prefix
|
45
45
|
rel = Pathname.new(key).relative_path_from(Pathname.new('vendor')).to_s
|
46
|
-
tar = Pathname.new(opts[:
|
46
|
+
tar = Pathname.new(opts[:vendor_cache].path).join(rel)
|
47
47
|
|
48
48
|
FileUtils.mkdir_p tar.dirname.to_s
|
49
49
|
Inspec::Log.debug "Copy #{tar} to cache directory"
|
@@ -56,7 +56,7 @@ module Inspec
|
|
56
56
|
rp = file_provider.relative_provider
|
57
57
|
|
58
58
|
# copy embedded dependecies into global cache
|
59
|
-
copy_deps_into_cache(rp, opts) unless opts[:
|
59
|
+
copy_deps_into_cache(rp, opts) unless opts[:vendor_cache].nil?
|
60
60
|
|
61
61
|
reader = Inspec::SourceReader.resolve(rp)
|
62
62
|
if reader.nil?
|
@@ -67,14 +67,14 @@ module Inspec
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def self.for_fetcher(fetcher, opts)
|
70
|
-
opts[:
|
70
|
+
opts[:vendor_cache] = opts[:vendor_cache] || Cache.new
|
71
71
|
path, writable = fetcher.fetch
|
72
72
|
for_path(path, opts.merge(target: fetcher.target, writable: writable))
|
73
73
|
end
|
74
74
|
|
75
75
|
def self.for_target(target, opts = {})
|
76
|
-
opts[:
|
77
|
-
fetcher = resolve_target(target, opts[:
|
76
|
+
opts[:vendor_cache] = opts[:vendor_cache] || Cache.new
|
77
|
+
fetcher = resolve_target(target, opts[:vendor_cache])
|
78
78
|
for_fetcher(fetcher, opts)
|
79
79
|
end
|
80
80
|
|
@@ -92,7 +92,7 @@ module Inspec
|
|
92
92
|
@controls = options[:controls] || []
|
93
93
|
@writable = options[:writable] || false
|
94
94
|
@profile_id = options[:id]
|
95
|
-
@cache = options[:
|
95
|
+
@cache = options[:vendor_cache] || Cache.new
|
96
96
|
@attr_values = options[:attributes]
|
97
97
|
@tests_collected = false
|
98
98
|
@libraries_loaded = false
|
@@ -136,15 +136,21 @@ module Inspec
|
|
136
136
|
# @returns [TrueClass, FalseClass]
|
137
137
|
#
|
138
138
|
def supported?
|
139
|
-
|
139
|
+
supports_platform? && supports_runtime?
|
140
140
|
end
|
141
141
|
|
142
|
-
def
|
143
|
-
|
142
|
+
def supports_platform?
|
143
|
+
if @supports_platform.nil?
|
144
|
+
@supports_platform = metadata.supports_platform?(@backend)
|
145
|
+
end
|
146
|
+
@supports_platform
|
144
147
|
end
|
145
148
|
|
146
149
|
def supports_runtime?
|
147
|
-
|
150
|
+
if @supports_runtime.nil?
|
151
|
+
@supports_runtime = metadata.supports_runtime?
|
152
|
+
end
|
153
|
+
@supports_runtime
|
148
154
|
end
|
149
155
|
|
150
156
|
def params
|
@@ -11,7 +11,7 @@ require 'securerandom'
|
|
11
11
|
require 'inspec/objects/attribute'
|
12
12
|
|
13
13
|
module Inspec
|
14
|
-
class ProfileContext
|
14
|
+
class ProfileContext
|
15
15
|
def self.for_profile(profile, backend, attributes)
|
16
16
|
new(profile.name, backend, { 'profile' => profile,
|
17
17
|
'attributes' => attributes,
|
@@ -63,10 +63,16 @@ module Inspec
|
|
63
63
|
@control_eval_context = nil
|
64
64
|
end
|
65
65
|
|
66
|
-
def
|
66
|
+
def profile_supports_platform?
|
67
67
|
return true if @conf['profile'].nil?
|
68
68
|
|
69
|
-
@conf['profile'].
|
69
|
+
@conf['profile'].supports_platform?
|
70
|
+
end
|
71
|
+
|
72
|
+
def profile_supports_inspec_version?
|
73
|
+
return true if @conf['profile'].nil?
|
74
|
+
|
75
|
+
@conf['profile'].supports_runtime?
|
70
76
|
end
|
71
77
|
|
72
78
|
def remove_rule(id)
|
data/lib/inspec/resource.rb
CHANGED
@@ -16,6 +16,10 @@ module Inspec
|
|
16
16
|
@registry ||= default_registry
|
17
17
|
end
|
18
18
|
|
19
|
+
def self.supports
|
20
|
+
@supports ||= {}
|
21
|
+
end
|
22
|
+
|
19
23
|
def self.new_registry
|
20
24
|
default_registry.dup
|
21
25
|
end
|
@@ -131,6 +135,7 @@ require 'resources/packages'
|
|
131
135
|
require 'resources/parse_config'
|
132
136
|
require 'resources/passwd'
|
133
137
|
require 'resources/pip'
|
138
|
+
require 'resources/platform'
|
134
139
|
require 'resources/port'
|
135
140
|
require 'resources/postgres'
|
136
141
|
require 'resources/postgres_conf'
|
@@ -110,7 +110,7 @@ class InspecRspecMiniJson < RSpec::Core::Formatters::JsonFormatter
|
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
-
class InspecRspecJson < InspecRspecMiniJson
|
113
|
+
class InspecRspecJson < InspecRspecMiniJson
|
114
114
|
RSpec::Core::Formatters.register self, :stop, :dump_summary
|
115
115
|
attr_writer :backend
|
116
116
|
|
@@ -279,7 +279,7 @@ class InspecRspecJson < InspecRspecMiniJson # rubocop:disable Metrics/ClassLengt
|
|
279
279
|
end
|
280
280
|
end
|
281
281
|
|
282
|
-
class InspecRspecCli < InspecRspecJson
|
282
|
+
class InspecRspecCli < InspecRspecJson
|
283
283
|
RSpec::Core::Formatters.register self, :close
|
284
284
|
|
285
285
|
case RUBY_PLATFORM
|
@@ -685,7 +685,7 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
685
685
|
# This class wraps a control hash object to provide a useful inteface for
|
686
686
|
# maintaining the associated profile, ids, results, title, etc.
|
687
687
|
#
|
688
|
-
class Control
|
688
|
+
class Control
|
689
689
|
include Comparable
|
690
690
|
|
691
691
|
STATUS_TYPES = {
|
data/lib/inspec/rule.rb
CHANGED
data/lib/inspec/runner.rb
CHANGED
@@ -28,7 +28,7 @@ module Inspec
|
|
28
28
|
# r.run
|
29
29
|
# ```
|
30
30
|
#
|
31
|
-
class Runner
|
31
|
+
class Runner
|
32
32
|
extend Forwardable
|
33
33
|
|
34
34
|
def_delegator :@test_collector, :report
|
@@ -40,9 +40,10 @@ module Inspec
|
|
40
40
|
@conf[:logger] ||= Logger.new(nil)
|
41
41
|
@target_profiles = []
|
42
42
|
@controls = @conf[:controls] || []
|
43
|
+
@depends = @conf[:depends] || []
|
43
44
|
@ignore_supports = @conf[:ignore_supports]
|
44
45
|
@create_lockfile = @conf[:create_lockfile]
|
45
|
-
@cache = Inspec::Cache.new(@conf[:
|
46
|
+
@cache = Inspec::Cache.new(@conf[:vendor_cache])
|
46
47
|
@test_collector = @conf.delete(:test_collector) || begin
|
47
48
|
require 'inspec/runner_rspec'
|
48
49
|
RunnerRspec.new(@conf)
|
@@ -168,7 +169,7 @@ module Inspec
|
|
168
169
|
#
|
169
170
|
def add_target(target, _opts = [])
|
170
171
|
profile = Inspec::Profile.for_target(target,
|
171
|
-
|
172
|
+
vendor_cache: @cache,
|
172
173
|
backend: @backend,
|
173
174
|
controls: @controls,
|
174
175
|
attributes: @conf[:attributes])
|
@@ -185,8 +186,8 @@ module Inspec
|
|
185
186
|
"InSpec v#{Inspec::VERSION}.\n"
|
186
187
|
end
|
187
188
|
|
188
|
-
if !profile.
|
189
|
-
raise "This OS/platform (#{@backend.
|
189
|
+
if !profile.supports_platform?
|
190
|
+
raise "This OS/platform (#{@backend.platform.name}/#{@backend.platform.release}) is not supported by this profile."
|
190
191
|
end
|
191
192
|
|
192
193
|
true
|
@@ -214,6 +215,13 @@ module Inspec
|
|
214
215
|
add_target({ 'inspec.yml' => 'name: inspec-shell' })
|
215
216
|
our_profile = @target_profiles.first
|
216
217
|
ctx = our_profile.runner_context
|
218
|
+
|
219
|
+
# Load local profile dependencies. This is used in inspec shell
|
220
|
+
# to provide access to local profiles that add resources.
|
221
|
+
@depends
|
222
|
+
.map { |x| Inspec::Profile.for_path(x, { profile_context: ctx }) }
|
223
|
+
.each(&:load_libraries)
|
224
|
+
|
217
225
|
ctx.load(command)
|
218
226
|
end
|
219
227
|
|