abide_dev_utils 0.11.2 → 0.12.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/abide_dev_utils/cem/generate/reference.rb +7 -2
- data/lib/abide_dev_utils/cem/mapping/mapper.rb +5 -3
- data/lib/abide_dev_utils/cli/jira.rb +22 -0
- data/lib/abide_dev_utils/jira.rb +45 -0
- data/lib/abide_dev_utils/version.rb +1 -1
- data/lib/abide_dev_utils/xccdf.rb +194 -66
- 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: 1e93a77cf4142b06ee4d41863ef2d0b737d21d37306b57082aa316f2731de5e9
|
4
|
+
data.tar.gz: 9b49e05aa575884d54efed8fd70b5662712845c083a8b59caeccf406a19f5633
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51316ad752020f3b2297acbdc4bb328c5275d03e499721ee12381aaac5da3a6e77ecb9efeb0ffa4b3b6bb512154dbb4b36bf249f4816944a0110d3ceeb871b2b
|
7
|
+
data.tar.gz: 40b83d7be09ccb1349650617548276f6f34e266fe2e590e8c1b28b8e9c44f4499c93652abf9e254d77469fec9c98e9394a1ae2f4b2d3f0921827c3ce302dfb7e
|
data/Gemfile.lock
CHANGED
@@ -120,7 +120,11 @@ module AbideDevUtils
|
|
120
120
|
private
|
121
121
|
|
122
122
|
def heading_builder
|
123
|
-
@
|
123
|
+
if @framework == 'stig'
|
124
|
+
@md.add_h2(@control.id)
|
125
|
+
else
|
126
|
+
@md.add_h2("#{@control.number} - #{@control.title}")
|
127
|
+
end
|
124
128
|
end
|
125
129
|
|
126
130
|
def control_has_valid_params?
|
@@ -216,12 +220,13 @@ module AbideDevUtils
|
|
216
220
|
end
|
217
221
|
return if out_str.empty?
|
218
222
|
|
219
|
-
out_str.unshift(" #{@control.title.dump}:")
|
223
|
+
@control.title.nil? ? out_str.unshift(" #{@control.id.dump}:") : out_str.unshift(" #{@control.title.dump}:")
|
220
224
|
out_str.unshift(' control_configs:')
|
221
225
|
out_str.unshift("#{@module_name}::config:")
|
222
226
|
@md.add_ul('Hiera Configuration Example:')
|
223
227
|
@md.add_code_block(out_str.join("\n"), language: 'yaml')
|
224
228
|
rescue StandardError => e
|
229
|
+
require 'pry'; binding.pry
|
225
230
|
err_msg = [
|
226
231
|
"Failed to generate config example for control #{@control.id}",
|
227
232
|
"Error: #{e.message}",
|
@@ -6,13 +6,13 @@ require 'abide_dev_utils/cem/hiera_data/mapping_data/mixins'
|
|
6
6
|
module AbideDevUtils
|
7
7
|
module CEM
|
8
8
|
module Mapping
|
9
|
-
ALL_TYPES = %w[hiera_title_num number hiera_title vulnid
|
9
|
+
ALL_TYPES = %w[hiera_title_num number hiera_title title vulnid ruleid].freeze
|
10
10
|
FRAMEWORK_TYPES = {
|
11
11
|
'cis' => %w[hiera_title_num number hiera_title title],
|
12
|
-
'stig' => %w[
|
12
|
+
'stig' => %w[vulnid ruleid],
|
13
13
|
}.freeze
|
14
14
|
CIS_TYPES = %w[hiera_title_num number hiera_title title].freeze
|
15
|
-
STIG_TYPES = %w[
|
15
|
+
STIG_TYPES = %w[vulnid ruleid].freeze
|
16
16
|
|
17
17
|
# Represents a single map data file
|
18
18
|
class MapData
|
@@ -168,6 +168,8 @@ module AbideDevUtils
|
|
168
168
|
'hiera_title'
|
169
169
|
when %r{^V-[0-9]{6}$}
|
170
170
|
'vulnid'
|
171
|
+
when %r{^SV-[0-9]+r[0-9]+_rule$}
|
172
|
+
'ruleid'
|
171
173
|
else
|
172
174
|
'title'
|
173
175
|
end
|
@@ -22,6 +22,7 @@ module Abide
|
|
22
22
|
add_command(JiraGetIssueCommand.new)
|
23
23
|
add_command(JiraNewIssueCommand.new)
|
24
24
|
add_command(JiraFromCoverageCommand.new)
|
25
|
+
add_command(JiraFromXccdfCommand.new)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
@@ -113,5 +114,26 @@ module Abide
|
|
113
114
|
end
|
114
115
|
end
|
115
116
|
end
|
117
|
+
|
118
|
+
class JiraFromXccdfCommand < CmdParse::Command
|
119
|
+
CMD_NAME = 'from_xccdf'
|
120
|
+
CMD_SHORT = 'Creates a parent issue with subtasks from a xccdf file'
|
121
|
+
CMD_LONG = 'Creates a parent issue with subtasks for a benchmark and any uncovered controls'
|
122
|
+
def initialize
|
123
|
+
super(CMD_NAME, takes_commands: false)
|
124
|
+
short_desc(CMD_SHORT)
|
125
|
+
long_desc(CMD_LONG)
|
126
|
+
argument_desc(PATH: 'An XCCDF file from the abide puppet ticket coverage command', PROJECT: 'A Jira project')
|
127
|
+
options.on('-d', '--dry-run', 'Print to console instead of saving objects') { |_| @data[:dry_run] = true }
|
128
|
+
end
|
129
|
+
|
130
|
+
def execute(path, project)
|
131
|
+
Abide::CLI::VALIDATE.file(path)
|
132
|
+
@data[:dry_run] = false if @data[:dry_run].nil?
|
133
|
+
client = JIRA.client(options: {})
|
134
|
+
proj = JIRA.project(client, project)
|
135
|
+
JIRA.new_issues_from_xccdf(client, proj, path, dry_run: @data[:dry_run])
|
136
|
+
end
|
137
|
+
end
|
116
138
|
end
|
117
139
|
end
|
data/lib/abide_dev_utils/jira.rb
CHANGED
@@ -135,6 +135,36 @@ module AbideDevUtils
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
+
def self.new_issues_from_xccdf(client, project, xccdf_path, dry_run: false)
|
139
|
+
dr_prefix = dry_run ? 'DRY RUN: ' : ''
|
140
|
+
i_attrs = all_project_issues_attrs(project)
|
141
|
+
|
142
|
+
xccdf = AbideDevUtils::XCCDF::Benchmark.new(xccdf_path)
|
143
|
+
|
144
|
+
summaries = summaries_from_xccdf(xccdf)
|
145
|
+
summaries.each do |profile_summary, control_summaries|
|
146
|
+
if summary_exist?(profile_summary, i_attrs)
|
147
|
+
AbideDevUtils::Output.simple("#{dr_prefix}Skipping #{profile_summary} as it already exists")
|
148
|
+
next
|
149
|
+
end
|
150
|
+
|
151
|
+
parent = new_issue(client, project.attrs['key'], profile_summary, dry_run: dry_run)
|
152
|
+
AbideDevUtils::Output.simple("#{dr_prefix}Created parent issue #{profile_summary}")
|
153
|
+
parent_issue = issue(client, parent.attrs['key']) unless parent.respond_to?(:dummy)
|
154
|
+
AbideDevUtils::Output.simple("#{dr_prefix}Creating subtasks, this can take a while...")
|
155
|
+
progress = AbideDevUtils::Output.progress(title: "#{dr_prefix}Creating Subtasks", total: nil)
|
156
|
+
control_summaries.each do |control_summary|
|
157
|
+
next if summary_exist?(control_summary, i_attrs)
|
158
|
+
|
159
|
+
progress.title = "#{dr_prefix}#{control_summary}"
|
160
|
+
new_subtask(client, parent_issue, control_summary, dry_run: dry_run)
|
161
|
+
progress.increment
|
162
|
+
end
|
163
|
+
final_text = "#{dr_prefix}Created #{control_summaries.count} subtasks for #{profile_summary}"
|
164
|
+
puts "\r\033[K#{final_text}\n"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
138
168
|
# def self.new_issues_from_comply_report(client, project, report, dry_run: false)
|
139
169
|
# dr_prefix = dry_run ? 'DRY RUN: ' : ''
|
140
170
|
# i_attrs = all_project_issues_attrs(project)
|
@@ -177,6 +207,21 @@ module AbideDevUtils
|
|
177
207
|
summaries.transform_keys { |k| "#{COV_PARENT_SUMMARY_PREFIX}#{benchmark}-#{k}"}
|
178
208
|
end
|
179
209
|
|
210
|
+
def self.summaries_from_xccdf(xccdf)
|
211
|
+
summaries = {}
|
212
|
+
facter_os = xccdf.facter_benchmark.join('-')
|
213
|
+
xccdf.profiles.each do |profile|
|
214
|
+
summaries["#{COV_PARENT_SUMMARY_PREFIX}#{facter_os} - #{profile.level} #{profile.title}"] = profile.controls.collect do |control|
|
215
|
+
summary = "#{COV_CHILD_SUMMARY_PREFIX}#{control.vulnid} - #{control.title}"
|
216
|
+
if summary.length > 255
|
217
|
+
summary = summary[0..251] + '...'
|
218
|
+
end
|
219
|
+
summary
|
220
|
+
end
|
221
|
+
end
|
222
|
+
summaries
|
223
|
+
end
|
224
|
+
|
180
225
|
# def self.summaries_from_comply_report(report)
|
181
226
|
# summaries = {}
|
182
227
|
# report.each do |_, v|
|
@@ -16,6 +16,8 @@ module AbideDevUtils
|
|
16
16
|
case type.downcase
|
17
17
|
when 'cis'
|
18
18
|
Benchmark.new(xccdf_file).gen_map(**opts)
|
19
|
+
when 'stig'
|
20
|
+
Benchmark.new(xccdf_file).gen_map(**opts)
|
19
21
|
else
|
20
22
|
raise AbideDevUtils::Errors::UnsupportedXCCDFError, "XCCDF type #{type} is unsupported!"
|
21
23
|
end
|
@@ -51,26 +53,31 @@ module AbideDevUtils
|
|
51
53
|
module Common
|
52
54
|
XPATHS = {
|
53
55
|
benchmark: {
|
54
|
-
all: '
|
55
|
-
title: '
|
56
|
-
version: '
|
56
|
+
all: 'Benchmark',
|
57
|
+
title: 'Benchmark/title',
|
58
|
+
version: 'Benchmark/version'
|
57
59
|
},
|
58
60
|
cis: {
|
59
61
|
profiles: {
|
60
|
-
all: '
|
61
|
-
relative_title: './
|
62
|
-
relative_select: './
|
62
|
+
all: 'Benchmark/Profile',
|
63
|
+
relative_title: './title',
|
64
|
+
relative_select: './select'
|
63
65
|
}
|
64
66
|
}
|
65
67
|
}.freeze
|
66
68
|
CONTROL_PREFIX = /^[\d.]+_/.freeze
|
67
69
|
UNDERSCORED = /(\s|\(|\)|-|\.)/.freeze
|
70
|
+
CIS_TITLE_MARKER = 'CIS'
|
68
71
|
CIS_NEXT_GEN_WINDOWS = /[Nn]ext_[Gg]eneration_[Ww]indows_[Ss]ecurity/.freeze
|
69
72
|
CIS_CONTROL_NUMBER = /([0-9.]+[0-9]+)/.freeze
|
70
73
|
CIS_LEVEL_CODE = /(?:_|^)([Ll]evel_[0-9]|[Ll]1|[Ll]2|[NnBb][GgLl]|#{CIS_NEXT_GEN_WINDOWS})/.freeze
|
71
74
|
CIS_CONTROL_PARTS = /#{CIS_CONTROL_NUMBER}#{CIS_LEVEL_CODE}?_+([A-Za-z].*)/.freeze
|
72
75
|
CIS_PROFILE_PARTS = /#{CIS_LEVEL_CODE}[_-]+([A-Za-z].*)/.freeze
|
73
|
-
|
76
|
+
STIG_TITLE_MARKER = 'Security Technical Implementation Guide'
|
77
|
+
STIG_CONTROL_PARTS = /(V-[0-9]+)/.freeze
|
78
|
+
STIG_PROFILE_PARTS = /(MAC-\d+)_([A-Za-z].+)/.freeze
|
79
|
+
PROFILE_PARTS = /#{CIS_PROFILE_PARTS}|#{STIG_PROFILE_PARTS}/.freeze
|
80
|
+
CONTROL_PARTS = /#{CIS_CONTROL_PARTS}|#{STIG_CONTROL_PARTS}/.freeze
|
74
81
|
|
75
82
|
def xpath(path)
|
76
83
|
@xml.xpath(path)
|
@@ -120,21 +127,41 @@ module AbideDevUtils
|
|
120
127
|
end
|
121
128
|
|
122
129
|
def profile_parts(profile)
|
123
|
-
|
124
|
-
|
125
|
-
parts = control_profile_text(profile).match(CIS_PROFILE_PARTS)
|
130
|
+
parts = control_profile_text(profile).match(PROFILE_PARTS)
|
126
131
|
raise AbideDevUtils::Errors::ProfilePartsError, profile if parts.nil?
|
127
132
|
|
128
|
-
parts[1]
|
129
|
-
|
133
|
+
if parts[1]
|
134
|
+
# CIS profile
|
135
|
+
parts[1].gsub!(/[Ll]evel_/, 'L')
|
136
|
+
parts[1..2]
|
137
|
+
elsif parts[3]
|
138
|
+
# STIG profile
|
139
|
+
parts[3..4]
|
140
|
+
else
|
141
|
+
raise AbideDevUtils::Errors::ProfilePartsError, profile
|
142
|
+
end
|
130
143
|
end
|
131
144
|
|
132
|
-
def control_parts(control
|
133
|
-
mdata = control_profile_text(control).match(
|
145
|
+
def control_parts(control)
|
146
|
+
mdata = control_profile_text(control).match(CONTROL_PARTS)
|
134
147
|
raise AbideDevUtils::Errors::ControlPartsError, control if mdata.nil?
|
135
148
|
|
136
|
-
mdata[
|
137
|
-
|
149
|
+
if mdata[1]
|
150
|
+
# CIS control
|
151
|
+
mdata[1..3]
|
152
|
+
elsif mdata[4]
|
153
|
+
# STIG control
|
154
|
+
vuln_id = mdata[4]
|
155
|
+
group = @benchmark.xpath("Group[@id='#{vuln_id}']")
|
156
|
+
if group.xpath('Rule').length != 1
|
157
|
+
raise AbideDevUtils::Errors::ControlPartsError, control
|
158
|
+
end
|
159
|
+
rule_id = group.xpath('Rule/@id').first.value
|
160
|
+
title = group.xpath('Rule/title').text
|
161
|
+
return [vuln_id, rule_id, title]
|
162
|
+
else
|
163
|
+
raise AbideDevUtils::Errors::ControlPartsError, control
|
164
|
+
end
|
138
165
|
end
|
139
166
|
|
140
167
|
def control_profile_text(item)
|
@@ -151,14 +178,6 @@ module AbideDevUtils
|
|
151
178
|
end
|
152
179
|
end
|
153
180
|
|
154
|
-
def sorted_control_classes(raw_select_list, sort_key: :number)
|
155
|
-
raw_select_list.map { |x| Control.new(x) }.sort_by(&sort_key)
|
156
|
-
end
|
157
|
-
|
158
|
-
def sorted_profile_classes(raw_profile_list, sort_key: :title)
|
159
|
-
raw_profile_list.map { |x| Profile.new(x) }.sort_by(&sort_key)
|
160
|
-
end
|
161
|
-
|
162
181
|
def ==(other)
|
163
182
|
diff_properties.map { |x| send(x) } == other.diff_properties.map { |x| other.send(x) }
|
164
183
|
end
|
@@ -172,14 +191,17 @@ module AbideDevUtils
|
|
172
191
|
class Benchmark
|
173
192
|
include AbideDevUtils::XCCDF::Common
|
174
193
|
|
175
|
-
|
194
|
+
CIS_MAP_INDICES = %w[title hiera_title hiera_title_num number].freeze
|
195
|
+
STIG_MAP_INDICES = %w[vulnid ruleid].freeze
|
176
196
|
|
177
|
-
attr_reader :xml, :title, :version, :diff_properties
|
197
|
+
attr_reader :xml, :title, :version, :diff_properties, :benchmark
|
178
198
|
|
179
199
|
def initialize(path)
|
180
200
|
@xml = parse(path)
|
181
|
-
@
|
182
|
-
@
|
201
|
+
@xml.remove_namespaces!
|
202
|
+
@benchmark = xpath('Benchmark')
|
203
|
+
@title = xpath('Benchmark/title').text
|
204
|
+
@version = xpath('Benchmark/version').text
|
183
205
|
@diff_properties = %i[title version profiles]
|
184
206
|
end
|
185
207
|
|
@@ -188,7 +210,7 @@ module AbideDevUtils
|
|
188
210
|
end
|
189
211
|
|
190
212
|
def profiles
|
191
|
-
@profiles ||= Profiles.new(xpath('
|
213
|
+
@profiles ||= Profiles.new(xpath('Benchmark/Profile'), @benchmark)
|
192
214
|
end
|
193
215
|
|
194
216
|
def profile_levels
|
@@ -200,7 +222,7 @@ module AbideDevUtils
|
|
200
222
|
end
|
201
223
|
|
202
224
|
def controls
|
203
|
-
@controls ||= Controls.new(xpath('//
|
225
|
+
@controls ||= Controls.new(xpath('//select'))
|
204
226
|
end
|
205
227
|
|
206
228
|
def controls_by_profile_level(level_code)
|
@@ -212,15 +234,22 @@ module AbideDevUtils
|
|
212
234
|
end
|
213
235
|
|
214
236
|
def gen_map(dir: nil, type: 'cis', parent_key_prefix: '', version_output_dir: false, **_)
|
215
|
-
|
237
|
+
case type
|
238
|
+
when 'cis'
|
239
|
+
os, ver = facter_platform
|
240
|
+
indicies = CIS_MAP_INDICES
|
241
|
+
when 'stig'
|
242
|
+
os, ver = facter_benchmark
|
243
|
+
indicies = STIG_MAP_INDICES
|
244
|
+
end
|
216
245
|
output_path = [type, os, ver]
|
217
246
|
output_path.unshift(File.expand_path(dir)) if dir
|
218
247
|
output_path << version if version_output_dir
|
219
248
|
mapping_dir = File.expand_path(File.join(output_path))
|
220
249
|
parent_key_prefix = '' if parent_key_prefix.nil?
|
221
|
-
|
250
|
+
indicies.each_with_object({}) do |idx, h|
|
222
251
|
map_file_path = "#{mapping_dir}/#{idx}.yaml"
|
223
|
-
h[map_file_path] = map_indexed(index: idx, framework: type, key_prefix: parent_key_prefix)
|
252
|
+
h[map_file_path] = map_indexed(indicies: indicies, index: idx, framework: type, key_prefix: parent_key_prefix)
|
224
253
|
end
|
225
254
|
end
|
226
255
|
|
@@ -240,10 +269,10 @@ module AbideDevUtils
|
|
240
269
|
}
|
241
270
|
end
|
242
271
|
|
243
|
-
def map_indexed(index: 'title', framework: 'cis', key_prefix: '')
|
272
|
+
def map_indexed(indicies: [], index: 'title', framework: 'cis', key_prefix: '')
|
244
273
|
c_map = profiles.each_with_object({}) do |profile, obj|
|
245
274
|
obj[profile.level.downcase] = {} unless obj[profile.level.downcase].is_a?(Hash)
|
246
|
-
obj[profile.level.downcase][profile.title.downcase] = map_controls_hash(profile, index).sort_by { |k, _| k }.to_h
|
275
|
+
obj[profile.level.downcase][profile.title.downcase] = map_controls_hash(profile, indicies, index).sort_by { |k, _| k }.to_h
|
247
276
|
end
|
248
277
|
|
249
278
|
c_map['benchmark'] = { 'title' => title, 'version' => version }
|
@@ -252,8 +281,13 @@ module AbideDevUtils
|
|
252
281
|
{ mappings.join('::') => c_map }.to_yaml
|
253
282
|
end
|
254
283
|
|
284
|
+
def facter_benchmark
|
285
|
+
id = xpath('Benchmark/@id').text
|
286
|
+
id.split('_')[0..-2]
|
287
|
+
end
|
288
|
+
|
255
289
|
def facter_platform
|
256
|
-
cpe = xpath('
|
290
|
+
cpe = xpath('Benchmark/platform')[0]['idref'].split(':')
|
257
291
|
if cpe.length > 4
|
258
292
|
product_name = cpe[4].split('_')
|
259
293
|
product_version = cpe[5].split('.') unless cpe[5].nil?
|
@@ -283,8 +317,8 @@ module AbideDevUtils
|
|
283
317
|
hash.to_yaml
|
284
318
|
end
|
285
319
|
|
286
|
-
def
|
287
|
-
xpath("//
|
320
|
+
def resolve_cis_control_reference(control)
|
321
|
+
xpath("//Rule[@id='#{control.reference}']")
|
288
322
|
end
|
289
323
|
|
290
324
|
private
|
@@ -294,15 +328,15 @@ module AbideDevUtils
|
|
294
328
|
when 'hiera_title_num'
|
295
329
|
control.hiera_title(number_format: true)
|
296
330
|
when 'title'
|
297
|
-
|
331
|
+
resolve_cis_control_reference(control).xpath('./title').text
|
298
332
|
else
|
299
333
|
control.send(index.to_sym)
|
300
334
|
end
|
301
335
|
end
|
302
336
|
|
303
|
-
def map_controls_hash(profile, index)
|
337
|
+
def map_controls_hash(profile, indicies, index)
|
304
338
|
profile.controls.each_with_object({}) do |ctrl, hsh|
|
305
|
-
control_array =
|
339
|
+
control_array = indicies.each_with_object([]) do |idx_sym, ary|
|
306
340
|
next if idx_sym == index
|
307
341
|
|
308
342
|
item = format_map_control_index(idx_sym, ctrl)
|
@@ -319,13 +353,9 @@ module AbideDevUtils
|
|
319
353
|
end
|
320
354
|
end
|
321
355
|
|
322
|
-
def sorted_profile_classes(raw_profile_list, sort_key: :level)
|
323
|
-
raw_profile_list.map { |x| Profile.new(x) }.sort_by(&sort_key)
|
324
|
-
end
|
325
|
-
|
326
356
|
def find_profiles
|
327
357
|
profs = {}
|
328
|
-
xpath('
|
358
|
+
xpath('Benchmark/Profile').each do |profile|
|
329
359
|
level_code, name = profile_parts(profile['id'])
|
330
360
|
profs[name] = {} unless profs.key?(name)
|
331
361
|
profs[name][level_code] = profile
|
@@ -352,11 +382,66 @@ module AbideDevUtils
|
|
352
382
|
end
|
353
383
|
end
|
354
384
|
|
355
|
-
class
|
385
|
+
class XccdfObject
|
386
|
+
include AbideDevUtils::XCCDF::Common
|
387
|
+
|
388
|
+
def initialize(benchmark)
|
389
|
+
@benchmark = benchmark
|
390
|
+
@benchmark_type = benchmark_type
|
391
|
+
end
|
392
|
+
|
393
|
+
def controls_class
|
394
|
+
case @benchmark_type
|
395
|
+
when :cis
|
396
|
+
CisControls
|
397
|
+
when :stig
|
398
|
+
StigControls
|
399
|
+
else
|
400
|
+
raise AbideDevUtils::Errors::UnsupportedXCCDFError
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
def control_sort_key
|
405
|
+
case @benchmark_type
|
406
|
+
when :cis
|
407
|
+
:number
|
408
|
+
when :stig
|
409
|
+
:vulnid
|
410
|
+
else
|
411
|
+
raise AbideDevUtils::Errors::UnsupportedXCCDFError
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
def control_class
|
416
|
+
case @benchmark_type
|
417
|
+
when :cis
|
418
|
+
CisControl
|
419
|
+
when :stig
|
420
|
+
StigControl
|
421
|
+
else
|
422
|
+
raise AbideDevUtils::Errors::UnsupportedXCCDFError
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
private
|
427
|
+
|
428
|
+
def benchmark_type
|
429
|
+
title = @benchmark.at_xpath('title').text
|
430
|
+
if title.include?(STIG_TITLE_MARKER)
|
431
|
+
return :stig
|
432
|
+
elsif title.include?(CIS_TITLE_MARKER)
|
433
|
+
return :cis
|
434
|
+
end
|
435
|
+
raise AbideDevUtils::Errors::UnsupportedXCCDFError, "XCCDF type is unsupported!"
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
class ObjectContainer < XccdfObject
|
356
440
|
include AbideDevUtils::XCCDF::Common
|
357
441
|
|
358
|
-
def initialize(list, object_creation_method, *args, **kwargs)
|
359
|
-
|
442
|
+
def initialize(list, object_creation_method, benchmark, *args, **kwargs)
|
443
|
+
super(benchmark)
|
444
|
+
@object_list = send(object_creation_method.to_sym, list, benchmark, *args, **kwargs)
|
360
445
|
@searchable = []
|
361
446
|
end
|
362
447
|
|
@@ -399,6 +484,14 @@ module AbideDevUtils
|
|
399
484
|
|
400
485
|
private
|
401
486
|
|
487
|
+
def sorted_control_classes(raw_select_list, benchmark)
|
488
|
+
raw_select_list.map { |x| control_class.new(x, benchmark) }.sort_by(&control_sort_key)
|
489
|
+
end
|
490
|
+
|
491
|
+
def sorted_profile_classes(raw_profile_list, benchmark)
|
492
|
+
raw_profile_list.map { |x| Profile.new(x, benchmark) }.sort_by(&:title)
|
493
|
+
end
|
494
|
+
|
402
495
|
def resolve_hash_key(obj)
|
403
496
|
return obj.send(:raw_title) unless defined?(@hash_key)
|
404
497
|
|
@@ -419,8 +512,8 @@ module AbideDevUtils
|
|
419
512
|
end
|
420
513
|
|
421
514
|
class Profiles < ObjectContainer
|
422
|
-
def initialize(list)
|
423
|
-
super(list, :sorted_profile_classes)
|
515
|
+
def initialize(list, benchmark)
|
516
|
+
super(list, :sorted_profile_classes, benchmark)
|
424
517
|
searchable! :level, :title
|
425
518
|
index! :title
|
426
519
|
hash_key! :level, :title
|
@@ -443,9 +536,34 @@ module AbideDevUtils
|
|
443
536
|
end
|
444
537
|
end
|
445
538
|
|
446
|
-
class
|
447
|
-
def initialize(list)
|
448
|
-
super(list, :sorted_control_classes)
|
539
|
+
class StigControls < ObjectContainer
|
540
|
+
def initialize(list, benchmark)
|
541
|
+
super(list, :sorted_control_classes, benchmark)
|
542
|
+
searchable! :vulnid, :ruleid
|
543
|
+
index! :vulnid
|
544
|
+
hash_key! :vulnid
|
545
|
+
end
|
546
|
+
|
547
|
+
def vulnids
|
548
|
+
@vulnids ||= @object_list.map(&:vulnid).sort
|
549
|
+
end
|
550
|
+
|
551
|
+
def ruleids
|
552
|
+
@ruleids ||= @object_list.map(&:ruleid).sort
|
553
|
+
end
|
554
|
+
|
555
|
+
def include_vulnid?(item)
|
556
|
+
@object_list.map(&:vulnid).include?(item)
|
557
|
+
end
|
558
|
+
|
559
|
+
def include_ruleid?(item)
|
560
|
+
@object_list.map(&:ruleid).include?(item)
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
class CisControls < ObjectContainer
|
565
|
+
def initialize(list, benchmark)
|
566
|
+
super(list, :sorted_control_classes, benchmark)
|
449
567
|
searchable! :level, :title, :number
|
450
568
|
index! :number
|
451
569
|
hash_key! :number
|
@@ -476,10 +594,11 @@ module AbideDevUtils
|
|
476
594
|
end
|
477
595
|
end
|
478
596
|
|
479
|
-
class XccdfElement
|
597
|
+
class XccdfElement < XccdfObject
|
480
598
|
include AbideDevUtils::XCCDF::Common
|
481
599
|
|
482
|
-
def initialize(element)
|
600
|
+
def initialize(element, benchmark)
|
601
|
+
super(benchmark)
|
483
602
|
@xml = element
|
484
603
|
@element_type = self.class.name.split('::').last.downcase
|
485
604
|
@raw_title = control_profile_text(element)
|
@@ -501,11 +620,12 @@ module AbideDevUtils
|
|
501
620
|
end
|
502
621
|
|
503
622
|
def reference
|
504
|
-
@reference ||= @element_type
|
623
|
+
@reference ||= @element_type.include?('control') ? @xml['idref'] : @xml['id']
|
505
624
|
end
|
506
625
|
|
507
626
|
def hiera_title(**opts)
|
508
|
-
|
627
|
+
e_type = @element_type.include?('control') ? 'control' : 'profile'
|
628
|
+
send("normalize_#{e_type}_name".to_sym, @xml, **opts)
|
509
629
|
end
|
510
630
|
|
511
631
|
private
|
@@ -527,19 +647,27 @@ module AbideDevUtils
|
|
527
647
|
end
|
528
648
|
|
529
649
|
class Profile < XccdfElement
|
530
|
-
def initialize(profile)
|
531
|
-
super(profile)
|
650
|
+
def initialize(profile, benchmark)
|
651
|
+
super(profile, benchmark)
|
532
652
|
@level, @title = profile_parts(control_profile_text(profile))
|
533
|
-
@plain_text_title = @xml.xpath('./
|
534
|
-
@controls =
|
653
|
+
@plain_text_title = @xml.xpath('./title').text
|
654
|
+
@controls = controls_class.new(xpath('./select'), benchmark)
|
535
655
|
properties :title, :level, :plain_text_title, controls: :to_h
|
536
656
|
end
|
537
657
|
end
|
538
658
|
|
539
|
-
class
|
540
|
-
def initialize(control,
|
541
|
-
super(control)
|
542
|
-
@
|
659
|
+
class StigControl < XccdfElement
|
660
|
+
def initialize(control, benchmark)
|
661
|
+
super(control, benchmark)
|
662
|
+
@vulnid, @ruleid, @title = control_parts(control_profile_text(control))
|
663
|
+
properties :vulnid, :ruleid, :title
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
class CisControl < XccdfElement
|
668
|
+
def initialize(control, benchmark)
|
669
|
+
super(control, benchmark)
|
670
|
+
@number, @level, @title = control_parts(control_profile_text(control))
|
543
671
|
properties :number, :level, :title
|
544
672
|
end
|
545
673
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abide_dev_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- abide-team
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|