inspec-core 4.18.100 → 4.19.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/inspec-core.gemspec +2 -2
  4. data/lib/inspec/base_cli.rb +4 -0
  5. data/lib/inspec/cli.rb +7 -17
  6. data/lib/inspec/config.rb +28 -6
  7. data/lib/inspec/fetcher/git.rb +1 -1
  8. data/lib/inspec/fetcher/local.rb +1 -1
  9. data/lib/inspec/fetcher/url.rb +1 -1
  10. data/lib/inspec/input.rb +9 -9
  11. data/lib/inspec/plugin/v2/installer.rb +23 -2
  12. data/lib/inspec/plugin/v2/plugin_types/reporter.rb +68 -0
  13. data/lib/inspec/profile.rb +16 -4
  14. data/lib/inspec/reporters.rb +4 -1
  15. data/lib/inspec/reporters/base.rb +22 -0
  16. data/lib/inspec/resources/service.rb +2 -2
  17. data/lib/inspec/resources/virtualization.rb +86 -2
  18. data/lib/inspec/resources/x509_certificate.rb +1 -1
  19. data/lib/inspec/rule.rb +8 -4
  20. data/lib/inspec/run_data.rb +64 -0
  21. data/lib/inspec/run_data/control.rb +83 -0
  22. data/lib/inspec/run_data/profile.rb +109 -0
  23. data/lib/inspec/run_data/result.rb +40 -0
  24. data/lib/inspec/run_data/statistics.rb +36 -0
  25. data/lib/inspec/shell.rb +8 -3
  26. data/lib/inspec/utils/json_profile_summary.rb +35 -0
  27. data/lib/inspec/version.rb +1 -1
  28. data/lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb +18 -1
  29. data/lib/plugins/inspec-compliance/lib/inspec-compliance/api.rb +4 -0
  30. data/lib/plugins/inspec-init/lib/inspec-init/cli_plugin.rb +28 -6
  31. data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/plugin.rb +18 -0
  32. data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/reporter.rb +27 -0
  33. data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +11 -8
  34. metadata +20 -6
@@ -0,0 +1,36 @@
1
+ module Inspec
2
+ class RunData
3
+ # {:duration=>0.018407, :controls=>{:total=>3, :passed=>{:total=>3}, :skipped=>{:total=>0}, :failed=>{:total=>0}}}
4
+ Statistics = Struct.new(
5
+ :duration,
6
+ :controls
7
+ ) do
8
+ include HashLikeStruct
9
+ def initialize(raw_stat_data)
10
+ self.controls = Inspec::RunData::Statistics::Controls.new(raw_stat_data[:controls])
11
+ self.duration = raw_stat_data[:duration]
12
+ end
13
+ end
14
+ class Statistics
15
+ Controls = Struct.new(
16
+ :total,
17
+ :passed,
18
+ :skipped,
19
+ :failed
20
+ ) do
21
+ include HashLikeStruct
22
+ def initialize(raw_stat_ctl_data)
23
+ self.total = raw_stat_ctl_data[:total]
24
+ self.passed = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:passed][:total])
25
+ self.skipped = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:skipped][:total])
26
+ self.failed = Inspec::RunData::Statistics::Controls::Total.new(raw_stat_ctl_data[:failed][:total])
27
+ end
28
+ end
29
+ class Controls
30
+ Total = Struct.new(:total) do
31
+ include HashLikeStruct
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -36,8 +36,13 @@ module Inspec
36
36
  end
37
37
 
38
38
  # configure pry shell prompt
