inspec-core 5.10.5 → 5.12.2

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: d96c590b3ff91ce5db5eaf8ee6ef68721fd17d103f250c8c3106941784f8f336
4
- data.tar.gz: 50b56c3506f186b51fcf07df23a59050461132e0c03245bed088961ef0e854fb
3
+ metadata.gz: b7242aa89bb64084dbeb75587b128af25c4967be0bc06ec8e9d8f386e821d36a
4
+ data.tar.gz: 876166ebb7e7ae59bb39fe1b9fd4523f45cdb6c22702f08e0074dad4662bf5bf
5
5
  SHA512:
6
- metadata.gz: 0eeb703b52391323d79b9ff99ce9bdc4b4aac5903fd6e10087b7ae92372b733b7a5779672fb67a3dc7aa6cfb2e3c859ca35ab81a6e49c0331ae623487e6ea241
7
- data.tar.gz: 7f076f8c2bef5080a73b6fb8886657137a558bf9c624dd11906c91ef9f555e8c6713af8f62282f9a2fa20e650624fbcd3172fe0e9557f59dd8eb539684192ff1
6
+ metadata.gz: 155d7f957519b8358c1e8d92373f50b8839cb7f31ca3f32af953a556a2753f768b69b9a78dc7fa2b228ed30e2a26a5b33a393dbe472c501fcc1bda0b54a353f8
7
+ data.tar.gz: af8ec2a17788ba7add5c58c07c0e842b31e8a7a92f6afd38ca0e794c2d297dde6464e8dd9cf8d8a07374042a2437ec41685226be098004a4396160432d68a14f
@@ -43,6 +43,19 @@ module Inspec::Resources
43
43
  status.downcase.start_with?("up") if object_info.entries.length == 1
44
44
  end
45
45
 
46
+ # has_volume? matcher checks if the volume specified in source path of host is mounted in destination path of docker
47
+ def has_volume?(destination, source)
48
+ # volume_info is the hash which contains the low-level information about the container
49
+ # if Mounts key is not present or is nil; raise exception
50
+ raise Inspec::Exceptions::ResourceFailed, "Could not find any mounted volumes for your container" unless volume_info.Mounts[0]
51
+
52
+ # Iterate through the list of mounted volumes and check if it matches with the given destination and source
53
+ # is_mounted flag is used to handle to return explict boolean values of true or false
54
+ is_mounted = false
55
+ volume_info.Mounts.detect { |mount| is_mounted = mount.Destination == destination && mount.Source == source }
56
+ is_mounted
57
+ end
58
+
46
59
  def status
47
60
  object_info.status[0] if object_info.entries.length == 1
48
61
  end
@@ -87,5 +100,13 @@ module Inspec::Resources
87
100
  opts = @opts
88
101
  @info = inspec.docker.containers.where { names == opts[:name] || (!id.nil? && !opts[:id].nil? && (id == opts[:id] || id.start_with?(opts[:id]))) }
89
102
  end
103
+
104
+ # volume_info returns the low-level information obtained on docker inspect [container_name/id]
105
+ def volume_info
106
+ return @mount_info if defined?(@mount_info)
107
+
108
+ # Check for either docker inspect [container_name] or docker inspect [container_id]
109
+ @mount_info = inspec.docker.object(@opts[:name] || @opts[:id])
110
+ end
90
111
  end
91
112
  end
@@ -48,6 +48,25 @@ module Inspec::Resources
48
48
  object_info.tags[0] if object_info.entries.size == 1
49
49
  end
50
50
 
51
+ # method_missing handles when hash_keys are invoked to check information obtained on docker inspect [image_name]
52
+ def method_missing(*hash_keys)
53
+ # User can test the low-level inspect information in three ways:
54
+ # Way 1: Serverspec style: its(['Config.Cmd']) { should include some_value }
55
+ # here, the value for hash_keys recieved is [:[], "Config.Cmd"]
56
+ # Way 2: InSpec style: its(['Config','Cmd']) { should include some_value }
57
+ # here, the value for hash_keys recieved is [:[], "Config", "Cmd"]
58
+ # Way 3: Mix of both: its(['GraphDriver.Data','MergedDir']) { should include some_value }
59
+ # here, the value for hash_keys recieved is [:[], "GraphDriver.Data", "MergedDir"]
60
+
61
+ # hash_keys are passed to this method to evaluate the value
62
+ image_hash_inspection(hash_keys)
63
+ end
64
+
65
+ # inspection property allows to test any of the hash key-value pairs as part of the image_inspect_info
66
+ def inspection
67
+ image_inspect_info
68
+ end
69
+
51
70
  def to_s
