Class: AbideDevUtils::XCCDF::Benchmark

Inherits:
Object
  • Object
show all
Includes:
Common
Defined in:
lib/abide_dev_utils/xccdf.rb

Overview

Class representation of an XCCDF benchmark

Constant Summary collapse

MAP_INDICES =
%w[title hiera_title hiera_title_num number].freeze

Constants included from Common

Common::CIS_CONTROL_NUMBER, Common::CIS_CONTROL_PARTS, Common::CIS_LEVEL_CODE, Common::CIS_NEXT_GEN_WINDOWS, Common::CIS_PROFILE_PARTS, Common::CONTROL_PREFIX, Common::UNDERSCORED, Common::XPATHS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Common

#==, #abide_object?, #control_parts, #control_profile_text, #default_diff_opts, #diff, #name_normalize_control, #normalize_control_name, #normalize_profile_name, #normalize_string, #number_normalize_control, #profile_parts, #sorted_control_classes, #text_normalize, #validate_xccdf, #xpath

Constructor Details

#initialize(path) ⇒ Benchmark

Returns a new instance of Benchmark.



199
200
201
202
203
204
# File 'lib/abide_dev_utils/xccdf.rb', line 199

def initialize(path)
  @xml = parse(path)
  @title = xpath('xccdf:Benchmark/xccdf:title').text
  @version = xpath('xccdf:Benchmark/xccdf:version').text
  @diff_properties = %i[title version profiles]
end

Instance Attribute Details

#diff_propertiesObject (readonly)

Returns the value of attribute diff_properties.



197
198
199
# File 'lib/abide_dev_utils/xccdf.rb', line 197

def diff_properties
  @diff_properties
end

#titleObject (readonly)

Returns the value of attribute title.



197
198
199
# File 'lib/abide_dev_utils/xccdf.rb', line 197

def title
  @title
end

#versionObject (readonly)

Returns the value of attribute version.



197
198
199
# File 'lib/abide_dev_utils/xccdf.rb', line 197

def version
  @version
end

#xmlObject (readonly)

Returns the value of attribute xml.



197
198
199
# File 'lib/abide_dev_utils/xccdf.rb', line 197

def xml
  @xml
end

Instance Method Details

#controlsObject



222
223
224
# File 'lib/abide_dev_utils/xccdf.rb', line 222

def controls
  @controls ||= Controls.new(xpath('//xccdf:select'))
end

#controls_by_profile_level(level_code) ⇒ Object



226
227
228
# File 'lib/abide_dev_utils/xccdf.rb', line 226

def controls_by_profile_level(level_code)
  profiles.select { |x| x.level == level_code }.map(&:controls).flatten.uniq
end

#controls_by_profile_title(profile_title) ⇒ Object



230
231
232
# File 'lib/abide_dev_utils/xccdf.rb', line 230

def controls_by_profile_title(profile_title)
  profiles.select { |x| x.title == profile_title }.controls
end

#diff_controls(other) ⇒ Object



283
284
285
# File 'lib/abide_dev_utils/xccdf.rb', line 283

def diff_controls(other)
  controls.diff(other.controls)
end

#diff_profiles(other) ⇒ Object



268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/abide_dev_utils/xccdf.rb', line 268

def diff_profiles(other)
  this_diff = {}
  other_hash = other.to_h[:profiles]
  to_h[:profiles].each do |name, data|
    diff_h = Hashdiff.diff(data, other_hash[name], default_diff_opts).each_with_object({}) do |x, a|
      val_to = x.length == 4 ? x[3] : nil
      a_key = x[2].is_a?(Hash) ? x[2][:title] : x[2]
      a[a_key] = [] unless a.key?(a_key)
      a[a_key] << ChangeSet.new(change: x[0], key: x[1], value: x[2], value_to: val_to)
    end
    this_diff[name] = diff_h
  end
  this_diff
end

#diff_title_version(other) ⇒ Object



260
261
262
263
264
265
266
# File 'lib/abide_dev_utils/xccdf.rb', line 260

def diff_title_version(other)
  Hashdiff.diff(
    to_h.reject { |k, _| k.to_s == 'profiles' },
    other.to_h.reject { |k, _| k.to_s == 'profiles' },
    default_diff_opts
  )
end

#facter_platformObject



