inspec-core 5.17.4 → 5.18.14
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 +1 -1
- data/etc/deprecations.json +4 -0
- data/inspec-core.gemspec +1 -1
- data/lib/inspec/base_cli.rb +5 -0
- data/lib/inspec/cli.rb +62 -9
- data/lib/inspec/dependencies/dependency_set.rb +6 -2
- data/lib/inspec/dsl.rb +18 -5
- data/lib/inspec/errors.rb +2 -0
- data/lib/inspec/exceptions.rb +2 -0
- data/lib/inspec/fetcher/url.rb +1 -1
- data/lib/inspec/file_provider.rb +36 -0
- data/lib/inspec/iaf_file.rb +127 -0
- data/lib/inspec/profile.rb +17 -7
- data/lib/inspec/resources/aide_conf.rb +4 -0
- data/lib/inspec/resources/apache.rb +4 -0
- data/lib/inspec/resources/apache_conf.rb +4 -0
- data/lib/inspec/resources/apt.rb +6 -1
- data/lib/inspec/resources/audit_policy.rb +5 -0
- data/lib/inspec/resources/auditd_conf.rb +4 -0
- data/lib/inspec/resources/bash.rb +4 -0
- data/lib/inspec/resources/bond.rb +4 -0
- data/lib/inspec/resources/bridge.rb +4 -0
- data/lib/inspec/resources/cassandradb_conf.rb +5 -0
- data/lib/inspec/resources/cassandradb_session.rb +8 -3
- data/lib/inspec/resources/chocolatey_package.rb +4 -0
- data/lib/inspec/resources/chrony_conf.rb +4 -0
- data/lib/inspec/resources/command.rb +5 -0
- data/lib/inspec/resources/cpan.rb +4 -0
- data/lib/inspec/resources/cran.rb +4 -0
- data/lib/inspec/resources/cron.rb +5 -0
- data/lib/inspec/resources/csv.rb +6 -1
- data/lib/inspec/resources/dh_params.rb +4 -0
- data/lib/inspec/resources/docker_container.rb +4 -0
- data/lib/inspec/resources/docker_image.rb +4 -0
- data/lib/inspec/resources/docker_plugin.rb +4 -0
- data/lib/inspec/resources/docker_service.rb +4 -0
- data/lib/inspec/resources/etc_group.rb +4 -0
- data/lib/inspec/resources/etc_hosts_allow_deny.rb +5 -0
- data/lib/inspec/resources/file.rb +6 -1
- data/lib/inspec/resources/filesystem.rb +4 -0
- data/lib/inspec/resources/gem.rb +4 -0
- data/lib/inspec/resources/groups.rb +4 -0
- data/lib/inspec/resources/grub_conf.rb +4 -0
- data/lib/inspec/resources/host.rb +4 -0
- data/lib/inspec/resources/http.rb +4 -0
- data/lib/inspec/resources/ibmdb2_conf.rb +8 -0
- data/lib/inspec/resources/ibmdb2_session.rb +12 -3
- data/lib/inspec/resources/iis_app.rb +4 -0
- data/lib/inspec/resources/iis_app_pool.rb +4 -0
- data/lib/inspec/resources/iis_site.rb +4 -0
- data/lib/inspec/resources/inetd_conf.rb +4 -0
- data/lib/inspec/resources/interface.rb +4 -0
- data/lib/inspec/resources/ip6tables.rb +4 -0
- data/lib/inspec/resources/ipfilter.rb +4 -0
- data/lib/inspec/resources/ipnat.rb +4 -0
- data/lib/inspec/resources/iptables.rb +4 -0
- data/lib/inspec/resources/json.rb +4 -0
- data/lib/inspec/resources/kernel_module.rb +4 -0
- data/lib/inspec/resources/kernel_parameter.rb +4 -0
- data/lib/inspec/resources/key_rsa.rb +4 -0
- data/lib/inspec/resources/ksh.rb +4 -0
- data/lib/inspec/resources/limits_conf.rb +4 -0
- data/lib/inspec/resources/login_defs.rb +4 -0
- data/lib/inspec/resources/mongodb.rb +4 -0
- data/lib/inspec/resources/mongodb_conf.rb +5 -0
- data/lib/inspec/resources/mongodb_session.rb +6 -1
- data/lib/inspec/resources/mount.rb +4 -0
- data/lib/inspec/resources/mssql_session.rb +4 -0
- data/lib/inspec/resources/mssql_sys_conf.rb +7 -0
- data/lib/inspec/resources/mysql_conf.rb +4 -0
- data/lib/inspec/resources/mysql_session.rb +8 -1
- data/lib/inspec/resources/nginx.rb +6 -1
- data/lib/inspec/resources/nginx_conf.rb +4 -0
- data/lib/inspec/resources/noop.rb +4 -0
- data/lib/inspec/resources/npm.rb +4 -0
- data/lib/inspec/resources/ntp_conf.rb +4 -0
- data/lib/inspec/resources/oneget.rb +4 -0
- data/lib/inspec/resources/opa_api.rb +10 -0
- data/lib/inspec/resources/opa_cli.rb +14 -0
- data/lib/inspec/resources/oracledb_conf.rb +5 -0
- data/lib/inspec/resources/oracledb_listener_conf.rb +4 -0
- data/lib/inspec/resources/oracledb_session.rb +10 -0
- data/lib/inspec/resources/os.rb +4 -0
- data/lib/inspec/resources/os_env.rb +4 -0
- data/lib/inspec/resources/package.rb +4 -0
- data/lib/inspec/resources/parse_config.rb +10 -1
- data/lib/inspec/resources/pip.rb +4 -0
- data/lib/inspec/resources/platform.rb +4 -0
- data/lib/inspec/resources/postfix_conf.rb +4 -0
- data/lib/inspec/resources/postgres_conf.rb +4 -0
- data/lib/inspec/resources/postgres_session.rb +8 -4
- data/lib/inspec/resources/powershell.rb +4 -0
- data/lib/inspec/resources/processes.rb +6 -4
- data/lib/inspec/resources/rabbitmq_config.rb +4 -0
- data/lib/inspec/resources/registry_key.rb +4 -0
- data/lib/inspec/resources/security_identifier.rb +4 -0
- data/lib/inspec/resources/security_policy.rb +4 -0
- data/lib/inspec/resources/service.rb +4 -0
- data/lib/inspec/resources/ssh_config.rb +4 -0
- data/lib/inspec/resources/sybase_conf.rb +4 -0
- data/lib/inspec/resources/sybase_session.rb +4 -0
- data/lib/inspec/resources/sys_info.rb +4 -0
- data/lib/inspec/resources/timezone.rb +4 -0
- data/lib/inspec/resources/users.rb +4 -0
- data/lib/inspec/resources/vbscript.rb +5 -0
- data/lib/inspec/resources/virtualization.rb +4 -0
- data/lib/inspec/resources/windows_feature.rb +5 -1
- data/lib/inspec/resources/windows_firewall.rb +4 -0
- data/lib/inspec/resources/windows_firewall_rule.rb +4 -0
- data/lib/inspec/resources/windows_hotfix.rb +4 -0
- data/lib/inspec/resources/windows_task.rb +4 -0
- data/lib/inspec/resources/wmi.rb +4 -0
- data/lib/inspec/resources/x509_certificate.rb +59 -0
- data/lib/inspec/resources/yum.rb +4 -0
- data/lib/inspec/resources/zfs_dataset.rb +4 -0
- data/lib/inspec/resources/zfs_pool.rb +4 -0
- data/lib/inspec/rule.rb +1 -1
- data/lib/inspec/secrets/yaml.rb +7 -1
- data/lib/inspec/ui.rb +1 -0
- data/lib/inspec/utils/yaml_profile_summary.rb +34 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/inspec-reporter-html2/templates/body.html.erb +4 -4
- data/lib/plugins/inspec-reporter-html2/templates/control.html.erb +1 -1
- data/lib/plugins/inspec-reporter-html2/templates/profile.html.erb +1 -1
- data/lib/plugins/{inspec-artifact/inspec-artifact.gemspec → inspec-sign/inspec-sign.gemspec} +2 -2
- data/lib/plugins/inspec-sign/lib/inspec-sign/base.rb +161 -0
- data/lib/plugins/{inspec-artifact/lib/inspec-artifact → inspec-sign/lib/inspec-sign}/cli.rb +14 -23
- data/lib/plugins/inspec-sign/lib/inspec-sign.rb +12 -0
- data/lib/source_readers/inspec.rb +8 -2
- metadata +10 -8
- data/lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb +0 -187
- data/lib/plugins/inspec-artifact/lib/inspec-artifact.rb +0 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ba97ee3e25e02fba9b85f797fa1a773d2e8fa7628112be422d187c0e46cfce40
|
|
4
|
+
data.tar.gz: a82f51e5c6ba3e1db8c4580f92a33d91bcc2e0c2a8339850e1f168c1569b8818
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: beb78893376f0b92b9cf33741f8fab471f66dd328fa1f28c87b05737da7f73266327eded07ca67f0b91a747625dfcb61011b42c06a25914d01f727b07a962456
|
|
7
|
+
data.tar.gz: 193aeef4576e2af4466a176b80e107cd45fe0c0c0f6db290d17696cec1eb7dbf6b58b555bf8c0df4b9bb4a9d5aa8d26f542993b5be1d600a296c3ec50e531d09
|
data/Gemfile
CHANGED
data/etc/deprecations.json
CHANGED
|
@@ -121,6 +121,10 @@
|
|
|
121
121
|
"cli_option_target_id":{
|
|
122
122
|
"action": "warn",
|
|
123
123
|
"prefix": "The --target-id option is deprecated in InSpec 5. Its value will be ignored."
|
|
124
|
+
},
|
|
125
|
+
"renamed_to_inspec_export":{
|
|
126
|
+
"action": "ignore",
|
|
127
|
+
"prefix": "The `inspec json` command is deprecated in InSpec 5 and replaced with `inspec export` command."
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
130
|
}
|
data/inspec-core.gemspec
CHANGED
data/lib/inspec/base_cli.rb
CHANGED
|
@@ -138,6 +138,8 @@ module Inspec
|
|
|
138
138
|
desc: "Provides path to Docker API endpoint (Docker)"
|
|
139
139
|
option :ssh_config_file, type: :array,
|
|
140
140
|
desc: "A list of paths to the ssh config file, e.g ~/.ssh/config or /etc/ssh/ssh_config"
|
|
141
|
+
option :podman_url, type: :string,
|
|
142
|
+
desc: "Provides path to Podman API endpoint"
|
|
141
143
|
end
|
|
142
144
|
|
|
143
145
|
def self.profile_options
|
|
@@ -323,6 +325,9 @@ module Inspec
|
|
|
323
325
|
|
|
324
326
|
def pretty_handle_exception(exception)
|
|
325
327
|
case exception
|
|
328
|
+
when Inspec::InvalidProfileSignature
|
|
329
|
+
$stderr.puts exception.message
|
|
330
|
+
Inspec::UI.new.exit(:bad_signature)
|
|
326
331
|
when Inspec::Error
|
|
327
332
|
$stderr.puts exception.message
|
|
328
333
|
exit(1)
|
data/lib/inspec/cli.rb
CHANGED
|
@@ -5,6 +5,7 @@ require "inspec/dist"
|
|
|
5
5
|
require "inspec/backend"
|
|
6
6
|
require "inspec/dependencies/cache"
|
|
7
7
|
require "inspec/utils/json_profile_summary"
|
|
8
|
+
require "inspec/utils/yaml_profile_summary"
|
|
8
9
|
|
|
9
10
|
module Inspec # TODO: move this somewhere "better"?
|
|
10
11
|
autoload :BaseCLI, "inspec/base_cli"
|
|
@@ -69,25 +70,77 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
|
69
70
|
desc: "A list of tags to filter controls and include only those. Ignore all other tests."
|
|
70
71
|
profile_options
|
|
71
72
|
def json(target)
|
|
72
|
-
|
|
73
|
+
# This deprecation warning is ignored currently.
|
|
74
|
+
Inspec.deprecate(:renamed_to_inspec_export)
|
|
75
|
+
export(target, true)
|
|
76
|
+
end
|
|
73
77
|
|
|
78
|
+
desc "export PATH", "read the profile in PATH and generate a summary in the given format."
|
|
79
|
+
option :what, type: :string,
|
|
80
|
+
desc: "What to export: profile (default), readme, metadata."
|
|
81
|
+
option :format, type: :string,
|
|
82
|
+
desc: "The output format to use: json, raw, yaml. If valid format is not provided then it will use the default for the given 'what'."
|
|
83
|
+
option :output, aliases: :o, type: :string,
|
|
84
|
+
desc: "Save the created output to a path"
|
|
85
|
+
option :controls, type: :array,
|
|
86
|
+
desc: "For --what=profile, a list of controls to include. Ignore all other tests."
|
|
87
|
+
option :tags, type: :array,
|
|
88
|
+
desc: "For --what=profile, a list of tags to filter controls and include only those. Ignore all other tests."
|
|
89
|
+
profile_options
|
|
90
|
+
def export(target, as_json = false)
|
|
74
91
|
o = config
|
|
75
92
|
diagnose(o)
|
|
76
93
|
o["log_location"] = $stderr
|
|
77
94
|
configure_logger(o)
|
|
78
95
|
|
|
96
|
+
# using dup to resolve "can't modify frozen String" error.
|
|
97
|
+
what = o[:what].dup || "profile"
|
|
98
|
+
what.downcase!
|
|
99
|
+
raise Inspec::Error.new("Unrecognized option '#{what}' for --what - expected one of profile, readme, or metadata.") unless %w{profile readme metadata}.include?(what)
|
|
100
|
+
|
|
101
|
+
default_format_for_what = {
|
|
102
|
+
"profile" => "yaml",
|
|
103
|
+
"metadata" => "raw",
|
|
104
|
+
"readme" => "raw",
|
|
105
|
+
}
|
|
106
|
+
valid_formats_for_what = {
|
|
107
|
+
"profile" => %w{yaml json},
|
|
108
|
+
"metadata" => %w{yaml raw}, # not going to argue
|
|
109
|
+
"readme" => ["raw"],
|
|
110
|
+
}
|
|
111
|
+
format = o[:format] || default_format_for_what[what]
|
|
112
|
+
# default is json if we were called as old json command
|
|
113
|
+
format = "json" if as_json
|
|
114
|
+
raise Inspec::Error.new("Invalid option '#{format}' for --format and --what combination") unless format && valid_formats_for_what[what].include?(format)
|
|
115
|
+
|
|
79
116
|
o[:backend] = Inspec::Backend.create(Inspec::Config.mock)
|
|
80
117
|
o[:check_mode] = true
|
|
81
118
|
o[:vendor_cache] = Inspec::Cache.new(o[:vendor_cache])
|
|
82
|
-
|
|
83
119
|
profile = Inspec::Profile.for_target(target, o)
|
|
84
120
|
dst = o[:output].to_s
|
|
85
121
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
122
|
+
case what
|
|
123
|
+
when "profile"
|
|
124
|
+
if format == "json"
|
|
125
|
+
require "json" unless defined?(JSON)
|
|
126
|
+
# Write JSON
|
|
127
|
+
Inspec::Utils::JsonProfileSummary.produce_json(
|
|
128
|
+
info: profile.info,
|
|
129
|
+
write_path: dst
|
|
130
|
+
)
|
|
131
|
+
elsif format == "yaml"
|
|
132
|
+
Inspec::Utils::YamlProfileSummary.produce_yaml(
|
|
133
|
+
info: profile.info,
|
|
134
|
+
write_path: dst
|
|
135
|
+
)
|
|
136
|
+
end
|
|
137
|
+
when "readme"
|
|
138
|
+
out = dst.empty? ? $stdout : File.open(dst, "w")
|
|
139
|
+
out.write(profile.readme)
|
|
140
|
+
when "metadata"
|
|
141
|
+
out = dst.empty? ? $stdout : File.open(dst, "w")
|
|
142
|
+
out.write(profile.metadata_src)
|
|
143
|
+
end
|
|
91
144
|
rescue StandardError => e
|
|
92
145
|
pretty_handle_exception(e)
|
|
93
146
|
end
|
|
@@ -189,12 +242,12 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
|
189
242
|
desc: "Fallback to using local archives if fetching fails."
|
|
190
243
|
option :ignore_errors, type: :boolean, default: false,
|
|
191
244
|
desc: "Ignore profile warnings."
|
|
192
|
-
def archive(path)
|
|
245
|
+
def archive(path, log_level = nil)
|
|
193
246
|
o = config
|
|
194
247
|
diagnose(o)
|
|
195
248
|
|
|
196
249
|
o[:logger] = Logger.new($stdout)
|
|
197
|
-
o[:logger].level = get_log_level(o[:log_level])
|
|
250
|
+
o[:logger].level = get_log_level(log_level || o[:log_level])
|
|
198
251
|
o[:backend] = Inspec::Backend.create(Inspec::Config.mock)
|
|
199
252
|
|
|
200
253
|
# Force vendoring with overwrite when archiving
|
|
@@ -25,7 +25,9 @@ module Inspec
|
|
|
25
25
|
def self.from_array(dependencies, cwd, cache, backend)
|
|
26
26
|
dep_list = {}
|
|
27
27
|
dependencies.each do |d|
|
|
28
|
-
|
|
28
|
+
# if depedent profile does not have a source version then only name is used in dependency hash
|
|
29
|
+
key_name = (d.source_version ? "#{d.name}-#{d.source_version}" : "#{d.name}") rescue "#{d.name}"
|
|
30
|
+
dep_list[key_name] = d
|
|
29
31
|
end
|
|
30
32
|
new(cwd, cache, dep_list, backend)
|
|
31
33
|
end
|
|
@@ -39,7 +41,9 @@ module Inspec
|
|
|
39
41
|
def self.flatten_dep_tree(dep_tree)
|
|
40
42
|
dep_list = {}
|
|
41
43
|
dep_tree.each do |d|
|
|
42
|
-
|
|
44
|
+
# if depedent profile does not have a source version then only name is used in dependency hash
|
|
45
|
+
key_name = (d.source_version ? "#{d.name}-#{d.source_version}" : "#{d.name}") rescue d.name
|
|
46
|
+
dep_list[key_name] = d
|
|
43
47
|
dep_list.merge!(flatten_dep_tree(d.dependencies))
|
|
44
48
|
end
|
|
45
49
|
dep_list
|
data/lib/inspec/dsl.rb
CHANGED
|
@@ -6,13 +6,13 @@ require "inspec/utils/deprecated_cloud_resources_list"
|
|
|
6
6
|
module Inspec::DSL
|
|
7
7
|
attr_accessor :backend
|
|
8
8
|
|
|
9
|
-
def require_controls(id, &block)
|
|
10
|
-
opts = { profile_id: id, include_all: false, backend: @backend, conf: @conf, dependencies: @dependencies }
|
|
9
|
+
def require_controls(id, version = nil, &block)
|
|
10
|
+
opts = { profile_id: id, include_all: false, backend: @backend, conf: @conf, dependencies: @dependencies, profile_version: version }
|
|
11
11
|
::Inspec::DSL.load_spec_files_for_profile(self, opts, &block)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def include_controls(id, &block)
|
|
15
|
-
opts = { profile_id: id, include_all: true, backend: @backend, conf: @conf, dependencies: @dependencies }
|
|
14
|
+
def include_controls(id, version = nil, &block)
|
|
15
|
+
opts = { profile_id: id, include_all: true, backend: @backend, conf: @conf, dependencies: @dependencies, profile_version: version }
|
|
16
16
|
::Inspec::DSL.load_spec_files_for_profile(self, opts, &block)
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -85,7 +85,20 @@ module Inspec::DSL
|
|
|
85
85
|
def self.load_spec_files_for_profile(bind_context, opts, &block)
|
|
86
86
|
dependencies = opts[:dependencies]
|
|
87
87
|
profile_id = opts[:profile_id]
|
|
88
|
-
|
|
88
|
+
profile_version = opts[:profile_version]
|
|
89
|
+
|
|
90
|
+
new_profile_id = nil
|
|
91
|
+
if profile_version
|
|
92
|
+
new_profile_id = "#{profile_id}-#{profile_version}"
|
|
93
|
+
else
|
|
94
|
+
dependencies.list.keys.each do |key|
|
|
95
|
+
# If dep profile does not contain a source version, key does not contain a version as well. In that case new_profile_id will be always nil and instead profile_id would be used to fetch profile from dependency list.
|
|
96
|
+
profile_id_key = key.split("-")
|
|
97
|
+
profile_id_key.pop
|
|
98
|
+
new_profile_id = key if profile_id_key.join("-") == profile_id
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
dep_entry = new_profile_id ? dependencies.list[new_profile_id] : dependencies.list[profile_id]
|
|
89
102
|
|
|
90
103
|
if dep_entry.nil?
|
|
91
104
|
raise <<~EOF
|
data/lib/inspec/errors.rb
CHANGED
data/lib/inspec/exceptions.rb
CHANGED
|
@@ -8,5 +8,7 @@ module Inspec
|
|
|
8
8
|
class ResourceFailed < StandardError; end
|
|
9
9
|
class ResourceSkipped < StandardError; end
|
|
10
10
|
class SecretsBackendNotFound < ArgumentError; end
|
|
11
|
+
class ProfileValidationKeyNotFound < ArgumentError; end
|
|
12
|
+
class ProfileSigningKeyNotFound < ArgumentError; end
|
|
11
13
|
end
|
|
12
14
|
end
|
data/lib/inspec/fetcher/url.rb
CHANGED
|
@@ -262,7 +262,7 @@ module Inspec::Fetcher
|
|
|
262
262
|
|
|
263
263
|
open(target, opts)
|
|
264
264
|
|
|
265
|
-
rescue SocketError, Errno::ECONNREFUSED, OpenURI::HTTPError => e
|
|
265
|
+
rescue SocketError, Net::OpenTimeout, Errno::ECONNREFUSED, OpenURI::HTTPError => e
|
|
266
266
|
raise Inspec::FetcherFailure, "Profile URL dependency #{target} could not be fetched: #{e.message}"
|
|
267
267
|
end
|
|
268
268
|
|
data/lib/inspec/file_provider.rb
CHANGED
|
@@ -2,6 +2,7 @@ require "rubygems/package" unless defined?(Gem::Package)
|
|
|
2
2
|
require "pathname" unless defined?(Pathname)
|
|
3
3
|
require "zlib" unless defined?(Zlib)
|
|
4
4
|
require "zip" unless defined?(Zip)
|
|
5
|
+
require "inspec/iaf_file"
|
|
5
6
|
|
|
6
7
|
module Inspec
|
|
7
8
|
class FileProvider
|
|
@@ -14,6 +15,13 @@ module Inspec
|
|
|
14
15
|
TarProvider.new(path)
|
|
15
16
|
elsif File.exist?(path) && path.end_with?(".zip")
|
|
16
17
|
ZipProvider.new(path)
|
|
18
|
+
elsif File.exist?(path) && path.end_with?(".iaf")
|
|
19
|
+
iaf_file = IafFile.new(path)
|
|
20
|
+
if iaf_file.valid?
|
|
21
|
+
IafProvider.new(path)
|
|
22
|
+
else
|
|
23
|
+
raise Inspec::InvalidProfileSignature, "Profile signature is invalid."
|
|
24
|
+
end
|
|
17
25
|
elsif File.exist?(path)
|
|
18
26
|
DirProvider.new(path)
|
|
19
27
|
else
|
|
@@ -216,6 +224,34 @@ module Inspec
|
|
|
216
224
|
end
|
|
217
225
|
end # class TarProvider
|
|
218
226
|
|
|
227
|
+
class IafProvider < TarProvider
|
|
228
|
+
attr_reader :files
|
|
229
|
+
|
|
230
|
+
def initialize(path)
|
|
231
|
+
f = File.open(path, "rb")
|
|
232
|
+
version = f.readline.strip!
|
|
233
|
+
if version == "INSPEC-PROFILE-1"
|
|
234
|
+
while f.readline != "\n" do end
|
|
235
|
+
content = f.read
|
|
236
|
+
f.close
|
|
237
|
+
elsif version == "INSPEC-PROFILE-2"
|
|
238
|
+
f.readline.strip!
|
|
239
|
+
content = f.read
|
|
240
|
+
f.close
|
|
241
|
+
content = content.slice(490, content.length).lstrip
|
|
242
|
+
else
|
|
243
|
+
raise Inspec::InvalidProfileSignature, "Unrecognized IAF version."
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
tmpfile = nil
|
|
247
|
+
Dir.mktmpdir do |workdir|
|
|
248
|
+
tmpfile = Pathname.new(workdir).join("temp_profile.tar.gz")
|
|
249
|
+
File.open(tmpfile, "wb") { |fl| fl.write(content) }
|
|
250
|
+
super(tmpfile)
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end # class IafProvider
|
|
254
|
+
|
|
219
255
|
class RelativeFileProvider
|
|
220
256
|
BLACKLIST_FILES = [
|
|
221
257
|
"/pax_global_header",
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
require "base64" unless defined?(Base64)
|
|
2
|
+
require "openssl" unless defined?(OpenSSL)
|
|
3
|
+
require "set" unless defined?(Set)
|
|
4
|
+
require "uri" unless defined?(URI)
|
|
5
|
+
|
|
6
|
+
module Inspec
|
|
7
|
+
class IafFile
|
|
8
|
+
KEY_ALG = OpenSSL::PKey::RSA
|
|
9
|
+
INSPEC_PROFILE_VERSION_1 = "INSPEC-PROFILE-1".freeze
|
|
10
|
+
INSPEC_PROFILE_VERSION_2 = "INSPEC-PROFILE-2".freeze
|
|
11
|
+
|
|
12
|
+
ARTIFACT_DIGEST = OpenSSL::Digest::SHA512
|
|
13
|
+
ARTIFACT_DIGEST_NAME = "SHA512".freeze
|
|
14
|
+
|
|
15
|
+
VALID_PROFILE_VERSIONS = Set.new [INSPEC_PROFILE_VERSION_1, INSPEC_PROFILE_VERSION_2]
|
|
16
|
+
VALID_PROFILE_DIGESTS = Set.new [ARTIFACT_DIGEST_NAME]
|
|
17
|
+
|
|
18
|
+
def self.find_validation_key(keyname)
|
|
19
|
+
[
|
|
20
|
+
".",
|
|
21
|
+
File.join(Inspec.config_dir, "keys"),
|
|
22
|
+
File.join(Inspec.src_root, "etc", "keys"),
|
|
23
|
+
].each do |path|
|
|
24
|
+
filename = File.join(path, "#{keyname}.pem.pub")
|
|
25
|
+
return filename if File.exist?(filename)
|
|
26
|
+
rescue ArgumentError => e
|
|
27
|
+
puts e
|
|
28
|
+
raise Inspec::Exceptions::ProfileValidationKeyNotFound.new("Validation key #{keyname} not found")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Retry if we can fetch it from github
|
|
32
|
+
return find_validation_key(keyname) if fetch_validation_key_from_github(keyname)
|
|
33
|
+
|
|
34
|
+
raise Inspec::Exceptions::ProfileValidationKeyNotFound.new("Validation key #{keyname} not found")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.find_signing_key(keyname)
|
|
38
|
+
[".", File.join(Inspec.config_dir, "keys")].each do |path|
|
|
39
|
+
filename = File.join(path, "#{keyname}.pem.key")
|
|
40
|
+
return filename if File.exist?(filename)
|
|
41
|
+
end
|
|
42
|
+
raise Inspec::Exceptions::ProfileSigningKeyNotFound.new("Signing key #{keyname} not found")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.fetch_validation_key_from_github(keyname)
|
|
46
|
+
URI.open("https://raw.githubusercontent.com/inspec/inspec/main/etc/keys/#{keyname}.pem.pub") do |r|
|
|
47
|
+
puts "Fetching validation key '#{keyname}' from github"
|
|
48
|
+
dir = File.join(Inspec.config_dir, "keys")
|
|
49
|
+
FileUtils.mkdir_p dir
|
|
50
|
+
key_file = File.join(dir, "#{keyname}.pem.pub")
|
|
51
|
+
File.open(key_file, "w") do |f|
|
|
52
|
+
r.each_line do |line|
|
|
53
|
+
f.puts line
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
true
|
|
58
|
+
rescue OpenURI::HTTPError
|
|
59
|
+
false
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
attr_reader :key_name, :version
|
|
63
|
+
|
|
64
|
+
def initialize(path)
|
|
65
|
+
@path = path
|
|
66
|
+
@key_name = nil
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def valid?
|
|
70
|
+
header = []
|
|
71
|
+
valid = true
|
|
72
|
+
f = File.open(@path, "rb")
|
|
73
|
+
@version = f.readline.strip!
|
|
74
|
+
if version == INSPEC_PROFILE_VERSION_1
|
|
75
|
+
header << version
|
|
76
|
+
header << f.readline.strip!
|
|
77
|
+
header << f.readline.strip!
|
|
78
|
+
|
|
79
|
+
file_sig = ""
|
|
80
|
+
# the signature is multi-line
|
|
81
|
+
while (line = f.readline) != "\n"
|
|
82
|
+
file_sig += line
|
|
83
|
+
end
|
|
84
|
+
header << file_sig.strip!
|
|
85
|
+
f.close
|
|
86
|
+
|
|
87
|
+
f = File.open(@path, "rb")
|
|
88
|
+
while f.readline != "\n" do end
|
|
89
|
+
content = f.read
|
|
90
|
+
f.close
|
|
91
|
+
elsif version == INSPEC_PROFILE_VERSION_2
|
|
92
|
+
header << version
|
|
93
|
+
header << f.readline.strip!
|
|
94
|
+
content = f.read
|
|
95
|
+
f.close
|
|
96
|
+
|
|
97
|
+
header_content = content.unpack("h*").pack("H*")
|
|
98
|
+
header << header_content.slice(0, 100).rstrip
|
|
99
|
+
header << header_content.slice(100, 20).rstrip
|
|
100
|
+
header << header_content.slice(120, 370).rstrip + "\n" # \n at the end is require in this field
|
|
101
|
+
content = content.slice(490, content.length).lstrip
|
|
102
|
+
else
|
|
103
|
+
valid = false
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
@key_name = header[2]
|
|
107
|
+
validation_key_path = Inspec::IafFile.find_validation_key(@key_name)
|
|
108
|
+
|
|
109
|
+
unless valid_header?(header)
|
|
110
|
+
valid = false
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
verification_key = KEY_ALG.new File.read validation_key_path
|
|
114
|
+
signature = Base64.decode64(header[4])
|
|
115
|
+
digest = ARTIFACT_DIGEST.new
|
|
116
|
+
unless verification_key.verify digest, signature, content
|
|
117
|
+
valid = false
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
valid
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def valid_header?(header)
|
|
124
|
+
VALID_PROFILE_VERSIONS.member?(header[0]) && VALID_PROFILE_DIGESTS.member?(header[3])
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
data/lib/inspec/profile.rb
CHANGED
|
@@ -350,22 +350,24 @@ module Inspec
|
|
|
350
350
|
def load_libraries
|
|
351
351
|
return @runner_context if @libraries_loaded
|
|
352
352
|
|
|
353
|
-
locked_dependencies.dep_list.each_with_index do |(_name, dep),
|
|
353
|
+
locked_dependencies.dep_list.each_with_index do |(_name, dep), index|
|
|
354
354
|
d = dep.profile
|
|
355
355
|
# this will force a dependent profile load so we are only going to add
|
|
356
356
|
# this metadata if the parent profile is supported.
|
|
357
357
|
if @supports_platform && !d.supports_platform?
|
|
358
358
|
# since ruby 1.9 hashes are ordered so we can just use index values here
|
|
359
359
|
# TODO: NO! this is a violation of encapsulation to an extreme
|
|
360
|
-
metadata.dependencies[
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
360
|
+
if metadata.dependencies[index]
|
|
361
|
+
metadata.dependencies[index][:status] = "skipped"
|
|
362
|
+
msg = "Skipping profile: '#{d.name}' on unsupported platform: '#{d.backend.platform.name}/#{d.backend.platform.release}'."
|
|
363
|
+
metadata.dependencies[index][:status_message] = msg
|
|
364
|
+
metadata.dependencies[index][:skip_message] = msg # Repeat as skip_message for backward compatibility
|
|
365
|
+
end
|
|
364
366
|
next
|
|
365
|
-
elsif metadata.dependencies[
|
|
367
|
+
elsif metadata.dependencies[index]
|
|
366
368
|
# Currently wrapper profiles will load all dependencies, and then we
|
|
367
369
|
# load them again when we dive down. This needs to be re-done.
|
|
368
|
-
metadata.dependencies[
|
|
370
|
+
metadata.dependencies[index][:status] = "loaded"
|
|
369
371
|
end
|
|
370
372
|
|
|
371
373
|
# rubocop:disable Layout/ExtraSpacing
|
|
@@ -746,6 +748,14 @@ module Inspec
|
|
|
746
748
|
@source_reader.target.files
|
|
747
749
|
end
|
|
748
750
|
|
|
751
|
+
def readme
|
|
752
|
+
@source_reader.readme&.values&.first
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
def metadata_src
|
|
756
|
+
@source_reader.metadata_src
|
|
757
|
+
end
|
|
758
|
+
|
|
749
759
|
#
|
|
750
760
|
# TODO(ssd): Relative path handling really needs to be carefully
|
|
751
761
|
# thought through, especially with respect to relative paths in
|
data/lib/inspec/resources/apt.rb
CHANGED
|
@@ -39,10 +39,11 @@ module Inspec::Resources
|
|
|
39
39
|
EXAMPLE
|
|
40
40
|
|
|
41
41
|
def initialize(ppa_name)
|
|
42
|
+
@ppa_name = ppa_name
|
|
42
43
|
@deb_url = nil
|
|
43
44
|
# check if the os is ubuntu or debian
|
|
44
45
|
if inspec.os.debian?
|
|
45
|
-
@deb_url = determine_ppa_url(ppa_name)
|
|
46
|
+
@deb_url = determine_ppa_url(@ppa_name)
|
|
46
47
|
else
|
|
47
48
|
# this resource is only supported on ubuntu and debian
|
|
48
49
|
skip_resource "The `apt` resource is not supported on your OS yet."
|
|
@@ -61,6 +62,10 @@ module Inspec::Resources
|
|
|
61
62
|
actives.size == 1 && actives[0] = true
|
|
62
63
|
end
|
|
63
64
|
|
|
65
|
+
def resource_id
|
|
66
|
+
@deb_url || @ppa_name || "apt repository"
|
|
67
|
+
end
|
|
68
|
+
|
|
64
69
|
def to_s
|
|
65
70
|
"Apt Repository #{@deb_url}"
|
|
66
71
|
end
|
|
@@ -31,6 +31,11 @@ module Inspec::Resources
|
|
|
31
31
|
super(@conf_path)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
# if system unables to determine the cassandra conf path the @conf_path can be nil so in that case sending "" string as resource_id
|
|
35
|
+
def resource_id
|
|
36
|
+
@conf_path || "cassandradb_conf"
|
|
37
|
+
end
|
|
38
|
+
|
|
34
39
|
private
|
|
35
40
|
|
|
36
41
|
def parse(content)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
module Inspec::Resources
|
|
2
2
|
class Lines
|
|
3
|
-
attr_reader :output
|
|
3
|
+
attr_reader :output, :exit_status
|
|
4
4
|
|
|
5
|
-
def initialize(raw, desc)
|
|
5
|
+
def initialize(raw, desc, exit_status)
|
|
6
6
|
@output = raw
|
|
7
7
|
@desc = desc
|
|
8
|
+
@exit_status = exit_status
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
def to_s
|
|
@@ -40,10 +41,14 @@ module Inspec::Resources
|
|
|
40
41
|
if cmd.exit_status != 0 || out =~ /Unable to connect to any servers/ || out.downcase =~ /^error:.*/
|
|
41
42
|
raise Inspec::Exceptions::ResourceFailed, "Cassandra query with errors: #{out}"
|
|
42
43
|
else
|
|
43
|
-
Lines.new(cmd.stdout.strip, "Cassandra query: #{q}")
|
|
44
|
+
Lines.new(cmd.stdout.strip, "Cassandra query: #{q}", cmd.exit_status)
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
47
|
|
|
48
|
+
def resource_id
|
|
49
|
+
"cassandradb_session:User:#{@user}:Host:#{host}"
|
|
50
|
+
end
|
|
51
|
+
|
|
47
52
|
def to_s
|
|
48
53
|
"Cassandra DB Session"
|
|
49
54
|
end
|