52
71
  img = @opts[:image] || @opts[:id]
53
72
  "Docker Image #{img}"
@@ -80,5 +99,39 @@ module Inspec::Resources
80
99
  (repository == opts[:repo] && tag == opts[:tag]) || (!id.nil? && !opts[:id].nil? && (id == opts[:id] || id.start_with?(opts[:id])))
81
100
  end
82
101
  end
102
+
103
+ # image_inspect_info returns the complete inspect hash_values of the image
104
+ def image_inspect_info
105
+ return @inspect_info if defined?(@inspect_info)
106
+
107
+ @inspect_info = inspec.docker.object(@opts[:image] || (!@opts[:id].nil? && @opts[:id]))
108
+ end
109
+
110
+ # image_hash_inspection formats the input hash_keys and checks if any value exists for such keys in @inspect_info(image_inspect_info)
111
+ def image_hash_inspection(hash_keys)
112
+ # The hash_keys recieved are in three formats as mentioned in method_missing
113
+ # The hash_keys recieved must be in array format [] and the zeroth index must be :[]
114
+ # Check for the conditions and remove the zeroth element from the hash_keys
115
+
116
+ hash_keys.shift if hash_keys.is_a?(Array) && hash_keys[0] == :[]
117
+
118
+ # When received hash_keys in Serverspec style or mix of both
119
+ # The hash_keys are to be splitted at '.' (dot) and flatten it so that it doesn't become array of arrays
120
+ # After splitting and flattening is done, hash_keys is now an array with individual keys
121
+ hash_keys = hash_keys.map { |key| key.split(".") }.flatten
122
+
123
+ # image_inspect_info returns the complete inspect hash_values of the image
124
+ # dig() finds the nested value specified by the sequence of the key object by calling dig at each step.
125
+ # hash_keys is the key object. If one of the key is bad, value will be nil.
126
+ hash_value = image_inspect_info.dig(*hash_keys)
127
+
128
+ # If one of the key is bad, hash_value will be nil, so raise exception which throws it in rescue block
129
+ # else return hash_value
130
+ raise Inspec::Exceptions::ResourceFailed if hash_value.nil?
131
+
132
+ hash_value
133
+ rescue
134
+ raise Inspec::Exceptions::ResourceFailed, "#{hash_keys.join(".")} is not a valid key for your image or has nil value."
135
+ end
83
136
  end
84
137
  end
