inspec-core 4.49.0 → 4.56.17
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 +7 -11
- data/inspec-core.gemspec +2 -2
- data/lib/bundles/inspec-supermarket/README.md +21 -2
- data/lib/bundles/inspec-supermarket/cli.rb +20 -3
- data/lib/bundles/inspec-supermarket/target.rb +3 -2
- data/lib/inspec/base_cli.rb +8 -0
- data/lib/inspec/cli.rb +12 -3
- data/lib/inspec/config.rb +5 -1
- data/lib/inspec/dependencies/requirement.rb +2 -1
- data/lib/inspec/formatters/base.rb +8 -6
- data/lib/inspec/globals.rb +5 -0
- data/lib/inspec/library_eval_context.rb +2 -0
- data/lib/inspec/plugin/v1/registry.rb +1 -1
- data/lib/inspec/plugin/v2/plugin_types/streaming_reporter.rb +10 -0
- data/lib/inspec/profile.rb +2 -0
- data/lib/inspec/profile_context.rb +1 -6
- data/lib/inspec/reporters/automate.rb +1 -1
- data/lib/inspec/reporters/json.rb +1 -1
- data/lib/inspec/resources/auditd.rb +5 -4
- data/lib/inspec/resources/bash.rb +2 -0
- data/lib/inspec/resources/file.rb +38 -0
- data/lib/inspec/resources/firewalld.rb +83 -9
- data/lib/inspec/resources/grub_conf.rb +1 -1
- data/lib/inspec/resources/http.rb +135 -54
- data/lib/inspec/resources/ibmdb2_session.rb +2 -2
- data/lib/inspec/resources/iptables.rb +18 -2
- data/lib/inspec/resources/kernel_parameters.rb +58 -0
- data/lib/inspec/resources/mssql_session.rb +11 -3
- data/lib/inspec/resources/oracledb_session.rb +3 -1
- data/lib/inspec/resources/package.rb +74 -1
- data/lib/inspec/resources/packages.rb +21 -0
- data/lib/inspec/resources/registry_key.rb +30 -0
- data/lib/inspec/resources/selinux.rb +6 -1
- data/lib/inspec/resources/service.rb +58 -9
- data/lib/inspec/resources/ssl.rb +7 -0
- data/lib/inspec/resources/timezone.rb +65 -0
- data/lib/inspec/resources.rb +2 -0
- data/lib/inspec/runner_rspec.rb +30 -0
- data/lib/inspec/utils/filter.rb +46 -2
- data/lib/inspec/utils/run_data_filters.rb +1 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/api.rb +1 -1
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/cli.rb +4 -3
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9930c475b5a1e282ab613db458f60c77561db82d6c009d6c7254f5a3789132f5
|
4
|
+
data.tar.gz: 8a11ae471b5954568be5bf6fc88e52d974a5ac9cb83caf2a6560dd3dd26d55fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0106f09ddcc1077650b6781631188dcb4231829b4e2b737680f49c6736b3c08001523d34a9398eb7499147dde9d22c4bbdd9058721c484424fe69933535e7557
|
7
|
+
data.tar.gz: b04b2c02c6d1009cee30a5ca32521d4c62e62fcf72727d0f720af5fa54da01029dbcd1b25656460f73d9d4cb7f3bf3b94b7e1f049479770a0a4848aa1f25034f
|
data/Gemfile
CHANGED
@@ -11,11 +11,6 @@ gem "inspec-bin", path: "./inspec-bin"
|
|
11
11
|
|
12
12
|
gem "ffi", ">= 1.9.14", "!= 1.13.0", "!= 1.14.2"
|
13
13
|
|
14
|
-
if Gem.ruby_version.to_s.start_with?("2.5")
|
15
|
-
# 16.7.23 required ruby 2.6+
|
16
|
-
gem "chef-utils", "< 16.7.23" # TODO: remove when we drop ruby 2.5
|
17
|
-
end
|
18
|
-
|
19
14
|
# inspec tests depend text output that changed in the 3.10 release
|
20
15
|
# but our runtime dep is still 3.9+
|
21
16
|
gem "rspec", ">= 3.10"
|
@@ -30,11 +25,7 @@ end
|
|
30
25
|
group :test do
|
31
26
|
gem "chefstyle", "~> 2.0.3"
|
32
27
|
gem "concurrent-ruby", "~> 1.0"
|
33
|
-
|
34
|
-
gem "html-proofer", "= 3.19.1" , platforms: :ruby # do not attempt to run proofer on windows
|
35
|
-
else
|
36
|
-
gem "html-proofer", platforms: :ruby # do not attempt to run proofer on windows
|
37
|
-
end
|
28
|
+
gem "html-proofer", platforms: :ruby # do not attempt to run proofer on windows
|
38
29
|
gem "json_schemer", ">= 0.2.1", "< 0.2.19"
|
39
30
|
gem "m"
|
40
31
|
gem "minitest-sprint", "~> 1.0"
|
@@ -45,7 +36,8 @@ group :test do
|
|
45
36
|
gem "pry", "~> 0.10"
|
46
37
|
gem "rake", ">= 10"
|
47
38
|
gem "ruby-progressbar", "~> 1.8"
|
48
|
-
gem "simplecov", "~> 0.
|
39
|
+
gem "simplecov", "~> 0.21"
|
40
|
+
gem "simplecov_json_formatter"
|
49
41
|
gem "webmock", "~> 3.0"
|
50
42
|
end
|
51
43
|
|
@@ -66,3 +58,7 @@ if Gem.ruby_version >= Gem::Version.new("2.7.0")
|
|
66
58
|
gem "git"
|
67
59
|
end
|
68
60
|
end
|
61
|
+
|
62
|
+
if Gem.ruby_version < Gem::Version.new("2.7.0")
|
63
|
+
gem "activesupport", "6.1.4.4"
|
64
|
+
end
|
data/inspec-core.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.license = "Apache-2.0"
|
14
14
|
spec.require_paths = ["lib"]
|
15
15
|
|
16
|
-
spec.required_ruby_version = ">= 2.
|
16
|
+
spec.required_ruby_version = ">= 2.6"
|
17
17
|
|
18
18
|
# the gemfile and gemspec are necessary for appbundler so don't remove it
|
19
19
|
spec.files =
|
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_dependency "thor", ">= 0.20", "< 2.0"
|
29
29
|
spec.add_dependency "method_source", ">= 0.8", "< 2.0"
|
30
30
|
spec.add_dependency "rubyzip", ">= 1.2.2", "< 3.0"
|
31
|
-
spec.add_dependency "rspec", ">= 3.9", "
|
31
|
+
spec.add_dependency "rspec", ">= 3.9", "<= 3.11"
|
32
32
|
spec.add_dependency "rspec-its", "~> 1.2"
|
33
33
|
spec.add_dependency "pry", "~> 0.13"
|
34
34
|
spec.add_dependency "hashie", ">= 3.4", "< 5.0"
|
@@ -8,8 +8,27 @@ To use the CLI, this InSpec add-on adds the following commands:
|
|
8
8
|
|
9
9
|
Compliance profiles from Supermarket can be executed in two ways:
|
10
10
|
|
11
|
-
- via supermarket exec:
|
12
|
-
|
11
|
+
- via supermarket exec:
|
12
|
+
|
13
|
+
**Public Supermarket**
|
14
|
+
|
15
|
+
`inspec supermarket exec nathenharvey/tmp-compliance-profile`
|
16
|
+
|
17
|
+
**Private Supermarket**
|
18
|
+
|
19
|
+
`inspec supermarket exec nathenharvey/tmp-compliance-profile --supermarket_url="PRIVATE_SUPERMARKET_URL"`
|
20
|
+
|
21
|
+
|
22
|
+
- via supermarket scheme:
|
23
|
+
|
24
|
+
**Public Supermarket**
|
25
|
+
|
26
|
+
`inspec exec supermarket://nathenharvey/tmp-compliance-profile`
|
27
|
+
|
28
|
+
**Private Supermarket**
|
29
|
+
|
30
|
+
`inspec exec supermarket://nathenharvey/tmp-compliance-profile --supermarket_url="PRIVATE_SUPERMARKET_URL"`
|
31
|
+
|
13
32
|
|
14
33
|
## Usage
|
15
34
|
|
@@ -15,10 +15,18 @@ module Supermarket
|
|
15
15
|
end
|
16
16
|
|
17
17
|
desc "profiles", "list all available profiles in Chef Supermarket"
|
18
|
+
supermarket_options
|
18
19
|
def profiles
|
19
|
-
|
20
|
-
|
20
|
+
o = config
|
21
|
+
diagnose(o)
|
22
|
+
configure_logger(o)
|
21
23
|
|
24
|
+
# display profiles in format user/profile
|
25
|
+
supermarket_profiles = if o["supermarket_url"]
|
26
|
+
Supermarket::API.profiles(o["supermarket_url"])
|
27
|
+
else
|
28
|
+
Supermarket::API.profiles
|
29
|
+
end
|
22
30
|
headline("Available profiles:")
|
23
31
|
supermarket_profiles.each do |p|
|
24
32
|
li("#{p["tool_name"]} #{mark_text(p["tool_owner"] + "/" + p["slug"])}")
|
@@ -45,9 +53,18 @@ module Supermarket
|
|
45
53
|
end
|
46
54
|
|
47
55
|
desc "info PROFILE", "display Supermarket profile details"
|
56
|
+
supermarket_options
|
48
57
|
def info(profile)
|
58
|
+
o = config
|
59
|
+
diagnose(o)
|
60
|
+
configure_logger(o)
|
61
|
+
|
49
62
|
# check that the profile is available
|
50
|
-
supermarket_profiles =
|
63
|
+
supermarket_profiles = if o["supermarket_url"]
|
64
|
+
Supermarket::API.profiles(o["supermarket_url"])
|
65
|
+
else
|
66
|
+
Supermarket::API.profiles
|
67
|
+
end
|
51
68
|
found = supermarket_profiles.select do |p|
|
52
69
|
profile == "#{p["tool_owner"]}/#{p["slug"]}"
|
53
70
|
end
|
@@ -9,10 +9,11 @@ module Supermarket
|
|
9
9
|
priority 500
|
10
10
|
|
11
11
|
def self.resolve(target, opts = {})
|
12
|
+
supermarket_url = opts["supermarket_url"] || Supermarket::API::SUPERMARKET_URL
|
12
13
|
supermarket_uri, supermarket_server = if target.is_a?(String) && URI(target).scheme == "supermarket"
|
13
|
-
[target,
|
14
|
+
[target, supermarket_url]
|
14
15
|
elsif target.respond_to?(:key?) && target.key?(:supermarket)
|
15
|
-
supermarket_server = target[:supermarket_url] ||
|
16
|
+
supermarket_server = target[:supermarket_url] || supermarket_url
|
16
17
|
["supermarket://#{target[:supermarket]}", supermarket_server]
|
17
18
|
end
|
18
19
|
return nil unless supermarket_uri
|
data/lib/inspec/base_cli.rb
CHANGED
@@ -126,6 +126,8 @@ module Inspec
|
|
126
126
|
desc: "Specify a shell type for winrm (eg. 'elevated' or 'powershell')"
|
127
127
|
option :docker_url, type: :string,
|
128
128
|
desc: "Provides path to Docker API endpoint (Docker)"
|
129
|
+
option :ssh_config_file, type: :array,
|
130
|
+
desc: "A list of paths to the ssh config file, e.g ~/.ssh/config or /etc/ssh/ssh_config"
|
129
131
|
end
|
130
132
|
|
131
133
|
def self.profile_options
|
@@ -135,9 +137,15 @@ module Inspec
|
|
135
137
|
desc: "Use the given path for caching dependencies. (default: ~/.inspec/cache)"
|
136
138
|
end
|
137
139
|
|
140
|
+
def self.supermarket_options
|
141
|
+
option :supermarket_url, type: :string,
|
142
|
+
desc: "Specify the URL of a private Chef Supermarket."
|
143
|
+
end
|
144
|
+
|
138
145
|
def self.exec_options
|
139
146
|
target_options
|
140
147
|
profile_options
|
148
|
+
supermarket_options
|
141
149
|
option :controls, type: :array,
|
142
150
|
desc: "A list of control names to run, or a list of /regexes/ to match against control names. Ignore all other tests."
|
143
151
|
option :tags, type: :array,
|
data/lib/inspec/cli.rb
CHANGED
@@ -122,8 +122,13 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
122
122
|
end
|
123
123
|
puts
|
124
124
|
|
125
|
+
enable_offenses = !Inspec.locally_windows? # See 5723
|
125
126
|
if result[:errors].empty? && result[:warnings].empty? && result[:offenses].empty?
|
126
|
-
|
127
|
+
if enable_offenses
|
128
|
+
ui.plain_line("No errors, warnings, or offenses")
|
129
|
+
else
|
130
|
+
ui.plain_line("No errors or warnings")
|
131
|
+
end
|
127
132
|
else
|
128
133
|
item_msg = lambda { |item|
|
129
134
|
pos = [item[:file], item[:line], item[:column]].compact.join(":")
|
@@ -135,7 +140,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
135
140
|
|
136
141
|
puts
|
137
142
|
|
138
|
-
|
143
|
+
if enable_offenses && !result[:offenses].empty?
|
139
144
|
puts "Offenses:\n"
|
140
145
|
result[:offenses].each { |item| ui.cyan(" #{Inspec::UI::GLYPHS[:script_x]} #{item_msg.call(item)}\n\n") }
|
141
146
|
end
|
@@ -143,7 +148,11 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
|
143
148
|
offenses = ui.cyan("#{result[:offenses].length} offenses", print: false)
|
144
149
|
errors = ui.red("#{result[:errors].length} errors", print: false)
|
145
150
|
warnings = ui.yellow("#{result[:warnings].length} warnings", print: false)
|
146
|
-
|
151
|
+
if enable_offenses
|
152
|
+
ui.plain_line("Summary: #{errors}, #{warnings}, #{offenses}")
|
153
|
+
else
|
154
|
+
ui.plain_line("Summary: #{errors}, #{warnings}")
|
155
|
+
end
|
147
156
|
end
|
148
157
|
end
|
149
158
|
|
data/lib/inspec/config.rb
CHANGED
@@ -367,7 +367,11 @@ module Inspec
|
|
367
367
|
.find_activators(plugin_type: :reporter)\
|
368
368
|
.map(&:activator_name).map(&:to_s)
|
369
369
|
|
370
|
-
|
370
|
+
streaming_reporters = Inspec::Plugin::V2::Registry.instance\
|
371
|
+
.find_activators(plugin_type: :streaming_reporter)\
|
372
|
+
.map(&:activator_name).map(&:to_s)
|
373
|
+
|
374
|
+
valid_types = rspec_built_in_formatters + inspec_reporters_that_are_not_yet_plugins + plugin_reporters + streaming_reporters
|
371
375
|
|
372
376
|
reporters.each do |reporter_name, reporter_config|
|
373
377
|
raise NotImplementedError, "'#{reporter_name}' is not a valid reporter type." unless valid_types.include?(reporter_name)
|
@@ -102,7 +102,8 @@ module Inspec
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def fetcher
|
105
|
-
@
|
105
|
+
@runner_options ||= (Inspec::Config.cached || {})
|
106
|
+
@fetcher ||= Inspec::CachedFetcher.new(opts, @cache, @runner_options)
|
106
107
|
end
|
107
108
|
|
108
109
|
# load dependencies of the dependency
|
@@ -70,6 +70,7 @@ module Inspec::Formatters
|
|
70
70
|
name: platform(:name),
|
71
71
|
release: platform(:release),
|
72
72
|
target: backend_target,
|
73
|
+
target_id: platform(:uuid),
|
73
74
|
}
|
74
75
|
end
|
75
76
|
|
@@ -205,12 +206,13 @@ module Inspec::Formatters
|
|
205
206
|
def platform(field)
|
206
207
|
return nil if @backend.nil?
|
207
208
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
209
|
+
@backend.platform[field]
|
210
|
+
rescue Train::PlatformUuidDetectionFailed
|
211
|
+
Inspec::Log.warn("Could not find platform target_id.")
|
212
|
+
nil
|
213
|
+
rescue Train::Error => e
|
214
|
+
Inspec::Log.warn(e.message)
|
215
|
+
nil
|
214
216
|
end
|
215
217
|
|
216
218
|
def backend_target
|
data/lib/inspec/globals.rb
CHANGED
@@ -11,7 +11,7 @@ class PluginRegistry
|
|
11
11
|
# @return [Plugin] plugin instance if it can be resolved, nil otherwise
|
12
12
|
def resolve(target, opts = {})
|
13
13
|
modules.each do |m|
|
14
|
-
res = if Inspec::Fetcher::Url
|
14
|
+
res = if ["Inspec::Fetcher::Url", "Supermarket::Fetcher"].include? m.to_s
|
15
15
|
m.resolve(target, opts)
|
16
16
|
else
|
17
17
|
m.resolve(target)
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Inspec::Plugin::V2::PluginType
|
2
|
+
class StreamingReporter < Inspec::Plugin::V2::PluginBase # TBD Superclass may need to change
|
3
|
+
register_plugin_type(:streaming_reporter)
|
4
|
+
|
5
|
+
#====================================================================#
|
6
|
+
# StreamingReporter plugin type API
|
7
|
+
#====================================================================#
|
8
|
+
# Implementation classes must implement these methods.
|
9
|
+
end
|
10
|
+
end
|
data/lib/inspec/profile.rb
CHANGED
@@ -450,6 +450,8 @@ module Inspec
|
|
450
450
|
|
451
451
|
def cookstyle_linting_check
|
452
452
|
msgs = []
|
453
|
+
return msgs if Inspec.locally_windows? # See #5723
|
454
|
+
|
453
455
|
output = cookstyle_rake_output.split("Offenses:").last
|
454
456
|
msgs = output.split("\n").select { |x| x =~ /[A-Z]:/ } unless output.nil?
|
455
457
|
msgs
|
@@ -68,6 +68,7 @@ module Inspec
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def reload_dsl
|
71
|
+
@resource_registry.merge!(Inspec::Resource.new_registry)
|
71
72
|
@control_eval_context = nil
|
72
73
|
end
|
73
74
|
|
@@ -263,9 +264,3 @@ module Inspec
|
|
263
264
|
end # DomainSpecificLunacy
|
264
265
|
end # ProfileContext
|
265
266
|
end
|
266
|
-
|
267
|
-
if RUBY_VERSION < "2.5"
|
268
|
-
class Module
|
269
|
-
public :define_method
|
270
|
-
end
|
271
|
-
end
|
@@ -21,7 +21,7 @@ module Inspec::Reporters
|
|
21
21
|
final_report[:type] = "inspec_report"
|
22
22
|
|
23
23
|
final_report[:end_time] = Time.now.utc.strftime("%FT%TZ")
|
24
|
-
final_report[:node_uuid] = @config["node_uuid"] || @config["target_id"]
|
24
|
+
final_report[:node_uuid] = report[:platform][:target_id] || @config["node_uuid"] || @config["target_id"]
|
25
25
|
raise Inspec::ReporterError, "Cannot find a UUID for your node. Please specify one via json-config." if final_report[:node_uuid].nil?
|
26
26
|
|
27
27
|
final_report[:report_uuid] = @config["report_uuid"] || uuid_from_string(final_report[:end_time] + final_report[:node_uuid])
|
@@ -28,12 +28,13 @@ module Inspec::Resources
|
|
28
28
|
EXAMPLE
|
29
29
|
|
30
30
|
def initialize
|
31
|
-
|
31
|
+
@auditctl_cmd_str = inspec.os.name.eql?("alpine") ? "/usr/sbin/auditctl" : "/sbin/auditctl"
|
32
|
+
unless inspec.command(@auditctl_cmd_str).exist?
|
32
33
|
raise Inspec::Exceptions::ResourceFailed,
|
33
|
-
"Command
|
34
|
+
"Command `#{@auditctl_cmd_str}` does not exist"
|
34
35
|
end
|
35
36
|
|
36
|
-
auditctl_cmd = "
|
37
|
+
auditctl_cmd = "#{@auditctl_cmd_str} -l"
|
37
38
|
result = inspec.command(auditctl_cmd)
|
38
39
|
|
39
40
|
if result.exit_status != 0
|
@@ -68,7 +69,7 @@ module Inspec::Resources
|
|
68
69
|
filter.install_filter_methods_on_resource(self, :params)
|
69
70
|
|
70
71
|
def status(name = nil)
|
71
|
-
@status_content ||= inspec.command("
|
72
|
+
@status_content ||= inspec.command("#{@auditctl_cmd_str} -s").stdout.chomp
|
72
73
|
|
73
74
|
# See: https://github.com/inspec/inspec/issues/3113
|
74
75
|
if @status_content =~ /^AUDIT_STATUS/
|
@@ -61,6 +61,24 @@ module Inspec::Resources
|
|
61
61
|
res.force_encoding("utf-8")
|
62
62
|
end
|
63
63
|
|
64
|
+
# returns hash containing list of users/groups and their file permissions.
|
65
|
+
def user_permissions
|
66
|
+
return {} unless exist?
|
67
|
+
|
68
|
+
return skip_reource"`user_permissions` is not supported on your OS yet." unless inspec.os.windows?
|
69
|
+
|
70
|
+
@perms_provider.user_permissions(file)
|
71
|
+
end
|
72
|
+
|
73
|
+
# returns true if inheritance is enabled on file or folder
|
74
|
+
def inherited?
|
75
|
+
return false unless exist?
|
76
|
+
|
77
|
+
return skip_resource "`inherited?` is not supported on your OS yet." unless inspec.os.windows?
|
78
|
+
|
79
|
+
@perms_provider.inherited?(file)
|
80
|
+
end
|
81
|
+
|
64
82
|
def contain(*_)
|
65
83
|
raise "Contain is not supported. Please use standard RSpec matchers."
|
66
84
|
end
|
@@ -244,6 +262,26 @@ module Inspec::Resources
|
|
244
262
|
end
|
245
263
|
|
246
264
|
class WindowsFilePermissions < FilePermissions
|
265
|
+
|
266
|
+
def user_permissions(file)
|
267
|
+
script = <<-EOH
|
268
|
+
$Acl = Get-Acl -Path #{file.path}
|
269
|
+
$Result = foreach ($Access in $acl.Access) {
|
270
|
+
[PSCustomObject]@{
|
271
|
+
$Access.IdentityReference.Value = $Access.FileSystemRights.ToString()
|
272
|
+
}
|
273
|
+
}
|
274
|
+
$Result | ConvertTo-Json
|
275
|
+
EOH
|
276
|
+
result = inspec.powershell(script)
|
277
|
+
JSON.load(result.stdout).inject(&:merge) unless result.stdout.empty?
|
278
|
+
end
|
279
|
+
|
280
|
+
def inherited?(file)
|
281
|
+
cmd = inspec.command("(Get-Acl -Path #{file.path}).access| Where-Object {$_.IsInherited -eq $true} | measure | % { $_.Count }")
|
282
|
+
cmd.stdout.chomp == "0" ? false : true
|
283
|
+
end
|
284
|
+
|
247
285
|
def check_file_permission_by_mask(_file, _access_type, _usergroup, _specific_user)
|
248
286
|
raise "`check_file_permission_by_mask` is not supported on Windows"
|
249
287
|
end
|
@@ -32,6 +32,17 @@ module Inspec::Resources
|
|
32
32
|
.register_column(:interfaces, field: "interfaces")
|
33
33
|
.register_column(:sources, field: "sources")
|
34
34
|
.register_column(:services, field: "services")
|
35
|
+
.register_column(:target, field: "target")
|
36
|
+
.register_column(:ports, field: "ports")
|
37
|
+
.register_column(:protocols, field: "protocols")
|
38
|
+
.register_column(:forward_ports, field: "forward_ports")
|
39
|
+
.register_column(:source_ports, field: "source_ports")
|
40
|
+
.register_column(:icmp_blocks, field: "icmp_blocks")
|
41
|
+
.register_column(:rich_rules, field: "rich_rules")
|
42
|
+
.register_custom_matcher(:icmp_block_inversion?) { |x| x.params[0]["icmp_block_inversion"] }
|
43
|
+
.register_custom_matcher(:has_icmp_block_inversion_enabled?) { |x| x.params[0]["icmp_block_inversion"] }
|
44
|
+
.register_custom_matcher(:masquerade?) { |x| x.params[0]["masquerade"] }
|
45
|
+
.register_custom_matcher(:has_masquerade_enabled?) { |x| x.params[0]["masquerade"] }
|
35
46
|
|
36
47
|
filter.install_filter_methods_on_resource(self, :params)
|
37
48
|
|
@@ -64,28 +75,28 @@ module Inspec::Resources
|
|
64
75
|
end
|
65
76
|
|
66
77
|
def has_service_enabled_in_zone?(query_service, query_zone = default_zone)
|
67
|
-
firewalld_command("--zone=#{query_zone} --query-service=#{query_service}") == "yes"
|
78
|
+
firewalld_command("--permanent --zone=#{query_zone} --query-service=#{query_service}") == "yes"
|
68
79
|
end
|
69
80
|
|
70
81
|
def service_ports_enabled_in_zone(query_service, query_zone = default_zone)
|
71
82
|
# return: String of ports open
|
72
83
|
# example: ['22/tcp', '4722/tcp']
|
73
|
-
firewalld_command("--zone=#{query_zone} --service=#{query_service} --get-ports
|
84
|
+
firewalld_command("--permanent --zone=#{query_zone} --service=#{query_service} --get-ports").split(" ")
|
74
85
|
end
|
75
86
|
|
76
87
|
def service_protocols_enabled_in_zone(query_service, query_zone = default_zone)
|
77
|
-
# return: String of
|
88
|
+
# return: String of protocols open
|
78
89
|
# example: ['icmp', 'ipv4', 'igmp']
|
79
|
-
firewalld_command("--zone=#{query_zone} --service=#{query_service} --get-protocols
|
90
|
+
firewalld_command("--permanent --zone=#{query_zone} --service=#{query_service} --get-protocols").split(" ")
|
80
91
|
end
|
81
92
|
|
82
93
|
def has_port_enabled_in_zone?(query_port, query_zone = default_zone)
|
83
|
-
firewalld_command("--zone=#{query_zone} --query-port=#{query_port}") == "yes"
|
94
|
+
firewalld_command("--permanent --zone=#{query_zone} --query-port=#{query_port}") == "yes"
|
84
95
|
end
|
85
96
|
|
86
97
|
def has_rule_enabled?(rule, query_zone = default_zone)
|
87
98
|
rule = "rule #{rule}" unless rule.start_with?("rule")
|
88
|
-
firewalld_command("--zone=#{query_zone} --query-rich-rule='#{rule}'") == "yes"
|
99
|
+
firewalld_command("--permanent --zone=#{query_zone} --query-rich-rule='#{rule}'") == "yes"
|
89
100
|
end
|
90
101
|
|
91
102
|
def to_s
|
@@ -120,19 +131,82 @@ module Inspec::Resources
|
|
120
131
|
"interfaces" => line.split(":")[1].split(" "),
|
121
132
|
"services" => services_bound(zone),
|
122
133
|
"sources" => sources_bound(zone),
|
134
|
+
"target" => target_bound(zone),
|
135
|
+
"icmp_block_inversion" => icmp_block_inversion_bound?(zone),
|
136
|
+
"ports" => ports_bound(zone),
|
137
|
+
"protocols" => protocols_bound(zone),
|
138
|
+
"masquerade" => masquerade_bound?(zone),
|
139
|
+
"forward_ports" => forward_ports_bound(zone),
|
140
|
+
"source_ports" => source_ports_bound(zone),
|
141
|
+
"icmp_blocks" => icmp_blocks_bound(zone),
|
142
|
+
"rich_rules" => rich_rules_bound(zone),
|
123
143
|
}
|
124
144
|
end
|
125
145
|
|
146
|
+
def target_bound(query_zone)
|
147
|
+
# result: a target bound for the zone
|
148
|
+
# example: 'DROP'
|
149
|
+
firewalld_command("--permanent --zone=#{query_zone} --get-target").strip
|
150
|
+
end
|
151
|
+
|
152
|
+
def icmp_block_inversion_bound?(query_zone)
|
153
|
+
# result: true/false whether inversion of icmp blocks has been enabled for a zone
|
154
|
+
# example: true
|
155
|
+
firewalld_command("--permanent --zone=#{query_zone} --query-icmp-block-inversion") == "yes"
|
156
|
+
end
|
157
|
+
|
158
|
+
def ports_bound(query_zone)
|
159
|
+
# result: a list of ports bound for a zone
|
160
|
+
# example: ['80/tcp', '443/tcp']
|
161
|
+
firewalld_command("--permanent --zone=#{query_zone} --list-ports").split(" ")
|
162
|
+
end
|
163
|
+
|
164
|
+
def protocols_bound(query_zone)
|
165
|
+
# result: a list of protocols added for a zone
|
166
|
+
# example: ['icmp', 'ipv4', 'igmp']
|
167
|
+
firewalld_command("--permanent --zone=#{query_zone} --list-protocols").split(" ")
|
168
|
+
end
|
169
|
+
|
170
|
+
def masquerade_bound?(query_zone)
|
171
|
+
# result: true/false whether IPv4 masquerading has been enabled for a zone
|
172
|
+
# example: true
|
173
|
+
firewalld_command("--permanent --zone=#{query_zone} --query-masquerade") == "yes"
|
174
|
+
end
|
175
|
+
|
176
|
+
def forward_ports_bound(query_zone)
|
177
|
+
# result: a list of IPv4 forward ports bound to a zone
|
178
|
+
# example: ['port=80:proto=tcp:toport=88', 'port=12345:proto=tcp:toport=54321:toaddr=192.168.1.3']
|
179
|
+
firewalld_command("--permanent --zone=#{query_zone} --list-forward-ports").split("\n")
|
180
|
+
end
|
181
|
+
|
182
|
+
def source_ports_bound(query_zone)
|
183
|
+
# result: a list of source ports bound to a zone
|
184
|
+
# example: ['80/tcp', '8080/tcp']
|
185
|
+
firewalld_command("--permanent --zone=#{query_zone} --list-source-ports").split(" ")
|
186
|
+
end
|
187
|
+
|
188
|
+
def icmp_blocks_bound(query_zone)
|
189
|
+
# result: a list of internet ICMP type blocks bound to a zone
|
190
|
+
# example: ['echo-request', 'echo-reply']
|
191
|
+
firewalld_command("--permanent --zone=#{query_zone} --list-icmp-blocks").split(" ")
|
192
|
+
end
|
193
|
+
|
194
|
+
def rich_rules_bound(query_zone)
|
195
|
+
# result: a list of rich language rules bound to a zone
|
196
|
+
# example: ['rule protocol value="ah" accept', 'rule service name="ftp" log limit value="1/m" audit accept']
|
197
|
+
firewalld_command("--permanent --zone=#{query_zone} --list-rich-rules").split("\n")
|
198
|
+
end
|
199
|
+
|
126
200
|
def sources_bound(query_zone)
|
127
201
|
# result: a list containing either an ip address or ip address with a mask, or a ipset or an ipset with the ipset prefix.
|
128
202
|
# example: ['192.168.0.4', '192.168.0.0/16', '2111:DB28:ABC:12::', '2111:db89:ab3d:0112::0/64']
|
129
|
-
firewalld_command("--zone=#{query_zone} --list-sources").split(" ")
|
203
|
+
firewalld_command("--permanent --zone=#{query_zone} --list-sources").split(" ")
|
130
204
|
end
|
131
205
|
|
132
206
|
def services_bound(query_zone)
|
133
207
|
# result: a list of services bound to a zone.
|
134
208
|
# example: ['ssh', 'dhcpv6-client']
|
135
|
-
firewalld_command("--zone=#{query_zone} --list-services").split(" ")
|
209
|
+
firewalld_command("--permanent --zone=#{query_zone} --list-services").split(" ")
|
136
210
|
end
|
137
211
|
|
138
212
|
def firewalld_command(command)
|
@@ -145,4 +219,4 @@ module Inspec::Resources
|
|
145
219
|
result.stdout.strip
|
146
220
|
end
|
147
221
|
end
|
148
|
-
end
|
222
|
+
end
|
@@ -162,7 +162,7 @@ module Inspec::Resources
|
|
162
162
|
|
163
163
|
current_kernel = file_line.split(" ", 2)[1]
|
164
164
|
lines.drop(index + 1).each do |kernel_line|
|
165
|
-
if kernel_line =~
|
165
|
+
if kernel_line =~ /(?:^\s*\w+)/ && !(kernel_line =~ /^title.*/)
|
166
166
|
option_type = kernel_line.split(" ")[0]
|
167
167
|
line_options = kernel_line.split(" ").drop(1)
|
168
168
|
if (menu_entry == conf["default"].to_i && @kernel == "default") || current_kernel == @kernel
|