inspec-core 5.22.3 → 5.22.36
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +6 -19
- data/inspec-core.gemspec +6 -4
- data/lib/inspec/cli.rb +22 -5
- data/lib/inspec/config.rb +32 -10
- data/lib/inspec/fetcher/git.rb +43 -28
- data/lib/inspec/formatters/base.rb +1 -1
- data/lib/inspec/profile.rb +340 -18
- data/lib/inspec/resources/host.rb +4 -16
- data/lib/inspec/resources/security_policy.rb +7 -2
- data/lib/inspec/rule.rb +5 -0
- data/lib/inspec/utils/profile_ast_helpers.rb +372 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/inspec/waiver_file_reader.rb +5 -3
- data/lib/plugins/inspec-compliance/lib/inspec-compliance/cli.rb +2 -2
- data/lib/plugins/inspec-reporter-html2/templates/control.html.erb +7 -6
- data/lib/plugins/inspec-reporter-html2/templates/default.js +6 -6
- metadata +11 -10
@@ -0,0 +1,372 @@
|
|
1
|
+
require "ast"
|
2
|
+
require "rubocop-ast"
|
3
|
+
module Inspec
|
4
|
+
class Profile
|
5
|
+
class AstHelper
|
6
|
+
class CollectorBase
|
7
|
+
include Parser::AST::Processor::Mixin
|
8
|
+
include RuboCop::AST::Traversal
|
9
|
+
|
10
|
+
attr_reader :memo
|
11
|
+
def initialize(memo)
|
12
|
+
@memo = memo
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class InputCollectorBase < CollectorBase
|
17
|
+
VALID_INPUT_OPTIONS = %i{name value type required priority pattern profile sensitive}.freeze
|
18
|
+
|
19
|
+
REQUIRED_VALUES_MAP = {
|
20
|
+
true: true,
|
21
|
+
false: false,
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
def initialize(memo)
|
25
|
+
@memo = memo
|
26
|
+
end
|
27
|
+
|
28
|
+
def collect_input(input_children)
|
29
|
+
input_name = input_children.children[2].value
|
30
|
+
|
31
|
+
# Check if memo[:inputs] already has a value for the input_name, if yes, then skip adding it to the array
|
32
|
+
unless memo[:inputs].any? { |input| input[:name] == input_name }
|
33
|
+
# The value will be updated if available in the input_children
|
34
|
+
opts = {
|
35
|
+
value: "Input '#{input_name}' does not have a value. Skipping test.",
|
36
|
+
}
|
37
|
+
|
38
|
+
if input_children.children[3]&.type == :hash
|
39
|
+
input_children.children[3].children.each do |child_node|
|
40
|
+
if VALID_INPUT_OPTIONS.include?(child_node.key.value)
|
41
|
+
if child_node.value.class == RuboCop::AST::Node && REQUIRED_VALUES_MAP.key?(child_node.value.type)
|
42
|
+
opts.merge!(child_node.key.value => REQUIRED_VALUES_MAP[child_node.value.type])
|
43
|
+
elsif child_node.value.class == RuboCop::AST::HashNode
|
44
|
+
# Here value will be a hash
|
45
|
+
values = {}
|
46
|
+
child_node.value.children.each do |grand_child_node|
|
47
|
+
values.merge!(grand_child_node.key.value => grand_child_node.value.value)
|
48
|
+
end
|
49
|
+
opts.merge!(child_node.key.value => values)
|
50
|
+
else
|
51
|
+
opts.merge!(child_node.key.value => child_node.value.value)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# TODO: Add rules for handling the input options or use existing rules if available
|
58
|
+
# 1. Handle pattern matching for the given input value
|
59
|
+
# 2. Handle data-type matching for the given input value
|
60
|
+
# 3. Handle required flag for the given input value
|
61
|
+
# 4. Handle sensitive flag for the given input value
|
62
|
+
memo[:inputs] ||= []
|
63
|
+
input_hash = {
|
64
|
+
name: input_name,
|
65
|
+
options: opts,
|
66
|
+
}
|
67
|
+
memo[:inputs] << input_hash
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def check_and_collect_input(node)
|
72
|
+
if input_pattern_match?(node)
|
73
|
+
collect_input(node)
|
74
|
+
else
|
75
|
+
node.children.each do |child_node|
|
76
|
+
check_and_collect_input(child_node) if input_pattern_match?(child_node)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def input_pattern_match?(node)
|
82
|
+
RuboCop::AST::NodePattern.new("(send nil? :input ...)").match(node)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class ImpactCollector < CollectorBase
|
87
|
+
def on_send(node)
|
88
|
+
if RuboCop::AST::NodePattern.new("(send nil? :impact ...)").match(node)
|
89
|
+
memo[:impact] = node.children[2].value
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class DescCollector < CollectorBase
|
95
|
+
def on_send(node)
|
96
|
+
if RuboCop::AST::NodePattern.new("(send nil? :desc ...)").match(node)
|
97
|
+
memo[:descriptions] ||= {}
|
98
|
+
if node.children[2] && node.children[3]
|
99
|
+
# NOTE: This assumes the description is as below
|
100
|
+
# desc 'label', 'An optional description with a label' # Pair a part of the description with a label
|
101
|
+
memo[:descriptions] = memo[:descriptions].merge(node.children[2].value => node.children[3].value)
|
102
|
+
else
|
103
|
+
memo[:desc] = node.children[2].value
|
104
|
+
memo[:descriptions] = memo[:descriptions].merge(default: node.children[2].value)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class TitleCollector < CollectorBase
|
111
|
+
def on_send(node)
|
112
|
+
if RuboCop::AST::NodePattern.new("(send nil? :title ...)").match(node)
|
113
|
+
# TODO - title may not be a simple string
|
114
|
+
memo[:title] = node.children[2].value
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class TagCollector < CollectorBase
|
120
|
+
|
121
|
+
ACCPETABLE_TAG_TYPE_TO_VALUES = {
|
122
|
+
false: false,
|
123
|
+
true: true,
|
124
|
+
nil: nil,
|
125
|
+
}.freeze
|
126
|
+
|
127
|
+
def on_send(node)
|
128
|
+
if RuboCop::AST::NodePattern.new("(send nil? :tag ...)").match(node)
|
129
|
+
memo[:tags] ||= {}
|
130
|
+
|
131
|
+
node.children[2..-1].each do |tag_node|
|
132
|
+
collect_tags(tag_node)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
def collect_tags(tag_node)
|
140
|
+
if tag_node.type == :str || tag_node.type == :sym
|
141
|
+
memo[:tags] = memo[:tags].merge(tag_node.value => nil)
|
142
|
+
elsif tag_node.type == :hash
|
143
|
+
tags_coll = {}
|
144
|
+
tag_node.children.each do |child_tag|
|
145
|
+
key = child_tag.key.value
|
146
|
+
if child_tag.value.type == :array
|
147
|
+
value = child_tag.value.children.map { |child_node| child_node.type == :str ? child_node.children.first : nil }
|
148
|
+
elsif ACCPETABLE_TAG_TYPE_TO_VALUES.key?(child_tag.value.type)
|
149
|
+
value = ACCPETABLE_TAG_TYPE_TO_VALUES[child_tag.value.type]
|
150
|
+
else
|
151
|
+
if child_tag.value.children.first.class == RuboCop::AST::SendNode
|
152
|
+
# Cases like this: (where there is no assignment of the value to a variable like gcp_project_id)
|
153
|
+
# tag project: gcp_project_id.to_s
|
154
|
+
#
|
155
|
+
# Lecacy evaluates gcp_project_id.to_s and then passes the value to the tag
|
156
|
+
# We are not evaluating the value here, so we are just passing the value as it is
|
157
|
+
#
|
158
|
+
# TODO: Do we need to evaluate the value here?
|
159
|
+
# (byebug) child_tag.value
|
160
|
+
# s(:send,
|
161
|
+
# s(:send, nil, :gcp_project_id), :to_s)
|
162
|
+
value = child_tag.value.children.first.children[1]
|
163
|
+
elsif child_tag.value.children.first.class == RuboCop::AST::Node
|
164
|
+
# Cases like this:
|
165
|
+
# control_id = '1.1'
|
166
|
+
# tag cis_gcp: control_id.to_s
|
167
|
+
value = child_tag.value.children.first.children[0]
|
168
|
+
else
|
169
|
+
value = child_tag.value.value
|
170
|
+
end
|
171
|
+
end
|
172
|
+
tags_coll.merge!(key => value)
|
173
|
+
end
|
174
|
+
memo[:tags] = memo[:tags].merge(tags_coll)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class RefCollector < CollectorBase
|
180
|
+
def on_send(node)
|
181
|
+
if RuboCop::AST::NodePattern.new("(send nil? :ref ...)").match(node)
|
182
|
+
# Construct the array of refs hash as below
|
183
|
+
|
184
|
+
# "refs": [
|
185
|
+
# {
|
186
|
+
# "url": "http://",
|
187
|
+
# "ref": "Some ref"
|
188
|
+
# },
|
189
|
+
# {
|
190
|
+
# "ref": "https://",
|
191
|
+
# }
|
192
|
+
# ]
|
193
|
+
|
194
|
+
# node.children[1] && node.children[1] == :ref - we don't need this check as the pattern match above will take care of it
|
195
|
+
return unless node.children[2]
|
196
|
+
|
197
|
+
references = {}
|
198
|
+
|
199
|
+
if node.children[2].type == :begin
|
200
|
+
# Case for: ref ({:ref=>"Some ref", :url=>"https://"})
|
201
|
+
# find the hash node
|
202
|
+
iterate_child_and_collect_ref(node.children[2].children, references)
|
203
|
+
elsif node.children[2].type == :str
|
204
|
+
# Case for: ref "ref1", url: "http://",
|
205
|
+
references.merge!(ref: node.children[2].value)
|
206
|
+
iterate_child_and_collect_ref(node.children[3..-1], references)
|
207
|
+
end
|
208
|
+
|
209
|
+
memo[:refs] ||= []
|
210
|
+
memo[:refs] << references
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
private
|
215
|
+
|
216
|
+
def iterate_child_and_collect_ref(child_node, references = {})
|
217
|
+
child_node.each do |ref_node|
|
218
|
+
if ref_node.type == :hash
|
219
|
+
iterate_hash_node(ref_node, references)
|
220
|
+
elsif ref_node.type == :str
|
221
|
+
references.merge!(ref_node.value => nil)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def iterate_hash_node(hash_node, references = {})
|
227
|
+
# hash node like this:
|
228
|
+
# s(:hash,
|
229
|
+
# s(:pair,
|
230
|
+
# s(:sym, :url),
|
231
|
+
# s(:str, "https://")))
|
232
|
+
#
|
233
|
+
# or like this:
|
234
|
+
# (byebug) hash_node
|
235
|
+
# s(:hash,
|
236
|
+
# s(:pair,
|
237
|
+
# s(:sym, :url),
|
238
|
+
# s(:send,
|
239
|
+
# s(:send, nil, :cis_url), :to_s)))
|
240
|
+
hash_node.children.each do |child_node|
|
241
|
+
if child_node.type == :pair
|
242
|
+
if child_node.value.children.first.class == RuboCop::AST::SendNode
|
243
|
+
# Case like this (where there is no assignment of the value to a variable like cis_url)
|
244
|
+
# ref 'CIS Benchmark', url: cis_url.to_s
|
245
|
+
# Lecacy evaluates cis_url.to_s and then passes the value to the ref
|
246
|
+
# We are not evaluating the value here, so we are just passing the value as it is
|
247
|
+
#
|
248
|
+
# TODO: Do we need to evaluate the value here?
|
249
|
+
#
|
250
|
+
# (byebug) child_node.value.children.first
|
251
|
+
# s(:send, nil, :cis_url)
|
252
|
+
value = child_node.value.children.first.children[1]
|
253
|
+
elsif child_node.value.class == RuboCop::AST::SendNode
|
254
|
+
# Cases like this:
|
255
|
+
# cis_url = attribute('cis_url')
|
256
|
+
# ref 'CIS Benchmark', url: cis_url.to_s
|
257
|
+
value = child_node.value.children.first.children[0]
|
258
|
+
else
|
259
|
+
# Cases like this: ref 'CIS Benchmark - 2', url: "https://"
|
260
|
+
# require 'byebug'; byebug
|
261
|
+
value = child_node.value.value
|
262
|
+
end
|
263
|
+
references.merge!(child_node.key.value => value)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
class ControlIDCollector < CollectorBase
|
270
|
+
attr_reader :seen_control_ids, :source_location_ref, :include_tests
|
271
|
+
def initialize(memo, source_location_ref, include_tests: false)
|
272
|
+
@memo = memo
|
273
|
+
@seen_control_ids = {}
|
274
|
+
@source_location_ref = source_location_ref
|
275
|
+
@include_tests = include_tests
|
276
|
+
end
|
277
|
+
|
278
|
+
def on_block(block_node)
|
279
|
+
if RuboCop::AST::NodePattern.new("(block (send nil? :control ...) ...)").match(block_node)
|
280
|
+
# NOTE: Assuming begin block is at the index 2
|
281
|
+
begin_block = block_node.children[2]
|
282
|
+
control_node = block_node.children[0]
|
283
|
+
|
284
|
+
# TODO - This assumes the control ID is always a plain string, which we know it is often not!
|
285
|
+
control_id = control_node.children[2].value
|
286
|
+
# TODO - BUG - this keeps seeing the same nodes over and over againa, and so repeating control IDs. We are ignoring duplicate control IDs, which is incorrect.
|
287
|
+
return if seen_control_ids[control_id]
|
288
|
+
|
289
|
+
seen_control_ids[control_id] = true
|
290
|
+
|
291
|
+
control_data = {
|
292
|
+
id: control_id,
|
293
|
+
code: block_node.source,
|
294
|
+
source_location: {
|
295
|
+
line: block_node.first_line,
|
296
|
+
ref: source_location_ref,
|
297
|
+
},
|
298
|
+
title: nil,
|
299
|
+
desc: nil,
|
300
|
+
descriptions: {},
|
301
|
+
impact: 0.5,
|
302
|
+
refs: [],
|
303
|
+
tags: {},
|
304
|
+
}
|
305
|
+
control_data[:checks] = [] if include_tests
|
306
|
+
|
307
|
+
# Scan the code block for per-control metadata
|
308
|
+
collectors = []
|
309
|
+
collectors.push ImpactCollector.new(control_data)
|
310
|
+
collectors.push DescCollector.new(control_data)
|
311
|
+
collectors.push TitleCollector.new(control_data)
|
312
|
+
collectors.push TagCollector.new(control_data)
|
313
|
+
collectors.push RefCollector.new(control_data)
|
314
|
+
collectors.push InputCollectorWithinControlBlock.new(@memo)
|
315
|
+
collectors.push TestsCollector.new(control_data) if include_tests
|
316
|
+
|
317
|
+
begin_block.each_node do |node_within_control|
|
318
|
+
collectors.each { |collector| collector.process(node_within_control) }
|
319
|
+
end
|
320
|
+
|
321
|
+
memo[:controls].push control_data
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
class InputCollectorWithinControlBlock < InputCollectorBase
|
327
|
+
def initialize(memo)
|
328
|
+
@memo = memo
|
329
|
+
end
|
330
|
+
|
331
|
+
def on_send(node)
|
332
|
+
check_and_collect_input(node)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
class InputCollectorOutsideControlBlock < InputCollectorBase
|
337
|
+
def initialize(memo)
|
338
|
+
@memo = memo
|
339
|
+
end
|
340
|
+
|
341
|
+
# TODO: There is scope to refactor InputCollectorOutsideControlBlock and InputCollectorWithinControlBlock
|
342
|
+
# 1. We can have a single class for both the collectors
|
343
|
+
# 2. We can have a on_send and on_lvasgn method in the same class
|
344
|
+
# :lvasgn in ast stands for "local variable assignment"
|
345
|
+
def on_lvasgn(node)
|
346
|
+
# We are looking for the following pattern in the AST
|
347
|
+
# (lvasgn :var_name (send nil? :input ...))
|
348
|
+
# example: a = input('a') or a = input('a', value: 'b')
|
349
|
+
# and not this: a = 1
|
350
|
+
if RuboCop::AST::NodePattern.new("(lvasgn _ (send nil? :input ...))").match(node)
|
351
|
+
input_children = node.children[1]
|
352
|
+
collect_input(input_children)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def on_send(node)
|
357
|
+
check_and_collect_input(node)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
class TestsCollector < CollectorBase
|
362
|
+
|
363
|
+
def on_block(node)
|
364
|
+
if RuboCop::AST::NodePattern.new("(block (send nil? :describe ...) ...)").match(node) ||
|
365
|
+
RuboCop::AST::NodePattern.new("(block (send nil? :expect ...) ...)").match(node)
|
366
|
+
memo[:checks] << node.source
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
data/lib/inspec/version.rb
CHANGED
@@ -19,15 +19,17 @@ module Inspec
|
|
19
19
|
data = nil
|
20
20
|
if [".yaml", ".yml"].include? file_extension
|
21
21
|
data = Secrets::YAML.resolve(file_path)
|
22
|
-
|
23
|
-
|
22
|
+
unless data.nil?
|
23
|
+
data = data.inputs
|
24
|
+
validate_json_yaml(data)
|
25
|
+
end
|
24
26
|
elsif file_extension == ".csv"
|
25
27
|
data = Waivers::CSVFileReader.resolve(file_path)
|
26
28
|
headers = Waivers::CSVFileReader.headers
|
27
29
|
validate_headers(headers)
|
28
30
|
elsif file_extension == ".json"
|
29
31
|
data = Waivers::JSONFileReader.resolve(file_path)
|
30
|
-
validate_json_yaml(data)
|
32
|
+
validate_json_yaml(data) unless data.nil?
|
31
33
|
end
|
32
34
|
output.merge!(data) if !data.nil? && data.is_a?(Hash)
|
33
35
|
|
@@ -168,10 +168,10 @@ module InspecPlugins
|
|
168
168
|
end
|
169
169
|
|
170
170
|
# read profile name from inspec.yml
|
171
|
-
profile_name = profile.
|
171
|
+
profile_name = profile.name
|
172
172
|
|
173
173
|
# read profile version from inspec.yml
|
174
|
-
profile_version = profile.
|
174
|
+
profile_version = profile.version
|
175
175
|
|
176
176
|
# check that the profile is not uploaded already,
|
177
177
|
# confirm upload to the user (overwrite with --force)
|
@@ -1,4 +1,5 @@
|
|
1
|
-
<%
|
1
|
+
<% slugged_control_id = control.id.tr(" ", "_") %>
|
2
|
+
<% slugged_profile_id = profile.name.gsub(/\W/, "_") %>
|
2
3
|
<%
|
3
4
|
if enhanced_outcomes
|
4
5
|
status = control.status
|
@@ -13,7 +14,7 @@
|
|
13
14
|
end
|
14
15
|
%>
|
15
16
|
|
16
|
-
<div class="control control-status-<%= status %>" id="control-<%=
|
17
|
+
<div class="control control-status-<%= status %>" id="profile-<%= slugged_profile_id %>-control-<%= slugged_control_id %>">
|
17
18
|
|
18
19
|
<%
|
19
20
|
# Determine range of impact
|
@@ -29,7 +30,7 @@
|
|
29
30
|
%>
|
30
31
|
|
31
32
|
<h3 class="control-title">Control <code><%= control.id %></code></h3>
|
32
|
-
<table class="control-metadata info" id="control-metadata-<%=
|
33
|
+
<table class="control-metadata info" id="profile-<%= slugged_profile_id %>-control-metadata-<%= slugged_control_id %>">
|
33
34
|
<caption>Control Table</caption>
|
34
35
|
<tr class="status status-<%= status %>"><th>Status:</th><td><div><%= status.capitalize %></div></td></tr>
|
35
36
|
<% if control.title %><tr class="title"><th>Title:</th><td><%= control.title %></td></tr> <% end %>
|
@@ -64,9 +65,9 @@
|
|
64
65
|
<tr class="code">
|
65
66
|
<th>Source Code:</th>
|
66
67
|
<td>
|
67
|
-
<input type="button" class="show-source-code" id="show-code-<%=
|
68
|
-
<input type="button" class="hide-source-code hidden" id="hide-code-<%=
|
69
|
-
<pre class="source-code hidden" id="source-code-<%=
|
68
|
+
<input type="button" class="show-source-code" id="show-code-<%= slugged_profile_id %>-<%= slugged_control_id %>" value="Show Source"/>
|
69
|
+
<input type="button" class="hide-source-code hidden" id="hide-code-<%= slugged_profile_id %>-<%= slugged_control_id %>" value="Hide Source"/>
|
70
|
+
<pre class="source-code hidden" id="source-code-<%= slugged_profile_id %>-<%= slugged_control_id %>">
|
70
71
|
<code>
|
71
72
|
<%= control.code %>
|
72
73
|
</code>
|
@@ -11,17 +11,17 @@ function removeCssClass(id, cls) {
|
|
11
11
|
}
|
12
12
|
|
13
13
|
function handleShowSource(evt) {
|
14
|
-
var
|
14
|
+
var slugged_id = evt.srcElement.id.replace("show-code-", "")
|
15
15
|
addCssClass(evt.srcElement.id, "hidden")
|
16
|
-
removeCssClass("hide-code-" +
|
17
|
-
removeCssClass("source-code-" +
|
16
|
+
removeCssClass("hide-code-" + slugged_id, "hidden")
|
17
|
+
removeCssClass("source-code-" + slugged_id, "hidden")
|
18
18
|
}
|
19
19
|
|
20
20
|
function handleHideSource(evt) {
|
21
|
-
var
|
21
|
+
var slugged_id = evt.srcElement.id.replace("hide-code-", "")
|
22
22
|
addCssClass(evt.srcElement.id, "hidden")
|
23
|
-
addCssClass("source-code-" +
|
24
|
-
removeCssClass("show-code-" +
|
23
|
+
addCssClass("source-code-" + slugged_id, "hidden")
|
24
|
+
removeCssClass("show-code-" + slugged_id, "hidden")
|
25
25
|
}
|
26
26
|
|
27
27
|
function handleSelectorChange(evt) {
|
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.22.
|
4
|
+
version: 5.22.36
|
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: 2023-
|
11
|
+
date: 2023-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-telemetry
|
@@ -59,7 +59,7 @@ dependencies:
|
|
59
59
|
version: '0.20'
|
60
60
|
- - "<"
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version:
|
62
|
+
version: 1.3.0
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -69,7 +69,7 @@ dependencies:
|
|
69
69
|
version: '0.20'
|
70
70
|
- - "<"
|
71
71
|
- !ruby/object:Gem::Version
|
72
|
-
version:
|
72
|
+
version: 1.3.0
|
73
73
|
- !ruby/object:Gem::Dependency
|
74
74
|
name: method_source
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,7 +119,7 @@ dependencies:
|
|
119
119
|
version: '3.9'
|
120
120
|
- - "<="
|
121
121
|
- !ruby/object:Gem::Version
|
122
|
-
version: '3.
|
122
|
+
version: '3.12'
|
123
123
|
type: :runtime
|
124
124
|
prerelease: false
|
125
125
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -129,7 +129,7 @@ dependencies:
|
|
129
129
|
version: '3.9'
|
130
130
|
- - "<="
|
131
131
|
- !ruby/object:Gem::Version
|
132
|
-
version: '3.
|
132
|
+
version: '3.12'
|
133
133
|
- !ruby/object:Gem::Dependency
|
134
134
|
name: rspec-its
|
135
135
|
requirement: !ruby/object:Gem::Requirement
|
@@ -167,7 +167,7 @@ dependencies:
|
|
167
167
|
version: '3.4'
|
168
168
|
- - "<"
|
169
169
|
- !ruby/object:Gem::Version
|
170
|
-
version: '
|
170
|
+
version: '6.0'
|
171
171
|
type: :runtime
|
172
172
|
prerelease: false
|
173
173
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -177,7 +177,7 @@ dependencies:
|
|
177
177
|
version: '3.4'
|
178
178
|
- - "<"
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: '
|
180
|
+
version: '6.0'
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: mixlib-log
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -325,7 +325,7 @@ dependencies:
|
|
325
325
|
version: '1.5'
|
326
326
|
- - "<"
|
327
327
|
- !ruby/object:Gem::Version
|
328
|
-
version: '
|
328
|
+
version: '3.0'
|
329
329
|
type: :runtime
|
330
330
|
prerelease: false
|
331
331
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -335,7 +335,7 @@ dependencies:
|
|
335
335
|
version: '1.5'
|
336
336
|
- - "<"
|
337
337
|
- !ruby/object:Gem::Version
|
338
|
-
version: '
|
338
|
+
version: '3.0'
|
339
339
|
- !ruby/object:Gem::Dependency
|
340
340
|
name: semverse
|
341
341
|
requirement: !ruby/object:Gem::Requirement
|
@@ -716,6 +716,7 @@ files:
|
|
716
716
|
- lib/inspec/utils/parser.rb
|
717
717
|
- lib/inspec/utils/pkey_reader.rb
|
718
718
|
- lib/inspec/utils/podman.rb
|
719
|
+
- lib/inspec/utils/profile_ast_helpers.rb
|
719
720
|
- lib/inspec/utils/run_data_filters.rb
|
720
721
|
- lib/inspec/utils/simpleconfig.rb
|
721
722
|
- lib/inspec/utils/spdx.rb
|