39
- Pry.config.prompt_name = "inspec"
40
- Pry.prompt = [proc { "#{readline_ignore("\e[1m\e[32m")}#{Pry.config.prompt_name}> #{readline_ignore("\e[0m")}" }]
39
+ Pry::Prompt.add(
40
+ :inspec,
41
+ "inspec custom prompt"
42
+ ) do |_context, _nesting, _pry_instance, _sep|
43
+ "#{readline_ignore("\e[1m\e[32m")}inspec> #{readline_ignore("\e[0m")}"
44
+ end
45
+ Pry.config.prompt = Pry::Prompt[:inspec]
41
46
 
42
47
  # Add a help menu as the default intro
43
48
  Pry.hooks.add_hook(:before_session, "inspec_intro") do
@@ -64,7 +69,7 @@ module Inspec
64
69
 
65
70
  pry.pager.open do |pager|
66
71
  pager.print pry.config.output_prefix
67
- Pry::ColorPrinter.pp(value, pager, Pry::Terminal.width! - 1)
72
+ Pry::ColorPrinter.pp(value, pager, Pry::Output.new(pry).width - 1)
68
73
  end
69
74
  end
70
75
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec
4
+ module Utils
5
+ #
6
+ # Inspec::Utils::JsonProfileSummary takes in certain information to identify a
7
+ # profile and then produces a JSON-formatted summary of that profile. It can
8
+ # return the results to STDOUT or a file. It is currently used in several
9
+ # places in the CLI such as `json`, `archive` and `artifact`.
10
+ #
11
+ #
12
+ module JsonProfileSummary
13
+ def self.produce_json(info:, write_path: "", suppress_output: false)
14
+ # add in inspec version
15
+ info[:generator] = {
16
+ name: "inspec",
17
+ version: Inspec::VERSION,
18
+ }
19
+ if write_path.empty?
20
+ puts JSON.dump(info)
21
+ else
22
+ unless suppress_output
23
+ if File.exist? write_path
24
+ Inspec::Log.info "----> updating #{write_path}"
25
+ else
26
+ Inspec::Log.info "----> creating #{write_path}"
27
+ end
28
+ end
29
+ full_write_path = File.expand_path(write_path)
30
+ File.write(full_write_path, JSON.dump(info))
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "4.18.100".freeze
2
+ VERSION = "4.19.0".freeze
3
3
  end
@@ -5,6 +5,7 @@ require "set"
5
5
  require "tempfile"
6
6
  require "yaml"
7
7
  require "inspec/dist"
8
+ require "inspec/utils/json_profile_summary"
8
9
 
9
10
  module InspecPlugins
10
11
  module Artifact
@@ -40,9 +41,13 @@ module InspecPlugins
40
41
 
41
42
  def self.profile_sign(options)
42
43
  artifact = new
44
+ path_to_profile = options["profile"]
45
+
46
+ # Write inspec.json file within artifact
47
+ write_inspec_json(path_to_profile, options)
48
+
43
49
  Dir.mktmpdir do |workdir|
44
50
  puts "Signing #{options["profile"]} with key #{options["keyname"]}"
45
- path_to_profile = options["profile"]
46
51
  profile_md = artifact.read_profile_metadata(path_to_profile)
47
52
  artifact_filename = "#{profile_md["name"]}-#{profile_md["version"]}.#{SIGNED_PROFILE_SUFFIX}"
48
53
  tarfile = artifact.profile_compress(path_to_profile, profile_md, workdir)
@@ -63,6 +68,9 @@ module InspecPlugins
63
68
  end
64
69
  puts "Successfully generated #{artifact_filename}"
65
70
  end
71
+
72
+ # Cleanup
73
+ File.delete("#{path_to_profile}/inspec.json")
66
74
  end
67
75
 
68
76
  def self.profile_verify(options)
@@ -165,6 +173,15 @@ module InspecPlugins
165
173
  raise "Artifact is invalid"
166
174
  end
167
175
  end
176
+
177
+ def self.write_inspec_json(root_path, opts)
178
+ profile = Inspec::Profile.for_path(root_path, opts)
179
+ Inspec::Utils::JsonProfileSummary.produce_json(
180
+ info: profile.info,
181
+ write_path: "#{root_path}/inspec.json",
182
+ suppress_output: true
183
+ )
184
+ end
168
185
  end
169
186
  end
170
187
  end
@@ -302,6 +302,10 @@ module InspecPlugins
302
302
  )
303
303
  true
304
304
  else
305
+ Inspec::Log.debug(
306
+ "Received #{response.code} from #{url}#{automate_endpoint} - " \
307
+ "assuming target is not an #{AUTOMATE_PRODUCT_NAME}2 instance"
308
+ )
305
309
  false
306
310
  end
307
311
  end
@@ -41,8 +41,9 @@ module InspecPlugins
41
41
  templates_path: TEMPLATES_PATH,
42
42
  overwrite: options[:overwrite],
43
43
  file_rename_map: make_rename_map(plugin_type, plugin_name, snake_case),
44
- skip_files: make_skip_list,
44
+ skip_files: make_skip_list(template_vars["hooks"].keys),
45
45
  }
46
+
46
47
  renderer = InspecPlugins::Init::Renderer.new(ui, render_opts)
47
48
 
48
49
  renderer.render_with_values(template_path, plugin_type + " plugin", template_vars)
@@ -72,6 +73,7 @@ module InspecPlugins
72
73
  File.join("lib", "inspec-plugin-template") => File.join("lib", plugin_name),
73
74
  File.join("lib", "inspec-plugin-template.rb") => File.join("lib", plugin_name + ".rb"),
74
75
  File.join("lib", "inspec-plugin-template", "cli_command.rb") => File.join("lib", plugin_name, "cli_command.rb"),
76
+ File.join("lib", "inspec-plugin-template", "reporter.rb") => File.join("lib", plugin_name, "reporter.rb"),
75
77
  File.join("lib", "inspec-plugin-template", "plugin.rb") => File.join("lib", plugin_name, "plugin.rb"),
76
78
  File.join("lib", "inspec-plugin-template", "version.rb") => File.join("lib", plugin_name, "version.rb"),
77
79
  File.join("test", "functional", "inspec_plugin_template_test.rb") => File.join("test", "functional", snake_case + "_test.rb"),
@@ -168,6 +170,9 @@ module InspecPlugins
168
170
  if hooks_by_type.key?(:cli_command)
169
171
  vars[:command_name_dashes] = hooks_by_type[:cli_command].tr("_", "-")
170
172
  vars[:command_name_snake] = hooks_by_type[:cli_command].tr("-", "_")
173
+ elsif hooks_by_type.key?(:reporter)
174
+ vars[:reporter_name_dashes] = hooks_by_type[:reporter].tr("_", "-")
175
+ vars[:reporter_name_snake] = hooks_by_type[:reporter].tr("-", "_")
171
176
  end
172
177
  vars
173
178
  end
@@ -205,19 +210,20 @@ module InspecPlugins
205
210
  end
206
211
  end
207
212
 
208
- def make_skip_list
213
+ def make_skip_list(requested_hooks)
214
+ skips = []
209
215
  case options[:detail]
210
- when "full"
211
- []
216
+ when "full" # rubocop: disable Lint/EmptyWhen
217
+ # Do nothing but allow this case for validation
212
218
  when "core"
213
- [
219
+ skips += [
214
220
  "Gemfile",
215
221
  "inspec-plugin-template.gemspec",
216
222
  "LICENSE",
217
223
  "Rakefile",
218
224
  ]
219
225
  when "test-fixture"
220
- [
226
+ skips += [
221
227
  "Gemfile",
222
228
  "inspec-plugin-template.gemspec",
223
229
  "LICENSE",
@@ -237,6 +243,22 @@ module InspecPlugins
237
243
  ui.error "Unrecognized value for 'detail': #{options[:detail]} - expected one of full, core, test-fixture"
238
244
  ui.exit(:usage_error)
239
245
  end
246
+
247
+ # Remove hook-specific files
248
+ unless requested_hooks.include?(:cli_command)
249
+ skips += [
250
+ File.join("lib", "inspec-plugin-template", "cli_command.rb"),
251
+ File.join("test", "unit", "cli_args_test.rb"),
252
+ File.join("test", "functional", "inspec_plugin_template_test.rb"),
253
+ ]
254
+ end
255
+ unless requested_hooks.include?(:reporter)
256
+ skips += [
257
+ File.join("lib", "inspec-plugin-template", "reporter.rb"),
258
+ ]
259
+ end
260
+
261
+ skips.uniq
240
262
  end
241
263
  end
242
264
  end
@@ -28,6 +28,7 @@ module InspecPlugins
28
28
  # Internal machine name of the plugin. InSpec will use this in errors, etc.
29
29
  plugin_name :'<%= plugin_name %>'
30
30
 
31
+ <% if hooks[:cli_command] %>
31
32
  # Define a new CLI subcommand.
32
33
  # The argument here will be used to match against the command line args,
33
34
  # and if the user said `inspec list-resources`, this hook will get called.
@@ -48,6 +49,23 @@ module InspecPlugins
48
49
  # CLI engine tap into it.
49
50
  InspecPlugins::<%= module_name %>::CliCommand
50
51
  end
52
+ <% end %>
53
+
54
+ <% if hooks[:reporter] %>
55
+ # Define a new Reporter.
56
+ # The argument here will be used to match against the CLI --reporter option.
57
+ # `--reporter <%= reporter_name_snake %>` will load your reporter and call its renderer.
58
+ reporter :<%= reporter_name_snake %> do
59
+ # Calling this hook doesn't mean the reporter is being executed - just
60
+ # that we should be ready to do so. So, load the file that defines the
61
+ # functionality.
62
+ require '<%= plugin_name %>/reporter'
63
+
64
+ # Having loaded our functionality, return a class that will let the
65
+ # reporting engine tap into it.
66
+ InspecPlugins::<%= module_name %>::Reporter
67
+ end
68
+ <% end %>
51
69
  end
52
70
  end
53
71
  end
@@ -0,0 +1,27 @@
1
+ module InspecPlugins::<%= module_name %>
2
+ # This class will provide the actual Reporter implementation.
3
+ # Its superclass is provided by another call to Inspec.plugin,
4
+ # this time with two args. The first arg specifies we are requesting
5
+ # version 2 of the Plugins API. The second says we are making a
6
+ # Reporter plugin component, so please make available any DSL needed
7
+ # for that.
8
+
9
+ class Reporter < Inspec.plugin(2, :reporter)
10
+
11
+ # All a Reporter *must* do is define a render() method that calls
12
+ # output(). You should access the run_data accessor to read off the
13
+ # results of the run.
14
+ def render
15
+ # There is much more to explore in the run_data structure!
16
+ run_data[:profiles].each do |profile|
17
+ output(profile[:title])
18
+ profile[:controls].each do |control|
19
+ output(control[:title])
20
+ control[:results].each do |test|
21
+ output(test[:status])
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -60,18 +60,19 @@ module InspecPlugins
60
60
  # inspec plugin search
61
61
  #==================================================================#
62
62
 
63
- desc "search [options] PATTERN", "Searches rubygems.org for plugins."
63
+ desc "search [options] PATTERN", "Searches for plugins."
64
64
  long_desc <<~EOLD
65
- Searches rubygems.org for #{PRODUCT_NAME} plugins. Exits 0 on a search hit, 1 on user error,
65
+ Searches rubygems.org or alternate source for #{PRODUCT_NAME} plugins. Exits 0 on a search hit, 1 on user error,
66
66
  2 on a search miss. PATTERN is a simple string; a wildcard will be added as
67
67
  a suffix, unless -e is used.
68
68
  EOLD
69
69
  option :all, desc: "List all available versions, not just the latest one.", type: :boolean, aliases: [:a]
70
70
  option :exact, desc: "Assume PATTERN is exact; do not add a wildcard to the end", type: :boolean, aliases: [:e]
71
71
  option :'include-test-fixture', type: :boolean, desc: "Internal use", hide: true
72
+ option :source, type: :string, desc: "URL of repository, defaults to https://rubygems.org", aliases: [:s]
72
73
  # Justification for disabling ABC: currently at 33.51/33
73
74
  def search(search_term) # rubocop: disable Metrics/AbcSize
74
- search_results = installer.search(search_term, exact: options[:exact])
75
+ search_results = installer.search(search_term, exact: options[:exact], source: options[:source])
75
76
  # The search results have already been filtered by the reject list. But the
76
77
  # RejectList doesn't filter {inspec, train}-test-fixture because we need those
77
78
  # for testing. We want to hide those from users, so unless we know we're in
@@ -102,9 +103,9 @@ module InspecPlugins
102
103
  #==================================================================#
103
104
  # inspec plugin install
104
105
  #==================================================================#
105
- desc "install [-v VERSION] PLUGIN", "Installs a plugin from rubygems.org, a gemfile, or a path to local source."
106
+ desc "install [options] PLUGIN", "Installs a plugin from rubygems.org, a gemfile, or a path to local source."
106
107
  long_desc <<~EOLD
107
- PLUGIN may be the name of a gem on rubygems.org that begins with inspec- or train-.
108
+ PLUGIN may be the name of a gem on rubygems.org (or an alternate source) that begins with `inspec-` or `train-`.
108
109
  PLUGIN may also be the path to a local gemfile, which will then be installed like
109
110
  any other gem. Finally, if PLUGIN is a path ending in .rb, it is taken to be a
110
111
  local file that will act as athe entry point for a plugin (this mode is provided
@@ -112,6 +113,7 @@ module InspecPlugins
112
113
  already installed, and 1 if any other error occurs.
113
114
  EOLD
114
115
  option :version, desc: "When installing from rubygems.org, specifies a specific version to install.", aliases: [:v]
116
+ option :source, type: :string, desc: "URL of repository, defaults to https://rubygems.org", aliases: [:s]
115
117
  def install(plugin_id_arg)
116
118
  if plugin_id_arg =~ /\.gem$/ # Does it end in .gem?
117
119
  install_from_gemfile(plugin_id_arg)
@@ -407,7 +409,7 @@ module InspecPlugins
407
409
 
408
410
  # Rationale for RuboCop variance: This is a one-line method with heavy UX-focused error handling.
409
411
  def install_attempt_install(plugin_name) # rubocop: disable Metrics/AbcSize
410
- installer.install(plugin_name, version: options[:version])
412
+ installer.install(plugin_name, version: options[:version], source: options[:source])
411
413
  rescue Inspec::Plugin::V2::PluginExcludedError => ex
412
414
  ui.red("Plugin on Exclusion List - #{plugin_name} is listed as an " \
413
415
  "incompatible gem - refusing to install.\n")
@@ -422,12 +424,13 @@ module InspecPlugins
422
424
  raise if Inspec::Log.level == :debug
423
425
 
424
426
  results = installer.search(plugin_name, exact: true)
427
+ source_host = URI(options[:source] || "https://rubygems.org/").host
425
428
  if results.empty?
426
429
  ui.red("No such plugin gem #{plugin_name} could be found on " \
427
- "rubygems.org - installation failed.\n")
430
+ "#{source_host} - installation failed.\n")
428
431
  elsif options[:version] && !results[plugin_name].include?(options[:version])
429
432
  ui.red("No such version - #{plugin_name} exists, but no such " \
430
- "version #{options[:version]} found on rubygems.org - " \
433
+ "version #{options[:version]} found on #{source_host} - " \
431
434
  "installation failed.\n")
432
435
  else
433
436
  ui.red("Unknown error occured - installation failed.\n")
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.18.100
4
+ version: 4.19.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: 2020-03-03 00:00:00.000000000 Z
11
+ date: 2020-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry
@@ -82,16 +82,22 @@ dependencies:
82
82
  name: method_source
83
83
  requirement: !ruby/object:Gem::Requirement
84
84
  requirements:
85
- - - "~>"
85
+ - - ">="
86
86
  - !ruby/object:Gem::Version
87
87
  version: '0.8'
88
+ - - "<"
89
+ - !ruby/object:Gem::Version
90
+ version: '2.0'
88
91
  type: :runtime
89
92
  prerelease: false
90
93
  version_requirements: !ruby/object:Gem::Requirement
91
94
  requirements:
92
- - - "~>"
95
+ - - ">="
93
96
  - !ruby/object:Gem::Version
94
97
  version: '0.8'
98
+ - - "<"
99
+ - !ruby/object:Gem::Version
100
+ version: '2.0'
95
101
  - !ruby/object:Gem::Dependency
96
102
  name: rubyzip
97
103
  requirement: !ruby/object:Gem::Requirement
@@ -146,14 +152,14 @@ dependencies:
146
152
  requirements:
147
153
  - - "~>"
148
154
  - !ruby/object:Gem::Version
149
- version: '0'
155
+ version: '0.13'
150
156
  type: :runtime
151
157
  prerelease: false
152
158
  version_requirements: !ruby/object:Gem::Requirement
153
159
  requirements:
154
160
  - - "~>"
155
161
  - !ruby/object:Gem::Version
156
- version: '0'
162
+ version: '0.13'
157
163
  - !ruby/object:Gem::Dependency
158
164
  name: hashie
159
165
  requirement: !ruby/object:Gem::Requirement
@@ -465,6 +471,7 @@ files:
465
471
  - lib/inspec/plugin/v2/plugin_types/dsl.rb
466
472
  - lib/inspec/plugin/v2/plugin_types/input.rb
467
473
  - lib/inspec/plugin/v2/plugin_types/mock.rb
474
+ - lib/inspec/plugin/v2/plugin_types/reporter.rb
468
475
  - lib/inspec/plugin/v2/registry.rb
469
476
  - lib/inspec/plugin/v2/status.rb
470
477
  - lib/inspec/profile.rb
@@ -607,6 +614,11 @@ files:
607
614
  - lib/inspec/resources/zfs_pool.rb
608
615
  - lib/inspec/rspec_extensions.rb
609
616
  - lib/inspec/rule.rb
617
+ - lib/inspec/run_data.rb
618
+ - lib/inspec/run_data/control.rb
619
+ - lib/inspec/run_data/profile.rb
620
+ - lib/inspec/run_data/result.rb
621
+ - lib/inspec/run_data/statistics.rb
610
622
  - lib/inspec/runner.rb
611
623
  - lib/inspec/runner_mock.rb
612
624
  - lib/inspec/runner_rspec.rb
@@ -642,6 +654,7 @@ files:
642
654
  - lib/inspec/utils/hash.rb
643
655
  - lib/inspec/utils/install_context.rb
644
656
  - lib/inspec/utils/json_log.rb
657
+ - lib/inspec/utils/json_profile_summary.rb
645
658
  - lib/inspec/utils/modulator.rb
646
659
  - lib/inspec/utils/nginx_parser.rb
647
660
  - lib/inspec/utils/object_traversal.rb
@@ -691,6 +704,7 @@ files:
691
704
  - lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template.rb
692
705
  - lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/cli_command.rb
693
706
  - lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/plugin.rb
707
+ - lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/reporter.rb
694
708
  - lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/lib/inspec-plugin-template/version.rb
695
709
  - lib/plugins/inspec-init/templates/profiles/aws/README.md
696
710
  - lib/plugins/inspec-init/templates/profiles/aws/attributes.yml