@@ -0,0 +1,46 @@
1
+ require "inspec/resources/command"
2
+ module Inspec::Resources
3
+ class Mailalias < Inspec.resource(1)
4
+ # resource internal name.
5
+ name "mail_alias"
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: "unix"
10
+
11
+ desc "Use the mail_alias InSpec audit resource to test mail alias present in the aliases file"
12
+
13
+ example <<~EXAMPLE
14
+ describe mail_alias("toor") do
15
+ it { should be_aliased_to "root" }
16
+ end
17
+ EXAMPLE
18
+
19
+ def initialize(alias_key)
20
+ skip_resource "The `mail_alias` resource is not yet available on your OS." unless inspec.os.unix?
21
+ @alias_key = alias_key
22
+ end
23
+
24
+ # resource_id is used in reporting engines to uniquely identify the individual resource.
25
+ def resource_id
26
+ "#{@alias_key}"
27
+ end
28
+
29
+ # resource appearance in test reports.
30
+ def to_s
31
+ "mail_alias #{resource_id}"
32
+ end
33
+
34
+ # aliased_to matcher checks if the given alias_value is set to the initialized alias_key
35
+ def aliased_to?(alias_value)
36
+ # /etc/aliases if the file where the alias and its value(s) are stored
37
+ cmd = inspec.command("cat /etc/aliases | grep '^#{@alias_key}:'")
38
+ raise Inspec::Exceptions::ResourceFailed, "#{@alias_key} is not a valid key in the aliases" if cmd.exit_status.to_i != 0
39
+
40
+ # in general aliases file contains : separated values like alias_key : alias_value1, alias_value2
41
+ alias_values_combined = cmd.stdout.split(":").map(&:strip)[1]
42
+ alias_values_splitted = alias_values_combined.split(",").map(&:strip)
43
+ alias_values_splitted.include?(alias_value)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,137 @@
1
+ require "inspec/resources/command"
2
+
3
+ module Inspec::Resources
4
+ class Routingtable < Inspec.resource(1)
5
+ # resource internal name.
6
+ name "routing_table"
7
+
8
+ # Restrict to only run on the below platforms (if none were given,
9
+ # all OS's and cloud API's supported)
10
+ supports platform: "unix"
11
+ supports platform: "windows"
12
+
13
+ desc "Use the `routing_table` Chef InSpec audit resource to test the routing information parameters(destination, gateway and interface) present in the routing table."
14
+
15
+ example <<~EXAMPLE
16
+ describe routing_table do
17
+ it do
18
+ should have_entry(
19
+ :destination => '192.168.43.1/32',
20
+ :interface => 'lxdbr0',
21
+ :gateway => '172.31.80.1',
22
+ )
23
+ end
24
+ end
25
+
26
+ describe routing_table do
27
+ it { should have_entry(destination: '0.0.0.0', interface: 'eth0', gateway: '172.31.80.1') }
28
+ end
29
+ EXAMPLE
30
+
31
+ def initialize
32
+ skip_resource "The `routing_table` resource is not yet available on your OS." unless inspec.os.unix? || inspec.os.windows?
33
+ # fetch the routing information and store it in @routing_info (could be hash, tbd)
34
+ @routing_info = {}
35
+ fetch_routing_information
36
+ end
37
+
38
+ # resource appearance in test reports.
39
+ def to_s
40
+ "routing_table"
41
+ end
42
+
43
+ def has_entry?(input_route)
44
+ # check if the destination, gateway, interface exists as part of the routing_info
45
+ if input_route.key?(:destination) && input_route.key?(:gateway) && input_route.key?(:interface)
46
+ # check if there is key with destination's value in hash;
47
+ # if yes, check if destination and gateway is present else return false
48
+ @routing_info.key?(input_route[:destination]) ? @routing_info[input_route[:destination]].include?([input_route[:gateway], input_route[:interface]]) : false
49
+ else
50
+ raise Inspec::Exceptions::ResourceSkipped, "One or more missing key, have_entry? matcher expects a hash with 3 keys: destination, gateway and interface"
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ # fetches the routing information for the system
57
+ def fetch_routing_information
58
+ # check if netstat is available on the system
59
+ utility = find_netstat_or_error
60
+
61
+ # the command to fetch the routing information
62
+ fetch_route_cmd = "#{utility} -rn"
63
+
64
+ # execute the above netstat command
65
+ cmd = inspec.command(fetch_route_cmd)
66
+
67
+ # raise error if the exit status is not zero;
68
+ raise Inspec::Exceptions::ResourceFailed, "Executing netstat failed: #{cmd.stderr}" if cmd.exit_status.to_i != 0
69
+
70
+ # Todo:
71
+ # Improve logic to fetch destination, gateway & interface efficiently.
72
+ # The below logic assumes the following:
73
+ # 1. destination, gateway & interface header is present as Destination, Gateway & (Iface or Netif or Interface) respectively.
74
+ # (Netif on BSD, Darwin,Iface on linux & Interface on Windows)
75
+ # 2. there is no blank data for any columns or the blank data are present after the interface column.
76
+
77
+ # cmd.stdout is the standard out of netstat -rn; split on new line to get the rows
78
+ raw_route_info = cmd.stdout.split("\n")
79
+
80
+ # since raw_route_info contains some row before the header (i.e. Destination Gateway ...); remove those rows
81
+ raw_route_info.shift until raw_route_info[0] =~ /Destination/i
82
+
83
+ # split each rows based on space to get the individual columns
84
+ # raw_route_info is now array of arrays with the routing information
85
+ raw_route_info.map! { |info| info.strip.split }
86
+
87
+ # these variables will store the indices where destination, gateway and interface are present
88
+ destination_index, gateway_index, interface_index = -1, -1, -1
89
+
90
+ # The headers in windows are as:
91
+ # Network Destination Netmask Gateway Interface Metric
92
+ # Splitting on space makes "Network Destination" to be two separate values as "Network" & "Destination"
93
+ # Remove "Network" value to apply the logic of finding index
94
+ raw_route_info[0].shift if inspec.os.windows?
95
+
96
+ # find the indices of destination, gateway and interface;
97
+ # because the position of gateway & interface varies with operating system
98
+ raw_route_info[0].each_with_index do |header, index|
99
+ if header =~ /Destination/i
100
+ destination_index = index
101
+ elsif header =~ /Gateway/i
102
+ gateway_index = index
103
+ elsif header =~ /Iface|Netif|Interface/i
104
+ interface_index = index
105
+ end
106
+ end
107
+
108
+ # remove the initial header consisting of Destination, Gateway, Mask, ... since this is of no use
109
+ raw_route_info.shift
110
+
111
+ # check the indices are assigned with some index and not -1
112
+ if destination_index != -1 && gateway_index != -1 && interface_index != -1
113
+ # iterate through the route_info; and find destination, gateway and interface from each row
114
+ raw_route_info.each do |info|
115
+ # if value exists at the destination_index, gateway_index, and interface_index; store the value in @routing_info
116
+ if !info[destination_index].nil? && !info[gateway_index].nil? && !info[interface_index].nil?
117
+ # if the destination_key is already present, append the gateway & interface; else create new array and add them
118
+ if @routing_info.key?(info[destination_index])
119
+ @routing_info[info[destination_index]] << [info[gateway_index], info[interface_index]]
120
+ else
121
+ @routing_info[info[destination_index]] = [[info[gateway_index], info[interface_index]]]
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ # check if netstat is available on the system
129
+ def find_netstat_or_error
130
+ %w{/usr/sbin/netstat /sbin/netstat /usr/bin/netstat /bin/netstat netstat}.each do |cmd|
131
+ return cmd if inspec.command(cmd).exist?
132
+ end
133
+
134
+ raise Inspec::Exceptions::ResourceFailed, "Could not find `netstat` utility to view routing table information"
135
+ end
136
+ end
137
+ end
@@ -537,9 +537,22 @@ module Inspec::Resources
537
537
  end
