abide_dev_utils 0.6.0 → 0.8.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.
@@ -1,166 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'yaml'
4
- require 'nokogiri'
5
- require 'abide_dev_utils/errors'
6
- require 'abide_dev_utils/xccdf/utils'
7
-
8
- module AbideDevUtils
9
- module XCCDF
10
- module CIS
11
- # Creates a Hiera structure by parsing a CIS XCCDF benchmark
12
- # @!attribute [r] title
13
- # @!attribute [r] version
14
- # @!attribute [r] yaml_title
15
- class Hiera
16
- include AbideDevUtils::XCCDF::Utils
17
-
18
- # CONTROL_PREFIX = /^[\d.]+_/.freeze
19
- # UNDERSCORED = /(\s|\(|\)|-|\.)/.freeze
20
- # XPATHS = {
21
- # benchmark: {
22
- # all: 'xccdf:Benchmark',
23
- # title: 'xccdf:Benchmark/xccdf:title',
24
- # version: 'xccdf:Benchmark/xccdf:version'
25
- # },
26
- # profiles: {
27
- # all: 'xccdf:Benchmark/xccdf:Profile',
28
- # relative_title: './xccdf:title',
29
- # relative_select: './xccdf:select'
30
- # }
31
- # }.freeze
32
- # NEXT_GEN_WINDOWS = /(next_generation_windows_security)/.freeze
33
-
34
- attr_reader :title, :version
35
-
36
- # Creates a new Hiera object
37
- # @param xccdf_file [String] path to an XCCDF file
38
- # @param parent_key_prefix [String] a string to be prepended to the
39
- # top-level key in the Hiera structure. Useful for namespacing
40
- # the top-level key.
41
- def initialize(xccdf_file, parent_key_prefix: nil, num: false)
42
- @doc = parse(xccdf_file)
43
- @title = xpath(CIS_XPATHS[:benchmark][:title]).children.to_s
44
- @version = xpath(CIS_XPATHS[:benchmark][:version]).children.to_s
45
- @profiles = xpath(CIS_XPATHS[:profiles][:all])
46
- @parent_key = make_parent_key(@doc, parent_key_prefix)
47
- @hash = make_hash(@doc, number_format: num)
48
- end
49
-
50
- def yaml_title
51
- normalize_string(@title)
52
- end
53
-
54
- # Convert the Hiera object to a hash
55
- # @return [Hash]
56
- def to_h
57
- @hash
58
- end
59
-
60
- # Convert the Hiera object to a string
61
- # @return [String]
62
- def to_s
63
- @hash.inspect
64
- end
65
-
66
- # Convert the Hiera object to YAML string
67
- # @return [String] YAML-formatted string
68
- def to_yaml
69
- yh = @hash.transform_keys do |k|
70
- [@parent_key, k].join('::').strip
71
- end
72
- yh.to_yaml
73
- end
74
-
75
- # If a method gets called on the Hiera object which is not defined,
76
- # this sends that method call to hash, then doc, then super.
77
- def method_missing(method, *args, &block)
78
- return true if ['exist?', 'exists?'].include?(method.to_s)
79
-
80
- return @hash.send(method, *args, &block) if @hash.respond_to?(method)
81
-
82
- return @doc.send(method, *args, &block) if @doc.respond_to?(method)
83
-
84
- super(method, *args, &block)
85
- end
86
-
87
- # Checks the respond_to? of hash, doc, or super
88
- def respond_to_missing?(method_name, include_private = false)
89
- return true if ['exist?', 'exists?'].include?(method_name.to_s)
90
-
91
- @hash || @doc || super
92
- end
93
-
94
- private
95
-
96
- attr_accessor :doc, :hash, :parent_key, :profiles
97
-
98
- # # Accepts a path to an xccdf xml file and returns a parsed Nokogiri object of the file
99
- # # @param xccdf_file [String] path to an xccdf xml file
100
- # # @return [Nokogiri::Node] A Nokogiri node object of the XML document
101
- # def parse(xccdf_file)
102
- # raise AbideDevUtils::Errors::FileNotFoundError, xccdf_file unless File.file?(xccdf_file)
103
-
104
- # Nokogiri.XML(File.open(xccdf_file))
105
- # end
106
-
107
- def make_hash(doc, number_format: false)
108
- hash = { 'title' => @title, 'version' => @version }
109
- profiles = doc.xpath('xccdf:Benchmark/xccdf:Profile')
110
- profiles.each do |p|
111
- title = normalize_profile_name(p.xpath('./xccdf:title').children.to_s)
112
- hash[title.to_s] = []
113
- selects = p.xpath('./xccdf:select')
114
- selects.each do |s|
115
- hash[title.to_s] << normalize_control_name(s['idref'].to_s, number_format: number_format)
116
- end
117
- end
118
- hash
119
- end
120
-
121
- # def normalize_str(str)
122
- # nstr = str.downcase
123
- # nstr.gsub!(/[^a-z0-9]$/, '')
124
- # nstr.gsub!(/^[^a-z]/, '')
125
- # nstr.gsub!(/^(l1_|l2_|ng_)/, '')
126
- # nstr.delete!('(/|\\|\+)')
127
- # nstr.gsub!(UNDERSCORED, '_')
128
- # nstr.strip!
129
- # nstr
130
- # end
131
-
132
- # def normalize_profile_name(prof)
133
- # prof_name = normalize_str("profile_#{prof}")
134
- # prof_name.gsub!(NEXT_GEN_WINDOWS, 'ngws')
135
- # prof_name.strip!
136
- # prof_name
137
- # end
138
-
139
- # def normalize_ctrl_name(ctrl, num)
140
- # return num_normalize_ctrl(ctrl) if num
141
-
142
- # name_normalize_ctrl(ctrl)
143
- # end
144
-
145
- # def name_normalize_ctrl(ctrl)
146
- # new_ctrl = ctrl.split('benchmarks_rule_')[-1].gsub(CONTROL_PREFIX, '')
147
- # normalize_str(new_ctrl)
148
- # end
149
-
150
- # def num_normalize_ctrl(ctrl)
151
- # part = ctrl.split('benchmarks_rule_')[-1]
152
- # numpart = CONTROL_PREFIX.match(part).to_s.chop.gsub(UNDERSCORED, '_')
153
- # "c#{numpart}"
154
- # end
155
-
156
- def make_parent_key(doc, prefix)
157
- doc_title = normalize_string(doc.xpath(CIS_XPATHS[:benchmark][:title]).children.to_s)
158
- return doc_title if prefix.nil?
159
-
160
- sepped_prefix = prefix.end_with?('::') ? prefix : "#{prefix}::"
161
- "#{sepped_prefix.chomp}#{doc_title}"
162
- end
163
- end
164
- end
165
- end
166
- end
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'abide_dev_utils/xccdf/cis/hiera'
@@ -1,85 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'nokogiri'
4
- require 'abide_dev_utils/validate'
5
- require 'pry'
6
-
7
- module AbideDevUtils
8
- module XCCDF
9
- module Utils
10
- CONTROL_PREFIX = /^[\d.]+_/.freeze
11
- UNDERSCORED = /(\s|\(|\)|-|\.)/.freeze
12
- CIS_NEXT_GEN_WINDOWS = /(next_generation_windows_security)/.freeze
13
- CIS_XPATHS = {
14
- benchmark: {
15
- all: 'xccdf:Benchmark',
16
- title: 'xccdf:Benchmark/xccdf:title',
17
- version: 'xccdf:Benchmark/xccdf:version'
18
- },
19
- profiles: {
20
- all: 'xccdf:Benchmark/xccdf:Profile',
21
- relative_title: './xccdf:title',
22
- relative_select: './xccdf:select'
23
- }
24
- }.freeze
25
-
26
- def parse(xccdf_file)
27
- AbideDevUtils::Validate.file(xccdf_file)
28
- File.open(xccdf_file) { |f| Nokogiri::XML(f) }
29
- end
30
-
31
- def normalize_string(str)
32
- nstr = str.downcase
33
- nstr.gsub!(/[^a-z0-9]$/, '')
34
- nstr.gsub!(/^[^a-z]/, '')
35
- nstr.gsub!(/^(l1_|l2_|ng_)/, '')
36
- nstr.delete!('(/|\\|\+)')
37
- nstr.gsub!(UNDERSCORED, '_')
38
- nstr.strip!
39
- nstr
40
- end
41
-
42
- def normalize_profile_name(prof)
43
- prof_name = normalize_string("profile_#{prof}")
44
- prof_name.gsub!(NEXT_GEN_WINDOWS, 'ngws')
45
- prof_name.strip!
46
- prof_name
47
- end
48
-
49
- def normalize_control_name(control, number_format: false)
50
- return number_normalize_control(control) if number_format
51
-
52
- name_normalize_control(control)
53
- end
54
-
55
- def name_normalize_control(control)
56
- new_ctrl = control.split('benchmarks_rule_')[-1].gsub(CONTROL_PREFIX, '')
57
- normalize_string(new_ctrl)
58
- end
59
-
60
- def number_normalize_control(control)
61
- part = control.split('benchmarks_rule_')[-1]
62
- numpart = CONTROL_PREFIX.match(part).to_s.chop.gsub(UNDERSCORED, '_')
63
- "c#{numpart}"
64
- end
65
-
66
- def text_normalize_control(control)
67
- control = control['idref'].to_s unless control.respond_to?(:split)
68
-
69
- control.split('benchmarks_rule_')[-1].tr('_', ' ')
70
- end
71
-
72
- def all_cis_recommendations(parsed_xccdf)
73
- parsed_xccdf.xpath('//xccdf:select').uniq
74
- end
75
-
76
- def find_cis_recommendation(name, recommendations, number_format: false)
77
- recommendations.each do |reco|
78
- if normalize_control_name(reco['idref'].to_s, number_format: number_format) == name
79
- return text_normalize_control(reco['idref'].to_s)
80
- end
81
- end
82
- end
83
- end
84
- end
85
- end