inspec-core 5.12.2 → 5.14.0

Sign up to get free protection for your applications and to get access to all the features.
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