inspec-core 4.7.24 → 4.10.4
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/README.md +1 -2
- data/lib/fetchers/git.rb +49 -10
- data/lib/inspec/cli.rb +23 -34
- data/lib/inspec/resources/windows_task.rb +5 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/inspec-habitat/lib/inspec-habitat/profile.rb +0 -12
- data/lib/plugins/inspec-habitat/templates/habitat/plan.sh.erb +1 -78
- data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +106 -69
- metadata +2 -6
- data/lib/inspec/utils/latest_version.rb +0 -13
- data/lib/plugins/inspec-habitat/templates/habitat/config/inspec_exec_config.json.erb +0 -25
- data/lib/plugins/inspec-habitat/templates/habitat/default.toml.erb +0 -9
- data/lib/plugins/inspec-habitat/templates/habitat/hooks/run.erb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 431744ec266e2ed0cbde565cc232ee4bb944ff76076d8c10d381c73346796337
|
4
|
+
data.tar.gz: a8a844283829729c5a886a9e324e7fc22b31a986eb25e36c0a01fe7a26fbda78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3678f2a31c972d7e6e08c3352249ce9bc72b82b7989a1758b70a3bdc41912cc0eb048bd70cc4da0794b929f53aacdfe6227e5defc13aeb3465cc5cc744393a8c
|
7
|
+
data.tar.gz: 5ded1f1c7315194f7ae8a791aea4e21221b524debdc4136fe2e60911b9c050c9e948af0529aca1eff1dcfd1e68a8f3ab17be448b65aab202bf16c789d0e7b4a1
|
data/README.md
CHANGED
@@ -7,8 +7,7 @@
|
|
7
7
|
For more information on project states and SLAs, see [this documentation](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md).
|
8
8
|
|
9
9
|
[](https://community-slack.chef.io/)
|
10
|
-
[](https://ci.appveyor.com/project/Chef/inspec/branch/master)
|
10
|
+
[](https://buildkite.com/chef-oss/inspec-inspec-master-verify)
|
12
11
|
[](https://coveralls.io/github/inspec/inspec?branch=master)
|
13
12
|
|
14
13
|
Chef InSpec is an open-source testing framework for infrastructure with a human- and machine-readable language for specifying compliance, security and policy requirements.
|
data/lib/fetchers/git.rb
CHANGED
@@ -39,28 +39,65 @@ module Fetchers
|
|
39
39
|
@branch = opts[:branch]
|
40
40
|
@tag = opts[:tag]
|
41
41
|
@ref = opts[:ref]
|
42
|
-
@remote_url = remote_url
|
42
|
+
@remote_url = expand_local_path(remote_url)
|
43
43
|
@repo_directory = nil
|
44
|
+
@relative_path = opts[:relative_path] if opts[:relative_path] && !opts[:relative_path].empty?
|
44
45
|
end
|
45
46
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
47
|
+
def expand_local_path(url_or_file_path)
|
48
|
+
# This paths to local on-disk repos, not relative paths within repos.
|
49
|
+
# This is especially needed with testing.
|
50
|
+
|
51
|
+
# We could try to do something clever with URI
|
52
|
+
# processing, but then again, if you passed a relative path
|
53
|
+
# to an on-disk repo, you probably expect it to exist.
|
54
|
+
return url_or_file_path unless File.exist?(url_or_file_path)
|
55
|
+
# It's important to expand this path, because it may be specified
|
56
|
+
# locally in the metadata files, and when we clone, we will be
|
57
|
+
# in a temp dir.
|
58
|
+
File.expand_path(url_or_file_path)
|
59
|
+
end
|
60
|
+
|
61
|
+
def fetch(destination_path)
|
62
|
+
@repo_directory = destination_path # Might be the cache, or vendoring, or something else
|
63
|
+
FileUtils.mkdir_p(destination_path) unless Dir.exist?(destination_path)
|
49
64
|
|
50
65
|
if cloned?
|
51
66
|
checkout
|
52
67
|
else
|
53
|
-
Dir.mktmpdir do |
|
54
|
-
checkout(
|
55
|
-
|
56
|
-
|
68
|
+
Dir.mktmpdir do |working_dir|
|
69
|
+
checkout(working_dir)
|
70
|
+
if @relative_path
|
71
|
+
perform_relative_path_fetch(destination_path, working_dir)
|
72
|
+
else
|
73
|
+
Inspec::Log.debug("Checkout of #{resolved_ref} successful. " \
|
74
|
+
"Moving checkout to #{destination_path}")
|
75
|
+
FileUtils.cp_r(working_dir + "/.", destination_path)
|
76
|
+
end
|
57
77
|
end
|
58
78
|
end
|
59
79
|
@repo_directory
|
60
80
|
end
|
61
81
|
|
82
|
+
def perform_relative_path_fetch(destination_path, working_dir)
|
83
|
+
Inspec::Log.debug("Checkout of #{resolved_ref} successful. " \
|
84
|
+
"Moving #{@relative_path} to #{destination_path}")
|
85
|
+
unless File.exist?("#{working_dir}/#{@relative_path}")
|
86
|
+
# Cleanup the destination path - otherwise we'll have an empty dir
|
87
|
+
# in the cache, which is enough to confuse the cache reader
|
88
|
+
# This is a courtesy, assuming we're writing to the cache; if we're
|
89
|
+
# vendoring to something more complex, don't bother.
|
90
|
+
FileUtils.rmdir(destination_path) if Dir.empty?(destination_path)
|
91
|
+
|
92
|
+
raise ArgumentError, "Cannot find relative path '#{@relative_path}' " \
|
93
|
+
"within profile in git repo specified by '#{@remote_url}'"
|
94
|
+
end
|
95
|
+
FileUtils.cp_r("#{working_dir}/#{@relative_path}", destination_path)
|
96
|
+
end
|
97
|
+
|
62
98
|
def cache_key
|
63
|
-
resolved_ref
|
99
|
+
return resolved_ref unless @relative_path
|
100
|
+
OpenSSL::Digest::SHA256.hexdigest(resolved_ref + @relative_path)
|
64
101
|
end
|
65
102
|
|
66
103
|
def archive_path
|
@@ -68,7 +105,9 @@ module Fetchers
|
|
68
105
|
end
|
69
106
|
|
70
107
|
def resolved_source
|
71
|
-
{ git: @remote_url, ref: resolved_ref }
|
108
|
+
source = { git: @remote_url, ref: resolved_ref }
|
109
|
+
source[:relative_path] = @relative_path if @relative_path
|
110
|
+
source
|
72
111
|
end
|
73
112
|
|
74
113
|
private
|
data/lib/inspec/cli.rb
CHANGED
@@ -123,36 +123,32 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
123
123
|
puts JSON.generate(result)
|
124
124
|
else
|
125
125
|
%w{location profile controls timestamp valid}.each do |item|
|
126
|
-
|
127
|
-
|
126
|
+
prepared_string = format("%-12s %s",
|
127
|
+
"#{item.to_s.capitalize} :",
|
128
|
+
result[:summary][item.to_sym])
|
129
|
+
ui.plain_line(prepared_string)
|
128
130
|
end
|
129
131
|
puts
|
130
132
|
|
131
133
|
if result[:errors].empty? && result[:warnings].empty?
|
132
|
-
|
134
|
+
ui.plain_line("No errors or warnings")
|
133
135
|
else
|
134
|
-
red = "\033[31m"
|
135
|
-
yellow = "\033[33m"
|
136
|
-
rst = "\033[0m"
|
137
|
-
|
138
136
|
item_msg = lambda { |item|
|
139
137
|
pos = [item[:file], item[:line], item[:column]].compact.join(":")
|
140
138
|
pos.empty? ? item[:msg] : pos + ": " + item[:msg]
|
141
139
|
}
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
result[:warnings].each do |item|
|
146
|
-
puts "#{yellow} ! #{item_msg.call(item)}#{rst}"
|
147
|
-
end
|
140
|
+
|
141
|
+
result[:errors].each { |item| ui.red " #{Inspec::UI::GLYPHS[:script_x]} #{item_msg.call(item)}\n" }
|
142
|
+
result[:warnings].each { |item| ui.yellow " ! #{item_msg.call(item)}\n" }
|
148
143
|
|
149
144
|
puts
|
150
|
-
|
151
|
-
|
152
|
-
|
145
|
+
|
146
|
+
errors = ui.red("#{result[:errors].length} errors", print: false)
|
147
|
+
warnings = ui.yellow("#{result[:warnings].length} warnings", print: false)
|
148
|
+
ui.plain_line("Summary: #{errors}, #{warnings}")
|
153
149
|
end
|
154
150
|
end
|
155
|
-
exit
|
151
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR unless result[:summary][:valid]
|
156
152
|
rescue StandardError => e
|
157
153
|
pretty_handle_exception(e)
|
158
154
|
end
|
@@ -203,11 +199,11 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
203
199
|
|
204
200
|
if result && !o[:ignore_errors] == false
|
205
201
|
o[:logger].info "Profile check failed. Please fix the profile before generating an archive."
|
206
|
-
return exit
|
202
|
+
return ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
207
203
|
end
|
208
204
|
|
209
205
|
# generate archive
|
210
|
-
exit
|
206
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR unless profile.archive(o)
|
211
207
|
rescue StandardError => e
|
212
208
|
pretty_handle_exception(e)
|
213
209
|
end
|
@@ -294,10 +290,10 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
294
290
|
runner = Inspec::Runner.new(o)
|
295
291
|
targets.each { |target| runner.add_target(target) }
|
296
292
|
|
297
|
-
exit runner.run
|
293
|
+
ui.exit runner.run
|
298
294
|
rescue ArgumentError, RuntimeError, Train::UserError => e
|
299
295
|
$stderr.puts e.message
|
300
|
-
exit
|
296
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
301
297
|
rescue StandardError => e
|
302
298
|
pretty_handle_exception(e)
|
303
299
|
end
|
@@ -312,12 +308,12 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
312
308
|
if o["format"] == "json"
|
313
309
|
puts res.to_json
|
314
310
|
else
|
315
|
-
headline("Platform Details")
|
316
|
-
|
311
|
+
ui.headline("Platform Details")
|
312
|
+
ui.plain Inspec::BaseCLI.format_platform_info(params: res, indent: 0, color: 36)
|
317
313
|
end
|
318
314
|
rescue ArgumentError, RuntimeError, Train::UserError => e
|
319
315
|
$stderr.puts e.message
|
320
|
-
exit
|
316
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
321
317
|
rescue StandardError => e
|
322
318
|
pretty_handle_exception(e)
|
323
319
|
end
|
@@ -348,12 +344,12 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
348
344
|
end
|
349
345
|
|
350
346
|
run_type, res = run_command(o)
|
351
|
-
exit res unless run_type == :ruby_eval
|
347
|
+
ui.exit res unless run_type == :ruby_eval
|
352
348
|
|
353
349
|
# No InSpec tests - just print evaluation output.
|
354
350
|
res = (res.respond_to?(:to_json) ? res.to_json : JSON.dump(res)) if o["reporter"]&.keys&.include?("json")
|
355
351
|
puts res
|
356
|
-
exit
|
352
|
+
ui.exit Inspec::UI::EXIT_NORMAL
|
357
353
|
rescue RuntimeError, Train::UserError => e
|
358
354
|
$stderr.puts e.message
|
359
355
|
rescue StandardError => e
|
@@ -385,14 +381,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
385
381
|
v = { version: Inspec::VERSION }
|
386
382
|
puts v.to_json
|
387
383
|
else
|
388
|
-
require "inspec/utils/latest_version"
|
389
384
|
puts Inspec::VERSION
|
390
|
-
# display outdated version
|
391
|
-
# TODO: remove this. Don't notify of update to a gem when they install omnibus
|
392
|
-
latest = LatestInSpecVersion.new.latest || Inspec::VERSION
|
393
|
-
if Gem::Version.new(Inspec::VERSION) < Gem::Version.new(latest)
|
394
|
-
puts "\nYour version of #{Inspec::Dist::PRODUCT_NAME} is out of date! The latest version is #{latest}."
|
395
|
-
end
|
396
385
|
end
|
397
386
|
end
|
398
387
|
map %w{-v --version} => :version
|
@@ -470,5 +459,5 @@ rescue Inspec::Plugin::V2::Exception => v2ex
|
|
470
459
|
else
|
471
460
|
Inspec::Log.error "Run again with --debug for a stacktrace."
|
472
461
|
end
|
473
|
-
exit
|
462
|
+
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
474
463
|
end
|
@@ -88,6 +88,11 @@ module Inspec::Resources
|
|
88
88
|
return nil
|
89
89
|
end
|
90
90
|
|
91
|
+
# If multiple triggers are defined, `schtasks` returns a list.
|
92
|
+
# This merges that list with the latest item taking precedence.
|
93
|
+
# This is the same behavior as `Get-ScheduledTask`.
|
94
|
+
params = params.reduce(:merge) if params.is_a?(Array)
|
95
|
+
|
91
96
|
@cache = {
|
92
97
|
uri: params["URI"],
|
93
98
|
state: params["State"],
|
data/lib/inspec/version.rb
CHANGED
@@ -64,18 +64,6 @@ module InspecPlugins
|
|
64
64
|
habitat_origin: read_habitat_config["origin"],
|
65
65
|
}
|
66
66
|
create_file_from_template(plan_file, "plan.sh.erb", vars)
|
67
|
-
|
68
|
-
run_hook_file = File.join(path, "habitat", "hooks", "run")
|
69
|
-
logger.info("Generating a Habitat run hook at #{run_hook_file}...")
|
70
|
-
create_file_from_template(run_hook_file, "hooks/run.erb")
|
71
|
-
|
72
|
-
default_toml = File.join(path, "habitat", "default.toml")
|
73
|
-
logger.info("Generating a Habitat default.toml at #{default_toml}...")
|
74
|
-
create_file_from_template(default_toml, "default.toml.erb")
|
75
|
-
|
76
|
-
config = File.join(path, "habitat", "config", "inspec_exec_config.json")
|
77
|
-
logger.info("Generating #{config} for `#{EXEC_NAME} exec`...")
|
78
|
-
create_file_from_template(config, "config/inspec_exec_config.json.erb")
|
79
67
|
end
|
80
68
|
|
81
69
|
def upload
|
@@ -5,81 +5,4 @@ pkg_deps=(chef/inspec)
|
|
5
5
|
pkg_build_deps=(chef/inspec core/jq-static)
|
6
6
|
pkg_svc_user=root
|
7
7
|
<%= "pkg_license='#{profile.metadata.params[:license]}'" if profile.metadata.params[:license]%>
|
8
|
-
|
9
|
-
do_before() {
|
10
|
-
# Exit with error if not in the directory with 'inspec.yml'.
|
11
|
-
# This can happen if someone does 'hab studio enter' from within the
|
12
|
-
# 'habitat/' directory.
|
13
|
-
if [ ! -f "$PLAN_CONTEXT/../inspec.yml" ]; then
|
14
|
-
message="ERROR: Cannot find inspec.yml."
|
15
|
-
message="$message Please build from the profile root"
|
16
|
-
build_line "$message"
|
17
|
-
|
18
|
-
return 1
|
19
|
-
fi
|
20
|
-
|
21
|
-
# Execute an '<%= Inspec::Dist::EXEC_NAME %> compliance login' if a profile needs to be fetched from
|
22
|
-
# the Automate server
|
23
|
-
if [ "$(grep "compliance: " "$PLAN_CONTEXT/../inspec.yml")" ]; then
|
24
|
-
_do_compliance_login;
|
25
|
-
fi
|
26
|
-
}
|
27
|
-
|
28
|
-
do_setup_environment() {
|
29
|
-
set_buildtime_env PROFILE_CACHE_DIR "$HAB_CACHE_SRC_PATH/$pkg_dirname"
|
30
|
-
set_buildtime_env ARCHIVE_NAME "$pkg_name-$pkg_version.tar.gz"
|
31
|
-
|
32
|
-
# <%= Inspec::Dist::PRODUCT_NAME %> loads `pry` which tries to expand `~`. This fails if HOME isn't set.
|
33
|
-
set_runtime_env HOME "$pkg_svc_var_path"
|
34
|
-
|
35
|
-
# <%= Inspec::Dist::PRODUCT_NAME %> will create a `.inspec` directory in the user's home directory.
|
36
|
-
# This overrides that to write to a place within the running service's path.
|
37
|
-
# NOTE: Setting HOME does the same currently. This is here to be explicit.
|
38
|
-
set_runtime_env INSPEC_CONFIG_DIR "$pkg_svc_var_path"
|
39
|
-
}
|
40
|
-
|
41
|
-
do_unpack() {
|
42
|
-
# Change directory to where the profile files are
|
43
|
-
pushd "$PLAN_CONTEXT/../" > /dev/null
|
44
|
-
|
45
|
-
# Get a list of all files in the profile except those that are Habitat related
|
46
|
-
profile_files=($(ls -I habitat -I results -I "*.hart"))
|
47
|
-
|
48
|
-
mkdir -p "$PROFILE_CACHE_DIR" > /dev/null
|
49
|
-
|
50
|
-
# Copy just the profile files to the profile cache directory
|
51
|
-
cp -r ${profile_files[@]} "$PROFILE_CACHE_DIR"
|
52
|
-
}
|
53
|
-
|
54
|
-
do_build() {
|
55
|
-
<%= Inspec::Dist::EXEC_NAME %> archive "$PROFILE_CACHE_DIR" \
|
56
|
-
--overwrite \
|
57
|
-
-o "$PROFILE_CACHE_DIR/$ARCHIVE_NAME"
|
58
|
-
}
|
59
|
-
|
60
|
-
do_install() {
|
61
|
-
cp "$PROFILE_CACHE_DIR/$ARCHIVE_NAME" "$pkg_prefix"
|
62
|
-
}
|
63
|
-
|
64
|
-
_do_compliance_login() {
|
65
|
-
if [ -z $COMPLIANCE_CREDS ]; then
|
66
|
-
message="ERROR: Please perform an '<%= Inspec::Dist::EXEC_NAME %> compliance login' and set"
|
67
|
-
message="$message \$HAB_STUDIO_SECRET_COMPLIANCE_CREDS to the contents of"
|
68
|
-
message="$message '~/.inspec/compliance/config.json'"
|
69
|
-
build_line "$message"
|
70
|
-
return 1
|
71
|
-
fi
|
72
|
-
|
73
|
-
user=$(echo $COMPLIANCE_CREDS | jq .user | sed 's/"//g')
|
74
|
-
token=$(echo $COMPLIANCE_CREDS | jq .token | sed 's/"//g')
|
75
|
-
automate_server=$(echo $COMPLIANCE_CREDS | \
|
76
|
-
jq .server | \
|
77
|
-
sed 's/\/api\/v0//' | \
|
78
|
-
sed 's/"//g'
|
79
|
-
)
|
80
|
-
insecure=$(echo $COMPLIANCE_CREDS | jq .insecure)
|
81
|
-
<%= Inspec::Dist::EXEC_NAME %> compliance login --insecure $insecure \
|
82
|
-
--user $user \
|
83
|
-
--token $token \
|
84
|
-
$automate_server
|
85
|
-
}
|
8
|
+
pkg_scaffolding="chef/scaffolding-chef-inspec"
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require "term/ansicolor"
|
2
1
|
require "pathname"
|
3
2
|
require "inspec/plugin/v2"
|
4
3
|
require "inspec/plugin/v2/installer"
|
@@ -7,7 +6,6 @@ require "inspec/dist"
|
|
7
6
|
module InspecPlugins
|
8
7
|
module PluginManager
|
9
8
|
class CliCommand < Inspec.plugin(2, :cli_command)
|
10
|
-
include Term::ANSIColor
|
11
9
|
include Inspec::Dist
|
12
10
|
|
13
11
|
subcommand_desc "plugin SUBCOMMAND", "Manage #{PRODUCT_NAME} and Train plugins"
|
@@ -22,15 +20,17 @@ module InspecPlugins
|
|
22
20
|
plugin_statuses = Inspec::Plugin::V2::Registry.instance.plugin_statuses
|
23
21
|
plugin_statuses.reject! { |s| %i{core bundle}.include?(s.installation_type) } unless options[:all]
|
24
22
|
|
25
|
-
# TODO: ui object support
|
26
23
|
puts
|
27
|
-
|
28
|
-
|
24
|
+
ui.bold(format(" %-30s%-10s%-8s%-6s", "Plugin Name", "Version", "Via", "ApiVer"))
|
25
|
+
ui.line
|
29
26
|
plugin_statuses.sort_by(&:name).each do |status|
|
30
|
-
|
27
|
+
ui.plain(format(" %-30s%-10s%-8s%-6s", status.name,
|
28
|
+
make_pretty_version(status),
|
29
|
+
status.installation_type,
|
30
|
+
status.api_generation.to_s))
|
31
31
|
end
|
32
|
-
|
33
|
-
|
32
|
+
ui.line
|
33
|
+
ui.plain(" #{plugin_statuses.count} plugin(s) total")
|
34
34
|
puts
|
35
35
|
end
|
36
36
|
|
@@ -59,23 +59,22 @@ module InspecPlugins
|
|
59
59
|
search_results.delete("train-test-fixture")
|
60
60
|
end
|
61
61
|
|
62
|
-
# TODO: ui object support
|
63
62
|
puts
|
64
|
-
|
65
|
-
|
63
|
+
ui.bold(format(" %-30s%-50s", "Plugin Name", "Versions Available"))
|
64
|
+
ui.line
|
66
65
|
search_results.keys.sort.each do |plugin_name|
|
67
66
|
versions = options[:all] ? search_results[plugin_name] : [search_results[plugin_name].first]
|
68
67
|
versions = "(" + versions.join(", ") + ")"
|
69
|
-
|
68
|
+
ui.plain(format(" %-30s%-50s", plugin_name, versions))
|
70
69
|
end
|
71
|
-
|
72
|
-
|
70
|
+
ui.line
|
71
|
+
ui.plain(" #{search_results.count} plugin(s) found")
|
73
72
|
puts
|
74
73
|
|
75
|
-
exit
|
74
|
+
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR if search_results.empty?
|
76
75
|
rescue Inspec::Plugin::V2::SearchError => ex
|
77
76
|
Inspec::Log.error ex.message
|
78
|
-
exit
|
77
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
79
78
|
end
|
80
79
|
|
81
80
|
#==================================================================#
|
@@ -119,13 +118,14 @@ module InspecPlugins
|
|
119
118
|
begin
|
120
119
|
installer.update(plugin_name)
|
121
120
|
rescue Inspec::Plugin::V2::UpdateError => ex
|
122
|
-
|
123
|
-
exit
|
121
|
+
ui.plain("#{ui.red('Update error:')} #{ex.message} - update failed")
|
122
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
124
123
|
end
|
125
124
|
post_update_versions = installer.list_installed_plugin_gems.select { |spec| spec.name == plugin_name }.map { |spec| spec.version.to_s }
|
126
125
|
new_version = (post_update_versions - pre_update_versions).first
|
127
126
|
|
128
|
-
|
127
|
+
ui.bold(plugin_name + " plugin, version #{old_version} -> " \
|
128
|
+
"#{new_version}, updated from rubygems.org")
|
129
129
|
end
|
130
130
|
|
131
131
|
#--------------------------
|
@@ -144,9 +144,9 @@ module InspecPlugins
|
|
144
144
|
def uninstall(plugin_name)
|
145
145
|
status = Inspec::Plugin::V2::Registry.instance[plugin_name.to_sym]
|
146
146
|
unless status
|
147
|
-
|
148
|
-
|
149
|
-
exit
|
147
|
+
ui.plain("#{ui.red('No such plugin installed:')} #{plugin_name} is not " \
|
148
|
+
"installed - uninstall failed")
|
149
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
150
150
|
end
|
151
151
|
installer = Inspec::Plugin::V2::Installer.instance
|
152
152
|
|
@@ -156,11 +156,13 @@ module InspecPlugins
|
|
156
156
|
installer.uninstall(plugin_name)
|
157
157
|
|
158
158
|
if status.installation_type == :path
|
159
|
-
|
159
|
+
ui.bold(plugin_name + " path-based plugin install has been " \
|
160
|
+
"uninstalled")
|
160
161
|
else
|
161
|
-
|
162
|
+
ui.bold(plugin_name + " plugin, version #{old_version}, has " \
|
163
|
+
"been uninstalled")
|
162
164
|
end
|
163
|
-
exit
|
165
|
+
ui.exit Inspec::UI::EXIT_NORMAL
|
164
166
|
end
|
165
167
|
|
166
168
|
private
|
@@ -172,8 +174,8 @@ module InspecPlugins
|
|
172
174
|
|
173
175
|
def install_from_gemfile(gem_file)
|
174
176
|
unless File.exist? gem_file
|
175
|
-
|
176
|
-
exit
|
177
|
+
ui.red("No such plugin gem file #{gem_file} - installation failed.")
|
178
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
177
179
|
end
|
178
180
|
|
179
181
|
plugin_name_parts = File.basename(gem_file, ".gem").split("-")
|
@@ -183,14 +185,15 @@ module InspecPlugins
|
|
183
185
|
|
184
186
|
installer.install(plugin_name, gem_file: gem_file)
|
185
187
|
|
186
|
-
|
187
|
-
|
188
|
+
ui.bold("#{plugin_name} plugin, version #{version}, installed from " \
|
189
|
+
"local .gem file")
|
190
|
+
ui.exit Inspec::UI::EXIT_NORMAL
|
188
191
|
end
|
189
192
|
|
190
193
|
def install_from_path(path)
|
191
194
|
unless File.exist? path
|
192
|
-
|
193
|
-
exit
|
195
|
+
ui.red("No such source code path #{path} - installation failed.")
|
196
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
194
197
|
end
|
195
198
|
|
196
199
|
plugin_name = File.basename(path, ".rb")
|
@@ -204,8 +207,10 @@ module InspecPlugins
|
|
204
207
|
|
205
208
|
# Already installed?
|
206
209
|
if registry.known_plugin?(plugin_name.to_sym)
|
207
|
-
|
208
|
-
|
210
|
+
ui.red("Plugin already installed - #{plugin_name} - Use '#{EXEC_NAME} " \
|
211
|
+
"plugin list' to see previously installed plugin - " \
|
212
|
+
"installation failed.")
|
213
|
+
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
209
214
|
end
|
210
215
|
|
211
216
|
# Can we figure out how to load it?
|
@@ -217,8 +222,9 @@ module InspecPlugins
|
|
217
222
|
# OK, install it!
|
218
223
|
installer.install(plugin_name, path: entry_point)
|
219
224
|
|
220
|
-
|
221
|
-
|
225
|
+
ui.bold("#{plugin_name} plugin installed via source path reference, " \
|
226
|
+
"resolved to entry point #{entry_point}")
|
227
|
+
ui.exit Inspec::UI::EXIT_NORMAL
|
222
228
|
end
|
223
229
|
|
224
230
|
# Rationale for rubocop variances: It's a heuristics method, and will be full of
|
@@ -229,6 +235,7 @@ module InspecPlugins
|
|
229
235
|
given = given.expand_path # Resolve any relative paths
|
230
236
|
name_regex = /^(inspec|train)-/
|
231
237
|
versioned_regex = /^(inspec|train)-[a-z0-9\-\_]+-\d+\.\d+\.\d+$/
|
238
|
+
sha_ref_regex = /^(inspec|train)-[a-z0-9\-\_]+-[0-9a-f]{5,40}$/
|
232
239
|
|
233
240
|
# What are the last four things like?
|
234
241
|
parts = [
|
@@ -257,14 +264,14 @@ module InspecPlugins
|
|
257
264
|
# In that case, we'll have a version on the plugin name in part 0
|
258
265
|
# /home/you/.gems/2.4.0/gems/inspec-something-3.45.1/lib/inspec-something.rb
|
259
266
|
# parts index: ^0^ ^1^ ^2^ ^3^
|
260
|
-
if parts[0] =~ versioned_regex && parts[1] == "lib" && parts[0].start_with?(parts[2]) && parts[3] == ".rb"
|
267
|
+
if (parts[0] =~ versioned_regex || parts[0] =~ sha_ref_regex) && parts[1] == "lib" && parts[0].start_with?(parts[2]) && parts[3] == ".rb"
|
261
268
|
return given.to_s
|
262
269
|
end
|
263
270
|
|
264
271
|
# Case 4: Like case 3, but missing the .rb
|
265
272
|
# /home/you/.gems/2.4.0/gems/inspec-something-3.45.1/lib/inspec-something
|
266
273
|
# parts index: ^0^ ^1^ ^2^ ^3^ (empty)
|
267
|
-
if parts[0] =~ versioned_regex && parts[1] == "lib" && parts[0].start_with?(parts[2]) && parts[3].empty?
|
274
|
+
if (parts[0] =~ versioned_regex || parts[0] =~ sha_ref_regex) && parts[1] == "lib" && parts[0].start_with?(parts[2]) && parts[3].empty?
|
268
275
|
return given.to_s + ".rb"
|
269
276
|
end
|
270
277
|
|
@@ -279,8 +286,10 @@ module InspecPlugins
|
|
279
286
|
|
280
287
|
# Well, if we got here, parts[2] matches an inspec/train prefix, but we have no idea about anything.
|
281
288
|
# Give up.
|
282
|
-
|
283
|
-
|
289
|
+
ui.red("Unrecognizable plugin structure - #{parts[2]} - When " \
|
290
|
+
"installing from a path, please provide the path of the " \
|
291
|
+
"entry point file - installation failed.")
|
292
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
284
293
|
end
|
285
294
|
|
286
295
|
def install_from_path__probe_load(entry_point, plugin_name)
|
@@ -288,9 +297,11 @@ module InspecPlugins
|
|
288
297
|
begin
|
289
298
|
require entry_point
|
290
299
|
rescue LoadError => ex
|
291
|
-
|
292
|
-
|
293
|
-
|
300
|
+
ui.red("Plugin contains errors - #{plugin_name} - Encountered " \
|
301
|
+
"errors while trying to test load the plugin entry point, " \
|
302
|
+
"resolved to #{entry_point} - installation failed")
|
303
|
+
ui.plain ex.message
|
304
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
294
305
|
end
|
295
306
|
|
296
307
|
# OK, the wheels didn't fall off. But is it a plugin?
|
@@ -299,13 +310,19 @@ module InspecPlugins
|
|
299
310
|
# And the registry is keyed on Strings
|
300
311
|
registry_key = plugin_name.to_s.sub(/^train-/, "")
|
301
312
|
unless Train::Plugins.registry.key?(registry_key)
|
302
|
-
|
303
|
-
|
313
|
+
ui.red("Does not appear to be a plugin - #{plugin_name} - After " \
|
314
|
+
"probe-loading the supposed plugin, it did not register " \
|
315
|
+
"itself to Train. Ensure something inherits from " \
|
316
|
+
"'Train.plugin(1)' - installation failed.")
|
317
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
304
318
|
end
|
305
319
|
else
|
306
320
|
unless registry.known_plugin?(plugin_name.to_sym)
|
307
|
-
|
308
|
-
|
321
|
+
ui.red("Does not appear to be a plugin - #{plugin_name} - After " \
|
322
|
+
"probe-loading the supposed plugin, it did not register " \
|
323
|
+
"itself to InSpec. Ensure something inherits from " \
|
324
|
+
"'Inspec.plugin(2)' - installation failed.")
|
325
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
309
326
|
end
|
310
327
|
end
|
311
328
|
end
|
@@ -325,8 +342,9 @@ module InspecPlugins
|
|
325
342
|
post_installed_versions = installer.list_installed_plugin_gems.select { |spec| spec.name == plugin_name }.map { |spec| spec.version.to_s }
|
326
343
|
new_version = (post_installed_versions - pre_installed_versions).first
|
327
344
|
|
328
|
-
|
329
|
-
|
345
|
+
ui.bold("#{plugin_name} plugin, version #{new_version}, installed " \
|
346
|
+
"from rubygems.org")
|
347
|
+
ui.exit Inspec::UI::EXIT_NORMAL
|
330
348
|
end
|
331
349
|
|
332
350
|
def install_from_remote_gem_verson_preflight_check(plugin_name, requested_version, pre_installed_versions)
|
@@ -348,38 +366,50 @@ module InspecPlugins
|
|
348
366
|
they_explicitly_asked_for_a_version = !options[:version].nil?
|
349
367
|
what_we_would_install_is_already_installed = pre_installed_versions.include?(requested_version)
|
350
368
|
if what_we_would_install_is_already_installed && they_explicitly_asked_for_a_version
|
351
|
-
|
369
|
+
ui.red("Plugin already installed at requested version - plugin " \
|
370
|
+
"#{plugin_name} #{requested_version} - refusing to install.")
|
352
371
|
elsif what_we_would_install_is_already_installed && !they_explicitly_asked_for_a_version
|
353
|
-
|
372
|
+
ui.red("Plugin already installed at latest version - plugin " \
|
373
|
+
"#{plugin_name} #{requested_version} - refusing to install.")
|
354
374
|
else
|
355
375
|
# There are existing versions installed, but none of them are what was requested
|
356
|
-
|
376
|
+
ui.red("Update required - plugin #{plugin_name}, requested " \
|
377
|
+
"#{requested_version}, have " \
|
378
|
+
"#{pre_installed_versions.join(', ')}; use `inspec " \
|
379
|
+
"plugin update` - refusing to install.")
|
357
380
|
end
|
358
381
|
|
359
|
-
exit
|
382
|
+
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
360
383
|
end
|
361
384
|
|
362
385
|
# Rationale for RuboCop variance: This is a one-line method with heavy UX-focused error handling.
|
363
386
|
def install_attempt_install(plugin_name) # rubocop: disable Metrics/AbcSize
|
364
387
|
installer.install(plugin_name, version: options[:version])
|
365
388
|
rescue Inspec::Plugin::V2::PluginExcludedError => ex
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
389
|
+
ui.red("Plugin on Exclusion List - #{plugin_name} is listed as an " \
|
390
|
+
"incompatible gem - refusing to install.")
|
391
|
+
ui.plain("Rationale: #{ex.details.rationale}")
|
392
|
+
ui.plain("Exclusion list location: " +
|
393
|
+
File.join(Inspec.src_root, "etc", "plugin_filters.json"))
|
394
|
+
ui.plain("If you disagree with this determination, please accept " \
|
395
|
+
"our apologies for the misunderstanding, and open an issue " \
|
396
|
+
"at https://github.com/inspec/inspec/issues/new")
|
397
|
+
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
371
398
|
rescue Inspec::Plugin::V2::InstallError
|
372
399
|
raise if Inspec::Log.level == :debug
|
373
400
|
|
374
401
|
results = installer.search(plugin_name, exact: true)
|
375
402
|
if results.empty?
|
376
|
-
|
403
|
+
ui.red("No such plugin gem #{plugin_name} could be found on " \
|
404
|
+
"rubygems.org - installation failed.")
|
377
405
|
elsif options[:version] && !results[plugin_name].include?(options[:version])
|
378
|
-
|
406
|
+
ui.red("No such version - #{plugin_name} exists, but no such " \
|
407
|
+
"version #{options[:version]} found on rubygems.org - " \
|
408
|
+
"installation failed.")
|
379
409
|
else
|
380
|
-
|
410
|
+
ui.red("Unknown error occured - installation failed.")
|
381
411
|
end
|
382
|
-
exit
|
412
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
383
413
|
end
|
384
414
|
|
385
415
|
#==================================================================#
|
@@ -390,11 +420,14 @@ module InspecPlugins
|
|
390
420
|
# Check for path install
|
391
421
|
status = Inspec::Plugin::V2::Registry.instance[plugin_name.to_sym]
|
392
422
|
if !status
|
393
|
-
|
394
|
-
exit
|
423
|
+
ui.plain("#{ui.red('No such plugin installed:')} #{plugin_name} - update failed")
|
424
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
395
425
|
elsif status.installation_type == :path
|
396
|
-
|
397
|
-
|
426
|
+
ui.plain("#{ui.red('Cannot update path-based install:')} " \
|
427
|
+
"#{plugin_name} is installed via path reference; " \
|
428
|
+
"use `inspec plugin uninstall` to remove - refusing to" \
|
429
|
+
"update")
|
430
|
+
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
398
431
|
end
|
399
432
|
end
|
400
433
|
|
@@ -403,8 +436,10 @@ module InspecPlugins
|
|
403
436
|
latest_version = latest_version[plugin_name]&.last
|
404
437
|
|
405
438
|
if pre_update_versions.include?(latest_version)
|
406
|
-
|
407
|
-
|
439
|
+
ui.plain("#{ui.red('Already installed at latest version:')} " \
|
440
|
+
"#{plugin_name} is at #{latest_version}, which the " \
|
441
|
+
"latest - refusing to update")
|
442
|
+
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
408
443
|
end
|
409
444
|
end
|
410
445
|
|
@@ -421,8 +456,10 @@ module InspecPlugins
|
|
421
456
|
|
422
457
|
def check_plugin_name(plugin_name, action)
|
423
458
|
unless plugin_name =~ /^(inspec|train)-/
|
424
|
-
|
425
|
-
|
459
|
+
ui.red("Invalid plugin name - #{plugin_name} - All inspec " \
|
460
|
+
"plugins must begin with either 'inspec-' or 'train-' " \
|
461
|
+
"- #{action} failed.")
|
462
|
+
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
426
463
|
end
|
427
464
|
end
|
428
465
|
|
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.10.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominik Richter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: train-core
|
@@ -598,7 +598,6 @@ files:
|
|
598
598
|
- lib/inspec/utils/find_files.rb
|
599
599
|
- lib/inspec/utils/hash.rb
|
600
600
|
- lib/inspec/utils/json_log.rb
|
601
|
-
- lib/inspec/utils/latest_version.rb
|
602
601
|
- lib/inspec/utils/modulator.rb
|
603
602
|
- lib/inspec/utils/nginx_parser.rb
|
604
603
|
- lib/inspec/utils/object_traversal.rb
|
@@ -633,9 +632,6 @@ files:
|
|
633
632
|
- lib/plugins/inspec-habitat/lib/inspec-habitat.rb
|
634
633
|
- lib/plugins/inspec-habitat/lib/inspec-habitat/cli.rb
|
635
634
|
- lib/plugins/inspec-habitat/lib/inspec-habitat/profile.rb
|
636
|
-
- lib/plugins/inspec-habitat/templates/habitat/config/inspec_exec_config.json.erb
|
637
|
-
- lib/plugins/inspec-habitat/templates/habitat/default.toml.erb
|
638
|
-
- lib/plugins/inspec-habitat/templates/habitat/hooks/run.erb
|
639
635
|
- lib/plugins/inspec-habitat/templates/habitat/plan.sh.erb
|
640
636
|
- lib/plugins/inspec-init/README.md
|
641
637
|
- lib/plugins/inspec-init/lib/inspec-init.rb
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require "json"
|
2
|
-
require "open-uri"
|
3
|
-
|
4
|
-
class LatestInSpecVersion
|
5
|
-
# fetches the latest version from rubygems server
|
6
|
-
def latest
|
7
|
-
uri = URI("https://rubygems.org/api/v1/gems/inspec.json")
|
8
|
-
inspec_info = JSON.parse(uri.read(open_timeout: 1.5, read_timeout: 1.5))
|
9
|
-
inspec_info["version"]
|
10
|
-
rescue StandardError
|
11
|
-
nil
|
12
|
-
end
|
13
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"target_id": "{{ sys.member_id }}",
|
3
|
-
"reporter": {
|
4
|
-
"cli": {
|
5
|
-
"stdout": {{cfg.report_to_stdout}}
|
6
|
-
},
|
7
|
-
"json": {
|
8
|
-
"file": "{{pkg.svc_path}}/logs/inspec_last_run.json"
|
9
|
-
}{{#if cfg.automate.token ~}},
|
10
|
-
"automate" : {
|
11
|
-
"url": "{{cfg.automate.url}}/data-collector/v0/",
|
12
|
-
"token": "{{cfg.automate.token}}",
|
13
|
-
"node_name": "{{ sys.hostname }}",
|
14
|
-
"verify_ssl": false
|
15
|
-
}{{/if ~}}
|
16
|
-
}
|
17
|
-
{{#if cfg.automate.token }},
|
18
|
-
"compliance": {
|
19
|
-
"server" : "{{cfg.automate.url}}",
|
20
|
-
"token" : "{{cfg.automate.token}}",
|
21
|
-
"user" : "{{cfg.automate.user}}",
|
22
|
-
"insecure" : true,
|
23
|
-
"ent" : "automate"
|
24
|
-
}{{/if }}
|
25
|
-
}
|
@@ -1,32 +0,0 @@
|
|
1
|
-
#!/bin/sh
|
2
|
-
|
3
|
-
exec 2>&1
|
4
|
-
|
5
|
-
CONFIG="{{pkg.svc_config_path}}/inspec_exec_config.json"
|
6
|
-
INTERVAL="{{cfg.interval}}"
|
7
|
-
LOG_FILE="{{pkg.svc_path}}/logs/inspec_log.txt"
|
8
|
-
PROFILE_IDENT="{{pkg.origin}}/{{pkg.name}}"
|
9
|
-
PROFILE_PATH="{{pkg.path}}/{{pkg.name}}-{{pkg.version}}.tar.gz"
|
10
|
-
|
11
|
-
while true; do
|
12
|
-
echo "Executing ${PROFILE_IDENT}"
|
13
|
-
exec <%= Inspec::Dist::EXEC_NAME %> exec ${PROFILE_PATH} --json-config ${CONFIG} 2>&1 | tee ${LOG_FILE}
|
14
|
-
|
15
|
-
exit_code=$?
|
16
|
-
if [ $exit_code -eq 1 ]; then
|
17
|
-
echo "<%= Inspec::Dist::PRODUCT_NAME %> run failed."
|
18
|
-
else
|
19
|
-
echo "<%= Inspec::Dist::PRODUCT_NAME %> run completed successfully."
|
20
|
-
if [ $exit_code -eq 0 ]; then
|
21
|
-
echo "No controls failed or were skipped."
|
22
|
-
elif [ $exit_code -eq 100 ]; then
|
23
|
-
echo "At least 1 control failed."
|
24
|
-
elif [ $exit_code -eq 101 ]; then
|
25
|
-
echo "No controls failed but at least 1 skipped."
|
26
|
-
fi
|
27
|
-
fi
|
28
|
-
echo "Results are logged here: ${LOG_FILE}"
|
29
|
-
|
30
|
-
echo "Sleeping for ${INTERVAL} seconds"
|
31
|
-
sleep ${INTERVAL}
|
32
|
-
done
|