inspec-core 4.50.3 → 4.52.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/lib/bundles/inspec-supermarket/README.md +21 -2
- data/lib/bundles/inspec-supermarket/cli.rb +20 -3
- data/lib/bundles/inspec-supermarket/target.rb +3 -2
- data/lib/inspec/base_cli.rb +8 -0
- data/lib/inspec/plugin/v1/registry.rb +1 -1
- data/lib/inspec/resources/auditd.rb +5 -4
- data/lib/inspec/resources/http.rb +31 -2
- data/lib/inspec/resources/ibmdb2_session.rb +2 -2
- data/lib/inspec/resources/oracledb_session.rb +3 -1
- data/lib/inspec/resources/packages.rb +21 -0
- data/lib/inspec/resources/service.rb +58 -9
- data/lib/inspec/resources/ssl.rb +7 -0
- data/lib/inspec/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5fc9c31a9983866ff40fb11326a3c2bac04342e1d473b845e81639bbca88a8c
|
4
|
+
data.tar.gz: 6fd55b54b5c1510572fa963d2d4833a8f3132ae5cbfb1871a4662f8b3da720d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9f356b30301430dbeeeb599b696aacfc4ec1caaadafd61e6af40462db60fa400cd2bf4add6a682fe379c65ed4adb0f926a858e6b072066f06296821725f7f92
|
7
|
+
data.tar.gz: 25381065952aa3d460cedd9c56a5b389625b2ed11841f2085047e81444c3aa1d788338468c640f5c27403b4074a5649b825a3289e0b63cdc96d70e8450cc664c
|
data/Gemfile
CHANGED
@@ -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:
|
12
|
-
|
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
|
-
|
20
|
-
|
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 =
|
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,
|
14
|
+
[target, supermarket_url]
|
14
15
|
elsif target.respond_to?(:key?) && target.key?(:supermarket)
|
15
|
-
supermarket_server = target[: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
|
data/lib/inspec/base_cli.rb
CHANGED
@@ -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,
|
@@ -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
|
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)
|
@@ -28,12 +28,13 @@ module Inspec::Resources
|
|
28
28
|
EXAMPLE
|
29
29
|
|
30
30
|
def initialize
|
31
|
-
|
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
|
34
|
+
"Command `#{@auditctl_cmd_str}` does not exist"
|
34
35
|
end
|
35
36
|
|
36
|
-
auditctl_cmd = "
|
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("
|
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/
|
@@ -121,6 +121,10 @@ module Inspec::Resources
|
|
121
121
|
def max_redirects
|
122
122
|
opts.fetch(:max_redirects, nil)
|
123
123
|
end
|
124
|
+
|
125
|
+
def proxy
|
126
|
+
opts.fetch(:proxy, nil)
|
127
|
+
end
|
124
128
|
end
|
125
129
|
|
126
130
|
class Local < Base
|
@@ -141,12 +145,18 @@ module Inspec::Resources
|
|
141
145
|
def response
|
142
146
|
return @response if @response
|
143
147
|
|
148
|
+
Faraday.ignore_env_proxy = true if proxy == "disable"
|
149
|
+
|
144
150
|
conn = Faraday.new(url: url, headers: request_headers, params: params, ssl: { verify: ssl_verify? }) do |builder|
|
145
151
|
builder.request :url_encoded
|
146
152
|
builder.use FaradayMiddleware::FollowRedirects, limit: max_redirects unless max_redirects.nil?
|
147
153
|
builder.adapter Faraday.default_adapter
|
148
154
|
end
|
149
155
|
|
156
|
+
unless proxy == "disable" || proxy.nil?
|
157
|
+
conn.proxy = proxy
|
158
|
+
end
|
159
|
+
|
150
160
|
# set basic authentication
|
151
161
|
conn.basic_auth username, password unless username.nil? || password.nil?
|
152
162
|
|
@@ -252,6 +262,14 @@ module Inspec::Resources
|
|
252
262
|
cmd << "-X #{http_method}"
|
253
263
|
end
|
254
264
|
|
265
|
+
cmd << "--noproxy '*'" if proxy == "disable"
|
266
|
+
unless proxy == "disable" || proxy.nil?
|
267
|
+
if proxy.is_a?(Hash)
|
268
|
+
cmd << "--proxy #{proxy[:uri]} --proxy-user #{proxy[:user]}:#{proxy[:password]}"
|
269
|
+
else
|
270
|
+
cmd << "--proxy #{proxy}"
|
271
|
+
end
|
272
|
+
end
|
255
273
|
cmd << "--connect-timeout #{open_timeout}"
|
256
274
|
cmd << "--max-time #{open_timeout + read_timeout}"
|
257
275
|
cmd << "--user \'#{username}:#{password}\'" unless username.nil? || password.nil?
|
@@ -292,6 +310,17 @@ module Inspec::Resources
|
|
292
310
|
else
|
293
311
|
cmd << "'#{url}?#{params.map { |e| e.join("=") }.join("&")}'"
|
294
312
|
end
|
313
|
+
|
314
|
+
proxy_script = ""
|
315
|
+
unless proxy == "disable" || proxy.nil?
|
316
|
+
cmd << "-Proxy #{proxy[:uri]}"
|
317
|
+
cmd << "-ProxyCredential $proxyCreds"
|
318
|
+
proxy_script = <<-EOH
|
319
|
+
$secPasswd = ConvertTo-SecureString "#{proxy[:password]}" -AsPlainText -Force
|
320
|
+
$proxyCreds = New-Object System.Management.Automation.PSCredential -ArgumentList "#{proxy[:user]}",$secPasswd
|
321
|
+
EOH
|
322
|
+
end
|
323
|
+
|
295
324
|
command = cmd.join(" ")
|
296
325
|
body = "\'#{request_body}\'"
|
297
326
|
script = <<-EOH
|
@@ -302,10 +331,10 @@ module Inspec::Resources
|
|
302
331
|
foreach ($property in $Body.PSObject.Properties) {
|
303
332
|
$HashTable[$property.Name] = $property.Value
|
304
333
|
}
|
305
|
-
$response = #{command} -Body $HashTable
|
334
|
+
$response = #{command} -Body $HashTable -UseBasicParsing
|
306
335
|
$response | Select-Object -Property * | ConvertTo-json # We use `Select-Object -Property * ` to get around an odd PowerShell error
|
307
336
|
EOH
|
308
|
-
script.strip
|
337
|
+
proxy_script.strip + "\n" + script.strip
|
309
338
|
end
|
310
339
|
end
|
311
340
|
end
|
@@ -46,12 +46,12 @@ module Inspec::Resources
|
|
46
46
|
|
47
47
|
# check if following specific error is there. Sourcing the db2profile to resolve the error.
|
48
48
|
if cmd.exit_status != 0 && out =~ /SQL10007N Message "-1390" could not be retrieved. Reason code: "3"/
|
49
|
-
cmd = inspec.command(". ~/sqllib/db2profile\; #{@db2_executable_file_path} attach to #{@db_instance}\; #{@db2_executable_file_path} connect to #{@db_name}\; #{@db2_executable_file_path} #{q}\;")
|
49
|
+
cmd = inspec.command(". ~/sqllib/db2profile\; #{@db2_executable_file_path} attach to #{@db_instance}\; #{@db2_executable_file_path} connect to #{@db_name}\; #{@db2_executable_file_path} \"#{q}\"\;")
|
50
50
|
out = cmd.stdout + "\n" + cmd.stderr
|
51
51
|
end
|
52
52
|
elsif inspec.os.platform?("windows")
|
53
53
|
# set-item command set the powershell to run the db2 commands.
|
54
|
-
cmd = inspec.command("set-item -path env:DB2CLP -value \"**$$**\"\; db2 connect to #{@db_name}\; db2 #{q}\;")
|
54
|
+
cmd = inspec.command("set-item -path env:DB2CLP -value \"**$$**\"\; db2 connect to #{@db_name}\; db2 \"#{q}\"\;")
|
55
55
|
out = cmd.stdout + "\n" + cmd.stderr
|
56
56
|
end
|
57
57
|
|
@@ -118,7 +118,9 @@ module Inspec::Resources
|
|
118
118
|
output = output.sub(/\r/, "").strip.gsub(",", "comma_query_sub")
|
119
119
|
converter = ->(header) { header.downcase }
|
120
120
|
CSV.parse(output, headers: true, header_converters: converter).map do |row|
|
121
|
-
|
121
|
+
next if row.entries.flatten.empty?
|
122
|
+
|
123
|
+
revised_row = row.entries.flatten.map { |entry| entry&.gsub("comma_query_sub", ",") }
|
122
124
|
Hashie::Mash.new([revised_row].to_h)
|
123
125
|
end
|
124
126
|
end
|
@@ -26,6 +26,8 @@ module Inspec::Resources
|
|
26
26
|
@pkgs = Debs.new(inspec)
|
27
27
|
elsif os.redhat? || %w{suse amazon fedora}.include?(os[:family])
|
28
28
|
@pkgs = Rpms.new(inspec)
|
29
|
+
elsif ["alpine"].include?(os[:name])
|
30
|
+
@pkgs = AlpinePkgs.new(inspec)
|
29
31
|
else
|
30
32
|
return skip_resource "The packages resource is not yet supported on OS #{inspec.os.name}"
|
31
33
|
end
|
@@ -108,4 +110,23 @@ module Inspec::Resources
|
|
108
110
|
end
|
109
111
|
end
|
110
112
|
end
|
113
|
+
|
114
|
+
# RedHat family
|
115
|
+
class AlpinePkgs < PkgsManagement
|
116
|
+
def build_package_list
|
117
|
+
command = "apk list --no-network --installed"
|
118
|
+
cmd = inspec.command(command)
|
119
|
+
all = cmd.stdout.split("\n")
|
120
|
+
return [] if all.nil? || cmd.exit_status.to_i != 0
|
121
|
+
|
122
|
+
all.map do |m|
|
123
|
+
next if m =~ /^WARNING/i
|
124
|
+
|
125
|
+
a = m.split(" ")
|
126
|
+
version = a[0].split("-")[-2]
|
127
|
+
name = a[2].gsub(/[{}^]*/, "")
|
128
|
+
PackageStruct.new("installed", name, version, a[1])
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
111
132
|
end
|
@@ -163,7 +163,12 @@ module Inspec::Resources
|
|
163
163
|
when "mac_os_x", "darwin"
|
164
164
|
LaunchCtl.new(inspec, service_ctl)
|
165
165
|
when "freebsd"
|
166
|
-
|
166
|
+
version = os[:release].to_f
|
167
|
+
if version < 10
|
168
|
+
BSDInit.new(inspec, service_ctl)
|
169
|
+
else
|
170
|
+
FreeBSD10Init.new(inspec, service_ctl)
|
171
|
+
end
|
167
172
|
when "arch"
|
168
173
|
Systemd.new(inspec, service_ctl)
|
169
174
|
when "coreos"
|
@@ -186,6 +191,8 @@ module Inspec::Resources
|
|
186
191
|
Svcs.new(inspec)
|
187
192
|
when "yocto"
|
188
193
|
Systemd.new(inspec, service_ctl)
|
194
|
+
when "alpine"
|
195
|
+
SysV.new(inspec, service_ctl)
|
189
196
|
end
|
190
197
|
end
|
191
198
|
|
@@ -478,6 +485,7 @@ module Inspec::Resources
|
|
478
485
|
|
479
486
|
# @see: https://www.freebsd.org/doc/en/articles/linux-users/startup.html
|
480
487
|
# @see: https://www.freebsd.org/cgi/man.cgi?query=rc.conf&sektion=5
|
488
|
+
# @see: https://www.freebsd.org/cgi/man.cgi?query=rc&apropos=0&sektion=8&manpath=FreeBSD+9.3-RELEASE&arch=default&format=html
|
481
489
|
class BSDInit < ServiceManager
|
482
490
|
def initialize(service_name, service_ctl = nil)
|
483
491
|
@service_ctl = service_ctl || "service"
|
@@ -485,17 +493,20 @@ module Inspec::Resources
|
|
485
493
|
end
|
486
494
|
|
487
495
|
def info(service_name)
|
488
|
-
#
|
489
|
-
#
|
490
|
-
#
|
491
|
-
#
|
492
|
-
#
|
493
|
-
#
|
496
|
+
# `service -e` lists all enabled services. Output format:
|
497
|
+
# % service -e
|
498
|
+
# /etc/rc.d/hostid
|
499
|
+
# /etc/rc.d/hostid_save
|
500
|
+
# /etc/rc.d/cleanvar
|
501
|
+
# /etc/rc.d/ip6addrctl
|
502
|
+
# /etc/rc.d/devd
|
503
|
+
|
494
504
|
cmd = inspec.command("#{service_ctl} -e")
|
495
505
|
return nil if cmd.exit_status != 0
|
496
506
|
|
497
507
|
# search for the service
|
498
|
-
|
508
|
+
|
509
|
+
srv = %r{^.*/(#{service_name}$)}.match(cmd.stdout)
|
499
510
|
return nil if srv.nil? || srv[0].nil?
|
500
511
|
|
501
512
|
enabled = true
|
@@ -516,6 +527,37 @@ module Inspec::Resources
|
|
516
527
|
end
|
517
528
|
end
|
518
529
|
|
530
|
+
# @see: https://www.freebsd.org/doc/en/articles/linux-users/startup.html
|
531
|
+
# @see: https://www.freebsd.org/cgi/man.cgi?query=rc.conf&sektion=5
|
532
|
+
# @see: https://www.freebsd.org/cgi/man.cgi?query=rc&apropos=0&sektion=8&manpath=FreeBSD+10.0-RELEASE&arch=default&format=html
|
533
|
+
class FreeBSD10Init < ServiceManager
|
534
|
+
def initialize(service_name, service_ctl = nil)
|
535
|
+
@service_ctl = service_ctl || "service"
|
536
|
+
super
|
537
|
+
end
|
538
|
+
|
539
|
+
def info(service_name)
|
540
|
+
# check if service is enabled
|
541
|
+
cmd = inspec.command("#{service_ctl} #{service_name} enabled")
|
542
|
+
|
543
|
+
enabled = cmd.exit_status == 0
|
544
|
+
|
545
|
+
# check if the service is running
|
546
|
+
# if the service is not available or not running, we always get an error code
|
547
|
+
cmd = inspec.command("#{service_ctl} #{service_name} onestatus")
|
548
|
+
running = cmd.exit_status == 0
|
549
|
+
|
550
|
+
{
|
551
|
+
name: service_name,
|
552
|
+
description: nil,
|
553
|
+
installed: true,
|
554
|
+
running: running,
|
555
|
+
enabled: enabled,
|
556
|
+
type: "bsd-init",
|
557
|
+
}
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
519
561
|
class Runit < ServiceManager
|
520
562
|
def initialize(service_name, service_ctl = nil)
|
521
563
|
@service_ctl = service_ctl || "sv"
|
@@ -782,7 +824,14 @@ module Inspec::Resources
|
|
782
824
|
EXAMPLE
|
783
825
|
|
784
826
|
def select_service_mgmt
|
785
|
-
|
827
|
+
os = inspec.os
|
828
|
+
version = os[:release].to_f
|
829
|
+
|
830
|
+
if version >= 10
|
831
|
+
FreeBSD10Init.new(inspec, service_ctl)
|
832
|
+
else
|
833
|
+
BSDInit.new(inspec, service_ctl)
|
834
|
+
end
|
786
835
|
end
|
787
836
|
end
|
788
837
|
|
data/lib/inspec/resources/ssl.rb
CHANGED
@@ -38,6 +38,7 @@ module Inspec::Resources
|
|
38
38
|
"tls1.0",
|
39
39
|
"tls1.1",
|
40
40
|
"tls1.2",
|
41
|
+
"tls1.3",
|
41
42
|
].freeze
|
42
43
|
|
43
44
|
attr_reader :host, :port, :timeout, :retries
|
@@ -72,6 +73,11 @@ module Inspec::Resources
|
|
72
73
|
protocol: proto, ciphers: e.map(&:cipher),
|
73
74
|
timeout: x.resource.timeout, retries: x.resource.retries, servername: x.resource.host)]
|
74
75
|
end
|
76
|
+
|
77
|
+
if !res[0].empty? && res[0][1].key?("error") && res[0][1]["error"].include?("Connection error Errno::ECONNREFUSED")
|
78
|
+
raise "#{res[0][1]["error"]}"
|
79
|
+
end
|
80
|
+
|
75
81
|
Hash[res]
|
76
82
|
end
|
77
83
|
.install_filter_methods_on_resource(self, :scan_config)
|
@@ -89,6 +95,7 @@ module Inspec::Resources
|
|
89
95
|
{ "protocol" => "tls1.0", "ciphers" => SSLShake::TLS::TLS10_CIPHERS.keys },
|
90
96
|
{ "protocol" => "tls1.1", "ciphers" => SSLShake::TLS::TLS10_CIPHERS.keys },
|
91
97
|
{ "protocol" => "tls1.2", "ciphers" => SSLShake::TLS::TLS_CIPHERS.keys },
|
98
|
+
{ "protocol" => "tls1.3", "ciphers" => SSLShake::TLS::TLS13_CIPHERS.keys },
|
92
99
|
].map do |line|
|
93
100
|
line["ciphers"].map do |cipher|
|
94
101
|
{ "protocol" => line["protocol"], "cipher" => cipher }
|
data/lib/inspec/version.rb
CHANGED
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: 4.
|
4
|
+
version: 4.52.9
|
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: 2021-
|
11
|
+
date: 2021-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-telemetry
|