inspec-core 5.12.2 → 5.14.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7242aa89bb64084dbeb75587b128af25c4967be0bc06ec8e9d8f386e821d36a
4
- data.tar.gz: 876166ebb7e7ae59bb39fe1b9fd4523f45cdb6c22702f08e0074dad4662bf5bf
3
+ metadata.gz: 3cb92e0f21964ecac43d5d9f208e7a2b07a57c2daa0fef4aad06515f933b9072
4
+ data.tar.gz: 6c4d5f59ed6dde73193198f4ad32c801515cec12d9c04924765d1ac7ee4bd5bc
5
5
  SHA512:
6
- metadata.gz: 155d7f957519b8358c1e8d92373f50b8839cb7f31ca3f32af953a556a2753f768b69b9a78dc7fa2b228ed30e2a26a5b33a393dbe472c501fcc1bda0b54a353f8
7
- data.tar.gz: af8ec2a17788ba7add5c58c07c0e842b31e8a7a92f6afd38ca0e794c2d297dde6464e8dd9cf8d8a07374042a2437ec41685226be098004a4396160432d68a14f
6
+ metadata.gz: 8397f679eea47dead2cb1952026b74c800adf7ea650120597b714c3ccdef1c7e0eeb6af387458a31c028173a6bc332b07de103d4d545dbd37257573b77c6e0b1
7
+ data.tar.gz: 96d8ac046aa00ec95fc173e81c28999d744ed823af7a4a6401e9d1776817e303e451e7c8d46450d2c39c02e6ef4ff4c82d1c425683e82299effa2f3384f9f93e
data/lib/inspec/cli.rb CHANGED
@@ -95,6 +95,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI
95
95
  desc "check PATH", "verify all tests at the specified PATH"
96
96
  option :format, type: :string,
97
97
  desc: "The output format to use doc (default), json. If valid format is not provided then it will use the default."
98
+ option :with_cookstyle, type: :boolean,
99
+ desc: "Enable or disable cookstyle checks.", default: false
98
100
  profile_options
99
101
  def check(path) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
100
102
  o = config
@@ -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
@@ -655,12 +656,13 @@ module Inspec
655
656
  end
656
657
 
657
658
  # Running cookstyle to check for code offenses
658
- cookstyle_linting_check.each do |lint_output|
659
- data = lint_output.split(":")
660
- msg = "#{data[-2]}:#{data[-1]}"
661
- offense.call(data[0], data[1], data[2], nil, msg)
659
+ if @check_cookstyle
660
+ cookstyle_linting_check.each do |lint_output|
661
+ data = lint_output.split(":")
662
+ msg = "#{data[-2]}:#{data[-1]}"
663
+ offense.call(data[0], data[1], data[2], nil, msg)
664
+ end
662
665
  end
663
-
664
666
  # profile is valid if we could not find any error & offenses
665
667
  result[:summary][:valid] = result[:errors].empty? && result[:offenses].empty?
666
668
 
@@ -0,0 +1,61 @@
1
+ require "inspec/resources/command"
2
+ require_relative "routing_table"
3
+
4
+ module Inspec::Resources
5
+ class Defaultgateway < Routingtable
6
+ # resource internal name.
7
+ name "default_gateway"
8
+
9
+ # Restrict to only run on the below platforms (if none were given,
10
+ # all OS's and cloud API's supported)
11
+ supports platform: "unix"
12
+ supports platform: "windows"
13
+
14
+ desc "Use the `default_gateway` Chef InSpec audit resource to test the assigned ip address and interface for the default route."
15
+
16
+ example <<~EXAMPLE
17
+ describe default_gateway do
18
+ its(:ipaddress) { should eq '172.31.80.1' }
19
+ end
20
+ describe default_gateway do
21
+ its("interface") { should eq 'eth0' }
22
+ end
23
+ EXAMPLE
24
+
25
+ def initialize
26
+ skip_resource "The `default_gateway` resource is not yet available on your OS." unless inspec.os.unix? || inspec.os.windows?
27
+ # invoke the routing_table initialize; which populates the @routing_info
28
+ super()
29
+ end
30
+
31
+ # resource appearance in test reports.
32
+ def to_s
33
+ "default_gateway"
34
+ end
35
+
36
+ # fetches the ipaddress assigned to the default gateway
37
+ # default gateway's destination is either `default` or `0.0.0.0`
38
+ def ipaddress
39
+ # @routing_info is the hash populated in routing_table resource
40
+ # @routing_info contain values as:
41
+ # {
42
+ # destination1: [ [gateway1x, interface1x], [gateway1y, interface1y] ],
43
+ # destination2: [gateway2, interface2]
44
+ # }
45
+ %w{default 0.0.0.0}.each do |destination|
46
+ return @routing_info[destination][0][0] if @routing_info.key?(destination)
47
+ end
48
+ # raise exception because no destination with value default or 0.0.0.0 is found in the routing table
49
+ raise Inspec::Exceptions::ResourceFailed, "No routing found as part of default gateway"
50
+ end
51
+
52
+ # fetches the interface assigned to the default gateway
53
+ def interface
54
+ %w{default 0.0.0.0}.each do |destination|
55
+ return @routing_info[destination][0][1] if @routing_info.key?(destination)
56
+ end
57
+ # raise exception because no destination with value default or 0.0.0.0 is found in the routing table
58
+ raise Inspec::Exceptions::ResourceFailed, "No routing found as part of default gateway"
59
+ end
60
+ end
61
+ end
@@ -181,6 +181,34 @@ module Inspec::Resources
181
181
  inv_mode & file.mode != 0
