inspec-core 5.18.14 → 5.22.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +19 -17
- data/inspec-core.gemspec +22 -22
- data/lib/inspec/base_cli.rb +19 -17
- data/lib/inspec/cli.rb +27 -25
- data/lib/inspec/dependencies/dependency_set.rb +2 -2
- data/lib/inspec/dsl.rb +9 -5
- data/lib/inspec/enhanced_outcomes.rb +19 -0
- data/lib/inspec/env_printer.rb +1 -1
- data/lib/inspec/exceptions.rb +2 -0
- data/lib/inspec/formatters/base.rb +69 -16
- data/lib/inspec/plugin/v2/loader.rb +19 -8
- data/lib/inspec/plugin/v2/plugin_types/reporter.rb +1 -0
- data/lib/inspec/plugin/v2/plugin_types/streaming_reporter.rb +54 -0
- data/lib/inspec/profile.rb +9 -8
- data/lib/inspec/reporters/base.rb +1 -0
- data/lib/inspec/reporters/cli.rb +94 -3
- data/lib/inspec/reporters/json.rb +3 -1
- data/lib/inspec/reporters/yaml.rb +3 -1
- data/lib/inspec/reporters.rb +2 -1
- data/lib/inspec/resources/file.rb +1 -1
- data/lib/inspec/resources/http.rb +5 -5
- data/lib/inspec/resources/lxc.rb +65 -9
- data/lib/inspec/resources/mongodb_session.rb +5 -0
- data/lib/inspec/resources/nftables.rb +251 -0
- data/lib/inspec/resources/oracledb_session.rb +13 -4
- data/lib/inspec/resources/podman.rb +353 -0
- data/lib/inspec/resources/podman_container.rb +84 -0
- data/lib/inspec/resources/podman_image.rb +108 -0
- data/lib/inspec/resources/podman_network.rb +81 -0
- data/lib/inspec/resources/podman_pod.rb +101 -0
- data/lib/inspec/resources/podman_volume.rb +87 -0
- data/lib/inspec/resources/postgres_session.rb +2 -1
- data/lib/inspec/resources/service.rb +1 -1
- data/lib/inspec/resources.rb +1 -0
- data/lib/inspec/rule.rb +54 -17
- data/lib/inspec/run_data/control.rb +6 -0
- data/lib/inspec/run_data/statistics.rb +8 -2
- data/lib/inspec/runner.rb +18 -8
- data/lib/inspec/runner_rspec.rb +3 -2
- data/lib/inspec/schema/exec_json.rb +78 -2
- data/lib/inspec/schema/output_schema.rb +4 -1
- data/lib/inspec/schema/profile_json.rb +46 -0
- data/lib/inspec/schema.rb +91 -0
- data/lib/inspec/utils/convert.rb +8 -0
- data/lib/inspec/utils/podman.rb +24 -0
- data/lib/inspec/utils/simpleconfig.rb +10 -2
- data/lib/inspec/utils/waivers/csv_file_reader.rb +34 -0
- data/lib/inspec/utils/waivers/excel_file_reader.rb +39 -0
- data/lib/inspec/utils/waivers/json_file_reader.rb +15 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/inspec/waiver_file_reader.rb +61 -0
- data/lib/matchers/matchers.rb +15 -2
- data/lib/plugins/inspec-init/templates/profiles/alicloud/README.md +27 -0
- data/lib/plugins/inspec-init/templates/profiles/alicloud/controls/example.rb +10 -0
- data/lib/plugins/inspec-init/templates/profiles/alicloud/inputs.yml +1 -0
- data/lib/plugins/inspec-init/templates/profiles/alicloud/inspec.yml +14 -0
- data/lib/plugins/inspec-reporter-html2/README.md +1 -1
- data/lib/plugins/inspec-reporter-html2/templates/body.html.erb +7 -1
- data/lib/plugins/inspec-reporter-html2/templates/control.html.erb +10 -6
- data/lib/plugins/inspec-reporter-html2/templates/default.css +12 -0
- data/lib/plugins/inspec-reporter-html2/templates/selector.html.erb +7 -1
- data/lib/plugins/inspec-sign/lib/inspec-sign/base.rb +5 -2
- data/lib/plugins/inspec-streaming-reporter-progress-bar/lib/inspec-streaming-reporter-progress-bar/streaming_reporter.rb +39 -13
- metadata +26 -9
@@ -178,7 +178,19 @@ module Inspec::Plugin::V2
|
|
178
178
|
# TODO: enforce first-level version pinning
|
179
179
|
plugin_deps = [Gem::Dependency.new(plugin_gem_name.to_s, version_constraint)]
|
180
180
|
managed_gem_set = Gem::Resolver::VendorSet.new
|
181
|
-
|
181
|
+
|
182
|
+
list_managed_gems.each do |spec|
|
183
|
+
if Gem::Specification.load spec.gem_dir
|
184
|
+
managed_gem_set.add_vendor_gem(spec.name, spec.gem_dir)
|
185
|
+
else
|
186
|
+
# In case of invalid gemspec as mentioned in this PR https://github.com/brianmario/yajl-ruby/pull/223
|
187
|
+
# the add_vendor_gem breaks. So this is patch to fix the loading issue.
|
188
|
+
# Horribly, chdir to gemspec path to honor . in gemspec
|
189
|
+
Dir.chdir(spec.gem_dir) do |dir|
|
190
|
+
managed_gem_set.add_vendor_gem(spec.name, spec.gem_dir)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
182
194
|
|
183
195
|
# TODO: Next two lines merge our managed gems with the other gems available
|
184
196
|
# in our "local universe" - which may be the system, or it could be in a Bundler microcosm,
|
@@ -278,7 +290,12 @@ module Inspec::Plugin::V2
|
|
278
290
|
when :user_gem
|
279
291
|
status.entry_point = status.name.to_s
|
280
292
|
status.version = plugin_entry[:version]
|
281
|
-
|
293
|
+
# Fetch the summary of the gem from local gemspec file instead of remote call using Gem::SpecFetcher.fetcher.
|
294
|
+
unless plugin_entry[:version].nil? # safe check very rare case.
|
295
|
+
version_string = plugin_entry[:version].gsub(/[=,~,>,<]/, "").strip
|
296
|
+
plugin_name_with_version = "#{status.name}-#{version_string}"
|
297
|
+
status.description = fetch_gemspec(File.join(plugin_gem_path, "gems", plugin_name_with_version, "/", status.name.to_s + ".gemspec"))&.summary
|
298
|
+
end
|
282
299
|
when :path
|
283
300
|
status.entry_point = plugin_entry[:installation_path]
|
284
301
|
end
|
@@ -287,12 +304,6 @@ module Inspec::Plugin::V2
|
|
287
304
|
end
|
288
305
|
end
|
289
306
|
|
290
|
-
def fetch_plugin_specs(plugin_name)
|
291
|
-
fetcher = Gem::SpecFetcher.fetcher
|
292
|
-
plugin_dependency = Gem::Dependency.new(plugin_name)
|
293
|
-
fetcher.spec_for_dependency(plugin_dependency).flatten.first
|
294
|
-
end
|
295
|
-
|
296
307
|
def fixup_train_plugin_status(status)
|
297
308
|
status.api_generation = :'train-1'
|
298
309
|
if status.installation_type == :user_gem
|
@@ -11,6 +11,7 @@ module Inspec::Plugin::V2::PluginType
|
|
11
11
|
@running_controls_list = []
|
12
12
|
@control_checks_count_map = {}
|
13
13
|
@controls_count = nil
|
14
|
+
@notifications = {}
|
14
15
|
end
|
15
16
|
|
16
17
|
private
|
@@ -49,5 +50,58 @@ module Inspec::Plugin::V2::PluginType
|
|
49
50
|
@control_checks_count_map = RSpec.configuration.formatters.grep(Inspec::Formatters::Base).first.get_control_checks_count_map
|
50
51
|
end
|
51
52
|
end
|
53
|
+
|
54
|
+
def enhanced_outcomes
|
55
|
+
@enhanced_outcomes ||= RSpec.configuration.formatters.grep(Inspec::Formatters::Base).first.enhanced_outcomes
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_enhanced_outcomes(control_id)
|
59
|
+
if control_has_error(@notifications[control_id])
|
60
|
+
"error"
|
61
|
+
elsif control_has_impact_zero(@notifications[control_id])
|
62
|
+
"not_applicable"
|
63
|
+
elsif control_has_all_tests_skipped(@notifications[control_id])
|
64
|
+
"not_reviewed"
|
65
|
+
elsif control_has_any_tests_failed(@notifications[control_id])
|
66
|
+
"failed"
|
67
|
+
else
|
68
|
+
"passed"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def control_has_error(notifications)
|
73
|
+
notifications.any? do |notification_data|
|
74
|
+
notification, _status = notification_data
|
75
|
+
!notification.example.exception.nil? && !(notification.example.exception.is_a? RSpec::Expectations::ExpectationNotMetError) && !notification.example.exception.backtrace.nil? && (!notification.description.include? "No-op") # No-op exception occurs in case of not_applicable_if
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def control_has_all_tests_skipped(notifications)
|
80
|
+
notifications.all? do |notification_data|
|
81
|
+
_notification, status = notification_data
|
82
|
+
status == "skipped"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def control_has_any_tests_failed(notifications)
|
87
|
+
notifications.any? do |notification_data|
|
88
|
+
_notification, status = notification_data
|
89
|
+
status == "failed"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def control_has_impact_zero(notifications)
|
94
|
+
notification_data = notifications.first
|
95
|
+
notification_impact = notification_data.first.example.metadata[:impact]
|
96
|
+
notification_data && !notification_impact.nil? && notification_impact.to_f == 0.0
|
97
|
+
end
|
98
|
+
|
99
|
+
def collect_notifications(notification, control_id, status)
|
100
|
+
if @notifications[control_id].nil?
|
101
|
+
@notifications[control_id] = [[notification, status]]
|
102
|
+
else
|
103
|
+
@notifications[control_id].push([notification, status])
|
104
|
+
end
|
105
|
+
end
|
52
106
|
end
|
53
107
|
end
|
data/lib/inspec/profile.rb
CHANGED
@@ -383,24 +383,25 @@ module Inspec
|
|
383
383
|
@runner_context
|
384
384
|
end
|
385
385
|
|
386
|
-
|
386
|
+
# This collects the gem dependencies data from parent and its dependent profiles
|
387
|
+
def collect_gem_dependencies
|
387
388
|
gem_dependencies = []
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
end
|
392
|
-
all_profiles << self
|
393
|
-
all_profiles.each do |profile|
|
389
|
+
# This collects the dependent profiles gem dependencies if any
|
390
|
+
locked_dependencies.dep_list.each do |_name, dep|
|
391
|
+
profile = dep.profile
|
394
392
|
gem_dependencies << profile.metadata.gem_dependencies unless profile.metadata.gem_dependencies.empty?
|
395
393
|
end
|
394
|
+
# Appends the parent profile gem dependencies which are available through metadata
|
395
|
+
gem_dependencies << metadata.gem_dependencies unless metadata.gem_dependencies.empty?
|
396
396
|
gem_dependencies.flatten.uniq
|
397
397
|
end
|
398
398
|
|
399
399
|
# Loads the required gems specified in the Profile's metadata file from default inspec gems path i.e. ~/.inspec/gems
|
400
400
|
# else installs and loads them.
|
401
401
|
def load_gem_dependencies
|
402
|
-
gem_dependencies = collect_gem_dependencies
|
402
|
+
gem_dependencies = collect_gem_dependencies
|
403
403
|
gem_dependencies.each do |gem_data|
|
404
|
+
|
404
405
|
dependency_loader = DependencyLoader.new
|
405
406
|
if dependency_loader.gem_version_installed?(gem_data[:name], gem_data[:version]) ||
|
406
407
|
dependency_loader.gem_installed?(gem_data[:name])
|
data/lib/inspec/reporters/cli.rb
CHANGED
@@ -9,6 +9,9 @@ module Inspec::Reporters
|
|
9
9
|
"passed" => "\033[0;1;32m",
|
10
10
|
"skipped" => "\033[0;37m",
|
11
11
|
"reset" => "\033[0m",
|
12
|
+
"error" => "\033[34m",
|
13
|
+
"not_applicable" => "\033[36m",
|
14
|
+
"not_reviewed" => "\033[33m",
|
12
15
|
}.freeze
|
13
16
|
|
14
17
|
# Most currently available Windows terminals have poor support
|
@@ -18,6 +21,9 @@ module Inspec::Reporters
|
|
18
21
|
"skipped" => "[SKIP]",
|
19
22
|
"passed" => "[PASS]",
|
20
23
|
"unknown" => "[UNKN]",
|
24
|
+
"error" => "[ERR]",
|
25
|
+
"not_applicable" => "[N/A]",
|
26
|
+
"not_reviewed" => "[N/R]",
|
21
27
|
}.freeze
|
22
28
|
else
|
23
29
|
# Extended colors for everyone else
|
@@ -26,6 +32,9 @@ module Inspec::Reporters
|
|
26
32
|
"passed" => "\033[38;5;41m",
|
27
33
|
"skipped" => "\033[38;5;247m",
|
28
34
|
"reset" => "\033[0m",
|
35
|
+
"error" => "\033[0;38;5;21m",
|
36
|
+
"not_applicable" => "\033[0;38;5;117m",
|
37
|
+
"not_reviewed" => "\033[0;38;5;214m",
|
29
38
|
}.freeze
|
30
39
|
|
31
40
|
# Groovy UTF-8 characters for everyone else...
|
@@ -35,6 +44,9 @@ module Inspec::Reporters
|
|
35
44
|
"skipped" => "↺",
|
36
45
|
"passed" => "✔",
|
37
46
|
"unknown" => "?",
|
47
|
+
"error" => "ERR",
|
48
|
+
"not_applicable" => "N/A",
|
49
|
+
"not_reviewed" => "N/R",
|
38
50
|
}.freeze
|
39
51
|
end
|
40
52
|
|
@@ -63,7 +75,11 @@ module Inspec::Reporters
|
|
63
75
|
end
|
64
76
|
|
65
77
|
output("")
|
66
|
-
|
78
|
+
if enhanced_outcomes
|
79
|
+
print_control_outcomes_summary
|
80
|
+
else
|
81
|
+
print_profile_summary
|
82
|
+
end
|
67
83
|
print_tests_summary
|
68
84
|
end
|
69
85
|
|
@@ -88,6 +104,7 @@ module Inspec::Reporters
|
|
88
104
|
def print_standard_control_results(profile)
|
89
105
|
standard_controls_from_profile(profile).each do |control_from_profile|
|
90
106
|
control = Control.new(control_from_profile)
|
107
|
+
control.enhanced_outcomes = enhanced_outcomes
|
91
108
|
next if control.results.nil?
|
92
109
|
|
93
110
|
output(format_control_header(control))
|
@@ -122,7 +139,7 @@ module Inspec::Reporters
|
|
122
139
|
end
|
123
140
|
|
124
141
|
def format_control_header(control)
|
125
|
-
impact = control.impact_string
|
142
|
+
impact = enhanced_outcomes ? control.impact_string_for_enhanced_outcomes : control.impact_string
|
126
143
|
format_message(
|
127
144
|
color: impact,
|
128
145
|
indicator: impact,
|
@@ -292,6 +309,68 @@ module Inspec::Reporters
|
|
292
309
|
}
|
293
310
|
end
|
294
311
|
|
312
|
+
def control_outcomes_summary
|
313
|
+
failed = 0
|
314
|
+
passed = 0
|
315
|
+
error = 0
|
316
|
+
not_reviewed = 0
|
317
|
+
not_applicable = 0
|
318
|
+
|
319
|
+
all_unique_controls.each do |control|
|
320
|
+
next if control[:status].empty?
|
321
|
+
|
322
|
+
if control[:status] == "failed"
|
323
|
+
failed += 1
|
324
|
+
elsif control[:status] == "error"
|
325
|
+
error += 1
|
326
|
+
elsif control[:status] == "not_reviewed"
|
327
|
+
not_reviewed += 1
|
328
|
+
elsif control[:status] == "not_applicable"
|
329
|
+
not_applicable += 1
|
330
|
+
else
|
331
|
+
passed += 1
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
total = failed + passed + error + not_reviewed + not_applicable
|
336
|
+
|
337
|
+
{
|
338
|
+
"total" => total,
|
339
|
+
"failed" => failed,
|
340
|
+
"passed" => passed,
|
341
|
+
"error" => error,
|
342
|
+
"not_reviewed" => not_reviewed,
|
343
|
+
"not_applicable" => not_applicable,
|
344
|
+
}
|
345
|
+
end
|
346
|
+
|
347
|
+
def print_control_outcomes_summary
|
348
|
+
summary = control_outcomes_summary
|
349
|
+
return unless summary["total"] > 0
|
350
|
+
|
351
|
+
success_str = summary["passed"] == 1 ? "1 successful control" : "#{summary["passed"]} successful controls"
|
352
|
+
failed_str = summary["failed"] == 1 ? "1 control failure" : "#{summary["failed"]} control failures"
|
353
|
+
error_str = summary["error"] == 1 ? "1 control has error" : "#{summary["error"]} controls have error"
|
354
|
+
not_rev_str = summary["not_reviewed"] == 1 ? "1 control not reviewed" : "#{summary["not_reviewed"]} controls not reviewed"
|
355
|
+
not_app_str = summary["not_applicable"] == 1 ? "1 control not applicable" : "#{summary["not_applicable"]} controls not applicable"
|
356
|
+
|
357
|
+
success_color = summary["passed"] > 0 ? "passed" : "no_color"
|
358
|
+
failed_color = summary["failed"] > 0 ? "failed" : "no_color"
|
359
|
+
error_color = summary["error"] > 0 ? "error" : "no_color"
|
360
|
+
not_rev_color = summary["not_reviewed"] > 0 ? "not_reviewed" : "no_color"
|
361
|
+
not_app_color = summary["not_applicable"] > 0 ? "not_applicable" : "no_color"
|
362
|
+
|
363
|
+
s = format(
|
364
|
+
"Profile Summary: %s, %s, %s, %s, %s",
|
365
|
+
format_with_color(success_color, success_str),
|
366
|
+
format_with_color(failed_color, failed_str),
|
367
|
+
format_with_color(not_rev_color, not_rev_str),
|
368
|
+
format_with_color(not_app_color, not_app_str),
|
369
|
+
format_with_color(error_color, error_str)
|
370
|
+
)
|
371
|
+
output(s) if summary["total"] > 0
|
372
|
+
end
|
373
|
+
|
295
374
|
def print_profile_summary
|
296
375
|
summary = profile_summary
|
297
376
|
return unless summary["total"] > 0
|
@@ -350,6 +429,7 @@ module Inspec::Reporters
|
|
350
429
|
|
351
430
|
class Control
|
352
431
|
attr_reader :data
|
432
|
+
attr_accessor :enhanced_outcomes
|
353
433
|
|
354
434
|
def initialize(control_hash)
|
355
435
|
@data = control_hash
|
@@ -379,6 +459,10 @@ module Inspec::Reporters
|
|
379
459
|
id.start_with?("(generated from ")
|
380
460
|
end
|
381
461
|
|
462
|
+
def status
|
463
|
+
data[:status]
|
464
|
+
end
|
465
|
+
|
382
466
|
def title_for_report
|
383
467
|
# if this is an anonymous control, just grab the resource title from any result entry
|
384
468
|
return results.first[:resource_title] if anonymous?
|
@@ -392,10 +476,17 @@ module Inspec::Reporters
|
|
392
476
|
# append a failure summary if appropriate.
|
393
477
|
title_for_report += " (#{failure_count} failed)" if failure_count > 0
|
394
478
|
title_for_report += " (#{skipped_count} skipped)" if skipped_count > 0
|
395
|
-
|
396
479
|
title_for_report
|
397
480
|
end
|
398
481
|
|
482
|
+
def impact_string_for_enhanced_outcomes
|
483
|
+
if impact.nil?
|
484
|
+
"unknown"
|
485
|
+
else
|
486
|
+
status
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
399
490
|
def impact_string
|
400
491
|
if anonymous?
|
401
492
|
nil
|
@@ -114,7 +114,7 @@ module Inspec::Reporters
|
|
114
114
|
|
115
115
|
def profile_controls(profile)
|
116
116
|
(profile[:controls] || []).map { |c|
|
117
|
-
{
|
117
|
+
control_hash = {
|
118
118
|
id: c[:id],
|
119
119
|
title: c[:title],
|
120
120
|
desc: c.dig(:descriptions, :default),
|
@@ -130,6 +130,8 @@ module Inspec::Reporters
|
|
130
130
|
waiver_data: c[:waiver_data] || {},
|
131
131
|
results: profile_results(c),
|
132
132
|
}
|
133
|
+
control_hash.merge!({ status: c[:status] }) if enhanced_outcomes
|
134
|
+
control_hash
|
133
135
|
}
|
134
136
|
end
|
135
137
|
|
@@ -3,7 +3,9 @@ require "yaml"
|
|
3
3
|
module Inspec::Reporters
|
4
4
|
class Yaml < Base
|
5
5
|
def render
|
6
|
-
|
6
|
+
json_reporter_obj = Inspec::Reporters::Json.new({ run_data: run_data })
|
7
|
+
json_reporter_obj.enhanced_outcomes = enhanced_outcomes
|
8
|
+
output(json_reporter_obj.report.to_yaml, false)
|
7
9
|
end
|
8
10
|
|
9
11
|
def report
|
data/lib/inspec/reporters.rb
CHANGED
@@ -7,7 +7,7 @@ require "inspec/reporters/yaml"
|
|
7
7
|
|
8
8
|
module Inspec::Reporters
|
9
9
|
# rubocop:disable Metrics/CyclomaticComplexity
|
10
|
-
def self.render(reporter, run_data)
|
10
|
+
def self.render(reporter, run_data, enhanced_outcomes = false)
|
11
11
|
name, config = reporter.dup
|
12
12
|
config[:run_data] = run_data
|
13
13
|
case name
|
@@ -29,6 +29,7 @@ module Inspec::Reporters
|
|
29
29
|
activator.activate!
|
30
30
|
reporter = activator.implementation_class.new(config)
|
31
31
|
end
|
32
|
+
reporter.enhanced_outcomes = enhanced_outcomes
|
32
33
|
|
33
34
|
# optional send_report method on reporter
|
34
35
|
return reporter.send_report if defined?(reporter.send_report)
|
@@ -66,7 +66,7 @@ module Inspec::Resources
|
|
66
66
|
def user_permissions
|
67
67
|
return {} unless exist?
|
68
68
|
|
69
|
-
return
|
69
|
+
return skip_resource "`user_permissions` is not supported on your OS yet." unless inspec.os.windows?
|
70
70
|
|
71
71
|
@perms_provider.user_permissions(file)
|
72
72
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
require "inspec/resources/command"
|
6
6
|
require "faraday" unless defined?(Faraday)
|
7
|
-
require "
|
7
|
+
require "faraday/follow_redirects"
|
8
8
|
require "hashie"
|
9
9
|
|
10
10
|
module Inspec::Resources
|
@@ -153,7 +153,7 @@ module Inspec::Resources
|
|
153
153
|
|
154
154
|
conn = Faraday.new(url: url, headers: request_headers, params: params, ssl: { verify: ssl_verify? }) do |builder|
|
155
155
|
builder.request :url_encoded
|
156
|
-
builder.use
|
156
|
+
builder.use Faraday::FollowRedirects::Middleware, limit: max_redirects unless max_redirects.nil?
|
157
157
|
builder.adapter Faraday.default_adapter
|
158
158
|
end
|
159
159
|
|
@@ -304,11 +304,11 @@ module Inspec::Resources
|
|
304
304
|
# Insecure not supported simply https://stackoverflow.com/questions/11696944/powershell-v3-invoke-webrequest-https-error
|
305
305
|
cmd << "-MaximumRedirection #{max_redirects}" unless max_redirects.nil?
|
306
306
|
request_headers["Authorization"] = """ '\"Basic ' + [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(\"#{username}:#{password}\")) +'\"' """ unless username.nil? || password.nil?
|
307
|
-
|
307
|
+
request_header_array = []
|
308
308
|
request_headers.each do |k, v|
|
309
|
-
|
309
|
+
request_header_array << " '#{k}' = '#{v}'"
|
310
310
|
end
|
311
|
-
cmd << "-Headers @{#{
|
311
|
+
cmd << "-Headers @{#{request_header_array.join(";")}}" unless request_header_array.empty?
|
312
312
|
if params.nil?
|
313
313
|
cmd << "'#{url}'"
|
314
314
|
else
|
data/lib/inspec/resources/lxc.rb
CHANGED
@@ -9,14 +9,26 @@ module Inspec::Resources
|
|
9
9
|
describe lxc("ubuntu-container") do
|
10
10
|
it { should exist }
|
11
11
|
it { should be_running }
|
12
|
+
its("name") { should eq "ubuntu-container" }
|
13
|
+
its("status") { should cmp "Running" }
|
14
|
+
its("type") { should eq "container" }
|
15
|
+
its("architecture") { should eq "x86_64" }
|
16
|
+
its("pid") { should eq 1378 }
|
17
|
+
its("created_at") { should eq "2022/08/16 12:07 UTC" }
|
18
|
+
its("last_used_at") { should eq "2022/08/17 05:06 UTC" }
|
19
|
+
its("resources") { should include "Disk usage" }
|
12
20
|
end
|
13
21
|
EXAMPLE
|
14
22
|
|
23
|
+
attr_reader :container_info, :container_name
|
24
|
+
|
15
25
|
# Resource initialization.
|
16
26
|
def initialize(container_name)
|
17
27
|
@container_name = container_name
|
18
28
|
|
19
29
|
raise Inspec::Exceptions::ResourceSkipped, "The `lxc` resource is not supported on your OS yet." unless inspec.os.linux?
|
30
|
+
|
31
|
+
@container_info = populate_container_info
|
20
32
|
end
|
21
33
|
|
22
34
|
def resource_id
|
@@ -28,17 +40,60 @@ module Inspec::Resources
|
|
28
40
|
end
|
29
41
|
|
30
42
|
def exists?
|
31
|
-
|
43
|
+
!@container_info.empty?
|
32
44
|
end
|
33
45
|
|
34
46
|
def running?
|
35
|
-
container_info
|
36
|
-
|
47
|
+
@container_info.key?("Status") && @container_info["Status"].casecmp("Running") == 0
|
48
|
+
end
|
49
|
+
|
50
|
+
def name
|
51
|
+
@container_info["Name"]
|
52
|
+
end
|
53
|
+
|
54
|
+
def status
|
55
|
+
@container_info["Status"]
|
56
|
+
end
|
57
|
+
|
58
|
+
def type
|
59
|
+
@container_info["Type"]
|
60
|
+
end
|
61
|
+
|
62
|
+
def architecture
|
63
|
+
@container_info["Architecture"]
|
64
|
+
end
|
65
|
+
|
66
|
+
def pid
|
67
|
+
@container_info["PID"]
|
68
|
+
end
|
69
|
+
|
70
|
+
def created_at
|
71
|
+
@container_info["Created"]
|
72
|
+
end
|
73
|
+
|
74
|
+
def last_used_at
|
75
|
+
@container_info["Last Used"]
|
76
|
+
end
|
77
|
+
|
78
|
+
def resources
|
79
|
+
@container_info["Resources"]
|
37
80
|
end
|
38
81
|
|
39
82
|
private
|
40
83
|
|
41
|
-
|
84
|
+
def populate_container_info
|
85
|
+
lxc_util = find_lxc_or_error
|
86
|
+
lxc_info_cmd = inspec.command("#{lxc_util} info #{@container_name}")
|
87
|
+
|
88
|
+
if lxc_info_cmd.exit_status.to_i == 0
|
89
|
+
parse_command_output(lxc_info_cmd.stdout)
|
90
|
+
elsif lxc_info_cmd.stderr =~ /Error: Instance not found/
|
91
|
+
{}
|
92
|
+
else
|
93
|
+
raise Inspec::Exceptions::ResourceFailed, "Unable to retrieve information for #{container_name}.\n#{lxc_info_cmd.stderr}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
42
97
|
def find_lxc_or_error
|
43
98
|
%w{/usr/sbin/lxc /sbin/lxc lxc}.each do |cmd|
|
44
99
|
return cmd if inspec.command(cmd).exist?
|
@@ -47,11 +102,12 @@ module Inspec::Resources
|
|
47
102
|
raise Inspec::Exceptions::ResourceFailed, "Could not find `lxc`"
|
48
103
|
end
|
49
104
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
105
|
+
def parse_command_output(output)
|
106
|
+
require "yaml" unless defined?(YAML)
|
107
|
+
YAML.load(output)
|
108
|
+
rescue Psych::SyntaxError => e
|
109
|
+
warn "Could not parse the command output.\n#{e.message}"
|
110
|
+
{}
|
55
111
|
end
|
56
112
|
end
|
57
113
|
end
|
@@ -84,6 +84,11 @@ module Inspec::Resources
|
|
84
84
|
options[:ssl_cert] = @ssl_cert unless @ssl_cert.nil?
|
85
85
|
options[:ssl_ca_cert] = @ssl_ca_cert unless @ssl_ca_cert.nil?
|
86
86
|
|
87
|
+
# Setting the logger level to INFO as mongo gem version 2.13.2 is using DEBUG as the log level Ref: https://github.com/mongodb/mongo-ruby-driver/blob/v2.13.2/lib/mongo/logger.rb#L79
|
88
|
+
# Latest version of the mongo gem don't have this issue as it set to INFO level Ref: https://github.com/mongodb/mongo-ruby-driver/blob/master/lib/mongo/logger.rb#L82
|
89
|
+
# We pinned the version to 2.13.2 as the latest version of the mongo gem has broken symlink https://jira.mongodb.org/browse/RUBY-2546 which causes omnibus build failure.
|
90
|
+
# Once we get the latest version working we can remove logger level set here.
|
91
|
+
Mongo::Logger.logger.level = Logger::INFO
|
87
92
|
@client = Mongo::Client.new([ "#{host}:#{port}" ], options)
|
88
93
|
|
89
94
|
rescue => e
|