inspec 1.48.0 → 1.49.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|