538
538
 
539
539
  def info(service_name)
540
+ # `service -l` lists all files in /etc/rc.d and the local startup directories
541
+ # % service -l
542
+ # accounting
543
+ # addswap
544
+ # adjkerntz
545
+ # apm
546
+ # archdep
547
+ cmd = inspec.command("#{service_ctl} -l")
548
+ return nil if cmd.exit_status != 0
549
+
550
+ # search for the service
551
+ srv = /^#{service_name}$/.match(cmd.stdout)
552
+ return nil if srv.nil? || srv[0].nil?
553
+
540
554
  # check if service is enabled
541
555
  cmd = inspec.command("#{service_ctl} #{service_name} enabled")
542
-
543
556
  enabled = cmd.exit_status == 0
544
557
 
545
558
  # check if the service is running
@@ -1 +1,13 @@
1
1
  require "inspec/resources/users"
2
+ # user resource belong_to matcher for serverspec compatibility
3
+ RSpec::Matchers.define :belong_to_primary_group do |group|
4
+ match do |user|
5
+ user.belongs_to_primary_group?(group)
6
+ end
7
+ end
8
+
9
+ RSpec::Matchers.define :belong_to_group do |group|
10
+ match do |user|
11
+ user.belongs_to_group?(group)
12
+ end
13
+ end
@@ -137,20 +137,17 @@ module Inspec::Resources
137
137
  # its('badpasswordattempts') { should eq 0 }
138
138
  # end
139
139
  #
140
- # The following Serverspec matchers are deprecated in favor for direct value access
140
+ # The following Serverspec matchers were deprecated in favor for direct value access
141
+ # but are made available as part of Serverspec compatibility in March, 2022.
141
142
  #