299
300
301
302
# File 'lib/abide_dev_utils/xccdf.rb', line 299

def facter_platform
  cpe = xpath('xccdf:Benchmark/xccdf:platform')[0]['idref'].split(':')
  [cpe[4].split('_')[0], cpe[5].split('.')[0]]
end

#find_cis_recommendation(name, number_format: false) ⇒ Object



244
245
246
247
248
249
250
# File 'lib/abide_dev_utils/xccdf.rb', line 244

def find_cis_recommendation(name, number_format: false)
  profiles.each do |profile|
    profile.controls.each do |ctrl|
      return [profile, ctrl] if normalize_control_name(ctrl, number_format: number_format) == name
    end
  end
end

#gen_map(dir: nil, type: 'CIS', parent_key_prefix: '', **_) ⇒ Object



234
235
236
237
238
239
240
241
242
# File 'lib/abide_dev_utils/xccdf.rb', line 234

def gen_map(dir: nil, type: 'CIS', parent_key_prefix: '', **_)
  os, ver = facter_platform
  mapping_dir = dir ? File.expand_path(File.join(dir, type, os, ver)) : ''
  parent_key_prefix = '' if parent_key_prefix.nil?
  MAP_INDICES.each_with_object({}) do |idx, h|
    map_file_path = "#{mapping_dir}/#{idx}.yaml"
    h[map_file_path] = map_indexed(index: idx, framework: type, key_prefix: parent_key_prefix)
  end
end

#map_indexed(index: 'title', framework: 'cis', key_prefix: '') ⇒ Object



287
288
289
290
291
292
293
294
295
296
297
# File 'lib/abide_dev_utils/xccdf.rb', line 287

def map_indexed(index: 'title', framework: 'cis', key_prefix: '')
  c_map = profiles.each_with_object({}) do |profile, obj|
    obj[profile.level.downcase] = {} unless obj[profile.level.downcase].is_a?(Hash)
    obj[profile.level.downcase][profile.title.downcase] = map_controls_hash(profile, index).sort_by { |k, _| k }.to_h
  end

  c_map['benchmark'] = { 'title' => title, 'version' => version }
  mappings = [framework, index]
  mappings.unshift(key_prefix) unless key_prefix.empty?
  { mappings.join('::') => c_map }.to_yaml
end

#normalized_titleObject



206
207
208
# File 'lib/abide_dev_utils/xccdf.rb', line 206

def normalized_title
  normalize_string(title)
end

#profile_levelsObject



214
215
216
# File 'lib/abide_dev_utils/xccdf.rb', line 214

def profile_levels
  @profiles.levels
end

#profile_titlesObject



218
219
220
# File 'lib/abide_dev_utils/xccdf.rb', line 218

def profile_titles
  @profiles.titles
end

#profilesObject



210
211
212
# File 'lib/abide_dev_utils/xccdf.rb', line 210

def profiles
  @profiles ||= Profiles.new(xpath('xccdf:Benchmark/xccdf:Profile'))
end

#resolve_control_reference(control) ⇒ Object



321
322
323
# File 'lib/abide_dev_utils/xccdf.rb', line 321

def resolve_control_reference(control)
  xpath("//xccdf:Rule[@id='#{control.reference}']")
end

#to_hObject



252
253
254
255
256
257
258
# File 'lib/abide_dev_utils/xccdf.rb', line 252

def to_h
  {
    title: title,
    version: version,
    profiles: profiles.to_h
  }
end

#to_hiera(parent_key_prefix: nil, num: false, levels: [], titles: [], **_kwargs) ⇒ String

Converts object to Hiera-formatted YAML

Returns:

  • (String)

    YAML-formatted string



306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'lib/abide_dev_utils/xccdf.rb', line 306

def to_hiera(parent_key_prefix: nil, num: false, levels: [], titles: [], **_kwargs)
  hash = { 'title' => title, 'version' => version }
  key_prefix = hiera_parent_key(parent_key_prefix)
  profiles.each do |profile|
    next unless levels.empty? || levels.include?(profile.level)
    next unless titles.empty? || titles.include?(profile.title)

    hash[profile.hiera_title] = hiera_controls_for_profile(profile, num)
  end
  hash.transform_keys! do |k|
    [key_prefix, k].join('::').strip
  end
  hash.to_yaml
end