inspec-core 5.12.2 → 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/etc/keys/progress-2022-05-04.pem.pub +9 -0
- data/inspec-core.gemspec +1 -1
- data/lib/inspec/base_cli.rb +5 -0
- data/lib/inspec/cli.rb +64 -9
- data/lib/inspec/dependencies/dependency_set.rb +6 -2
- data/lib/inspec/dependency_loader.rb +5 -1
- 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 +31 -14
- 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/default_gateway.rb +61 -0
- 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 +97 -1
- data/lib/inspec/resources/filesystem.rb +4 -0
- data/lib/inspec/resources/gem.rb +4 -0
- data/lib/inspec/resources/groups.rb +9 -0
- data/lib/inspec/resources/grub_conf.rb +4 -0
- data/lib/inspec/resources/host.rb +46 -3
- 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/linux_audit_system.rb +81 -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/php_config.rb +72 -0
- 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 +17 -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 +80 -1
- 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/x509_private_key.rb +93 -0
- data/lib/inspec/resources/yum.rb +4 -0
- data/lib/inspec/resources/zfs.rb +48 -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 +16 -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
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
-----BEGIN PUBLIC KEY-----
|
|
2
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8FWKhVwT5ilFdk5/schY
|
|
3
|
+
J3X6DkDbZPul7MAKYuicmyvrk4VZFqFJYzUo9G+ZvtWCjCMZF3JLDbg0VJ+V3j2b
|
|
4
|
+
A5MRUDMH1MtbQZS8u0AIUAitHsSiMgu4w/EHUSHODoDmbdaHT1xkFe9IxMSM1/AV
|
|
5
|
+
/s5u2uAMuiayo+dGW5i9xf/LMZN1JCeX8Yqw85CpS01gMC2XxoUu5wGLwBwXkdql
|
|
6
|
+
+H3SaWRdDTtccgtu0Rxt9dzRtHAPNWKSLl9TScW6Qt/+7bgb3M6+7od/FuPziAS9
|
|
7
|
+
1NGUiKL9vajpafxUJF8863q0l64dAXGWXVFed7/7GFiNVuLxBksPzK8VrkyCS214
|
|
8
|
+
kQIDAQAB
|
|
9
|
+
-----END PUBLIC KEY-----
|
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
|
|
@@ -95,6 +148,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
|
95
148
|
desc "check PATH", "verify all tests at the specified PATH"
|
|
96
149
|
option :format, type: :string,
|
|
97
150
|
desc: "The output format to use doc (default), json. If valid format is not provided then it will use the default."
|
|
151
|
+
option :with_cookstyle, type: :boolean,
|
|
152
|
+
desc: "Enable or disable cookstyle checks.", default: false
|
|
98
153
|
profile_options
|
|
99
154
|
def check(path) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
100
155
|
o = config
|
|
@@ -187,12 +242,12 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
|
187
242
|
desc: "Fallback to using local archives if fetching fails."
|
|
188
243
|
option :ignore_errors, type: :boolean, default: false,
|
|
189
244
|
desc: "Ignore profile warnings."
|
|
190
|
-
def archive(path)
|
|
245
|
+
def archive(path, log_level = nil)
|
|
191
246
|
o = config
|
|
192
247
|
diagnose(o)
|
|
193
248
|
|
|
194
249
|
o[:logger] = Logger.new($stdout)
|
|
195
|
-
o[:logger].level = get_log_level(o[:log_level])
|
|
250
|
+
o[:logger].level = get_log_level(log_level || o[:log_level])
|
|
196
251
|
o[:backend] = Inspec::Backend.create(Inspec::Config.mock)
|
|
197
252
|
|
|
198
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
|
|
@@ -50,7 +50,11 @@ module Inspec
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def gem_version_installed?(name, version)
|
|
53
|
-
|
|
53
|
+
if version.nil?
|
|
54
|
+
list_installed_gems.any? { |s| s.name == name }
|
|
55
|
+
else
|
|
56
|
+
list_installed_gems.any? { |s| s.name == name && Gem::Requirement.new(version.split(",")) =~ s.version }
|
|
57
|
+
end
|
|
54
58
|
end
|
|
55
59
|
|
|
56
60
|
private
|
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
|
@@ -105,6 +105,7 @@ module Inspec
|
|
|
105
105
|
@check_mode = options[:check_mode] || false
|
|
106
106
|
@parent_profile = options[:parent_profile]
|
|
107
107
|
@legacy_profile_path = options[:profiles_path] || false
|
|
108
|
+
@check_cookstyle = options[:with_cookstyle]
|
|
108
109
|
Metadata.finalize(@source_reader.metadata, @profile_id, options)
|
|
109
110
|
|
|
110
111
|
# if a backend has already been created, clone it so each profile has its own unique backend object
|
|
@@ -349,22 +350,24 @@ module Inspec
|
|
|
349
350
|
def load_libraries
|
|
350
351
|
return @runner_context if @libraries_loaded
|
|
351
352
|
|
|
352
|
-
locked_dependencies.dep_list.each_with_index do |(_name, dep),
|
|
353
|
+
locked_dependencies.dep_list.each_with_index do |(_name, dep), index|
|
|
353
354
|
d = dep.profile
|
|
354
355
|
# this will force a dependent profile load so we are only going to add
|
|
355
356
|
# this metadata if the parent profile is supported.
|
|
356
357
|
if @supports_platform && !d.supports_platform?
|
|
357
358
|
# since ruby 1.9 hashes are ordered so we can just use index values here
|
|
358
359
|
# TODO: NO! this is a violation of encapsulation to an extreme
|
|
359
|
-
metadata.dependencies[
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
|
363
366
|
next
|
|
364
|
-
elsif metadata.dependencies[
|
|
367
|
+
elsif metadata.dependencies[index]
|
|
365
368
|
# Currently wrapper profiles will load all dependencies, and then we
|
|
366
369
|
# load them again when we dive down. This needs to be re-done.
|
|
367
|
-
metadata.dependencies[
|
|
370
|
+
metadata.dependencies[index][:status] = "loaded"
|
|
368
371
|
end
|
|
369
372
|
|
|
370
373
|
# rubocop:disable Layout/ExtraSpacing
|
|
@@ -409,7 +412,7 @@ module Inspec
|
|
|
409
412
|
else
|
|
410
413
|
ui = Inspec::UI.new
|
|
411
414
|
gem_dependencies.each { |gem_dependency| ui.list_item("#{gem_dependency[:name]} #{gem_dependency[:version]}") }
|
|
412
|
-
choice = ui.prompt.select("Would you like to install
|
|
415
|
+
choice = ui.prompt.select("The above listed gem dependencies are required to run the profile. Would you like to install them ?", %w{Yes No})
|
|
413
416
|
if choice == "Yes"
|
|
414
417
|
Inspec::Config.cached[:auto_install_gems] = true
|
|
415
418
|
load_gem_dependencies
|
|
@@ -655,12 +658,13 @@ module Inspec
|
|
|
655
658
|
end
|
|
656
659
|
|
|
657
660
|
# Running cookstyle to check for code offenses
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
661
|
+
if @check_cookstyle
|
|
662
|
+
cookstyle_linting_check.each do |lint_output|
|
|
663
|
+
data = lint_output.split(":")
|
|
664
|
+
msg = "#{data[-2]}:#{data[-1]}"
|
|
665
|
+
offense.call(data[0], data[1], data[2], nil, msg)
|
|
666
|
+
end
|
|
662
667
|
end
|
|
663
|
-
|
|
664
668
|
# profile is valid if we could not find any error & offenses
|
|
665
669
|
result[:summary][:valid] = result[:errors].empty? && result[:offenses].empty?
|
|
666
670
|
|
|
@@ -744,6 +748,14 @@ module Inspec
|
|
|
744
748
|
@source_reader.target.files
|
|
745
749
|
end
|
|
746
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
|
+
|
|
747
759
|
#
|
|
748
760
|
# TODO(ssd): Relative path handling really needs to be carefully
|
|
749
761
|
# thought through, especially with respect to relative paths in
|
|
@@ -848,7 +860,12 @@ module Inspec
|
|
|
848
860
|
f = load_rule_filepath(prefix, rule)
|
|
849
861
|
load_rule(rule, f, controls, groups)
|
|
850
862
|
end
|
|
851
|
-
|
|
863
|
+
if @profile_id.nil?
|
|
864
|
+
# identifying inputs using profile name
|
|
865
|
+
params[:inputs] = Inspec::InputRegistry.list_inputs_for_profile(params[:name])
|
|
866
|
+
else
|
|
867
|
+
params[:inputs] = Inspec::InputRegistry.list_inputs_for_profile(@profile_id)
|
|
868
|
+
end
|
|
852
869
|
params
|
|
853
870
|
end
|
|
854
871
|
|
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
|