inspec-core 5.7.9 → 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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/etc/deprecations.json +0 -5
  3. data/lib/inspec/cli.rb +2 -0
  4. data/lib/inspec/plugin/v2/installer.rb +9 -2
  5. data/lib/inspec/plugin/v2/loader.rb +13 -0
  6. data/lib/inspec/plugin/v2/status.rb +2 -1
  7. data/lib/inspec/profile.rb +7 -5
  8. data/lib/inspec/resources/apt.rb +12 -6
  9. data/lib/inspec/resources/cgroup.rb +101 -0
  10. data/lib/inspec/resources/default_gateway.rb +61 -0
  11. data/lib/inspec/resources/docker_container.rb +21 -0
  12. data/lib/inspec/resources/docker_image.rb +53 -0
  13. data/lib/inspec/resources/file.rb +91 -0
  14. data/lib/inspec/resources/groups.rb +5 -0
  15. data/lib/inspec/resources/linux_audit_system.rb +81 -0
  16. data/lib/inspec/resources/lxc.rb +57 -0
  17. data/lib/inspec/resources/mail_alias.rb +46 -0
  18. data/lib/inspec/resources/oracledb_session.rb +7 -3
  19. data/lib/inspec/resources/postgres_session.rb +4 -2
  20. data/lib/inspec/resources/routing_table.rb +137 -0
  21. data/lib/inspec/resources/service.rb +87 -1
  22. data/lib/inspec/resources/user.rb +12 -0
  23. data/lib/inspec/resources/users.rb +79 -14
  24. data/lib/inspec/resources/virtualization.rb +9 -3
  25. data/lib/inspec/ui.rb +9 -0
  26. data/lib/inspec/version.rb +1 -1
  27. data/lib/plugins/inspec-artifact/inspec-artifact.gemspec +9 -0
  28. data/lib/plugins/inspec-compliance/inspec-compliance.gemspec +9 -0
  29. data/lib/plugins/inspec-habitat/inspec-habitat.gemspec +9 -0
  30. data/lib/plugins/inspec-init/inspec-init.gemspec +9 -0
  31. data/lib/plugins/inspec-plugin-manager-cli/inspec-plugin-manager-cli.gemspec +10 -0
  32. data/lib/plugins/inspec-plugin-manager-cli/lib/inspec-plugin-manager-cli/cli_command.rb +15 -11
  33. data/lib/plugins/inspec-reporter-html2/inspec-reporter-html2.gemspec +9 -0
  34. data/lib/plugins/inspec-reporter-json-min/inspec-reporter-json-min.gemspec +9 -0
  35. data/lib/plugins/inspec-reporter-junit/inspec-reporter-junit.gemspec +9 -0
  36. data/lib/plugins/inspec-streaming-reporter-progress-bar/inspec-streaming-reporter-progress-bar.gemspec +9 -0
  37. data/lib/plugins/inspec-streaming-reporter-progress-bar/lib/inspec-streaming-reporter-progress-bar/streaming_reporter.rb +32 -21
  38. metadata +17 -2
@@ -0,0 +1,57 @@
1
+ require "inspec/resources/command"
2
+ module Inspec::Resources
3
+ class Lxc < Inspec.resource(1)
4
+ name "lxc"
5
+ # Restrict to only run on the below platforms
6
+ supports platform: "linux"
7
+ desc "Use the lxc InSpec audit resource to test if container exists and/or is running for linux container"
8
+ example <<~EXAMPLE
9
+ describe lxc("ubuntu-container") do
10
+ it { should exist }
11
+ it { should be_running }
12
+ end
13
+ EXAMPLE
14
+
15
+ # Resource initialization.
16
+ def initialize(container_name)
17
+ @container_name = container_name
18
+
19
+ raise Inspec::Exceptions::ResourceSkipped, "The `lxc` resource is not supported on your OS yet." unless inspec.os.linux?
20
+ end
21
+
22
+ def resource_id
23
+ @container_name
24
+ end
25
+
26
+ def to_s
27
+ "lxc #{resource_id}"
28
+ end
29
+
30
+ def exists?
31
+ lxc_info_cmd.exit_status.to_i == 0
32
+ end
33
+
34
+ def running?
35
+ container_info = lxc_info_cmd.stdout.split(":").map(&:strip)
36
+ container_info[0] == "Status" && container_info[1] == "Running"
37
+ end
38
+
39
+ private
40
+
41
+ # Method to find lxc
42
+ def find_lxc_or_error
43
+ %w{/usr/sbin/lxc /sbin/lxc lxc}.each do |cmd|
44
+ return cmd if inspec.command(cmd).exist?
45
+ end
46
+
47
+ raise Inspec::Exceptions::ResourceFailed, "Could not find `lxc`"
48
+ end
49
+
50
+ def lxc_info_cmd
51
+ bin = find_lxc_or_error
52
+ info_cmd = "info #{@container_name} | grep -i Status"
53
+ lxc_cmd = format("%s %s", bin, info_cmd).strip
54
+ inspec.command(lxc_cmd)
55
+ end
56
+ end
57
+ 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
@@ -61,9 +61,13 @@ module Inspec::Resources
61
61
  raise Inspec::Exceptions::ResourceFailed, "Oracle query with errors: #{out}"
