inspec-core 4.31.0 → 4.37.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/Gemfile +13 -0
- data/inspec-core.gemspec +2 -2
- data/lib/inspec/base_cli.rb +5 -3
- data/lib/inspec/cli.rb +12 -4
- data/lib/inspec/control_eval_context.rb +1 -0
- data/lib/inspec/input.rb +39 -4
- data/lib/inspec/input_registry.rb +1 -0
- data/lib/inspec/objects/input.rb +1 -1
- data/lib/inspec/plugin/v2/loader.rb +9 -0
- data/lib/inspec/profile_context.rb +1 -1
- data/lib/inspec/reporters/cli.rb +63 -0
- data/lib/inspec/resources.rb +1 -0
- data/lib/inspec/resources/command.rb +3 -8
- data/lib/inspec/resources/groups.rb +21 -6
- data/lib/inspec/resources/selinux.rb +154 -0
- data/lib/inspec/resources/windows_firewall_rule.rb +1 -1
- data/lib/inspec/rule.rb +9 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/inspec-compliance/README.md +125 -2
- data/lib/plugins/inspec-compliance/lib/inspec-compliance.rb +5 -0
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/api.rb +1 -1
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/api/login.rb +2 -2
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/cli.rb +22 -22
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/target.rb +5 -4
- metadata +11 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65d5a9d62e8e76b31b944e42f4ae6fc1784e3823fa578ce8ee439a2270a80816
|
4
|
+
data.tar.gz: 1aa950d1012bd41e061cc58e5693003d9197749c3798d3fb7d50b434c33c13de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69e11bec35bfef9ccd66679c4c04a65afe7b8e2acb4f20ab1f2643ee594961148b269a21e4e84996053a5d18ae96120063f1cbfe634831488b8b830cb22b9942
|
7
|
+
data.tar.gz: 0476cf2df46ae81d3dd0a797d39190425ef28eeb7d8c36c3157d68d7ae658b1922f02251948fce8e5f2a48305f5c9e6ff520bc39a532e655b7f32284c7c67b46
|
data/Gemfile
CHANGED
@@ -48,3 +48,16 @@ end
|
|
48
48
|
group :deploy do
|
49
49
|
gem "inquirer"
|
50
50
|
end
|
51
|
+
|
52
|
+
# Only include Test Kitchen support if we are on Ruby 2.7 or higher
|
53
|
+
# as chef-zero support requires Ruby 2.6
|
54
|
+
# See https://github.com/inspec/inspec/pull/5341
|
55
|
+
if Gem.ruby_version >= Gem::Version.new("2.7.0")
|
56
|
+
group :kitchen do
|
57
|
+
gem "berkshelf"
|
58
|
+
gem "test-kitchen", ">= 2.8"
|
59
|
+
gem "kitchen-inspec", ">= 2.0"
|
60
|
+
gem "kitchen-dokken", ">= 2.11"
|
61
|
+
gem "git"
|
62
|
+
end
|
63
|
+
end
|
data/inspec-core.gemspec
CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
.reject { |f| File.directory?(f) }
|
24
24
|
|
25
25
|
# Implementation dependencies
|
26
|
-
spec.add_dependency "chef-telemetry", "~> 1.0"
|
26
|
+
spec.add_dependency "chef-telemetry", "~> 1.0", ">= 1.0.8" # 1.0.8+ removes the http dep
|
27
27
|
spec.add_dependency "license-acceptance", ">= 0.2.13", "< 3.0"
|
28
28
|
spec.add_dependency "thor", ">= 0.20", "< 2.0"
|
29
29
|
spec.add_dependency "method_source", ">= 0.8", "< 2.0"
|
@@ -35,7 +35,7 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.add_dependency "mixlib-log", "~> 3.0"
|
36
36
|
spec.add_dependency "sslshake", "~> 1.2"
|
37
37
|
spec.add_dependency "parallel", "~> 1.9"
|
38
|
-
spec.add_dependency "faraday", ">= 0.9.0", "< 1.
|
38
|
+
spec.add_dependency "faraday", ">= 0.9.0", "< 1.5"
|
39
39
|
spec.add_dependency "faraday_middleware", "~> 1.0"
|
40
40
|
spec.add_dependency "tty-table", "~> 0.10"
|
41
41
|
spec.add_dependency "tty-prompt", "~> 0.17"
|
data/lib/inspec/base_cli.rb
CHANGED
@@ -168,9 +168,11 @@ module Inspec
|
|
168
168
|
desc: "After normal execution order, results are sorted by control ID, or by file (default), or randomly. None uses legacy unsorted mode."
|
169
169
|
option :filter_empty_profiles, type: :boolean, default: false,
|
170
170
|
desc: "Filter empty profiles (profiles without controls) from the report."
|
171
|
-
option :command_timeout, type: :numeric,
|
172
|
-
desc: "Maximum seconds to allow commands to run during execution.
|
173
|
-
long_desc: "Maximum seconds to allow commands to run during execution.
|
171
|
+
option :command_timeout, type: :numeric,
|
172
|
+
desc: "Maximum seconds to allow commands to run during execution.",
|
173
|
+
long_desc: "Maximum seconds to allow commands to run during execution. A timed out command is considered an error."
|
174
|
+
option :reporter_include_source, type: :boolean, default: false,
|
175
|
+
desc: "Include full source code of controls in the CLI report"
|
174
176
|
end
|
175
177
|
|
176
178
|
def self.help(*args)
|
data/lib/inspec/cli.rb
CHANGED
@@ -218,9 +218,13 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
218
218
|
|
219
219
|
Automate:
|
220
220
|
```
|
221
|
-
#{Inspec::Dist::EXEC_NAME}
|
221
|
+
#{Inspec::Dist::EXEC_NAME} automate login
|
222
222
|
#{Inspec::Dist::EXEC_NAME} exec compliance://username/linux-baseline
|
223
223
|
```
|
224
|
+
`inspec compliance` is a backwards compatible alias for `inspec automate` and works the same way:
|
225
|
+
```
|
226
|
+
#{Inspec::Dist::EXEC_NAME} compliance login
|
227
|
+
```
|
224
228
|
|
225
229
|
Supermarket:
|
226
230
|
```
|
@@ -321,10 +325,14 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
321
325
|
desc: "A space-delimited list of local folders containing profiles whose libraries and resources will be loaded into the new shell"
|
322
326
|
option :distinct_exit, type: :boolean, default: true,
|
323
327
|
desc: "Exit with code 100 if any tests fail, and 101 if any are skipped but none failed (default). If disabled, exit 0 on skips and 1 for failures."
|
324
|
-
option :command_timeout, type: :numeric,
|
325
|
-
desc: "Maximum seconds to allow a command to run.
|
326
|
-
long_desc: "Maximum seconds to allow commands to run.
|
328
|
+
option :command_timeout, type: :numeric,
|
329
|
+
desc: "Maximum seconds to allow a command to run.",
|
330
|
+
long_desc: "Maximum seconds to allow commands to run. A timed out command is considered an error."
|
327
331
|
option :inspect, type: :boolean, default: false, desc: "Use verbose/debugging output for resources."
|
332
|
+
option :input_file, type: :array,
|
333
|
+
desc: "Load one or more input files, a YAML file with values for the shell to use"
|
334
|
+
option :input, type: :array, banner: "name1=value1 name2=value2",
|
335
|
+
desc: "Specify one or more inputs directly on the command line to the shell, as --input NAME=VALUE. Accepts single-quoted YAML and JSON structures."
|
328
336
|
def shell_func
|
329
337
|
o = config
|
330
338
|
diagnose(o)
|
@@ -194,6 +194,7 @@ module Inspec
|
|
194
194
|
|
195
195
|
# Check if the given control exist in the --controls option
|
196
196
|
def control_exist_in_controls_list?(id)
|
197
|
+
id_exist_in_list = false
|
197
198
|
if profile_config_exist?
|
198
199
|
id_exist_in_list = @conf["profile"].include_controls_list.any? do |inclusion|
|
199
200
|
# Try to see if the inclusion is a regex, and if it matches
|
data/lib/inspec/input.rb
CHANGED
@@ -19,12 +19,17 @@ module Inspec
|
|
19
19
|
attr_accessor :input_name
|
20
20
|
attr_accessor :input_value
|
21
21
|
attr_accessor :input_type
|
22
|
+
attr_accessor :input_pattern
|
22
23
|
end
|
23
24
|
|
24
25
|
class TypeError < Error
|
25
26
|
attr_accessor :input_type
|
26
27
|
end
|
27
28
|
|
29
|
+
class PatternError < Error
|
30
|
+
attr_accessor :input_pattern
|
31
|
+
end
|
32
|
+
|
28
33
|
class RequiredError < Error
|
29
34
|
attr_accessor :input_name
|
30
35
|
end
|
@@ -56,7 +61,6 @@ module Inspec
|
|
56
61
|
|
57
62
|
def initialize(properties = {})
|
58
63
|
@value_has_been_set = false
|
59
|
-
|
60
64
|
properties.each do |prop_name, prop_value|
|
61
65
|
if EVENT_PROPERTIES.include? prop_name
|
62
66
|
# OK, save the property
|
@@ -174,7 +178,7 @@ module Inspec
|
|
174
178
|
# are free to go higher.
|
175
179
|
DEFAULT_PRIORITY_FOR_VALUE_SET = 60
|
176
180
|
|
177
|
-
attr_reader :description, :events, :identifier, :name, :required, :sensitive, :title, :type
|
181
|
+
attr_reader :description, :events, :identifier, :name, :required, :sensitive, :title, :type, :pattern
|
178
182
|
|
179
183
|
def initialize(name, options = {})
|
180
184
|
@name = name
|
@@ -192,7 +196,6 @@ module Inspec
|
|
192
196
|
# debugging record of when and how the value changed.
|
193
197
|
@events = []
|
194
198
|
events.push make_creation_event(options)
|
195
|
-
|
196
199
|
update(options)
|
197
200
|
end
|
198
201
|
|
@@ -213,6 +216,7 @@ module Inspec
|
|
213
216
|
def update(options)
|
214
217
|
_update_set_metadata(options)
|
215
218
|
normalize_type_restriction!
|
219
|
+
normalize_pattern_restriction!
|
216
220
|
|
217
221
|
# Values are set by passing events in; but we can also infer an event.
|
218
222
|
if options.key?(:value) || options.key?(:default)
|
@@ -227,6 +231,7 @@ module Inspec
|
|
227
231
|
events << options[:event] if options.key? :event
|
228
232
|
|
229
233
|
enforce_type_restriction!
|
234
|
+
enforce_pattern_restriction!
|
230
235
|
end
|
231
236
|
|
232
237
|
# We can determine a value:
|
@@ -268,6 +273,7 @@ module Inspec
|
|
268
273
|
@identifier = options[:identifier] if options.key?(:identifier) # TODO: determine if this is ever used
|
269
274
|
@type = options[:type] if options.key?(:type)
|
270
275
|
@sensitive = options[:sensitive] if options.key?(:sensitive)
|
276
|
+
@pattern = options[:pattern] if options.key?(:pattern)
|
271
277
|
end
|
272
278
|
|
273
279
|
def make_creation_event(options)
|
@@ -310,7 +316,9 @@ module Inspec
|
|
310
316
|
file: location.path,
|
311
317
|
line: location.lineno
|
312
318
|
)
|
319
|
+
|
313
320
|
enforce_type_restriction!
|
321
|
+
enforce_pattern_restriction!
|
314
322
|
end
|
315
323
|
|
316
324
|
def value
|
@@ -324,7 +332,7 @@ module Inspec
|
|
324
332
|
|
325
333
|
def to_hash
|
326
334
|
as_hash = { name: name, options: {} }
|
327
|
-
%i{description title identifier type required value sensitive}.each do |field|
|
335
|
+
%i{description title identifier type required value sensitive pattern}.each do |field|
|
328
336
|
val = send(field)
|
329
337
|
next if val.nil?
|
330
338
|
|
@@ -407,6 +415,33 @@ module Inspec
|
|
407
415
|
@type = type_req
|
408
416
|
end
|
409
417
|
|
418
|
+
def enforce_pattern_restriction!
|
419
|
+
return unless pattern
|
420
|
+
return unless has_value?
|
421
|
+
|
422
|
+
string_value = current_value(false).to_s
|
423
|
+
|
424
|
+
valid_pattern = string_value.match?(pattern)
|
425
|
+
unless valid_pattern
|
426
|
+
error = Inspec::Input::ValidationError.new
|
427
|
+
error.input_name = @name
|
428
|
+
error.input_value = string_value
|
429
|
+
error.input_pattern = pattern
|
430
|
+
raise error, "Input '#{error.input_name}' with value '#{error.input_value}' does not validate to pattern '#{error.input_pattern}'."
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
def normalize_pattern_restriction!
|
435
|
+
return unless pattern
|
436
|
+
|
437
|
+
unless valid_regexp?(pattern)
|
438
|
+
error = Inspec::Input::PatternError.new
|
439
|
+
error.input_pattern = pattern
|
440
|
+
raise error, "Pattern '#{error.input_pattern}' is not a valid regex pattern."
|
441
|
+
end
|
442
|
+
@pattern = pattern
|
443
|
+
end
|
444
|
+
|
410
445
|
def valid_numeric?(value)
|
411
446
|
Float(value)
|
412
447
|
true
|
data/lib/inspec/objects/input.rb
CHANGED
@@ -20,7 +20,7 @@ module Inspec
|
|
20
20
|
|
21
21
|
def to_hash
|
22
22
|
as_hash = { name: name, options: {} }
|
23
|
-
%i{description title identifier type required value}.each do |field|
|
23
|
+
%i{description title identifier type required value pattern}.each do |field|
|
24
24
|
val = send(field)
|
25
25
|
next if val.nil?
|
26
26
|
|
@@ -117,6 +117,15 @@ module Inspec::Plugin::V2
|
|
117
117
|
# `inspec dosomething` => activate the :dosomething hook
|
118
118
|
activate_me ||= cli_args.include?(act.activator_name.to_s)
|
119
119
|
|
120
|
+
# Only one compliance command to be activated at one time.
|
121
|
+
# Since both commands are defined in the same class,
|
122
|
+
# activators were not getting fetched uniquely.
|
123
|
+
if cli_args.include?("automate") && act.activator_name.to_s.eql?("compliance")
|
124
|
+
activate_me = false
|
125
|
+
elsif cli_args.include?("compliance") && act.activator_name.to_s.eql?("automate")
|
126
|
+
activate_me = false
|
127
|
+
end
|
128
|
+
|
120
129
|
# OK, activate.
|
121
130
|
if activate_me
|
122
131
|
act.activate
|
data/lib/inspec/reporters/cli.rb
CHANGED
@@ -41,12 +41,14 @@ module Inspec::Reporters
|
|
41
41
|
MULTI_TEST_CONTROL_SUMMARY_MAX_LEN = 60
|
42
42
|
|
43
43
|
def render
|
44
|
+
@src_extent_map = {}
|
44
45
|
run_data[:profiles].each do |profile|
|
45
46
|
if profile[:status] == "skipped"
|
46
47
|
platform = run_data[:platform]
|
47
48
|
output("Skipping profile: '#{profile[:name]}' on unsupported platform: '#{platform[:name]}/#{platform[:release]}'.")
|
48
49
|
next
|
49
50
|
end
|
51
|
+
read_control_source(profile)
|
50
52
|
@control_count = 0
|
51
53
|
output("")
|
52
54
|
print_profile_header(profile)
|
@@ -89,6 +91,7 @@ module Inspec::Reporters
|
|
89
91
|
next if control.results.nil?
|
90
92
|
|
91
93
|
output(format_control_header(control))
|
94
|
+
output(format_control_source(control)) if Inspec::Config.cached[:reporter_include_source]
|
92
95
|
control.results.each do |result|
|
93
96
|
output(format_result(control, result, :standard))
|
94
97
|
@control_count += 1
|
@@ -127,6 +130,62 @@ module Inspec::Reporters
|
|
127
130
|
)
|
128
131
|
end
|
129
132
|
|
133
|
+
def format_control_source(control)
|
134
|
+
src = @control_source[control.id]
|
135
|
+
message = "Control Source from #{src[:path]}:#{src[:start]}..#{src[:end]}\n"
|
136
|
+
message += src[:content]
|
137
|
+
format_message(
|
138
|
+
color: "skipped",
|
139
|
+
indentation: 5,
|
140
|
+
message: message
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
def read_control_source(profile)
|
145
|
+
return unless Inspec::Config.cached[:reporter_include_source]
|
146
|
+
|
147
|
+
@control_source = {}
|
148
|
+
src_extent_map = {}
|
149
|
+
|
150
|
+
# First pass: build map of paths => ids => [start]
|
151
|
+
all_unique_controls.each do |control|
|
152
|
+
id = control[:id]
|
153
|
+
path = control[:source_location][:ref]
|
154
|
+
start = control[:source_location][:line]
|
155
|
+
next if path.nil? || start.nil?
|
156
|
+
|
157
|
+
src_extent_map[path] ||= []
|
158
|
+
src_extent_map[path] << { start: start, id: id }
|
159
|
+
end
|
160
|
+
|
161
|
+
# Now sort the controls by their starting line in their control file
|
162
|
+
src_extent_map.values.each do |extent_list|
|
163
|
+
extent_list.sort! { |a, b| a[:start] <=> b[:start] }
|
164
|
+
end
|
165
|
+
|
166
|
+
# Third pass: Read in files and split into lines
|
167
|
+
src_extent_map.keys.each do |path|
|
168
|
+
control_file_lines = File.read(path).lines # TODO error handling
|
169
|
+
last_line_in_file = control_file_lines.count
|
170
|
+
extent_list = src_extent_map[path]
|
171
|
+
extent_list.each_with_index do |extent, idx|
|
172
|
+
if idx == extent_list.count - 1 # Last entry
|
173
|
+
extent[:end] = last_line_in_file
|
174
|
+
else
|
175
|
+
extent[:end] = extent_list[idx + 1][:start] - 1
|
176
|
+
end
|
177
|
+
|
178
|
+
@control_source[extent[:id]] =
|
179
|
+
{
|
180
|
+
path: path,
|
181
|
+
start: extent[:start],
|
182
|
+
end: extent[:end],
|
183
|
+
content: control_file_lines.slice(extent[:start] - 1, extent[:end] - extent[:start] + 1).join(""),
|
184
|
+
}
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
130
189
|
def format_result(control, result, type)
|
131
190
|
impact = control.impact_string_for_result(result)
|
132
191
|
|
@@ -312,6 +371,10 @@ module Inspec::Reporters
|
|
312
371
|
data[:impact]
|
313
372
|
end
|
314
373
|
|
374
|
+
def source_location
|
375
|
+
data[:source_location]
|
376
|
+
end
|
377
|
+
|
315
378
|
def anonymous?
|
316
379
|
id.start_with?("(generated from ")
|
317
380
|
end
|
data/lib/inspec/resources.rb
CHANGED
@@ -103,6 +103,7 @@ require "inspec/resources/rabbitmq_config"
|
|
103
103
|
require "inspec/resources/registry_key"
|
104
104
|
require "inspec/resources/security_identifier"
|
105
105
|
require "inspec/resources/security_policy"
|
106
|
+
require "inspec/resources/selinux"
|
106
107
|
require "inspec/resources/service"
|
107
108
|
require "inspec/resources/shadow"
|
108
109
|
require "inspec/resources/ssh_config"
|
@@ -31,16 +31,11 @@ module Inspec::Resources
|
|
31
31
|
end
|
32
32
|
|
33
33
|
@command = cmd
|
34
|
-
|
35
|
-
cli_timeout = Inspec::Config.cached["command_timeout"].to_i
|
34
|
+
cli_timeout = Inspec::Config.cached["command_timeout"]&.to_i
|
36
35
|
# Can access this via Inspec::InspecCLI.commands["exec"].options[:command_timeout].default,
|
37
36
|
# but that may not be loaded for kitchen-inspec and other pure gem consumers
|
38
|
-
|
39
|
-
|
40
|
-
@timeout = cli_timeout
|
41
|
-
else
|
42
|
-
@timeout = options[:timeout]&.to_i || default_cli_timeout
|
43
|
-
end
|
37
|
+
cli_timeout = nil if cli_timeout == 0 # Under test-kitchen we get a 0 timeout, which can't be a resonable value
|
38
|
+
@timeout = cli_timeout || options[:timeout]&.to_i
|
44
39
|
|
45
40
|
if options[:redact_regex]
|
46
41
|
unless options[:redact_regex].is_a?(Regexp)
|
@@ -49,10 +49,11 @@ module Inspec::Resources
|
|
49
49
|
|
50
50
|
filter = FilterTable.create
|
51
51
|
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
52
|
-
filter.register_column(:names,
|
53
|
-
.register_column(:gids,
|
54
|
-
.register_column(:domains,
|
55
|
-
.register_column(:members,
|
52
|
+
filter.register_column(:names, field: "name")
|
53
|
+
.register_column(:gids, field: "gid")
|
54
|
+
.register_column(:domains, field: "domain")
|
55
|
+
.register_column(:members, field: "members", style: :simple)
|
56
|
+
.register_column(:members_array, field: "members_array", style: :simple)
|
56
57
|
filter.install_filter_methods_on_resource(self, :collect_group_details)
|
57
58
|
|
58
59
|
def to_s
|
@@ -63,7 +64,13 @@ module Inspec::Resources
|
|
63
64
|
|
64
65
|
# collects information about every group
|
65
66
|
def collect_group_details
|
66
|
-
|
67
|
+
unless @group_provider.nil?
|
68
|
+
modified_groups_info = @group_provider.groups
|
69
|
+
unless modified_groups_info.empty?
|
70
|
+
modified_groups_info.each { |hashmap| hashmap["members_array"] = hashmap["members"].is_a?(Array) ? hashmap["members"] : hashmap["members"]&.split(",") }
|
71
|
+
end
|
72
|
+
return @groups_cache ||= modified_groups_info
|
73
|
+
end
|
67
74
|
|
68
75
|
[]
|
69
76
|
end
|
@@ -111,7 +118,11 @@ module Inspec::Resources
|
|
111
118
|
end
|
112
119
|
|
113
120
|
def members
|
114
|
-
flatten_entry(group_info, "members")
|
121
|
+
flatten_entry(group_info, "members") || empty_value_for_members
|
122
|
+
end
|
123
|
+
|
124
|
+
def members_array
|
125
|
+
flatten_entry(group_info, "members_array") || []
|
115
126
|
end
|
116
127
|
|
117
128
|
def local
|
@@ -141,6 +152,10 @@ module Inspec::Resources
|
|
141
152
|
group = @group.dup
|
142
153
|
@groups_cache ||= inspec.groups.where { name == group }
|
143
154
|
end
|
155
|
+
|
156
|
+
def empty_value_for_members
|
157
|
+
inspec.os.windows? ? [] : ""
|
158
|
+
end
|
144
159
|
end
|
145
160
|
|
146
161
|
class GroupInfo
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require "inspec/resources/command"
|
2
|
+
require "inspec/utils/filter"
|
3
|
+
|
4
|
+
module Inspec::Resources
|
5
|
+
class SelinuxModuleFilter
|
6
|
+
# use filtertable for SELinux Modules
|
7
|
+
filter = FilterTable.create
|
8
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
9
|
+
filter.register_column(:names, field: :name)
|
10
|
+
filter.register_column(:status, field: :status)
|
11
|
+
filter.register_column(:states, field: :state)
|
12
|
+
filter.register_column(:priorities , field: :priority)
|
13
|
+
filter.register_custom_matcher(:enabled?) { |x| x.states[0] == "enabled" }
|
14
|
+
filter.register_custom_matcher(:installed?) { |x| x.status[0] == "installed" }
|
15
|
+
filter.install_filter_methods_on_resource(self, :modules)
|
16
|
+
|
17
|
+
attr_reader :modules
|
18
|
+
def initialize(modules)
|
19
|
+
@modules = modules
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
"SELinux modules"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class SelinuxBooleanFilter
|
28
|
+
# use filtertable for SELinux Booleans
|
29
|
+
filter = FilterTable.create
|
30
|
+
filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
|
31
|
+
filter.register_column(:names, field: :name)
|
32
|
+
filter.register_column(:states, field: :state)
|
33
|
+
filter.register_column(:defaults, field: :default)
|
34
|
+
filter.register_custom_matcher(:on?) { |x| x.states[0] == "on" }
|
35
|
+
filter.install_filter_methods_on_resource(self, :booleans)
|
36
|
+
|
37
|
+
attr_reader :booleans
|
38
|
+
def initialize(booleans)
|
39
|
+
@booleans = booleans
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_s
|
43
|
+
"SELinux booleans"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Selinux < Inspec.resource(1)
|
48
|
+
name "selinux"
|
49
|
+
supports platform: "linux"
|
50
|
+
|
51
|
+
desc "Use the selinux Chef InSpec resource to test the configuration data of the SELinux policy, SELinux modules, and SELinux booleans."
|
52
|
+
|
53
|
+
example <<~EXAMPLE
|
54
|
+
describe selinux do
|
55
|
+
it { should be_installed }
|
56
|
+
it { should be_disabled }
|
57
|
+
it { should be_permissive }
|
58
|
+
it { should be_enforcing }
|
59
|
+
end
|
60
|
+
|
61
|
+
describe selinux do
|
62
|
+
its('policy') { should eq "targeted"}
|
63
|
+
end
|
64
|
+
|
65
|
+
describe selinux.modules.where("zebra") do
|
66
|
+
it { should exist }
|
67
|
+
it { should be_installed }
|
68
|
+
it { should be_enabled }
|
69
|
+
end
|
70
|
+
|
71
|
+
describe selinux.modules.where(status: "installed") do
|
72
|
+
it { should exist }
|
73
|
+
its('count') { should cmp 404 }
|
74
|
+
end
|
75
|
+
|
76
|
+
describe selinux.booleans.where(name: "xend_run_blktap") do
|
77
|
+
it { should be_on }
|
78
|
+
end
|
79
|
+
|
80
|
+
describe selinux.booleans.where { name == "xend_run_blktap" && state == "on" } do
|
81
|
+
it { should exist }
|
82
|
+
end
|
83
|
+
EXAMPLE
|
84
|
+
|
85
|
+
def initialize(selinux_path = "/etc/selinux/config")
|
86
|
+
@path = selinux_path
|
87
|
+
cmd = inspec.command("sestatus")
|
88
|
+
|
89
|
+
if cmd.exit_status != 0
|
90
|
+
# `sestatus` command not found error message comes in stdout so handling both here
|
91
|
+
out = cmd.stdout + "\n" + cmd.stderr
|
92
|
+
return skip_resource "Skipping resource: #{out}"
|
93
|
+
end
|
94
|
+
|
95
|
+
result = cmd.stdout.delete(" ").gsub(/\n/, ",").gsub(/\r/, "").downcase
|
96
|
+
@data = Hash[result.scan(/([^:]+):([^,]+)[,$]/)]
|
97
|
+
end
|
98
|
+
|
99
|
+
def installed?
|
100
|
+
inspec.file(@path).exist?
|
101
|
+
end
|
102
|
+
|
103
|
+
def disabled?
|
104
|
+
@data["selinuxstatus"] == "disabled"
|
105
|
+
end
|
106
|
+
|
107
|
+
def enforcing?
|
108
|
+
@data["currentmode"] == "enforcing"
|
109
|
+
end
|
110
|
+
|
111
|
+
def permissive?
|
112
|
+
@data["currentmode"] == "permissive"
|
113
|
+
end
|
114
|
+
|
115
|
+
def policy
|
116
|
+
@data["loadedpolicyname"]
|
117
|
+
end
|
118
|
+
|
119
|
+
def modules
|
120
|
+
SelinuxModuleFilter.new(parse_modules)
|
121
|
+
end
|
122
|
+
|
123
|
+
def booleans
|
124
|
+
SelinuxBooleanFilter.new(parse_booleans)
|
125
|
+
end
|
126
|
+
|
127
|
+
def to_s
|
128
|
+
"SELinux"
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def parse_modules
|
134
|
+
raw_modules = inspec.command("semodule -lfull").stdout
|
135
|
+
r_modules = []
|
136
|
+
raw_modules.each_line do |entry|
|
137
|
+
data = entry.split.map(&:strip)
|
138
|
+
state = data.length == 4 ? data[3] : "enabled"
|
139
|
+
r_modules.push({ name: data[1], status: "installed", state: state, priority: data[0] })
|
140
|
+
end
|
141
|
+
r_modules
|
142
|
+
end
|
143
|
+
|
144
|
+
def parse_booleans
|
145
|
+
raw_booleans = inspec.command("semanage boolean -l -n").stdout
|
146
|
+
r_booleans = []
|
147
|
+
raw_booleans.each_line do |entry|
|
148
|
+
data = entry.scan(/([^(,)]+)/).flatten.map(&:strip)
|
149
|
+
r_booleans.push({ name: data[0], state: data[1], default: data[2] })
|
150
|
+
end
|
151
|
+
r_booleans
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -105,7 +105,7 @@ module Inspec::Resources
|
|
105
105
|
# @see https://github.com/chef/chef/blob/master/lib/chef/resource/windows_firewall_rule.rb
|
106
106
|
def load_firewall_state(rule_name)
|
107
107
|
<<-EOH
|
108
|
-
|
108
|
+
Get-TypeData -TypeName System.Array | Remove-TypeData # workaround for PS bug here: https://bit.ly/2SRMQ8M
|
109
109
|
$rule = Get-NetFirewallRule -Name "#{rule_name}"
|
110
110
|
$addressFilter = $rule | Get-NetFirewallAddressFilter
|
111
111
|
$portFilter = $rule | Get-NetFirewallPortFilter
|
data/lib/inspec/rule.rb
CHANGED
@@ -180,7 +180,15 @@ module Inspec
|
|
180
180
|
options[:priority] ||= 20
|
181
181
|
options[:provider] = :inline_control_code
|
182
182
|
evt = Inspec::Input.infer_event(options)
|
183
|
-
Inspec::InputRegistry.find_or_register_input(
|
183
|
+
Inspec::InputRegistry.find_or_register_input(
|
184
|
+
input_name,
|
185
|
+
__profile_id,
|
186
|
+
type: options[:type],
|
187
|
+
required: options[:required],
|
188
|
+
description: options[:description],
|
189
|
+
pattern: options[:pattern],
|
190
|
+
event: evt
|
191
|
+
).value
|
184
192
|
end
|
185
193
|
end
|
186
194
|
|
data/lib/inspec/version.rb
CHANGED
@@ -6,24 +6,50 @@ This extensions offers the following features:
|
|
6
6
|
- execute profiles directly from Chef Automate/Chef Compliance locally
|
7
7
|
- upload a local profile to Chef Automate/Chef Compliance
|
8
8
|
|
9
|
+
`inspec compliance` is a backwards compatible alias for `inspec automate` and works the same way.
|
10
|
+
|
9
11
|
To use the CLI, this InSpec add-on adds the following commands:
|
10
12
|
|
13
|
+
* `$ inspec automate login` - authentication of the API token against Chef Automate/Chef Compliance
|
14
|
+
* `$ inspec automate profiles` - list all available Compliance profiles
|
15
|
+
* `$ inspec exec compliance://profile` - runs a Compliance profile
|
16
|
+
* `$ inspec automate upload path/to/local/profile` - uploads a local profile to Chef Automate/Chef Compliance
|
17
|
+
* `$ inspec automate logout` - logout of Chef Automate/Chef Compliance
|
18
|
+
|
19
|
+
Similar to these CLI commands are:
|
20
|
+
|
11
21
|
* `$ inspec compliance login` - authentication of the API token against Chef Automate/Chef Compliance
|
12
22
|
* `$ inspec compliance profiles` - list all available Compliance profiles
|
13
|
-
* `$ inspec exec compliance://profile` - runs a Compliance profile
|
14
23
|
* `$ inspec compliance upload path/to/local/profile` - uploads a local profile to Chef Automate/Chef Compliance
|
15
24
|
* `$ inspec compliance logout` - logout of Chef Automate/Chef Compliance
|
16
25
|
|
17
26
|
Compliance profiles can be executed in two ways:
|
18
27
|
|
19
|
-
- via compliance exec: `inspec compliance exec profile`
|
28
|
+
- via compliance exec: `inspec automate exec profile` or `inspec compliance exec profile`
|
20
29
|
- via compliance scheme: `inspec exec compliance://profile`
|
21
30
|
|
22
31
|
|
32
|
+
|
33
|
+
|
23
34
|
## Usage
|
24
35
|
|
25
36
|
### Command options
|
26
37
|
|
38
|
+
```
|
39
|
+
$ inspec automate
|
40
|
+
Commands:
|
41
|
+
inspec automate download PROFILE # downloads a profile from Chef Compliance
|
42
|
+
inspec automate exec PROFILE # executes a Chef Compliance profile
|
43
|
+
inspec automate help [COMMAND] # Describe subcommands or one specific subcommand
|
44
|
+
inspec automate login SERVER # Log in to a Chef Automate/Chef Compliance SERVER
|
45
|
+
inspec automate logout # user logout from Chef Compliance
|
46
|
+
inspec automate profiles # list all available profiles in Chef Compliance
|
47
|
+
inspec automate upload PATH # uploads a local profile to Chef Compliance
|
48
|
+
inspec automate version # displays the version of the Chef Compliance server
|
49
|
+
```
|
50
|
+
|
51
|
+
or
|
52
|
+
|
27
53
|
```
|
28
54
|
$ inspec compliance
|
29
55
|
Commands:
|
@@ -41,6 +67,12 @@ Commands:
|
|
41
67
|
|
42
68
|
You will need an API token for authentication. You can retrieve one via the admin section of your A2 web gui.
|
43
69
|
|
70
|
+
```
|
71
|
+
$ inspec automate login https://automate2.compliance.test --insecure --user 'admin' --token 'zuop..._KzE'
|
72
|
+
```
|
73
|
+
|
74
|
+
or
|
75
|
+
|
44
76
|
```
|
45
77
|
$ inspec compliance login https://automate2.compliance.test --insecure --user 'admin' --token 'zuop..._KzE'
|
46
78
|
```
|
@@ -63,6 +95,12 @@ Example:
|
|
63
95
|
|
64
96
|
You will need an access token for authentication. You can retrieve one via [UI](https://docs.chef.io/api_delivery.html) or [CLI](https://docs.chef.io/ctl_delivery.html#delivery-token).
|
65
97
|
|
98
|
+
```
|
99
|
+
$ inspec automate login https://automate.compliance.test --insecure --user 'admin' --ent 'brewinc' --token 'zuop..._KzE'
|
100
|
+
```
|
101
|
+
|
102
|
+
or
|
103
|
+
|
66
104
|
```
|
67
105
|
$ inspec compliance login https://automate.compliance.test --insecure --user 'admin' --ent 'brewinc' --token 'zuop..._KzE'
|
68
106
|
```
|
@@ -75,12 +113,42 @@ You will need an access token for authentication. You can retrieve one via:
|
|
75
113
|
|
76
114
|
You can choose the access token (`--token`) or the refresh token (`--refresh_token`)
|
77
115
|
|
116
|
+
```
|
117
|
+
$ inspec automate login https://compliance.test --user admin --insecure --token '...'
|
118
|
+
```
|
119
|
+
|
120
|
+
or
|
121
|
+
|
78
122
|
```
|
79
123
|
$ inspec compliance login https://compliance.test --user admin --insecure --token '...'
|
80
124
|
```
|
81
125
|
|
82
126
|
### List available profiles via Chef Compliance / Automate
|
83
127
|
|
128
|
+
```
|
129
|
+
$ inspec automate profiles
|
130
|
+
Available profiles:
|
131
|
+
-------------------
|
132
|
+
* base/apache
|
133
|
+
* base/linux
|
134
|
+
* base/mysql
|
135
|
+
* base/postgres
|
136
|
+
* base/ssh
|
137
|
+
* base/windows
|
138
|
+
* cis/cis-centos6-level1
|
139
|
+
* cis/cis-centos6-level2
|
140
|
+
* cis/cis-centos7-level1
|
141
|
+
* cis/cis-centos7-level2
|
142
|
+
* cis/cis-rhel7-level1
|
143
|
+
* cis/cis-rhel7-level2
|
144
|
+
* cis/cis-ubuntu12.04lts-level1
|
145
|
+
* cis/cis-ubuntu12.04lts-level2
|
146
|
+
* cis/cis-ubuntu14.04lts-level1
|
147
|
+
* cis/cis-ubuntu14.04lts-level2
|
148
|
+
```
|
149
|
+
|
150
|
+
or
|
151
|
+
|
84
152
|
```
|
85
153
|
$ inspec compliance profiles
|
86
154
|
Available profiles:
|
@@ -105,6 +173,47 @@ Available profiles:
|
|
105
173
|
|
106
174
|
### Upload a profile to Chef Compliance / Automate
|
107
175
|
|
176
|
+
```
|
177
|
+
$ inspec automate version
|
178
|
+
Chef Compliance version: 1.0.11
|
179
|
+
➜ inspec git:(chris-rock/cc-error-not-loggedin) ✗ b inspec automate upload examples/profile
|
180
|
+
I, [2016-05-06T14:27:20.907547 #37592] INFO -- : Checking profile in examples/profile
|
181
|
+
I, [2016-05-06T14:27:20.907668 #37592] INFO -- : Metadata OK.
|
182
|
+
I, [2016-05-06T14:27:20.968584 #37592] INFO -- : Found 4 controls.
|
183
|
+
I, [2016-05-06T14:27:20.968638 #37592] INFO -- : Control definitions OK.
|
184
|
+
Profile is valid
|
185
|
+
Generate temporary profile archive at /var/folders/jy/2bnrfb4s36jbjtzllvhhyqhw0000gn/T/profile20160506-37592-1tf326f.tar.gz
|
186
|
+
I, [2016-05-06T14:27:21.020017 #37592] INFO -- : Generate archive /var/folders/jy/2bnrfb4s36jbjtzllvhhyqhw0000gn/T/profile20160506-37592-1tf326f.tar.gz.
|
187
|
+
I, [2016-05-06T14:27:21.024837 #37592] INFO -- : Finished archive generation.
|
188
|
+
Start upload to admin/profile
|
189
|
+
Uploading to Chef Compliance
|
190
|
+
Successfully uploaded profile
|
191
|
+
|
192
|
+
# display all profiles
|
193
|
+
$ inspec automate profiles
|
194
|
+
Available profiles:
|
195
|
+
-------------------
|
196
|
+
* admin/profile
|
197
|
+
* base/apache
|
198
|
+
* base/linux
|
199
|
+
* base/mysql
|
200
|
+
* base/postgres
|
201
|
+
* base/ssh
|
202
|
+
* base/windows
|
203
|
+
* cis/cis-centos6-level1
|
204
|
+
* cis/cis-centos6-level2
|
205
|
+
* cis/cis-centos7-level1
|
206
|
+
* cis/cis-centos7-level2
|
207
|
+
* cis/cis-rhel7-level1
|
208
|
+
* cis/cis-rhel7-level2
|
209
|
+
* cis/cis-ubuntu12.04lts-level1
|
210
|
+
* cis/cis-ubuntu12.04lts-level2
|
211
|
+
* cis/cis-ubuntu14.04lts-level1
|
212
|
+
* cis/cis-ubuntu14.04lts-level2
|
213
|
+
```
|
214
|
+
|
215
|
+
or
|
216
|
+
|
108
217
|
```
|
109
218
|
$ inspec compliance version
|
110
219
|
Chef Compliance version: 1.0.11
|
@@ -168,17 +277,31 @@ $ inspec exec compliance://admin/apache-baseline#2.0.1
|
|
168
277
|
```
|
169
278
|
|
170
279
|
Download a specific version(2.0.2) of a profile when logged in with Automate:
|
280
|
+
```
|
281
|
+
$ inspec automate download compliance://admin/apache-baseline#2.0.2
|
282
|
+
```
|
283
|
+
|
284
|
+
or
|
285
|
+
|
171
286
|
```
|
172
287
|
$ inspec compliance download compliance://admin/apache-baseline#2.0.2
|
173
288
|
```
|
174
289
|
|
175
290
|
### To Logout from Chef Compliance
|
176
291
|
|
292
|
+
```
|
293
|
+
$ inspec automate logout
|
294
|
+
Successfully logged out
|
295
|
+
```
|
296
|
+
|
297
|
+
or
|
298
|
+
|
177
299
|
```
|
178
300
|
$ inspec compliance logout
|
179
301
|
Successfully logged out
|
180
302
|
```
|
181
303
|
|
304
|
+
|
182
305
|
## Integration Tests
|
183
306
|
|
184
307
|
At this point of time, InSpec is not able to pick up the token directly, therefore the integration test is semi-automatic at this point of time:
|
@@ -7,6 +7,11 @@ module InspecPlugins
|
|
7
7
|
require_relative "inspec-compliance/cli"
|
8
8
|
InspecPlugins::Compliance::CLI
|
9
9
|
end
|
10
|
+
|
11
|
+
cli_command :automate do
|
12
|
+
require_relative "inspec-compliance/cli"
|
13
|
+
InspecPlugins::Compliance::CLI
|
14
|
+
end
|
10
15
|
end
|
11
16
|
|
12
17
|
autoload :Configuration, "plugins/inspec-compliance/lib/inspec-compliance/configuration"
|
@@ -9,7 +9,7 @@ module InspecPlugins
|
|
9
9
|
class CannotDetermineServerType < StandardError; end
|
10
10
|
|
11
11
|
def login(options)
|
12
|
-
raise ArgumentError, "Please specify a server using `#{EXEC_NAME} compliance login https://SERVER`" unless options["server"]
|
12
|
+
raise ArgumentError, "Please specify a server using `#{EXEC_NAME} automate login https://SERVER` or `#{EXEC_NAME} compliance login https://SERVER`" unless options["server"]
|
13
13
|
|
14
14
|
options["server"] = URI("https://#{options["server"]}").to_s if URI(options["server"]).scheme.nil?
|
15
15
|
|
@@ -179,7 +179,7 @@ module InspecPlugins
|
|
179
179
|
def self.compliance_verify_thor_options(o)
|
180
180
|
error_msg = []
|
181
181
|
|
182
|
-
error_msg.push("Please specify a server using `#{EXEC_NAME} compliance login https://SERVER`") if o["server"].nil?
|
182
|
+
error_msg.push("Please specify a server using `#{EXEC_NAME} automate login https://SERVER` or `#{EXEC_NAME} compliance login https://SERVER`") if o["server"].nil?
|
183
183
|
|
184
184
|
if o["user"].nil? && o["refresh_token"].nil?
|
185
185
|
error_msg.push("Please specify a `--user='USER'` or a `--refresh-token='TOKEN'`")
|
@@ -6,13 +6,12 @@ module InspecPlugins
|
|
6
6
|
module Compliance
|
7
7
|
class CLI < Inspec.plugin(2, :cli_command)
|
8
8
|
include Inspec::Dist
|
9
|
-
|
10
|
-
subcommand_desc "compliance SUBCOMMAND", "#{COMPLIANCE_PRODUCT_NAME} commands"
|
9
|
+
subcommand_desc "automate SUBCOMMAND or compliance SUBCOMMAND", "#{AUTOMATE_PRODUCT_NAME} commands"
|
11
10
|
|
12
11
|
# desc "login https://SERVER --insecure --user='USER' --ent='ENTERPRISE' --token='TOKEN'", 'Log in to a Chef Compliance/Chef Automate SERVER'
|
13
|
-
desc "login", "Log in to a #{
|
12
|
+
desc "login", "Log in to a #{AUTOMATE_PRODUCT_NAME} SERVER"
|
14
13
|
long_desc <<-LONGDESC
|
15
|
-
`login` allows you to use InSpec with #{AUTOMATE_PRODUCT_NAME}
|
14
|
+
`login` allows you to use InSpec with #{AUTOMATE_PRODUCT_NAME} Server
|
16
15
|
|
17
16
|
You need to a token for communication. More information about token retrieval
|
18
17
|
is available at:
|
@@ -24,11 +23,11 @@ module InspecPlugins
|
|
24
23
|
option :user, type: :string, required: false,
|
25
24
|
desc: "Username"
|
26
25
|
option :password, type: :string, required: false,
|
27
|
-
desc: "Password (#{
|
26
|
+
desc: "Password (#{AUTOMATE_PRODUCT_NAME} Only)"
|
28
27
|
option :token, type: :string, required: false,
|
29
28
|
desc: "Access token"
|
30
29
|
option :refresh_token, type: :string, required: false,
|
31
|
-
desc: "#{
|
30
|
+
desc: "#{AUTOMATE_PRODUCT_NAME} refresh token (#{AUTOMATE_PRODUCT_NAME} Only)"
|
32
31
|
option :dctoken, type: :string, required: false,
|
33
32
|
desc: "Data Collector token (#{AUTOMATE_PRODUCT_NAME} Only)"
|
34
33
|
option :ent, type: :string, required: false,
|
@@ -40,7 +39,7 @@ module InspecPlugins
|
|
40
39
|
puts "Stored configuration for Chef #{config["server_type"].capitalize}: #{config["server"]}' with user: '#{config["user"]}'"
|
41
40
|
end
|
42
41
|
|
43
|
-
desc "profiles", "list all available profiles in #{
|
42
|
+
desc "profiles", "list all available profiles in #{AUTOMATE_PRODUCT_NAME}"
|
44
43
|
option :owner, type: :string, required: false,
|
45
44
|
desc: "owner whose profiles to list"
|
46
45
|
def profiles
|
@@ -65,11 +64,11 @@ module InspecPlugins
|
|
65
64
|
exit 1
|
66
65
|
end
|
67
66
|
rescue InspecPlugins::Compliance::ServerConfigurationMissing
|
68
|
-
$stderr.puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME}
|
67
|
+
$stderr.puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME} #{subcommand_name} login`"
|
69
68
|
exit 1
|
70
69
|
end
|
71
70
|
|
72
|
-
desc "exec PROFILE", "executes a #{
|
71
|
+
desc "exec PROFILE", "executes a #{AUTOMATE_PRODUCT_NAME} profile"
|
73
72
|
exec_options
|
74
73
|
def exec(*tests)
|
75
74
|
compliance_config = InspecPlugins::Compliance::Configuration.new
|
@@ -91,7 +90,7 @@ module InspecPlugins
|
|
91
90
|
exit 1
|
92
91
|
end
|
93
92
|
|
94
|
-
desc "download PROFILE", "downloads a profile from #{
|
93
|
+
desc "download PROFILE", "downloads a profile from #{AUTOMATE_PRODUCT_NAME}"
|
95
94
|
option :name, type: :string,
|
96
95
|
desc: "Name of the archive filename (file type will be added)"
|
97
96
|
def download(profile_name)
|
@@ -116,12 +115,12 @@ module InspecPlugins
|
|
116
115
|
file_name = fetcher.fetch(o.name || id)
|
117
116
|
puts "Profile stored to #{file_name}"
|
118
117
|
else
|
119
|
-
puts "Profile #{profile_name} is not available in #{
|
118
|
+
puts "Profile #{profile_name} is not available in #{AUTOMATE_PRODUCT_NAME}."
|
120
119
|
exit 1
|
121
120
|
end
|
122
121
|
end
|
123
122
|
|
124
|
-
desc "upload PATH", "uploads a local profile to #{
|
123
|
+
desc "upload PATH", "uploads a local profile to #{AUTOMATE_PRODUCT_NAME}"
|
125
124
|
option :overwrite, type: :boolean, default: false,
|
126
125
|
desc: "Overwrite existing profile on Server."
|
127
126
|
option :owner, type: :string, required: false,
|
@@ -167,7 +166,7 @@ module InspecPlugins
|
|
167
166
|
|
168
167
|
# determine user information
|
169
168
|
if (config["token"].nil? && config["refresh_token"].nil?) || config["user"].nil?
|
170
|
-
error.call("Please login via `#{EXEC_NAME}
|
169
|
+
error.call("Please login via `#{EXEC_NAME} #{subcommand_name} login`")
|
171
170
|
end
|
172
171
|
|
173
172
|
# read profile name from inspec.yml
|
@@ -202,11 +201,8 @@ module InspecPlugins
|
|
202
201
|
puts "Start upload to #{config["owner"]}/#{profile_name}"
|
203
202
|
pname = ERB::Util.url_encode(profile_name)
|
204
203
|
|
205
|
-
|
206
|
-
|
207
|
-
else
|
208
|
-
puts "Uploading to #{COMPLIANCE_PRODUCT_NAME}"
|
209
|
-
end
|
204
|
+
puts "Uploading to #{AUTOMATE_PRODUCT_NAME}"
|
205
|
+
|
210
206
|
success, msg = InspecPlugins::Compliance::API.upload(config, config["owner"], pname, archive_path)
|
211
207
|
|
212
208
|
# delete temp file if it was temporary generated
|
@@ -221,7 +217,7 @@ module InspecPlugins
|
|
221
217
|
end
|
222
218
|
end
|
223
219
|
|
224
|
-
desc "version", "displays the version of the #{
|
220
|
+
desc "version", "displays the version of the #{AUTOMATE_PRODUCT_NAME} server"
|
225
221
|
def version
|
226
222
|
config = InspecPlugins::Compliance::Configuration.new
|
227
223
|
info = InspecPlugins::Compliance::API.version(config)
|
@@ -233,11 +229,11 @@ module InspecPlugins
|
|
233
229
|
exit 1
|
234
230
|
end
|
235
231
|
rescue InspecPlugins::Compliance::ServerConfigurationMissing
|
236
|
-
puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME}
|
232
|
+
puts "\nServer configuration information is missing. Please login using `#{EXEC_NAME} #{subcommand_name} login`"
|
237
233
|
exit 1
|
238
234
|
end
|
239
235
|
|
240
|
-
desc "logout", "user logout from #{
|
236
|
+
desc "logout", "user logout from #{AUTOMATE_PRODUCT_NAME}"
|
241
237
|
def logout
|
242
238
|
config = InspecPlugins::Compliance::Configuration.new
|
243
239
|
unless config.supported?(:oidc) || config["token"].nil? || config["server_type"] == "automate"
|
@@ -258,9 +254,13 @@ module InspecPlugins
|
|
258
254
|
|
259
255
|
def loggedin(config)
|
260
256
|
serverknown = !config["server"].nil?
|
261
|
-
puts "You need to login first with `#{EXEC_NAME}
|
257
|
+
puts "You need to login first with `#{EXEC_NAME} #{subcommand_name} login`" unless serverknown
|
262
258
|
serverknown
|
263
259
|
end
|
260
|
+
|
261
|
+
def subcommand_name
|
262
|
+
@_invocations[Inspec::InspecCLI]&.first || "automate"
|
263
|
+
end
|
264
264
|
end
|
265
265
|
|
266
266
|
# register the subcommand to InSpec CLI registry
|
@@ -34,13 +34,13 @@ module InspecPlugins
|
|
34
34
|
if config["token"].nil? && config["refresh_token"].nil?
|
35
35
|
if config["server_type"] == "automate"
|
36
36
|
server = "automate"
|
37
|
-
msg = "#{EXEC_NAME} compliance login https://your_automate_server --user USER --ent ENT --dctoken DCTOKEN or --token USERTOKEN"
|
37
|
+
msg = "#{EXEC_NAME} [automate|compliance] login https://your_automate_server --user USER --ent ENT --dctoken DCTOKEN or --token USERTOKEN"
|
38
38
|
elsif config["server_type"] == "automate2"
|
39
39
|
server = "automate2"
|
40
|
-
msg = "#{EXEC_NAME} compliance login https://your_automate2_server --user USER --token APITOKEN"
|
40
|
+
msg = "#{EXEC_NAME} [automate|compliance] login https://your_automate2_server --user USER --token APITOKEN"
|
41
41
|
else
|
42
42
|
server = "compliance"
|
43
|
-
msg = "#{EXEC_NAME} compliance login https://your_compliance_server --user admin --insecure --token 'PASTE TOKEN HERE' "
|
43
|
+
msg = "#{EXEC_NAME} [automate|compliance] login https://your_compliance_server --user admin --insecure --token 'PASTE TOKEN HERE' "
|
44
44
|
end
|
45
45
|
raise Inspec::FetcherFailure, <<~EOF
|
46
46
|
|
@@ -112,7 +112,7 @@ module InspecPlugins
|
|
112
112
|
end
|
113
113
|
|
114
114
|
def to_s
|
115
|
-
"#{
|
115
|
+
"#{AUTOMATE_PRODUCT_NAME} Profile Loader"
|
116
116
|
end
|
117
117
|
|
118
118
|
private
|
@@ -136,6 +136,7 @@ module InspecPlugins
|
|
136
136
|
if m.nil?
|
137
137
|
raise "Unable to determine compliance profile name. This can be caused by " \
|
138
138
|
"an incorrect server in your configuration. Try to login to compliance " \
|
139
|
+
"via the `#{EXEC_NAME} automate login` command or " \
|
139
140
|
"via the `#{EXEC_NAME} compliance login` command."
|
140
141
|
end
|
141
142
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inspec-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.37.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef InSpec Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-telemetry
|
@@ -17,6 +17,9 @@ dependencies:
|
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.8
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -24,6 +27,9 @@ dependencies:
|
|
24
27
|
- - "~>"
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '1.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.8
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: license-acceptance
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -223,7 +229,7 @@ dependencies:
|
|
223
229
|
version: 0.9.0
|
224
230
|
- - "<"
|
225
231
|
- !ruby/object:Gem::Version
|
226
|
-
version: '1.
|
232
|
+
version: '1.5'
|
227
233
|
type: :runtime
|
228
234
|
prerelease: false
|
229
235
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -233,7 +239,7 @@ dependencies:
|
|
233
239
|
version: 0.9.0
|
234
240
|
- - "<"
|
235
241
|
- !ruby/object:Gem::Version
|
236
|
-
version: '1.
|
242
|
+
version: '1.5'
|
237
243
|
- !ruby/object:Gem::Dependency
|
238
244
|
name: faraday_middleware
|
239
245
|
requirement: !ruby/object:Gem::Requirement
|
@@ -586,6 +592,7 @@ files:
|
|
586
592
|
- lib/inspec/resources/script.rb
|
587
593
|
- lib/inspec/resources/security_identifier.rb
|
588
594
|
- lib/inspec/resources/security_policy.rb
|
595
|
+
- lib/inspec/resources/selinux.rb
|
589
596
|
- lib/inspec/resources/service.rb
|
590
597
|
- lib/inspec/resources/shadow.rb
|
591
598
|
- lib/inspec/resources/ssh_config.rb
|