inspec-core 4.49.0 → 4.56.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +7 -11
  3. data/inspec-core.gemspec +2 -2
  4. data/lib/bundles/inspec-supermarket/README.md +21 -2
  5. data/lib/bundles/inspec-supermarket/cli.rb +20 -3
  6. data/lib/bundles/inspec-supermarket/target.rb +3 -2
  7. data/lib/inspec/base_cli.rb +8 -0
  8. data/lib/inspec/cli.rb +12 -3
  9. data/lib/inspec/config.rb +5 -1
  10. data/lib/inspec/dependencies/requirement.rb +2 -1
  11. data/lib/inspec/formatters/base.rb +8 -6
  12. data/lib/inspec/globals.rb +5 -0
  13. data/lib/inspec/library_eval_context.rb +2 -0
  14. data/lib/inspec/plugin/v1/registry.rb +1 -1
  15. data/lib/inspec/plugin/v2/plugin_types/streaming_reporter.rb +10 -0
  16. data/lib/inspec/profile.rb +2 -0
  17. data/lib/inspec/profile_context.rb +1 -6
  18. data/lib/inspec/reporters/automate.rb +1 -1
  19. data/lib/inspec/reporters/json.rb +1 -1
  20. data/lib/inspec/resources/auditd.rb +5 -4
  21. data/lib/inspec/resources/bash.rb +2 -0
  22. data/lib/inspec/resources/file.rb +38 -0
  23. data/lib/inspec/resources/firewalld.rb +83 -9
  24. data/lib/inspec/resources/grub_conf.rb +1 -1
  25. data/lib/inspec/resources/http.rb +135 -54
  26. data/lib/inspec/resources/ibmdb2_session.rb +2 -2
  27. data/lib/inspec/resources/iptables.rb +18 -2
  28. data/lib/inspec/resources/kernel_parameters.rb +58 -0
  29. data/lib/inspec/resources/mssql_session.rb +11 -3
  30. data/lib/inspec/resources/oracledb_session.rb +3 -1
  31. data/lib/inspec/resources/package.rb +74 -1
  32. data/lib/inspec/resources/packages.rb +21 -0
  33. data/lib/inspec/resources/registry_key.rb +30 -0
  34. data/lib/inspec/resources/selinux.rb +6 -1
  35. data/lib/inspec/resources/service.rb +58 -9
  36. data/lib/inspec/resources/ssl.rb +7 -0
  37. data/lib/inspec/resources/timezone.rb +65 -0
  38. data/lib/inspec/resources.rb +2 -0
  39. data/lib/inspec/runner_rspec.rb +30 -0
  40. data/lib/inspec/utils/filter.rb +46 -2
  41. data/lib/inspec/utils/run_data_filters.rb +1 -1
  42. data/lib/inspec/version.rb +1 -1
  43. data/lib/plugins/inspec-compliance/lib/inspec-compliance/api.rb +1 -1
  44. data/lib/plugins/inspec-compliance/lib/inspec-compliance/cli.rb +4 -3
  45. metadata +8 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31dcab9ba9621f43755fc390ad061c08b7e6ab19466d26a38921d33960e1bbf5
4
- data.tar.gz: eecdf0ec772ef012bfbf5185b379c47dd008fe902b9e91d4feee6979b0294c0f
3
+ metadata.gz: 9930c475b5a1e282ab613db458f60c77561db82d6c009d6c7254f5a3789132f5
4
+ data.tar.gz: 8a11ae471b5954568be5bf6fc88e52d974a5ac9cb83caf2a6560dd3dd26d55fe
5
5
  SHA512:
6
- metadata.gz: 1059703ad59c2bf7c213a0914f94a8852cc550b1d305f634e07a08b364edae5c0f550927a8bcec9e712cd313949388082fdebf5c3164147ef12c21df952281b9
7
- data.tar.gz: 1d4e6e64b8851c40349b7d696d46904fa73c0683d19c70afaa942a4c4bef4591a3ed4d7ec2c89aa5f7717da70617d70f182a7e9b894338da77592231b4c62234
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
- if Gem.ruby_version.to_s.start_with?("2.5")
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.18"
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.5"
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", "< 3.11"
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: `inspec supermarket exec nathenharvey/tmp-compliance-profile`
12
- - via supermarket scheme: `inspec exec supermarket://nathenharvey/tmp-compliance-profile`
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
- # display profiles in format user/profile
20
- supermarket_profiles = Supermarket::API.profiles
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 = Supermarket::API.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, Supermarket::API::SUPERMARKET_URL]
14
+ [target, supermarket_url]
14
15
  elsif target.respond_to?(:key?) && target.key?(:supermarket)
15
- supermarket_server = target[:supermarket_url] || Supermarket::API::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
@@ -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
- ui.plain_line("No errors, warnings, or offenses")
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
- unless result[:offenses].empty?
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
- ui.plain_line("Summary: #{errors}, #{warnings}, #{offenses}")
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
- valid_types = rspec_built_in_formatters + inspec_reporters_that_are_not_yet_plugins + plugin_reporters
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
- @fetcher ||= Inspec::CachedFetcher.new(opts, @cache)
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
- begin
209
- @backend.platform[field]
210
- rescue Train::Error => e
211
- Inspec::Log.warn(e.message)
212
- nil
213
- end
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
@@ -18,4 +18,9 @@ module Inspec
18
18
  require "etc" unless defined?(Etc)
19
19
  Etc.getpwuid.dir
20
20
  end
21
+
22
+ def self.locally_windows?
23
+ require "rbconfig" unless defined?(RbConfig)
24
+ RbConfig::CONFIG["host_os"] =~ /mswin|mingw|cygwin/
25
+ end
21
26
  end
@@ -30,6 +30,8 @@ module Inspec
30
30
 
31
31
  c3 = Class.new do
32
32
  include Inspec::DSL::RequireOverride
33
+ include Inspec::Resources
34
+
33
35
  def initialize(require_loader)
34
36
  @require_loader = require_loader
35
37
  @inspec_binding = nil
@@ -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 == m
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
@@ -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])
@@ -29,7 +29,7 @@ module Inspec::Reporters
29
29
  {
30
30
  name: run_data[:platform][:name],
31
31
  release: run_data[:platform][:release],
32
- target_id: @config["target_id"],
32
+ target_id: run_data[:platform][:target_id] || @config["target_id"],
33
33
  }.reject { |_k, v| v.nil? }
34
34
  end
35
35
 
@@ -28,12 +28,13 @@ module Inspec::Resources
28
28
  EXAMPLE
29
29
 
30
30
  def initialize
31
- unless inspec.command("/sbin/auditctl").exist?
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 `/sbin/auditctl` does not exist"
34
+ "Command `#{@auditctl_cmd_str}` does not exist"
34
35
  end
35
36
 
36
- auditctl_cmd = "/sbin/auditctl -l"
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("/sbin/auditctl -s").stdout.chomp
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/
@@ -5,6 +5,8 @@ module Inspec::Resources
5
5
  class Bash < Cmd
6
6
  name "bash"
7
7
  supports platform: "unix"
8
+ supports platform: "esx"
9
+
8
10
  desc "Run a command or script in BASH."
9
11
  example <<~EXAMPLE
10
12
  describe bash('ls -al /') do
@@ -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 --permanent").split(" ")
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 protocoals open
88
+ # return: String of protocols open
78
89
  # example: ['icmp', 'ipv4', 'igmp']
79
- firewalld_command("--zone=#{query_zone} --service=#{query_service} --get-protocols --permanent").split(" ")
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 =~ /^\s.*/
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