62
62
  else
63
63
  begin
64
- DatabaseHelper::SQLQueryResult.new(inspec_cmd, parse_csv_result(inspec_cmd.stdout))
65
- rescue
66
- raise Inspec::Exceptions::ResourceFailed, "Oracle query with errors: #{out}"
64
+ unless inspec_cmd.stdout.empty?
65
+ DatabaseHelper::SQLQueryResult.new(inspec_cmd, parse_csv_result(inspec_cmd.stdout))
66
+ else
67
+ inspec_cmd.stdout
68
+ end
69
+ rescue Exception => ex
70
+ raise Inspec::Exceptions::ResourceFailed, "Oracle query with exception: #{ex}"
67
71
  end
68
72
  end
69
73
  end
@@ -55,8 +55,10 @@ module Inspec::Resources
55
55
  psql_cmd = create_psql_cmd(query, db)
56
56
  cmd = inspec.command(psql_cmd, redact_regex: %r{(:\/\/[a-z]*:).*(@)})
57
57
  out = cmd.stdout + "\n" + cmd.stderr
58
- if cmd.exit_status != 0 || out =~ /could not connect to .*/ || out.downcase =~ /^error:.*/
59
- raise Inspec::Exceptions::ResourceFailed, "PostgreSQL query with errors: #{out}"
58
+ if cmd.exit_status != 0 && ( out =~ /could not connect to/ || out =~ /password authentication failed/ ) && out.downcase =~ /error:/
59
+ raise Inspec::Exceptions::ResourceFailed, "PostgreSQL connection error: #{out}"
60
+ elsif cmd.exit_status != 0 && out.downcase =~ /error:/
61
+ Lines.new(out, "PostgreSQL query with error: #{query}")
60
62
  else
61
63
  Lines.new(cmd.stdout.strip, "PostgreSQL query: #{query}")
62
64
  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
@@ -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
@@ -537,9 +561,22 @@ module Inspec::Resources
537
561
  end
538
562
 
539
563
  def info(service_name)
564
+ # `service -l` lists all files in /etc/rc.d and the local startup directories
565
+ # % service -l
566
+ # accounting
567
+ # addswap
568
+ # adjkerntz
569
+ # apm
570
+ # archdep
571
+ cmd = inspec.command("#{service_ctl} -l")
572
+ return nil if cmd.exit_status != 0
573
+
574
+ # search for the service
575
+ srv = /^#{service_name}$/.match(cmd.stdout)
576
+ return nil if srv.nil? || srv[0].nil?
577
+
540
578
  # check if service is enabled
541
579
  cmd = inspec.command("#{service_ctl} #{service_name} enabled")
542
-
543
580
  enabled = cmd.exit_status == 0
544
581
 
545
582
  # check if the service is running
@@ -880,4 +917,53 @@ module Inspec::Resources
880
917
  Runit.new(inspec, service_ctl)
881
918
  end
882
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
883
969
  end
@@ -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
@@ -190,7 +190,7 @@ module Inspec::Resources
190
190
  true
191
191
  end
192
192
 
193
- # Detect LXC/Docker
193
+ # Detect LXC/Docker/k8s/podman
194
194
  #
195
195
  # /proc/self/cgroup will look like this inside a docker container:
196
196
  # <index #>:<subsystem>:/lxc/<hexadecimal container id>
@@ -208,7 +208,7 @@ module Inspec::Resources
208
208
  #
209
209
  # Full notes, https://tickets.opscode.com/browse/OHAI-551
210
210
  # Kernel docs, https://www.kernel.org/doc/Documentation/cgroups
211
- def detect_lxc_docker
211
+ def detect_container
212
212
  return false unless inspec.file("/proc/self/cgroup").exist?
213
213
 