142
143
  # describe user('root') do
143
144
  # it { should belong_to_group 'root' }
145
+ # it { should belong_to_primary_group 'root' }
144
146
  # it { should have_uid 0 }
145
147
  # it { should have_home_directory '/root' }
146
148
  # it { should have_login_shell '/bin/bash' }
147
149
  # its('minimum_days_between_password_change') { should eq 0 }
148
150
  # its('maximum_days_between_password_change') { should eq 99 }
149
- # end
150
- #
151
- # ServerSpec tests that are not supported:
152
- #
153
- # describe user('root') do
154
151
  # it { should have_authorized_key 'ssh-rsa ADg54...3434 user@example.local' }
155
152
  # its(:encrypted_password) { should eq 1234 }
156
153
  # end
@@ -258,36 +255,56 @@ module Inspec::Resources
258
255
 
259
256
  # implement 'mindays' method to be compatible with serverspec
260
257
  def minimum_days_between_password_change
261
- Inspec.deprecate(:resource_user_serverspec_compat, "The user resource `minimum_days_between_password_change` property is deprecated. Please use `mindays`.")
262
258
  mindays
263
259
  end
264
260
 
265
261
  # implement 'maxdays' method to be compatible with serverspec
266
262
  def maximum_days_between_password_change
267
- Inspec.deprecate(:resource_user_serverspec_compat, "The user resource `maximum_days_between_password_change` property is deprecated. Please use `maxdays`.")
268
263
  maxdays
269
264
  end
270
265
 
271
266
  # implements rspec has matcher, to be compatible with serverspec
272
267
  # @see: https://github.com/rspec/rspec-expectations/blob/master/lib/rspec/matchers/built_in/has.rb
268
+ # has_uid matcher: compatibility with serverspec
273
269
  def has_uid?(compare_uid)
274
- Inspec.deprecate(:resource_user_serverspec_compat, "The user resource `has_uid?` matcher is deprecated.")
275
270
  uid == compare_uid
276
271
  end
277
272
 
273
+ # has_home_directory matcher: compatibility with serverspec
278
274
  def has_home_directory?(compare_home)
279
- Inspec.deprecate(:resource_user_serverspec_compat, "The user resource `has_home_directory?` matcher is deprecated. Please use `its('home')`.")
280
275
  home == compare_home
281
276
  end
282
277
 
278
+ # has_login_shell matcher: compatibility with serverspec
283
279
  def has_login_shell?(compare_shell)
284
- Inspec.deprecate(:resource_user_serverspec_compat, "The user resource `has_login_shell?` matcher is deprecated. Please use `its('shell')`.")
285
280
  shell == compare_shell
286
281
  end
287
282
 
288
- def has_authorized_key?(_compare_key)
289
- Inspec.deprecate(:resource_user_serverspec_compat, "The user resource `has_authorized_key?` matcher is deprecated. There is no currently implemented alternative")
290
- raise NotImplementedError
283
+ # has_authorized_key matcher: compatibility with serverspec
284
+ def has_authorized_key?(compare_key)
285
+ # get_authorized_keys returns the list of key, check if given key is included.
286
+ get_authorized_keys.include?(compare_key)
287
+ end
288
+
289
+ # belongs_to_primary_group matcher: compatibility with serverspec
290
+ def belongs_to_primary_group?(group_name)
291
+ groupname == group_name
292
+ end
293
+
294
+ # belongs_to_group matcher: compatibility with serverspec
295
+ def belongs_to_group?(group_name)
296
+ groups.include?(group_name)
297
+ end
298
+
299
+ # encrypted_password property: compatibility with serverspec
300
+ # it allows to run test against the hashed passwords of the given user
301
+ # applicable for unix/linux systems with getent utility.
302
+ def encrypted_password
303
+ raise Inspec::Exceptions::ResourceSkipped, "encrypted_password property is not applicable for your system" if inspec.os.windows? || inspec.os.darwin?
304
+
305
+ # shadow_information returns array of the information from the shadow file
306
+ # the value at 1st index is the encrypted_password information
307
+ shadow_information[1]
291
308
  end
292
309
 
293
310
  def to_s