182
182
  end
183
183
 
184
+ def immutable?
185
+ raise Inspec::Exceptions::ResourceSkipped, "The `be_immutable` matcher is not supported on your OS yet." unless inspec.os.unix?
186
+
187
+ if inspec.os.linux?
188
+ file_info = LinuxImmutableFlagCheck.new(inspec, file)
189
+ else
190
+ file_info = UnixImmutableFlagCheck.new(inspec, file)
191
+ end
192
+
193
+ file_info.is_immutable?
194
+ end
195
+
196
+ # parse the json file content and returns the content
197
+ def content_as_json
198
+ require "json" unless defined?(JSON)
199
+ JSON.parse(file.content)
200
+ rescue => e
201
+ raise Inspec::Exceptions::ResourceFailed, "Unable to parse the given JSON file: #{e.message}"
202
+ end
203
+
204
+ # parse the yaml file content and returns the content
205
+ def content_as_yaml
206
+ require "yaml" unless defined?(YAML)
207
+ YAML.load(file.content)
208
+ rescue => e
209
+ raise Inspec::Exceptions::ResourceFailed, "Unable to parse the given YAML file: #{e.message}"
210
+ end
211
+
184
212
  def to_s
185
213
  if file
186
214
  "File #{source_path}"
@@ -373,4 +401,67 @@ module Inspec::Resources
373
401
  end
374
402
  end
375
403
  end
404
+
405
+ # Helper class for immutable matcher.
406
+ class ImmutableFlagCheck
407
+ attr_reader :inspec, :file_path
408
+ def initialize(inspec, file)
409
+ @inspec = inspec
410
+ @file_path = file.path
411
+ end
412
+
413
+ def find_utility_or_error(utility_name)
414
+ [
415
+ "/usr/sbin/#{utility_name}",
416
+ "/sbin/#{utility_name}",
417
+ "/usr/bin/#{utility_name}",
418
+ "/bin/#{utility_name}",
419
+ "#{utility_name}",
420
+ ].each do |cmd|
421
+ return cmd if inspec.command(cmd).exist?
422
+ end
423
+
424
+ raise Inspec::Exceptions::ResourceFailed, "Could not find `#{utility_name}`"
425
+ end
426
+ end
427
+
428
+ class LinuxImmutableFlagCheck < ImmutableFlagCheck
429
+ def is_immutable?
430
+ # Check if lsattr is available. In general, all linux system has lsattr & chattr
431
+ # This logic check is valid for immutable flag set with chattr
432
+ utility = find_utility_or_error("lsattr")
433
+ utility_cmd = inspec.command("#{utility} #{file_path}")
434
+
435
+ raise Inspec::Exceptions::ResourceFailed, "Executing #{utility} #{file_path} failed: #{utility_cmd.stderr}" if utility_cmd.exit_status.to_i != 0
436
+
437
+ # General output for lsattr file_name is:
438
+ # ----i---------e----- file_name
439
+ # The fifth char resembles the immutable flag. Total 20 flags are allowed.
440
+ lsattr_info = utility_cmd.stdout.strip.squeeze(" ")
441
+ lsattr_info =~ /^.{4}i.{15} .*/
442
+ end
443
+ end
444
+
445
+ class UnixImmutableFlagCheck < ImmutableFlagCheck
446
+ def is_immutable?
447
+ # Check if chflags is available on the system. Most unix-like system comes with chflags.
448
+ # This logic check is valid for immutable flag set with chflags
449
+ find_utility_or_error("chflags")
450
+
451
+ # In general ls -lO is used to check immutable flag set by chflags
452
+ utility_cmd = inspec.command("ls -lO #{file_path}")
453
+
454
+ # But on some bsd system (eg: freebsd) ls -lo is used instead of ls -lO
455
+ utility_cmd = inspec.command("ls -lo #{file_path}") if utility_cmd.exit_status.to_i != 0
456
+
457
+ raise Inspec::Exceptions::ResourceFailed, "Executing ls -lo #{file_path} and ls -lO #{file_path} failed: #{utility_cmd.stderr}" if utility_cmd.exit_status.to_i != 0
458
+
459
+ # General output for ls -lO file_name is:
460
+ # -rw-r--r-- 1 current_user 1083951318 uchg 0 Apr 6 12:45 file_name
461
+ # The schg flag and the uchg flag represents the immutable flags
462
+ # uchg => user immutable flag, schg => system immutable flag.
463
+ file_info = utility_cmd.stdout.strip.split
464
+ file_info.include?("uchg") || file_info.include?("schg")
465
+ end
466
+ end
376
467
  end