214
214
  cgroup_content = inspec.file("/proc/self/cgroup").content
@@ -216,6 +216,12 @@ module Inspec::Resources
216
216
  cgroup_content =~ %r{^\d+:[^:]+:/[^/]+/(lxc|docker)-.+$} # rubocop:disable Layout/MultilineOperationIndentation
217
217
  @virtualization_data[:system] = $1 # rubocop:disable Style/PerlBackrefs
218
218
  @virtualization_data[:role] = "guest"
219
+ elsif cgroup_content =~ %r{^\d+:[^:]+:/(kubepods)/.+$}
220
+ @virtualization_data[:system] = $1
221
+ @virtualization_data[:role] = "guest"
222
+ elsif /container=podman/.match?(file_read("/proc/1/environ"))
223
+ @virtualization_data[:system] = "podman"
224
+ @virtualization_data[:role] = "guest"
219
225
  elsif lxc_version_exists? && cgroup_content =~ %r{\d:[^:]+:/$}
220
226
  # lxc-version shouldn't be installed by default
221
227
  # Even so, it is likely we are on an LXC capable host that is not being used as such
@@ -297,7 +303,7 @@ module Inspec::Resources
297
303
  return if detect_docker
298
304
  return if detect_virtualbox
299
305
  return if detect_lxd
300
- return if detect_lxc_docker
306
+ return if detect_container
301
307
  return if detect_linux_vserver
302
308
  return if detect_kvm_from_cpuinfo
303
309
  return if detect_kvm_from_sys
data/lib/inspec/ui.rb CHANGED
@@ -140,6 +140,15 @@ module Inspec
140
140
  print_or_return(result, opts[:print])
141
141
  end
142
142
 
143
+ def line_with_width(width = 80, opts = { print: true } )
144
+ if color?
145
+ result = ANSI_CODES[:bold] + GLYPHS[:heavy_dash] * width + ANSI_CODES[:reset] + "\n"
146
+ else
147
+ result = "-" * width + "\n"
148
+ end
149
+ print_or_return(result, opts[:print])
150
+ end
151
+
143
152
  # Makes a bullet point.
144
153
  def list_item(str, opts = { print: true })
145
154
  bullet = color? ? ANSI_CODES[:bold] + ANSI_CODES[:color][:white] + GLYPHS[:bullet] + ANSI_CODES[:reset] : "*"
@@ -1,3 +1,3 @@
1
1
  module Inspec
2
- VERSION = "5.7.9".freeze
2
+ VERSION = "5.14.0".freeze
3
3
  end
@@ -0,0 +1,9 @@
1
+ # .gemspec file is added to add plugin details
2
+ # These specs are used in plugin list and search command
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "inspec-artifact"
6
+ spec.summary = ""
7
+ spec.description = "Plugin to generate asymmetrical keys that you can use to encrypt profiles"
8
+ spec.license = "Apache-2.0"
9
+ end
@@ -0,0 +1,9 @@
1
+ # .gemspec file is added to add plugin details
2
+ # These specs are used in plugin list and search command
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "inspec-compliance"
6
+ spec.summary = "Plugin to perform operations with Chef Automate"
7
+ spec.description = "This extensions will allow you to interact with Chef Automate"
8
+ spec.license = "Apache-2.0"
9
+ end
@@ -0,0 +1,9 @@
1
+ # .gemspec file is added to add plugin details
2
+ # These specs are used in plugin list and search command
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "inspec-habitat"
6
+ spec.summary = "Plugin to create/upload habitat package"
7
+ spec.description = "This extensions will allow you to create/upload habitat package from an inspec profile."
8
+ spec.license = "Apache-2.0"
9
+ end
@@ -0,0 +1,9 @@
1
+ # .gemspec file is added to add plugin details
2
+ # These specs are used in plugin list and search command
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "inspec-init"
6
+ spec.summary = "Plugin for scaffolding profile, plugin or a resource"
7
+ spec.description = "This extensions helps you to easily create a new profile, plugin or a resource."
8
+ spec.license = "Apache-2.0"
9
+ end
@@ -0,0 +1,10 @@
1
+ # .gemspec file is added to add plugin details
2
+ # These specs are used in plugin list and search command
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "inspec-plugin-manager-cli"
6
+ spec.summary = "CLI plugin for InSpec"
7
+ spec.description = "This is a CLI plugin for InSpec. It uses the Plugins API v2 to create a
8
+ series of commands to manage plugins."
9
+ spec.license = "Apache-2.0"
10
+ end