@@ -314,6 +331,54 @@ module Inspec::Resources
314
331
 
315
332
  @cred_cache = @user_provider.credentials(@username) unless @user_provider.nil?
316
333
  end
334
+
335
+ # helper method for has_authorized_key matcher
336
+ # get_authorized_keys return the key/keys stored in the authorized_keys path
337
+ def get_authorized_keys
338
+ # cat is used in unix system to display content of file; similarly type is used for windows
339
+ bin = inspec.os.windows? ? "type" : "cat"
340
+
341
+ # auth_path gets assigned with the valid path for authorized_keys
342
+ auth_path = ""
343
+
344
+ # possible paths where authorized_keys are stored
345
+ # inspec.command is used over inspec.file because inspec.file requires absolute path
346
+ %w{~/.ssh/authorized_keys ~/.ssh/authorized_keys2}.each do |path|
347
+ if inspec.command("#{bin} #{path}").exit_status == 0
348
+ auth_path = path
349
+ break
350
+ end
351
+ end
352
+
353
+ # if auth_path is empty, no valid path was found, hence raise exception
354
+ raise Inspec::Exceptions::ResourceSkipped, "Can't find any valid path for authorized_keys" if auth_path.empty?
355
+
356
+ # authorized_keys are obtained in the standard output;
357
+ # split keys on newline if more than one keys are part of authorized_keys
358
+ inspec.command("#{bin} #{auth_path}").stdout.split("\n").map(&:strip)
359
+ end
360
+
361
+ # Helper method for encrypted_password property
362
+ def shadow_information
363
+ # check if getent is available on the system
364
+ bin = find_getent_utility
365
+
366
+ # fetch details of the passwd file for the current user using getent
367
+ cmd = inspec.command("#{bin} shadow #{@username}")
368
+ raise Inspec::Exceptions::ResourceFailed, "Executing #{bin} shadow #{@username} failed: #{cmd.stderr}" if cmd.exit_status.to_i != 0
369
+
370
+ # shadow information are : separated values, split and return
371
+ cmd.stdout.split(":").map(&:strip)
372
+ end
373
+
374
+ # check if getent exist in the system
375
+ def find_getent_utility
376
+ %w{/usr/bin/getent /bin/getent getent}.each do |cmd|
377
+ return cmd if inspec.command(cmd).exist?
378
+ end
379
+
380
+ raise Inspec::Exceptions::ResourceFailed, "Could not find `getent` on your system."
381
+ end
317
382
  end
318
383
 
319
384
  # Class defined to compare for groups without case-sensitivity
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "5.10.5".freeze
2
+ VERSION = "5.12.2".freeze
3
3
  end
@@ -41,9 +41,9 @@ module InspecPlugins::StreamingReporterProgressBar
41
41
  # Groovy UTF-8 characters for everyone else...
42
42
  # ...even though they probably only work on Mac
43
43
  INDICATORS = {
44
- "failed" => "×",
45
- "skipped" => "↺",
46
- "passed" => "✔",
44
+ "failed" => "× [FAILED] ",
45
+ "skipped" => "↺ [SKIPPED]",
46
+ "passed" => "✔ [PASSED] ",
47
47
  }.freeze
48
48
  end
49
49
 
@@ -54,58 +54,69 @@ module InspecPlugins::StreamingReporterProgressBar
54
54
  end
55
55
 
56
56
  def example_passed(notification)
57
- control_id = notification.example.metadata[:id]
58
- set_status_mapping(control_id, "passed")
59
- show_progress(control_id) if control_ended?(control_id)
57
+ set_example(notification, "passed")
60
58
  end
61
59
 
62
60
  def example_failed(notification)
63
- control_id = notification.example.metadata[:id]
64
- set_status_mapping(control_id, "failed")
65
- show_progress(control_id) if control_ended?(control_id)
61
+ set_example(notification, "failed")
66
62
  end
67
63
 
68
64
  def example_pending(notification)
69
- control_id = notification.example.metadata[:id]
70
- set_status_mapping(control_id, "skipped")
71
- show_progress(control_id) if control_ended?(control_id)
65
+ set_example(notification, "skipped")
72
66
  end
73
67
 
74
68
  private