@@ -145,6 +145,11 @@ module Inspec::Resources
145
145
  true
146
146
  end
147
147
 
148
+ # matcher equivalent to gid property.
149
+ def has_gid?(gid_value)
150
+ gid_value == gid
151
+ end
152
+
148
153
  def to_s
149
154
  "Group #{@group}"
150
155
  end
@@ -0,0 +1,81 @@
1
+ require "inspec/resources/command"
2
+ module Inspec::Resources
3
+ class LinuxAuditSystem < Inspec.resource(1)
4
+ # Resource's internal name.
5
+ name "linux_audit_system"
6
+
7
+ # Restrict to only run on the below platforms (if none were given,
8
+ # all OS's and cloud API's supported)
9
+ supports platform: "linux"
10
+
11
+ desc "Use the `linux_audit_system` Chef InSpec audit resource to test the configuration of linux audit system."
12
+
13
+ example <<~EXAMPLE
14
+ describe linux_audit_system do
15
+ it { should be_enabled }
16
+ it { should be_running }
17
+ its("rules") { should include "-w /etc -p wa" }
18
+ its("rules") { should include %r{-w /etc -p wa} }
19
+ its("rules") { should include %r!-w /etc -p wa! }
20
+ end
21
+ EXAMPLE
22
+
23
+ attr_reader :auditctl_utility
24
+
25
+ # Resource initialization.
26
+ def initialize
27
+ skip_resource "The `linux_audit_system` resource is not yet available on your OS." unless inspec.os.linux?
28
+ @auditctl_utility = find_auditctl_or_error
29
+ end
30
+
31
+ # Resource appearance in test reports.
32
+ def to_s
33
+ "linux_audit_system"
34
+ end
35
+
36
+ # The be_enabled matcher checks if the auditing is enabled.
37
+ # The enabled flag 1 indicates that the auditing is enabled.
38
+ def enabled?
39
+ auditctl_cmd = inspec.command("#{auditctl_utility} -s | grep enabled")
40
+
41
+ raise Inspec::Exceptions::ResourceFailed, "Executing #{auditctl_utility} -s | grep enabled failed: #{auditctl_cmd.stderr}" if auditctl_cmd.exit_status.to_i != 0
42
+
43
+ # Sample stdout: enabled 1
44
+ auditctl_enabled_status = auditctl_cmd.stdout.strip.split
45
+ auditctl_enabled_status[1].to_i == 1
46
+ end
47
+
48
+ # The be_running matcher checks if the audit daemon is running.
49
+ # A pid of 0 indicates that the audit daemon is not running.
50
+ def running?
51
+ auditctl_cmd = inspec.command("#{auditctl_utility} -s | grep pid")
52
+
53
+ raise Inspec::Exceptions::ResourceFailed, "Executing #{auditctl_utility} -s | grep enabled failed: #{auditctl_cmd.stderr}" if auditctl_cmd.exit_status.to_i != 0
54
+
55
+ # Sample stdout: pid 682462
56
+ auditctl_running_status = auditctl_cmd.stdout.strip.split
57
+ !auditctl_running_status[1].nil? && auditctl_running_status[1].to_i != 0
58
+ end
59
+
60
+ # The rules property returns the array of audit rules obtained on auditctl -l.
61
+ # The auditctl -l list all rules, 1 per line.
62
+ def rules
63
+ auditctl_cmd = inspec.command("#{auditctl_utility} -l")
64
+
65
+ raise Inspec::Exceptions::ResourceFailed, "Executing #{auditctl_utility} -l: #{auditctl_cmd.stderr}" if auditctl_cmd.exit_status.to_i != 0
66
+
67
+ auditctl_cmd.stdout.strip.split("\n")
68
+ end
69
+
70
+ private
71
+
72
+ # Check if auditctl is available on the system.
73
+ def find_auditctl_or_error
74
+ %w{/usr/sbin/auditctl /sbin/auditctl auditctl}.each do |cmd|
75
+ return cmd if inspec.command(cmd).exist?
76
+ end
77
+
78
+ raise Inspec::Exceptions::ResourceFailed, "Could not find `auditctl`. This resource requires `auditctl` utility to be available on the system."
79
+ end
80
+ end
81
+ end
@@ -271,6 +271,30 @@ module Inspec::Resources
271
271
  info[:startname]
