abide_dev_utils 0.9.7 → 0.10.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +24 -8
- data/abide_dev_utils.gemspec +1 -0
- data/lib/abide_dev_utils/cem.rb +72 -0
- data/lib/abide_dev_utils/cli/cem.rb +73 -0
- data/lib/abide_dev_utils/cli/xccdf.rb +12 -1
- data/lib/abide_dev_utils/cli.rb +2 -0
- data/lib/abide_dev_utils/files.rb +34 -0
- data/lib/abide_dev_utils/version.rb +1 -1
- data/lib/abide_dev_utils/xccdf/diff/benchmark/number_title.rb +270 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark/profile.rb +104 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark/property.rb +127 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark/property_existence.rb +47 -0
- data/lib/abide_dev_utils/xccdf/diff/benchmark.rb +267 -0
- data/lib/abide_dev_utils/xccdf/diff/utils.rb +30 -0
- data/lib/abide_dev_utils/xccdf/diff.rb +233 -0
- data/lib/abide_dev_utils/xccdf/parser/objects/digest_object.rb +118 -0
- data/lib/abide_dev_utils/xccdf/parser/objects/numbered_object.rb +104 -0
- data/lib/abide_dev_utils/xccdf/parser/objects.rb +741 -0
- data/lib/abide_dev_utils/xccdf/parser.rb +52 -0
- data/lib/abide_dev_utils/xccdf.rb +9 -122
- data/new_diff.rb +48 -0
- metadata +34 -6
@@ -0,0 +1,741 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
require_relative './objects/digest_object'
|
5
|
+
require_relative './objects/numbered_object'
|
6
|
+
|
7
|
+
module AbideDevUtils
|
8
|
+
module XCCDF
|
9
|
+
module Parser
|
10
|
+
# Holds individual XCCDF objects
|
11
|
+
module Objects
|
12
|
+
# Base class for XCCDF element objects
|
13
|
+
class ElementBase
|
14
|
+
include AbideDevUtils::XCCDF::Parser::Objects::DigestObject
|
15
|
+
attr_reader :children, :child_labels, :link_labels
|
16
|
+
|
17
|
+
def initialize(*_args, **_kwargs)
|
18
|
+
@children = []
|
19
|
+
@links = []
|
20
|
+
@link_labels = []
|
21
|
+
@child_labels = []
|
22
|
+
@label_method_values = {}
|
23
|
+
exclude_from_digest(%i[@digest @children @child_labels @label @exclude_from_digest @label_method_values])
|
24
|
+
end
|
25
|
+
|
26
|
+
# For subclasses that are associated with a specific
|
27
|
+
# XCCDF element, this method returns the element's
|
28
|
+
# xpath. Must be overridden by subclasses that
|
29
|
+
# implement this method.
|
30
|
+
def self.xpath
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
# Takes the last segment of the class name, splits on captial letters,
|
35
|
+
# and returns a downcased string joined by dashes. This gives us the
|
36
|
+
# XCCDF element type. Example: 'AbideDevUtils::XCCDF::Parser::Objects::ComplexCheck'
|
37
|
+
# returns 'complex-check'.
|
38
|
+
def xccdf_type
|
39
|
+
self.class.name.split('::').last.split(/(?=[A-Z])/).reject { |x| x == 'Xccdf' }.join('-').downcase
|
40
|
+
end
|
41
|
+
|
42
|
+
def all_values
|
43
|
+
@child_labels.map { |label| send(label.to_sym) }
|
44
|
+
@label_method_values
|
45
|
+
end
|
46
|
+
|
47
|
+
# Allows access to child objects by label
|
48
|
+
def method_missing(method_name, *args, &block)
|
49
|
+
m_name_string = method_name.to_s.downcase
|
50
|
+
return @label_method_values[m_name_string] if @label_method_values.key?(m_name_string)
|
51
|
+
|
52
|
+
label_str = m_name_string.start_with?('linked_') ? m_name_string.split('_')[1..].join('_') : m_name_string
|
53
|
+
if m_name_string.start_with?('linked_') && @link_labels.include?(label_str)
|
54
|
+
found = @links.select { |link| link.label == label_str }
|
55
|
+
@label_method_values["linked_#{label_str}"] = if found.length == 1
|
56
|
+
found.first
|
57
|
+
else
|
58
|
+
found
|
59
|
+
end
|
60
|
+
@label_method_values["linked_#{label_str}"]
|
61
|
+
elsif @child_labels.include?(label_str)
|
62
|
+
found = @children.select { |child| child.label == label_str }
|
63
|
+
@label_method_values[label_str] = if found.length == 1
|
64
|
+
found.first
|
65
|
+
else
|
66
|
+
found
|
67
|
+
end
|
68
|
+
@label_method_values[label_str]
|
69
|
+
else
|
70
|
+
super
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def respond_to_missing?(method_name, include_private = false)
|
75
|
+
m_name_string = method_name.to_s.downcase
|
76
|
+
label_str = m_name_string.start_with?('linked_') ? m_name_string.split('_')[1..].join('_') : m_name_string
|
77
|
+
(m_name_string.start_with?('linked_') && @link_labels.include?(label_str)) ||
|
78
|
+
@child_labels.include?(label_str) ||
|
79
|
+
super
|
80
|
+
end
|
81
|
+
|
82
|
+
def label
|
83
|
+
return @label if defined?(@label)
|
84
|
+
|
85
|
+
@label = case self.class.name
|
86
|
+
when 'AbideDevUtils::XCCDF::Parser::Objects::AttributeValue'
|
87
|
+
@attribute.to_s
|
88
|
+
when /AbideDevUtils::XCCDF::Parser::Objects::(ShortText|LongText)/
|
89
|
+
'text'
|
90
|
+
else
|
91
|
+
self.class.name.split('::').last.split(/(?=[A-Z])/).join('_').downcase
|
92
|
+
end
|
93
|
+
@label
|
94
|
+
end
|
95
|
+
|
96
|
+
def recursive_select_children(children_to_search = children, &block)
|
97
|
+
search_hits = []
|
98
|
+
children_to_search.each do |child|
|
99
|
+
found = yield child
|
100
|
+
if found
|
101
|
+
search_hits << child
|
102
|
+
elsif child.respond_to?(:children)
|
103
|
+
search_hits << recursive_select_children(child.children, &block)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
search_hits.flatten.compact.uniq
|
107
|
+
end
|
108
|
+
|
109
|
+
def recursive_find_child(children_to_search = children, &block)
|
110
|
+
rescursive_select_children(children_to_search, &block).first
|
111
|
+
end
|
112
|
+
|
113
|
+
def find_children_that_respond_to(method, recurse: false)
|
114
|
+
return recursive_select_children { |child| child.respond_to?(method) } if recurse
|
115
|
+
|
116
|
+
children.select { |c| c.respond_to?(method.to_sym) }
|
117
|
+
end
|
118
|
+
|
119
|
+
def find_children_by_class(klass, recurse: false)
|
120
|
+
return recursive_select_children { |child| child.instance_of?(klass) } if recurse
|
121
|
+
|
122
|
+
children.select { |child| child.instance_of?(klass) }
|
123
|
+
end
|
124
|
+
|
125
|
+
def find_child_by_class(klass, recurse: false)
|
126
|
+
return recursive_find_child { |child| child.is_a?(klass) } if recurse
|
127
|
+
|
128
|
+
find_children_by_class(klass).first
|
129
|
+
end
|
130
|
+
|
131
|
+
def find_children_by_xpath(xpath, recurse: false)
|
132
|
+
return recursive_select_children { |child| child.xpath == xpath } if recurse
|
133
|
+
|
134
|
+
children.select { |child| child.xpath == xpath }
|
135
|
+
end
|
136
|
+
|
137
|
+
def find_child_by_xpath(xpath, recurse: false)
|
138
|
+
return recursive_find_child { |child| child.xpath == xpath } if recurse
|
139
|
+
|
140
|
+
find_children_by_xpath(xpath).first
|
141
|
+
end
|
142
|
+
|
143
|
+
def find_children_by_attribute(attribute, recurse: false)
|
144
|
+
pr = proc do |child|
|
145
|
+
next unless child.instance_of?(AbideDevUtils::XCCDF::Parser::Objects::AttributeValue)
|
146
|
+
|
147
|
+
child.attribute == attribute
|
148
|
+
end
|
149
|
+
return recursive_select_children(&pr) if recurse
|
150
|
+
|
151
|
+
children.select(&pr)
|
152
|
+
end
|
153
|
+
|
154
|
+
def find_child_by_attribute(attribute, recurse: false)
|
155
|
+
find_children_by_attribute(attribute, recurse: recurse).first
|
156
|
+
end
|
157
|
+
|
158
|
+
def find_children_by_attribute_value(attribute, value, recurse: false)
|
159
|
+
pr = proc do |child|
|
160
|
+
next unless child.instance_of?(AbideDevUtils::XCCDF::Parser::Objects::AttributeValue)
|
161
|
+
|
162
|
+
child.attribute == attribute && child.value == value
|
163
|
+
end
|
164
|
+
return recursive_select_children(&pr) if recurse
|
165
|
+
|
166
|
+
children.select(&pr)
|
167
|
+
end
|
168
|
+
|
169
|
+
def find_child_by_attribute_value(attribute, value, recurse: false)
|
170
|
+
find_children_by_attribute_value(attribute, value, recurse: recurse).first
|
171
|
+
end
|
172
|
+
|
173
|
+
def add_link(object)
|
174
|
+
@links << object
|
175
|
+
@link_labels << object.label unless @link_labels.include?(object.label)
|
176
|
+
end
|
177
|
+
|
178
|
+
def add_links(objects)
|
179
|
+
objects.each { |object| add_object_as_child(object) }
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def with_safe_methods(default: nil)
|
185
|
+
yield
|
186
|
+
rescue NoMethodError
|
187
|
+
default
|
188
|
+
end
|
189
|
+
|
190
|
+
def namespace_safe_xpath(element, path)
|
191
|
+
element.xpath(path)
|
192
|
+
rescue Nokogiri::XML::XPath::SyntaxError
|
193
|
+
element.xpath("*[name()='#{path}']")
|
194
|
+
end
|
195
|
+
|
196
|
+
def namespace_safe_at_xpath(element, path)
|
197
|
+
element.at_xpath(path)
|
198
|
+
rescue Nokogiri::XML::XPath::SyntaxError
|
199
|
+
element.at_xpath("*[name()='#{path}']")
|
200
|
+
end
|
201
|
+
|
202
|
+
def add_child(klass, element, *args, **kwargs)
|
203
|
+
return if element.nil?
|
204
|
+
|
205
|
+
real_element = klass.xpath.nil? ? element : namespace_safe_at_xpath(element, klass.xpath)
|
206
|
+
return if real_element.nil?
|
207
|
+
|
208
|
+
obj = new_object(klass, real_element, *args, **kwargs)
|
209
|
+
@children << obj
|
210
|
+
@child_labels << obj.label unless @child_labels.include?(obj.label)
|
211
|
+
rescue StandardError => e
|
212
|
+
raise(
|
213
|
+
e,
|
214
|
+
"Failed to add child #{klass.to_s.split('::').last} to #{self.class.to_s.split('::').last}: #{e.message}",
|
215
|
+
e.backtrace,
|
216
|
+
)
|
217
|
+
end
|
218
|
+
|
219
|
+
def add_children(klass, element, *args, **kwargs)
|
220
|
+
return if element.nil?
|
221
|
+
|
222
|
+
real_elements = klass.xpath.nil? ? element : namespace_safe_xpath(element, klass.xpath)
|
223
|
+
return if real_elements.nil?
|
224
|
+
|
225
|
+
real_elements.each do |e|
|
226
|
+
obj = new_object(klass, e, *args, **kwargs)
|
227
|
+
@children << obj
|
228
|
+
@child_labels << obj.label unless @child_labels.include?(obj.label)
|
229
|
+
end
|
230
|
+
rescue StandardError => e
|
231
|
+
raise(
|
232
|
+
e,
|
233
|
+
"Failed to add children #{klass.to_s.split('::').last} to #{self.class.to_s.split('::').last}: #{e.message}",
|
234
|
+
e.backtrace,
|
235
|
+
)
|
236
|
+
end
|
237
|
+
|
238
|
+
def new_object(klass, element, *args, **kwargs)
|
239
|
+
klass.new(element, *args, **kwargs)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# Holds text content that does not use multiple lines
|
244
|
+
class ShortText < ElementBase
|
245
|
+
attr_reader :text
|
246
|
+
|
247
|
+
def initialize(element)
|
248
|
+
super
|
249
|
+
text = element.respond_to?(:text) ? element.text : element
|
250
|
+
@text = text.to_s
|
251
|
+
end
|
252
|
+
|
253
|
+
def to_s
|
254
|
+
@text
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
# Holds text content that consists of multiple lines
|
259
|
+
class LongText < ElementBase
|
260
|
+
attr_reader :text
|
261
|
+
|
262
|
+
def initialize(element)
|
263
|
+
super
|
264
|
+
text = element.respond_to?(:text) ? element.text : element
|
265
|
+
@text = text.to_s
|
266
|
+
@string_text = text.to_s.tr("\n", ' ').gsub(/\s+/, ' ')
|
267
|
+
end
|
268
|
+
|
269
|
+
def to_s
|
270
|
+
@string_text
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
# Represents a value of an element attribute
|
275
|
+
class AttributeValue < ElementBase
|
276
|
+
attr_reader :attribute, :value
|
277
|
+
|
278
|
+
def initialize(element, attribute)
|
279
|
+
super
|
280
|
+
@attribute = attribute
|
281
|
+
@value = element[attribute]
|
282
|
+
end
|
283
|
+
|
284
|
+
def to_s
|
285
|
+
"#{@attribute}=#{@value}"
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
# Class for an XCCDF element title
|
290
|
+
class Title < ElementBase
|
291
|
+
def initialize(element)
|
292
|
+
super
|
293
|
+
add_child(ShortText, element)
|
294
|
+
end
|
295
|
+
|
296
|
+
def self.xpath
|
297
|
+
'xccdf:title'
|
298
|
+
end
|
299
|
+
|
300
|
+
def to_s
|
301
|
+
find_child_by_class(ShortText).to_s
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
# Class for an XCCDF element description
|
306
|
+
class Description < ElementBase
|
307
|
+
def initialize(element)
|
308
|
+
super
|
309
|
+
add_child(LongText, element)
|
310
|
+
end
|
311
|
+
|
312
|
+
def self.xpath
|
313
|
+
'xccdf:description'
|
314
|
+
end
|
315
|
+
|
316
|
+
def to_s
|
317
|
+
find_child_by_class(LongText).to_s
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
# Base class for elements that have the ID attribute
|
322
|
+
class ElementWithId < ElementBase
|
323
|
+
attr_reader :id
|
324
|
+
|
325
|
+
def initialize(element)
|
326
|
+
super
|
327
|
+
add_child(AttributeValue, element, 'id')
|
328
|
+
@id = find_child_by_attribute('id').value.to_s
|
329
|
+
end
|
330
|
+
|
331
|
+
def to_s
|
332
|
+
@id
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
# Base class for elements that have the idref attribute
|
337
|
+
class ElementWithIdref < ElementBase
|
338
|
+
attr_reader :idref
|
339
|
+
|
340
|
+
def initialize(element)
|
341
|
+
super
|
342
|
+
add_child(AttributeValue, element, 'idref')
|
343
|
+
@idref = find_child_by_attribute('idref').value.to_s
|
344
|
+
end
|
345
|
+
|
346
|
+
def to_s
|
347
|
+
@idref
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
# Class for an XCCDF select element
|
352
|
+
class XccdfSelect < ElementWithIdref
|
353
|
+
def initialize(element)
|
354
|
+
super
|
355
|
+
add_child(AttributeValue, element, 'selected')
|
356
|
+
end
|
357
|
+
|
358
|
+
def self.xpath
|
359
|
+
'xccdf:select'
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
# Class for XCCDF profile
|
364
|
+
class Profile < ElementWithId
|
365
|
+
def initialize(element)
|
366
|
+
super
|
367
|
+
add_child(Title, element)
|
368
|
+
add_child(Description, element)
|
369
|
+
add_children(XccdfSelect, element)
|
370
|
+
end
|
371
|
+
|
372
|
+
def level
|
373
|
+
return @level if defined?(@level)
|
374
|
+
|
375
|
+
level_match = title.to_s.match(/([Ll]evel [0-9]+)/)
|
376
|
+
@level = level_match.nil? ? level_match : level_match[1]
|
377
|
+
@level
|
378
|
+
end
|
379
|
+
|
380
|
+
def self.xpath
|
381
|
+
'xccdf:Profile'
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
# Class for XCCDF group
|
386
|
+
class Group < ElementWithId
|
387
|
+
include AbideDevUtils::XCCDF::Parser::Objects::NumberedObject
|
388
|
+
attr_reader :number
|
389
|
+
|
390
|
+
def initialize(element)
|
391
|
+
super
|
392
|
+
@number = to_s[/group_([0-9]+\.)+[0-9]+|group_([0-9]+)/].gsub(/group_/, '')
|
393
|
+
add_child(Title, element)
|
394
|
+
add_child(Description, element)
|
395
|
+
add_children(Group, element)
|
396
|
+
add_children(Rule, element)
|
397
|
+
end
|
398
|
+
|
399
|
+
def self.xpath
|
400
|
+
'xccdf:Group'
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
# Class for XCCDF check-export
|
405
|
+
class CheckExport < ElementBase
|
406
|
+
def initialize(element)
|
407
|
+
super
|
408
|
+
add_child(AttributeValue, element, 'export-name')
|
409
|
+
add_child(AttributeValue, element, 'value-id')
|
410
|
+
end
|
411
|
+
|
412
|
+
def self.xpath
|
413
|
+
'xccdf:check-export'
|
414
|
+
end
|
415
|
+
|
416
|
+
def to_s
|
417
|
+
[find_child_by_attribute('export-name').to_s, find_child_by_attribute('value-id').to_s].join('|')
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
# Class for XCCDF check-content-ref
|
422
|
+
class CheckContentRef < ElementBase
|
423
|
+
def initialize(element)
|
424
|
+
super
|
425
|
+
add_child(AttributeValue, element, 'href')
|
426
|
+
add_child(AttributeValue, element, 'name')
|
427
|
+
end
|
428
|
+
|
429
|
+
def self.xpath
|
430
|
+
'xccdf:check-content-ref'
|
431
|
+
end
|
432
|
+
|
433
|
+
def to_s
|
434
|
+
[find_child_by_attribute('href').to_s, find_child_by_attribute('name').to_s].join('|')
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
# Class for XCCDF check
|
439
|
+
class Check < ElementBase
|
440
|
+
def initialize(element)
|
441
|
+
super
|
442
|
+
add_child(AttributeValue, element, 'system')
|
443
|
+
add_children(CheckExport, element)
|
444
|
+
add_children(CheckContentRef, element)
|
445
|
+
end
|
446
|
+
|
447
|
+
def self.xpath
|
448
|
+
'xccdf:check'
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
# Class for XCCDF Ident ControlURI element
|
453
|
+
class ControlURI < ElementBase
|
454
|
+
def initialize(element)
|
455
|
+
super
|
456
|
+
@namespace = element.attributes['controlURI'].namespace.prefix
|
457
|
+
@value = element.attributes['controlURI'].value
|
458
|
+
end
|
459
|
+
|
460
|
+
def to_s
|
461
|
+
[label, @namespace, @value].join(':')
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
# Class for XCCDF Ident System element
|
466
|
+
class System < ElementBase
|
467
|
+
def initialize(element)
|
468
|
+
super
|
469
|
+
@system = element.attributes['system'].value
|
470
|
+
@text = element.text
|
471
|
+
end
|
472
|
+
|
473
|
+
def to_s
|
474
|
+
[label, @system, @text].join(':')
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
# Class for XCCDF rule ident
|
479
|
+
class Ident < ElementBase
|
480
|
+
def initialize(element)
|
481
|
+
super
|
482
|
+
with_safe_methods { add_child(ControlURI, element) }
|
483
|
+
with_safe_methods { add_child(System, element) }
|
484
|
+
end
|
485
|
+
|
486
|
+
def self.xpath
|
487
|
+
'xccdf:ident'
|
488
|
+
end
|
489
|
+
|
490
|
+
def to_s
|
491
|
+
@children.map(&:to_s).join('|')
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
# Class for XCCDF rule complex check
|
496
|
+
class ComplexCheck < ElementBase
|
497
|
+
attr_reader :operator, :check
|
498
|
+
|
499
|
+
def initialize(element, parent: nil)
|
500
|
+
super
|
501
|
+
add_child(AttributeValue, element, 'operator')
|
502
|
+
add_children(Check, element)
|
503
|
+
end
|
504
|
+
|
505
|
+
def self.xpath
|
506
|
+
'xccdf:complex-check'
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
# Class for XCCDF rule metadata cis_controls framework safeguard
|
511
|
+
class MetadataCisControlsFrameworkSafeguard < ElementBase
|
512
|
+
def initialize(element)
|
513
|
+
super
|
514
|
+
add_child(ShortText, element['title'])
|
515
|
+
add_child(ShortText, element['urn'])
|
516
|
+
new_implementation_groups(element)
|
517
|
+
add_child(ShortText, namespace_safe_at_xpath(element, 'controls:asset_type').text)
|
518
|
+
add_child(ShortText, namespace_safe_at_xpath(element, 'controls:security_function').text)
|
519
|
+
end
|
520
|
+
|
521
|
+
def self.xpath
|
522
|
+
'controls:safeguard'
|
523
|
+
end
|
524
|
+
|
525
|
+
private
|
526
|
+
|
527
|
+
def new_implementation_groups(element)
|
528
|
+
igroup = namespace_safe_at_xpath(element, 'controls:implementation_groups')
|
529
|
+
add_child(ShortText, igroup['ig1']) if igroup['ig1']
|
530
|
+
add_child(ShortText, igroup['ig2']) if igroup['ig2']
|
531
|
+
add_child(ShortText, igroup['ig3']) if igroup['ig3']
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
# Class for XCCDF rule metadata cis_controls framework
|
536
|
+
class MetadataCisControlsFramework < ElementBase
|
537
|
+
def initialize(element)
|
538
|
+
super
|
539
|
+
add_child(AttributeValue, element, 'urn')
|
540
|
+
add_children(MetadataCisControlsFrameworkSafeguard, element)
|
541
|
+
end
|
542
|
+
|
543
|
+
def self.xpath
|
544
|
+
'controls:framework'
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
# Class for XCCDF metadata cis_controls element
|
549
|
+
class MetadataCisControls < ElementBase
|
550
|
+
def initialize(element, parent: nil)
|
551
|
+
super
|
552
|
+
add_child(AttributeValue, element, 'xmlns:controls')
|
553
|
+
add_children(MetadataCisControlsFramework, element)
|
554
|
+
end
|
555
|
+
|
556
|
+
def self.xpath
|
557
|
+
'controls:cis_controls'
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
561
|
+
# Class for XCCDF rule metadata element
|
562
|
+
class Metadata < ElementBase
|
563
|
+
def initialize(element, parent: nil)
|
564
|
+
super
|
565
|
+
add_children(MetadataCisControls, element)
|
566
|
+
end
|
567
|
+
|
568
|
+
def self.xpath
|
569
|
+
'xccdf:metadata'
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
# Class for XCCDF Rule child element Rationale
|
574
|
+
class Rationale < ElementBase
|
575
|
+
def initialize(element)
|
576
|
+
super
|
577
|
+
add_child(LongText, element)
|
578
|
+
end
|
579
|
+
|
580
|
+
def digest
|
581
|
+
@digest ||= find_child_by_class(LongText).digest
|
582
|
+
end
|
583
|
+
|
584
|
+
def self.xpath
|
585
|
+
'xccdf:rationale'
|
586
|
+
end
|
587
|
+
|
588
|
+
def to_s
|
589
|
+
find_child_by_class(LongText).to_s
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
593
|
+
# Class for XCCDF Rule child element Fixtext
|
594
|
+
class Fixtext < ElementBase
|
595
|
+
def initialize(element)
|
596
|
+
super
|
597
|
+
add_child(LongText, element)
|
598
|
+
end
|
599
|
+
|
600
|
+
def digest
|
601
|
+
@digest ||= find_child_by_class(LongText).digest
|
602
|
+
end
|
603
|
+
|
604
|
+
def self.xpath
|
605
|
+
'xccdf:fixtext'
|
606
|
+
end
|
607
|
+
|
608
|
+
def to_s
|
609
|
+
find_child_by_class(LongText).to_s
|
610
|
+
end
|
611
|
+
end
|
612
|
+
|
613
|
+
# Class for XCCDF rule
|
614
|
+
class Rule < ElementWithId
|
615
|
+
include AbideDevUtils::XCCDF::Parser::Objects::NumberedObject
|
616
|
+
attr_reader :number
|
617
|
+
|
618
|
+
def initialize(element)
|
619
|
+
super
|
620
|
+
@number = to_s[/([0-9]+\.)+[0-9]+/]
|
621
|
+
add_child(AttributeValue, element, 'role')
|
622
|
+
add_child(AttributeValue, element, 'selected')
|
623
|
+
add_child(AttributeValue, element, 'weight')
|
624
|
+
add_child(Title, element)
|
625
|
+
add_child(Description, element)
|
626
|
+
add_child(Rationale, element)
|
627
|
+
add_children(Ident, element)
|
628
|
+
add_child(Fixtext, element)
|
629
|
+
add_children(Check, element)
|
630
|
+
add_child(ComplexCheck, element)
|
631
|
+
add_child(Metadata, element)
|
632
|
+
end
|
633
|
+
|
634
|
+
def self.xpath
|
635
|
+
'xccdf:Rule'
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
639
|
+
# Class for XCCDF Value
|
640
|
+
class Value < ElementWithId
|
641
|
+
def initialize(element)
|
642
|
+
super
|
643
|
+
add_child(AttributeValue, element, 'operator')
|
644
|
+
add_child(AttributeValue, element, 'type')
|
645
|
+
add_child(Title, element)
|
646
|
+
add_child(Description, element)
|
647
|
+
add_child(ShortText, element.at_xpath('xccdf:value'))
|
648
|
+
end
|
649
|
+
|
650
|
+
def self.xpath
|
651
|
+
'xccdf:Value'
|
652
|
+
end
|
653
|
+
|
654
|
+
def to_s
|
655
|
+
find_child_by_class(Title).to_s
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
# Class for XCCDF benchmark status
|
660
|
+
class Status < ElementBase
|
661
|
+
def initialize(element)
|
662
|
+
super
|
663
|
+
add_child(ShortText, element)
|
664
|
+
add_child(AttributeValue, element, 'date')
|
665
|
+
end
|
666
|
+
|
667
|
+
def self.xpath
|
668
|
+
'xccdf:status'
|
669
|
+
end
|
670
|
+
|
671
|
+
def to_s
|
672
|
+
[
|
673
|
+
"Status:#{find_child_by_class(ShortText)}",
|
674
|
+
"Date:#{find_child_by_class(AttributeValue)}",
|
675
|
+
].join('|')
|
676
|
+
end
|
677
|
+
end
|
678
|
+
|
679
|
+
# Class for XCCDF benchmark version
|
680
|
+
class Version < ElementBase
|
681
|
+
def initialize(element)
|
682
|
+
super
|
683
|
+
add_child(ShortText, element)
|
684
|
+
end
|
685
|
+
|
686
|
+
def self.xpath
|
687
|
+
'xccdf:version'
|
688
|
+
end
|
689
|
+
|
690
|
+
def to_s
|
691
|
+
find_child_by_class(ShortText).to_s
|
692
|
+
end
|
693
|
+
end
|
694
|
+
|
695
|
+
# Class for XCCDF benchmark platform
|
696
|
+
class Platform < ElementBase
|
697
|
+
def initialize(element)
|
698
|
+
super
|
699
|
+
add_child(AttributeValue, element, 'idref')
|
700
|
+
end
|
701
|
+
|
702
|
+
def self.xpath
|
703
|
+
'xccdf:platform'
|
704
|
+
end
|
705
|
+
|
706
|
+
def to_s
|
707
|
+
find_child_by_class(AttributeValue).to_s
|
708
|
+
end
|
709
|
+
end
|
710
|
+
|
711
|
+
# Class for XCCDF benchmark
|
712
|
+
class Benchmark < ElementBase
|
713
|
+
include AbideDevUtils::XCCDF::Parser::Objects::NumberedObject
|
714
|
+
|
715
|
+
def initialize(element)
|
716
|
+
super
|
717
|
+
element = element.at_xpath('xccdf:Benchmark')
|
718
|
+
raise 'No Benchmark element found' if element.nil?
|
719
|
+
|
720
|
+
add_child(Status, element)
|
721
|
+
add_child(Title, element)
|
722
|
+
add_child(Description, element)
|
723
|
+
add_child(Platform, element)
|
724
|
+
add_child(Version, element)
|
725
|
+
add_children(Profile, element)
|
726
|
+
add_children(Group, element)
|
727
|
+
add_children(Value, element)
|
728
|
+
end
|
729
|
+
|
730
|
+
def self.xpath
|
731
|
+
'xccdf:Benchmark'
|
732
|
+
end
|
733
|
+
|
734
|
+
def to_s
|
735
|
+
[find_child_by_class(Title).to_s, find_child_by_class(Version).to_s].join(' ')
|
736
|
+
end
|
737
|
+
end
|
738
|
+
end
|
739
|
+
end
|
740
|
+
end
|
741
|
+
end
|