inspec 1.45.9 → 1.45.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +54 -32
- data/CHANGELOG.md +29 -21
- data/Gemfile +1 -1
- data/docs/resources/ini.md.erb +14 -1
- data/docs/shell.md +1 -1
- data/inspec.gemspec +2 -2
- data/lib/bundles/inspec-artifact/cli.rb +3 -8
- data/lib/bundles/inspec-compliance/configuration.rb +5 -5
- data/lib/bundles/inspec-compliance/http.rb +2 -5
- data/lib/bundles/inspec-compliance/target.rb +6 -6
- data/lib/bundles/inspec-compliance/test/integration/default/cli.rb +1 -1
- data/lib/bundles/inspec-habitat/profile.rb +68 -74
- data/lib/bundles/inspec-supermarket/api.rb +7 -7
- data/lib/bundles/inspec-supermarket/cli.rb +1 -1
- data/lib/fetchers/git.rb +3 -8
- data/lib/fetchers/local.rb +7 -13
- data/lib/fetchers/url.rb +1 -1
- data/lib/inspec/backend.rb +0 -1
- data/lib/inspec/base_cli.rb +1 -1
- data/lib/inspec/cached_fetcher.rb +11 -12
- data/lib/inspec/cli.rb +0 -1
- data/lib/inspec/control_eval_context.rb +2 -2
- data/lib/inspec/dependencies/lockfile.rb +13 -15
- data/lib/inspec/dependencies/requirement.rb +1 -1
- data/lib/inspec/dependencies/resolver.rb +3 -5
- data/lib/inspec/dsl.rb +5 -5
- data/lib/inspec/dsl_shared.rb +1 -1
- data/lib/inspec/env_printer.rb +26 -26
- data/lib/inspec/metadata.rb +11 -10
- data/lib/inspec/objects/or_test.rb +4 -2
- data/lib/inspec/objects/test.rb +1 -1
- data/lib/inspec/profile.rb +2 -2
- data/lib/inspec/resource.rb +1 -3
- data/lib/inspec/rspec_json_formatter.rb +6 -8
- data/lib/inspec/shell.rb +51 -52
- data/lib/inspec/version.rb +1 -1
- data/lib/matchers/matchers.rb +1 -2
- data/lib/resources/audit_policy.rb +2 -2
- data/lib/resources/auditd.rb +6 -3
- data/lib/resources/dh_params.rb +1 -2
- data/lib/resources/docker.rb +2 -2
- data/lib/resources/docker_container.rb +4 -4
- data/lib/resources/elasticsearch.rb +2 -6
- data/lib/resources/etc_group.rb +2 -4
- data/lib/resources/groups.rb +14 -14
- data/lib/resources/host.rb +2 -3
- data/lib/resources/packages.rb +1 -1
- data/lib/resources/port.rb +1 -1
- data/lib/resources/postgres.rb +6 -6
- data/lib/resources/powershell.rb +1 -1
- data/lib/resources/service.rb +4 -5
- data/lib/resources/users.rb +58 -58
- data/lib/resources/vbscript.rb +10 -10
- data/lib/resources/virtualization.rb +3 -4
- data/lib/resources/x509_certificate.rb +1 -1
- data/lib/resources/yum.rb +1 -1
- data/lib/source_readers/inspec.rb +2 -1
- data/lib/utils/command_wrapper.rb +3 -8
- data/lib/utils/filter.rb +1 -1
- data/lib/utils/json_log.rb +2 -1
- data/lib/utils/latest_version.rb +5 -4
- data/lib/utils/object_traversal.rb +1 -1
- data/lib/utils/parser.rb +2 -2
- metadata +4 -4
@@ -54,11 +54,11 @@ module Supermarket
|
|
54
54
|
|
55
55
|
def self.find(profile, supermarket_url = SUPERMARKET_URL)
|
56
56
|
profiles = Supermarket::API.profiles(supermarket_url)
|
57
|
-
if
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
return if profiles.empty?
|
58
|
+
|
59
|
+
index = profiles.index { |t| same?(profile, t, supermarket_url) }
|
60
|
+
# return profile or nil
|
61
|
+
profiles[index] if !index.nil? && index >= 0
|
62
62
|
end
|
63
63
|
|
64
64
|
# verifies that a profile exists
|
@@ -75,9 +75,9 @@ module Supermarket
|
|
75
75
|
|
76
76
|
def self.send_request(uri, req)
|
77
77
|
# send request
|
78
|
-
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https')
|
78
|
+
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
79
79
|
http.request(req)
|
80
|
-
|
80
|
+
end
|
81
81
|
[res.is_a?(Net::HTTPSuccess), res.body]
|
82
82
|
end
|
83
83
|
end
|
@@ -42,7 +42,7 @@ module Supermarket
|
|
42
42
|
# check that the profile is available
|
43
43
|
supermarket_profiles = Supermarket::API.profiles
|
44
44
|
found = supermarket_profiles.select { |p|
|
45
|
-
"#{p['tool_owner']}/#{p['slug']}"
|
45
|
+
profile == "#{p['tool_owner']}/#{p['slug']}"
|
46
46
|
}
|
47
47
|
|
48
48
|
if found.empty?
|
data/lib/fetchers/git.rb
CHANGED
@@ -24,14 +24,12 @@ module Fetchers
|
|
24
24
|
# you got to this file during debugging, you may want to look at the
|
25
25
|
# omnibus source for hints.
|
26
26
|
#
|
27
|
-
class Git < Inspec.fetcher(1)
|
27
|
+
class Git < Inspec.fetcher(1)
|
28
28
|
name 'git'
|
29
29
|
priority 200
|
30
30
|
|
31
31
|
def self.resolve(target, opts = {})
|
32
|
-
if target.respond_to?(:has_key?) &&target.key?(:git)
|
33
|
-
new(target[:git], opts.merge(target))
|
34
|
-
end
|
32
|
+
new(target[:git], opts.merge(target)) if target.respond_to?(:has_key?) && target.key?(:git)
|
35
33
|
end
|
36
34
|
|
37
35
|
def initialize(remote_url, opts = {})
|
@@ -121,10 +119,7 @@ module Fetchers
|
|
121
119
|
if tagged_commit
|
122
120
|
tagged_commit.first
|
123
121
|
else
|
124
|
-
|
125
|
-
if found
|
126
|
-
found.first
|
127
|
-
end
|
122
|
+
pairs.find { |m| m[1].end_with?(ref_name.to_s) }&.first
|
128
123
|
end
|
129
124
|
end
|
130
125
|
|
data/lib/fetchers/local.rb
CHANGED
@@ -16,19 +16,15 @@ module Fetchers
|
|
16
16
|
resolve_from_hash(target)
|
17
17
|
end
|
18
18
|
|
19
|
-
if local_path
|
20
|
-
new(local_path)
|
21
|
-
end
|
19
|
+
new(local_path) if local_path
|
22
20
|
end
|
23
21
|
|
24
22
|
def self.resolve_from_hash(target)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
local_path
|
31
|
-
end
|
23
|
+
return unless target.key?(:path)
|
24
|
+
|
25
|
+
local_path = target[:path]
|
26
|
+
local_path = File.expand_path(local_path, target[:cwd]) if target.key?(:cwd)
|
27
|
+
local_path
|
32
28
|
end
|
33
29
|
|
34
30
|
def self.resolve_from_string(target)
|
@@ -40,9 +36,7 @@ module Fetchers
|
|
40
36
|
target = target.tr('\\', '/')
|
41
37
|
end
|
42
38
|
|
43
|
-
if File.exist?(target)
|
44
|
-
target
|
45
|
-
end
|
39
|
+
target if File.exist?(target)
|
46
40
|
end
|
47
41
|
|
48
42
|
def initialize(target)
|
data/lib/fetchers/url.rb
CHANGED
@@ -141,7 +141,7 @@ module Fetchers
|
|
141
141
|
|
142
142
|
# Downloads archive to temporary file with side effect :( of setting @archive_type
|
143
143
|
def download_archive_to_temp
|
144
|
-
return @temp_archive_path if
|
144
|
+
return @temp_archive_path if !@temp_archive_path.nil?
|
145
145
|
Inspec::Log.debug("Fetching URL: #{@target}")
|
146
146
|
remote = open(@target, http_opts)
|
147
147
|
@archive_type = file_type_from_remote(remote) # side effect :(
|
data/lib/inspec/backend.rb
CHANGED
data/lib/inspec/base_cli.rb
CHANGED
@@ -48,20 +48,19 @@ module Inspec
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def assert_cache_sanity!
|
51
|
-
|
52
|
-
if fetcher.resolved_source[:sha256] != target[:sha256]
|
53
|
-
raise <<EOF
|
54
|
-
The remote source #{fetcher} no longer has the requested content:
|
51
|
+
return unless target.respond_to?(:key?) && target.key?(:sha256)
|
55
52
|
|
56
|
-
|
57
|
-
|
53
|
+
exception_message = <<~EOF
|
54
|
+
The remote source #{fetcher} no longer has the requested content:
|
58
55
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
56
|
+
Request Content Hash: #{target[:sha256]}
|
57
|
+
Actual Content Hash: #{fetcher.resolved_source[:sha256]}
|
58
|
+
|
59
|
+
For URL, supermarket, compliance, and other sources that do not
|
60
|
+
provide versioned artifacts, this likely means that the remote source
|
61
|
+
has changed since your lockfile was generated.
|
62
|
+
EOF
|
63
|
+
raise exception_message if fetcher.resolved_source[:sha256] != target[:sha256]
|
65
64
|
end
|
66
65
|
end
|
67
66
|
end
|
data/lib/inspec/cli.rb
CHANGED
@@ -40,7 +40,7 @@ module Inspec
|
|
40
40
|
profile_context_owner = profile_context
|
41
41
|
profile_id = profile_context.profile_id
|
42
42
|
|
43
|
-
Class.new do
|
43
|
+
Class.new do # rubocop:disable Metrics/BlockLength
|
44
44
|
include Inspec::DSL
|
45
45
|
include Inspec::DSL::RequireOverride
|
46
46
|
include resources_dsl
|
@@ -80,7 +80,7 @@ module Inspec
|
|
80
80
|
# the describe block in the context of that control.
|
81
81
|
#
|
82
82
|
define_method :describe do |*args, &block|
|
83
|
-
loc = block_location(block, caller
|
83
|
+
loc = block_location(block, caller(1..1).first)
|
84
84
|
id = "(generated from #{loc} #{SecureRandom.hex})"
|
85
85
|
|
86
86
|
res = nil
|
@@ -31,22 +31,22 @@ module Inspec
|
|
31
31
|
# rubocop:disable Style/GuardClause
|
32
32
|
def self.validate_lockfile_version!(version)
|
33
33
|
if version < MINIMUM_SUPPORTED_VERSION
|
34
|
-
raise
|
35
|
-
This lockfile specifies a lockfile_version of #{version} which is
|
36
|
-
lower than the minimum supported version #{MINIMUM_SUPPORTED_VERSION}.
|
34
|
+
raise <<~EOF
|
35
|
+
This lockfile specifies a lockfile_version of #{version} which is
|
36
|
+
lower than the minimum supported version #{MINIMUM_SUPPORTED_VERSION}.
|
37
37
|
|
38
|
-
Please create a new lockfile for this project by running:
|
38
|
+
Please create a new lockfile for this project by running:
|
39
39
|
|
40
|
-
|
41
|
-
EOF
|
40
|
+
inspec vendor
|
41
|
+
EOF
|
42
42
|
elsif version > CURRENT_LOCKFILE_VERSION
|
43
|
-
raise
|
44
|
-
This lockfile claims to be version #{version} which is greater than
|
45
|
-
the most recent lockfile version(#{CURRENT_LOCKFILE_VERSION}).
|
43
|
+
raise <<~EOF
|
44
|
+
This lockfile claims to be version #{version} which is greater than
|
45
|
+
the most recent lockfile version(#{CURRENT_LOCKFILE_VERSION}).
|
46
46
|
|
47
|
-
This may happen if you are using an older version of inspec than was
|
48
|
-
used to create the lockfile.
|
49
|
-
EOF
|
47
|
+
This may happen if you are using an older version of inspec than was
|
48
|
+
used to create the lockfile.
|
49
|
+
EOF
|
50
50
|
end
|
51
51
|
end
|
52
52
|
# rubocop:enable Style/GuardClause
|
@@ -87,9 +87,7 @@ EOF
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def parse_content_hash_1(lockfile_content_hash)
|
90
|
-
@deps =
|
91
|
-
lockfile_content_hash['depends'].map { |i| symbolize_keys(i) }
|
92
|
-
end
|
90
|
+
@deps = lockfile_content_hash['depends']&.map { |i| symbolize_keys(i) }
|
93
91
|
end
|
94
92
|
|
95
93
|
def mutate_hash_keys_with(hash, fun)
|
@@ -64,11 +64,9 @@ module Inspec
|
|
64
64
|
path_string + " -> #{dep.name}"
|
65
65
|
end
|
66
66
|
|
67
|
-
if new_seen_items.key?(dep.resolved_source)
|
68
|
-
|
69
|
-
|
70
|
-
new_seen_items[dep.resolved_source] = true
|
71
|
-
end
|
67
|
+
raise Inspec::CyclicDependencyError, "Dependency #{dep} would cause a dependency cycle (#{new_path_string})" if new_seen_items.key?(dep.resolved_source)
|
68
|
+
|
69
|
+
new_seen_items[dep.resolved_source] = true
|
72
70
|
|
73
71
|
if !dep.source_satisfies_spec?
|
74
72
|
raise Inspec::UnsatisfiedVersionSpecification, "The profile #{dep.name} from #{dep.resolved_source} has a version #{dep.source_version} which doesn't match #{dep.version_constraints}"
|
data/lib/inspec/dsl.rb
CHANGED
@@ -33,12 +33,12 @@ module Inspec::DSL
|
|
33
33
|
|
34
34
|
dep_entry = dependencies.list[profile_id]
|
35
35
|
if dep_entry.nil?
|
36
|
-
raise
|
37
|
-
Cannot load #{profile_id} since it is not listed as a dependency of #{bind_context.profile_name}.
|
36
|
+
raise <<~EOF
|
37
|
+
Cannot load #{profile_id} since it is not listed as a dependency of #{bind_context.profile_name}.
|
38
38
|
|
39
|
-
Dependencies available from this context are:
|
40
|
-
|
41
|
-
EOF
|
39
|
+
Dependencies available from this context are:
|
40
|
+
#{dependencies.list.keys.join("\n ")}
|
41
|
+
EOF
|
42
42
|
end
|
43
43
|
|
44
44
|
context = dep_entry.profile.runner_context
|
data/lib/inspec/dsl_shared.rb
CHANGED
@@ -18,7 +18,7 @@ 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
|
-
eval(content, TOPLEVEL_BINDING, path, line) # rubocop:disable
|
21
|
+
eval(content, TOPLEVEL_BINDING, path, line) # rubocop:disable Security/Eval
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
data/lib/inspec/env_printer.rb
CHANGED
@@ -41,7 +41,7 @@ module Inspec
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def have_shell?
|
44
|
-
!
|
44
|
+
!(@shell.nil? || @shell.empty?)
|
45
45
|
end
|
46
46
|
|
47
47
|
def have_shell_completion?
|
@@ -61,26 +61,26 @@ module Inspec
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def print_usage_guidance
|
64
|
-
puts
|
65
|
-
# To use this, eval it in your shell
|
66
|
-
#
|
67
|
-
# #{EVAL_COMMANDS[shell]}
|
68
|
-
#
|
69
|
-
#
|
70
|
-
EOF
|
64
|
+
puts <<~EOF
|
65
|
+
# To use this, eval it in your shell
|
66
|
+
#
|
67
|
+
# #{EVAL_COMMANDS[shell]}
|
68
|
+
#
|
69
|
+
#
|
70
|
+
EOF
|
71
71
|
end
|
72
72
|
|
73
73
|
def print_detection_warning(device)
|
74
|
-
device.puts
|
75
|
-
#
|
76
|
-
# The shell #{@shell} was auto-detected. If this is incorrect, please
|
77
|
-
# specify a shell explicitly by running:
|
78
|
-
#
|
79
|
-
# inspec env SHELLNAME
|
80
|
-
#
|
81
|
-
# Currently supported shells are: #{shells_with_completions.join(', ')}
|
82
|
-
#
|
83
|
-
EOF
|
74
|
+
device.puts <<~EOF
|
75
|
+
#
|
76
|
+
# The shell #{@shell} was auto-detected. If this is incorrect, please
|
77
|
+
# specify a shell explicitly by running:
|
78
|
+
#
|
79
|
+
# inspec env SHELLNAME
|
80
|
+
#
|
81
|
+
# Currently supported shells are: #{shells_with_completions.join(', ')}
|
82
|
+
#
|
83
|
+
EOF
|
84
84
|
end
|
85
85
|
|
86
86
|
def exit_no_completion
|
@@ -93,14 +93,14 @@ EOF
|
|
93
93
|
if @detected
|
94
94
|
$stderr.puts '# Unable to automatically detect shell and no shell was provided.'
|
95
95
|
end
|
96
|
-
$stderr.puts
|
97
|
-
#
|
98
|
-
# Please provide the name of your shell via the command line:
|
99
|
-
#
|
100
|
-
# inspec env SHELLNAME
|
101
|
-
#
|
102
|
-
# Currently supported shells are: #{shells_with_completions.join(', ')}
|
103
|
-
EOF
|
96
|
+
$stderr.puts <<~EOF
|
97
|
+
#
|
98
|
+
# Please provide the name of your shell via the command line:
|
99
|
+
#
|
100
|
+
# inspec env SHELLNAME
|
101
|
+
#
|
102
|
+
# Currently supported shells are: #{shells_with_completions.join(', ')}
|
103
|
+
EOF
|
104
104
|
exit 1
|
105
105
|
end
|
106
106
|
|
data/lib/inspec/metadata.rb
CHANGED
@@ -110,7 +110,7 @@ module Inspec
|
|
110
110
|
errors = []
|
111
111
|
warnings = []
|
112
112
|
|
113
|
-
%w{
|
113
|
+
%w{name version}.each do |field|
|
114
114
|
next unless params[field.to_sym].nil?
|
115
115
|
errors.push("Missing profile #{field} in #{ref}")
|
116
116
|
end
|
@@ -126,7 +126,7 @@ module Inspec
|
|
126
126
|
errors.push('Version needs to be in SemVer format')
|
127
127
|
end
|
128
128
|
|
129
|
-
%w{
|
129
|
+
%w{title summary maintainer copyright license}.each do |field|
|
130
130
|
next unless params[field.to_sym].nil?
|
131
131
|
warnings.push("Missing profile #{field} in #{ref}")
|
132
132
|
end
|
@@ -165,11 +165,11 @@ module Inspec
|
|
165
165
|
return obj.map { |i| symbolize_keys(i) } if obj.is_a?(Array)
|
166
166
|
return obj unless obj.is_a?(Hash)
|
167
167
|
|
168
|
-
obj.each_with_object({})
|
168
|
+
obj.each_with_object({}) do |(k, v), h|
|
169
169
|
v = symbolize_keys(v) if v.is_a?(Hash)
|
170
170
|
v = symbolize_keys(v) if v.is_a?(Array)
|
171
171
|
h[k.to_sym] = v
|
172
|
-
|
172
|
+
end
|
173
173
|
end
|
174
174
|
|
175
175
|
def self.finalize_supports_elem(elem, logger)
|
@@ -188,7 +188,8 @@ module Inspec
|
|
188
188
|
logger ||= Logger.new(nil)
|
189
189
|
logger.warn(
|
190
190
|
"Do not use deprecated `supports: #{x}` syntax. Instead use:\n"\
|
191
|
-
"supports:\n - os-family: #{x}\n\n"
|
191
|
+
"supports:\n - os-family: #{x}\n\n",
|
192
|
+
)
|
192
193
|
{ :'os-family' => x } # rubocop:disable Style/HashSyntax
|
193
194
|
end
|
194
195
|
end
|
@@ -202,7 +203,8 @@ module Inspec
|
|
202
203
|
logger ||= Logger.new(nil)
|
203
204
|
logger.warn(
|
204
205
|
"Do not use deprecated `supports: #{x}` syntax. Instead use:\n"\
|
205
|
-
"supports:\n - os-family: #{x}\n\n"
|
206
|
+
"supports:\n - os-family: #{x}\n\n",
|
207
|
+
)
|
206
208
|
[{ :'os-family' => x }] # rubocop:disable Style/HashSyntax
|
207
209
|
end
|
208
210
|
end
|
@@ -223,10 +225,9 @@ module Inspec
|
|
223
225
|
# create a new name based on the original target if it exists
|
224
226
|
# Crudely slug the target to not contain slashes, to avoid breaking
|
225
227
|
# unit tests that look for warning sequences
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
end
|
228
|
+
return if original_target.to_s.empty?
|
229
|
+
metadata.params[:title] = "tests from #{original_target}"
|
230
|
+
metadata.params[:name] = metadata.params[:title].gsub(%r{[\\\/]}, '.')
|
230
231
|
end
|
231
232
|
|
232
233
|
def self.finalize(metadata, profile_id, options, logger = nil)
|
@@ -24,10 +24,12 @@ module Inspec
|
|
24
24
|
test.negate!
|
25
25
|
test
|
26
26
|
}.map(&:to_ruby).join("\n")
|
27
|
-
|
27
|
+
|
28
|
+
all_tests
|
28
29
|
else
|
29
30
|
all_tests = @tests.map(&:to_ruby).join("\n").gsub("\n", "\n ")
|
30
|
-
|
31
|
+
|
32
|
+
format("describe.one do\n %s\nend", all_tests)
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|