272
272
  end
273
273
 
274
+ # matcher equivalent to startmode property; compares start-up mode
275
+ # supported only on windows.
276
+ def has_start_mode?(mode)
277
+ raise Inspec::Exceptions::ResourceSkipped, "The `has_start_mode` matcher is not supported on your OS yet." unless inspec.os.windows?
278
+
279
+ mode == startmode
280
+ end
281
+
282
+ # matcher to check if the service is monitored by the given monitoring tool/software
283
+ def monitored_by?(monitoring_tool)
284
+ # Currently supported monitoring tools are: monit & god
285
+ # To add support for new monitoring tools, extend the case statement with additional monitoring tool and
286
+ # add the definition and logic in a new class (inheriting the base class MonitoringTool: optional)
287
+ case monitoring_tool
288
+ when "monit"
289
+ current_monitoring_tool = Monit.new(inspec, @service_name)
290
+ when "god"
291
+ current_monitoring_tool = God.new(inspec, @service_name)
292
+ else
293
+ puts "The monitoring tool #{monitoring_tool} is not yet supported by InSpec."
294
+ end
295
+ current_monitoring_tool.is_service_monitored?
296
+ end
297
+
274
298
  def to_s
275
299
  "Service #{@service_name}"
276
300
  end
@@ -893,4 +917,53 @@ module Inspec::Resources
893
917
  Runit.new(inspec, service_ctl)
894
918
  end
895
919
  end
920
+
921
+ # Helper class for monitored_by matcher
922
+ class MonitoringTool
923
+ attr_reader :inspec, :service_name
924
+ def initialize(inspec, service_name)
925
+ @inspec = inspec
926
+ @service_name ||= service_name
927
+ end
928
+
929
+ def find_utility_or_error(utility_name)
930
+ [ "/usr/sbin/#{utility_name}" , "/sbin/#{utility_name}" , "/usr/bin/#{utility_name}" , "/bin/#{utility_name}" , "#{utility_name}" ].each do |cmd|
931
+ return cmd if inspec.command(cmd).exist?
932
+ end
933
+
934
+ raise Inspec::Exceptions::ResourceFailed, "Could not find `#{utility_name}`"
935
+ end
936
+ end
937
+
938
+ class Monit < MonitoringTool
939
+ def is_service_monitored?
940
+ utility = find_utility_or_error("monit")
941
+ utility_cmd = inspec.command("#{utility} summary")
942
+
943
+ raise Inspec::Exceptions::ResourceFailed, "Executing #{utility} summary failed: #{utility_cmd.stderr}" if utility_cmd.exit_status.to_i != 0
944
+
945
+ monitoring_info = utility_cmd.stdout.split("\n")
946
+ monitoring_info.map! { |info| info.strip.squeeze(" ") }
947
+ is_monitored = false
948
+ monitoring_info.each do |info|
949
+ if info =~ /^#{service_name} OK.*/
950
+ is_monitored = true
951
+ break
952
+ end
953
+ end
954
+ is_monitored
955
+ end
956
+ end
957
+
958
+ class God < MonitoringTool
959
+ def is_service_monitored?
960
+ utility = find_utility_or_error("god")
961
+ utility_cmd = inspec.command("#{utility} status #{service_name}")
962
+
963
+ raise Inspec::Exceptions::ResourceFailed, "Executing #{utility} status #{service_name} failed: #{utility_cmd.stderr}" if utility_cmd.exit_status.to_i != 0
964
+
965
+ monitoring_info = utility_cmd.stdout.strip
966
+ monitoring_info =~ /^#{service_name}: up/
967
+ end
968
+ end
896
969
  end
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "5.12.2".freeze
2
+ VERSION = "5.14.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.12.2
4
+ version: 5.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef InSpec Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-08 00:00:00.000000000 Z
11
+ date: 2022-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry
@@ -520,6 +520,7 @@ files:
520
520
  - lib/inspec/resources/cron.rb
521
521
  - lib/inspec/resources/crontab.rb
522
522
  - lib/inspec/resources/csv.rb
523
+ - lib/inspec/resources/default_gateway.rb
523
524
  - lib/inspec/resources/dh_params.rb
524
525
  - lib/inspec/resources/directory.rb
525
526
  - lib/inspec/resources/docker.rb
@@ -566,6 +567,7 @@ files:
566
567
  - lib/inspec/resources/ksh.rb
567
568
  - lib/inspec/resources/launchd_service.rb
568
569
  - lib/inspec/resources/limits_conf.rb
570
+ - lib/inspec/resources/linux_audit_system.rb
569
571
  - lib/inspec/resources/linux_kernel_parameter.rb
570
572
  - lib/inspec/resources/login_defs.rb
571
573
  - lib/inspec/resources/lxc.rb