75
69
 
76
- def show_progress(control_id)
70
+ def set_example(notification, status)
71
+ control_id = notification.example.metadata[:id]
72
+ title = notification.example.metadata[:title]
73
+ full_description = notification.example.metadata[:full_description]
74
+ control_impact = notification.example.metadata[:impact]
75
+ set_status_mapping(control_id, status)
76
+ show_progress(control_id, title, full_description, control_impact) if control_ended?(control_id)
77
+ end
78
+
79
+ def show_progress(control_id, title, full_description, control_impact)
77
80
  @bar ||= ProgressBar.new(controls_count, :bar, :counter, :percentage)
78
81
  sleep 0.1
79
82
  @bar.increment!
80
- @bar.puts format_it(control_id)
81
- rescue Exception => ex
82
- raise "Exception in Progress Bar streaming reporter: #{ex}"
83
+ @bar.puts format_it(control_id, title, full_description, control_impact)
84
+ rescue StandardError => e
85
+ raise "Exception in Progress Bar streaming reporter: #{e}"
83
86
  end
84
87
 
85
- def format_it(control_id)
88
+ def format_it(control_id, title, full_description, control_impact)
86
89
  control_status = if @status_mapping[control_id].include? "failed"
87
90
  "failed"
88
- elsif @status_mapping[control_id].include? "skipped"
89
- "skipped"
90
91
  elsif @status_mapping[control_id].include? "passed"
91
92
  "passed"
93
+ else
94
+ @status_mapping[control_id].include? "skipped"
95
+ "skipped"
92
96
  end
93
-
94
97
  indicator = INDICATORS[control_status]
95
98
  message_to_format = ""
96
99
  message_to_format += "#{indicator} "
97
- message_to_format += control_id.to_s.lstrip.force_encoding(Encoding::UTF_8)
100
+ message_to_format += "#{control_id.to_s.strip.dup.force_encoding(Encoding::UTF_8)} "
101
+ message_to_format += "#{title.gsub(/\n*\s+/, " ").to_s.force_encoding(Encoding::UTF_8)} " if title
102
+ message_to_format += "#{full_description.gsub(/\n*\s+/, " ").to_s.force_encoding(Encoding::UTF_8)} " unless title
98
103
  format_with_color(control_status, message_to_format)
104
+ rescue Exception => e
105
+ raise "Exception in show_progress: #{e}"
99
106
  end
100
107
 
101
108
  def format_with_color(color_name, text)
102
109
  "#{COLORS[color_name]}#{text}#{COLORS["reset"]}"
110
+ rescue StandardError => e
111
+ raise "Exception in format_with_color: #{e}"
103
112
  end
104
113
 
105
114
  # status mapping with control id to decide the final state of the control
106
115
  def set_status_mapping(control_id, status)
107
116
  @status_mapping[control_id] = [] if @status_mapping[control_id].nil?
108
117
  @status_mapping[control_id].push(status)
118
+ rescue StandardError => e
119
+ raise "Exception in format_with_color: #{e}"
109
120
  end
110
121
 
111
122
  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.10.5
4
+ version: 5.12.2
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-03-23 00:00:00.000000000 Z
11
+ date: 2022-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-telemetry
@@ -569,6 +569,7 @@ files:
569
569
  - lib/inspec/resources/linux_kernel_parameter.rb
570
570
  - lib/inspec/resources/login_defs.rb
571
571
  - lib/inspec/resources/lxc.rb
572
+ - lib/inspec/resources/mail_alias.rb
572
573
  - lib/inspec/resources/mongodb.rb
573
574
  - lib/inspec/resources/mongodb_conf.rb
574
575
  - lib/inspec/resources/mongodb_session.rb
@@ -613,6 +614,7 @@ files:
613
614
  - lib/inspec/resources/rabbitmq_conf.rb
614
615
  - lib/inspec/resources/rabbitmq_config.rb
615
616
  - lib/inspec/resources/registry_key.rb
617
+ - lib/inspec/resources/routing_table.rb
616
618
  - lib/inspec/resources/runit_service.rb
617
619
  - lib/inspec/resources/script.rb
618
620
  - lib/inspec/resources/security_identifier.rb