abide-data-processor 0.3.0 → 1.1.1
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 +11 -25
- data/README.md +278 -7
- data/abide-data-processor.gemspec +4 -2
- data/lib/abide-data-processor/parser.rb +741 -0
- data/lib/abide-data-processor/processor.rb +4 -275
- data/lib/abide-data-processor/version.rb +1 -1
- metadata +22 -7
@@ -1,283 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'set'
|
3
|
+
require 'abide-data-processor/parser'
|
5
4
|
|
6
5
|
module AbideDataProcessor
|
7
6
|
module Processor
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# @param control_maps: The control mappings to valid IDs
|
12
|
-
# @param module_name: The name of the module
|
13
|
-
# @param logger: The logger that we will use to log information for the user
|
14
|
-
def initialize(control_maps, logger)
|
15
|
-
@control_maps = control_maps
|
16
|
-
@logger = logger
|
17
|
-
end
|
18
|
-
|
19
|
-
# control_key_maps
|
20
|
-
# Gets all control key maps from Hiera for indexed control ID permutation searches
|
21
|
-
# @return An array of four control ID maps, each indexed by one of the four different valid permutations of a control ID
|
22
|
-
def self.control_key_maps(module_name)
|
23
|
-
key_prefix = "#{module_name}::mappings::cis"
|
24
|
-
%w[hiera_title hiera_title_num number title].each_with_object([]) do |key, ary|
|
25
|
-
ary << [key_prefix, key].join('::')
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def cis_hiera_key(prefix, key)
|
30
|
-
"#{prefix}::#{key}"
|
31
|
-
end
|
32
|
-
|
33
|
-
# create_resources
|
34
|
-
# @param resources_hash: the hash of controls to be enforces, user will provide this
|
35
|
-
# @param only: the list of controls to be enforce only, pulled from cis.pp
|
36
|
-
# @param ignore: the list of controls to be ignore, pulled from cis.pp
|
37
|
-
# @param control_configs: the custom control configurations pulled from cis.pp
|
38
|
-
# Return a hash to be convert to Puppet code.
|
39
|
-
def create_resources(resources_hash, only, ignore, control_configs)
|
40
|
-
unfreezed_resources = Marshal.load(Marshal.dump(resources_hash))
|
41
|
-
resources = real_resources(unfreezed_resources, only.to_set, ignore.to_set, control_configs)
|
42
|
-
ordered_resources = order_resources(resources)
|
43
|
-
|
44
|
-
mutate_ordering_params!(ordered_resources[1])
|
45
|
-
ordered_resources
|
46
|
-
end
|
47
|
-
|
48
|
-
# Everything else except the create_resource function will be private
|
49
|
-
private
|
50
|
-
|
51
|
-
# real_resources
|
52
|
-
# Formats a Hiera resources hash into a hash used by order_resources()
|
53
|
-
# @param resources_hash The raw resources hash pulled from hiera
|
54
|
-
# @param only The $only parameter from cis.pp
|
55
|
-
# @param ignore The $ignore parameter from cis.pp
|
56
|
-
# @param control_configs The $control_configs parameter from cis.pp
|
57
|
-
def real_resources(resources_hash, only, ignore, control_configs)
|
58
|
-
real_resources = {}
|
59
|
-
all_controls_name = Set.new # subject to change
|
60
|
-
|
61
|
-
# Grabbing all the control name here into a set
|
62
|
-
resources_hash.each do |_title, data|
|
63
|
-
all_controls_name |= data['controls'].keys.to_set
|
64
|
-
end
|
65
|
-
|
66
|
-
resources_hash.each do |title, data|
|
67
|
-
resource_params = if data.key?('controls')
|
68
|
-
extract_control_params(data['controls'], only, ignore, control_configs, all_controls_name)
|
69
|
-
else
|
70
|
-
{}
|
71
|
-
end
|
72
|
-
if real_resources.key?(data['type']) && real_resources[data['type']].key?(title)
|
73
|
-
real_resources[data['type']][title].deep_merge!(resource_params, merge_hash_arrays: true)
|
74
|
-
else
|
75
|
-
real_resources[data['type']] = { title => resource_params }
|
76
|
-
end
|
77
|
-
end
|
78
|
-
real_resources
|
79
|
-
end
|
80
|
-
|
81
|
-
# extract_control_params
|
82
|
-
# Extracts resource parameters from a Hiera resource hash item's `controls` key
|
83
|
-
# @param control_data The resource hash item's `controls` key-value pair (i.e. data['controls'])
|
84
|
-
# @param only The $only parameter from cis.pp
|
85
|
-
# @param ignore The $ignore parameter from cis.pp
|
86
|
-
# @param control_configs The $control_configs parameter from cis.pp
|
87
|
-
# @param all_controls_name: All of the controls name
|
88
|
-
def extract_control_params(control_data, only, ignore, control_configs, all_controls_name)
|
89
|
-
control_params = {}
|
90
|
-
control_data.each do |name, params|
|
91
|
-
name_map = map_for_control_name(name, @control_maps)
|
92
|
-
next if name_map.nil?
|
93
|
-
# Only and ignore list check
|
94
|
-
# The name_map that got passed in here is a hash
|
95
|
-
next unless only_and_ignore_check(name, name_map, only, ignore)
|
96
|
-
|
97
|
-
# Control dependent check
|
98
|
-
if params.key?('dependent')
|
99
|
-
unless dependent_check(all_controls_name, params['dependent'], ignore, only)
|
100
|
-
# Below is just a sure fire way to make sure that we will never use the resource
|
101
|
-
only.delete(name) # Remove from the only list
|
102
|
-
ignore.add(name) # Add the name of the current control to the ignore list if we're not gonna enforce it
|
103
|
-
@logger.debug("Control #{name} will not be enforced because the controls that it depends on is invalid.")
|
104
|
-
next
|
105
|
-
end
|
106
|
-
end
|
107
|
-
# Find if there are any custom control configs from the cis.pp based on the control's name and its permutation
|
108
|
-
customized = find_control_customization(name, name_map[name], control_configs) # Check for failuer here
|
109
|
-
params.deep_merge!(customized, merge_hash_arrays: true)
|
110
|
-
control_params.deep_merge!(params, merge_hash_arrays: true)
|
111
|
-
end
|
112
|
-
control_params
|
113
|
-
end
|
114
|
-
|
115
|
-
# dependent_check
|
116
|
-
# @param all_controls_name: Set of all controls name that parsed from the hiera data
|
117
|
-
# @param all_dependent_resources: An array of all the resources that is relied upon
|
118
|
-
# @param ignore: List of controls to be ignore
|
119
|
-
# @param only: List of only controls that need to be enforce
|
120
|
-
# return true if a dependent control is
|
121
|
-
def dependent_check(all_controls_name, all_dependent_resources, ignore, only)
|
122
|
-
all_dependent_resources.each do |resource_name|
|
123
|
-
valid_resource_name = map_for_control_name(resource_name, @control_maps)
|
124
|
-
# Bounce immediately if it is not a part of the controls we're enforcing
|
125
|
-
return false unless filter_function(resource_name, valid_resource_name, all_controls_name)
|
126
|
-
|
127
|
-
if !ignore.empty?
|
128
|
-
return false if filter_function(resource_name, valid_resource_name, ignore)
|
129
|
-
elsif !only.empty?
|
130
|
-
return false unless filter_function(resource_name, valid_resource_name, only)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
# order_resources
|
136
|
-
# A work in progress to integrate more metaparamenters in
|
137
|
-
# Checks for and creates resources based off of `before`, `after`, `notify`, `require` parameters
|
138
|
-
# specified in a controls hash
|
139
|
-
# @param resources Output of real_resources()
|
140
|
-
# @return An array of resource hashes indexed in the order their contents should be created
|
141
|
-
def order_resources(resources)
|
142
|
-
before = {}
|
143
|
-
after = {}
|
144
|
-
req = {}
|
145
|
-
notify = {}
|
146
|
-
resources.each do |_, data|
|
147
|
-
create_ordered_resource!('before', before, data)
|
148
|
-
create_ordered_resource!('notify', notify, data)
|
149
|
-
create_ordered_resource!('after', after, data)
|
150
|
-
create_ordered_resource!('require', req, data)
|
151
|
-
end
|
152
|
-
|
153
|
-
before.deep_merge!(notify)
|
154
|
-
after.deep_merge!(req)
|
155
|
-
|
156
|
-
[before, resources, after]
|
157
|
-
end
|
158
|
-
|
159
|
-
# filter_function
|
160
|
-
# A general function to see if a control name is in a supply list of control name
|
161
|
-
# @param name: The name of the control that we have
|
162
|
-
# @param name_map: Hash that contains all valid control ID permutation of the param name
|
163
|
-
# @set_of_control: Either the ignore or the only list to go through
|
164
|
-
# return true if control ID is found in set_of_control
|
165
|
-
def filter_function(name, name_map, set_of_control)
|
166
|
-
name_list = name_map[name] # Grab the array that contain all valid permutation of the ID
|
167
|
-
return true if set_of_control.include?(name)
|
168
|
-
|
169
|
-
name_list.each do |n|
|
170
|
-
return true if set_of_control.include?(n)
|
171
|
-
end
|
172
|
-
|
173
|
-
false
|
174
|
-
end
|
175
|
-
|
176
|
-
# only_and_ignore_check
|
177
|
-
# @param name: name of the control to check if it's in either only or ignore list
|
178
|
-
# @param name_map: a hash of the name map of valid ID permutation for the `name` param
|
179
|
-
# @param only: the list of controls that will get enforced only
|
180
|
-
# @param ignore: the list of controls that will be ignored
|
181
|
-
# @return false when control is either not in the only list or is in the ignore list.
|
182
|
-
# else return true
|
183
|
-
def only_and_ignore_check(name, name_map, only, ignore)
|
184
|
-
if !only.empty? && !filter_function(name, name_map, only)
|
185
|
-
@logger.debug("Control #{name} will be skipped because it is not in the only list.")
|
186
|
-
return false
|
187
|
-
end
|
188
|
-
|
189
|
-
if !ignore.empty? && filter_function(name, name_map, ignore)
|
190
|
-
@logger.debug("Control #{name} will be skipped because it is in the ignore list.")
|
191
|
-
return false
|
192
|
-
end
|
193
|
-
true
|
194
|
-
end
|
195
|
-
|
196
|
-
# create_ordered_resource!
|
197
|
-
# Creates a resource hash from a resource declaration found in a `before`, `after`, `require`, or `notify` parameter
|
198
|
-
# @param order_key Either 'before', 'after', `notify`, or `require`
|
199
|
-
# @param container Either the before hash, the notify hash, the require hash or the after hash.
|
200
|
-
# The container is modified in place.
|
201
|
-
# @param res_data Resource data from the real_resources hash
|
202
|
-
def create_ordered_resource!(order_key, container, res_data)
|
203
|
-
res_data.each do |_, data|
|
204
|
-
next unless data.key?(order_key)
|
205
|
-
|
206
|
-
data[order_key].each do |title, params|
|
207
|
-
container[params['type']] = {} unless container.key?(params['type'])
|
208
|
-
container[params['type']][title] = params.reject { |k, _| k == 'type' }
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
# mutate_ordering_params!
|
214
|
-
# This takes the Hiera resource declarations in a `before` or `after` param and transforms
|
215
|
-
# them into and array of Puppet resource references. Puppet resource references take the
|
216
|
-
# form: Resource::Type['<resource title'].
|
217
|
-
# @param resources Output from real_resources()
|
218
|
-
def mutate_ordering_params!(resources)
|
219
|
-
resources.each do |res_type, res_data|
|
220
|
-
%w[before notify after require].each do |order_key|
|
221
|
-
res_data.each do |res_title, params|
|
222
|
-
next unless params.key?(order_key)
|
223
|
-
|
224
|
-
references = []
|
225
|
-
params[order_key].each do |k, v|
|
226
|
-
references << resource_reference(v['type'], k)
|
227
|
-
end
|
228
|
-
resources[res_type][res_title][order_key] = references
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
# resource_reference
|
235
|
-
# Returns a Puppet resource reference string
|
236
|
-
# @param res_type A Puppet resource type
|
237
|
-
# @param title A Puppet resource title
|
238
|
-
def resource_reference(res_type, title)
|
239
|
-
type_ref = res_type.split('::').map(&:capitalize).join('::')
|
240
|
-
"#{type_ref}[#{title}]"
|
241
|
-
end
|
242
|
-
|
243
|
-
# find_control_customization
|
244
|
-
# Finds any control parameter customizations passed in via control_configs
|
245
|
-
# @param name The control name (or other valid permutation)
|
246
|
-
# @param control_configs The $control_configs parameter from cis.pp
|
247
|
-
# @param name_map: The array of valid permutation of name
|
248
|
-
# @return A hash of customized parameters. If none were found, nil
|
249
|
-
def find_control_customization(name, name_map, control_configs)
|
250
|
-
return {} if control_configs.empty?
|
251
|
-
|
252
|
-
mapped_key(control_configs, name, name_map)
|
253
|
-
end
|
254
|
-
|
255
|
-
# map_for_control_name
|
256
|
-
# Returns a hash of all valid permutations of the given control id
|
257
|
-
# @param name The control name or other valid permutation
|
258
|
-
# @param maps All maps
|
259
|
-
def map_for_control_name(name, maps)
|
260
|
-
maps.each do |map|
|
261
|
-
return map if map&.fetch(name, false) # returns the map if fetch returns false
|
262
|
-
end
|
263
|
-
nil
|
264
|
-
end
|
265
|
-
|
266
|
-
# mapped_key
|
267
|
-
# Finds an item in the given hash that matches one of the values in name_map
|
268
|
-
# @param hsh The hash to search i.e the custom config hash
|
269
|
-
# @param name The name of the current control that we're looking to see if it has any custom configs
|
270
|
-
# @param name_map An array name for valid control permutations
|
271
|
-
# @return The value from the hash if found, or nil
|
272
|
-
def mapped_key(hsh, name, name_map)
|
273
|
-
return hsh[name] if hsh&.fetch(name, false)
|
274
|
-
|
275
|
-
name_map.each do |pkey|
|
276
|
-
return hsh[pkey] if hsh&.fetch(pkey, false)
|
277
|
-
end
|
278
|
-
nil
|
279
|
-
end
|
280
|
-
|
7
|
+
def self.create_resources(resources_hash, control_maps, only, ignore, control_configs)
|
8
|
+
unfrozen_resources = Marshal.load(Marshal.dump(resources_hash))
|
9
|
+
AbideDataProcessor::Parser.parse(unfrozen_resources, control_maps, only: only, ignore: ignore, control_configs: control_configs)
|
281
10
|
end
|
282
11
|
end
|
283
12
|
end
|
metadata
CHANGED
@@ -1,29 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abide-data-processor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- abide-team
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: deep_merge
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rgl
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.5'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
40
|
+
version: '0.5'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -241,6 +255,7 @@ files:
|
|
241
255
|
- bin/setup
|
242
256
|
- lib/abide-data-processor.rb
|
243
257
|
- lib/abide-data-processor/logger.rb
|
258
|
+
- lib/abide-data-processor/parser.rb
|
244
259
|
- lib/abide-data-processor/processor.rb
|
245
260
|
- lib/abide-data-processor/version.rb
|
246
261
|
homepage: https://github.com/puppetlabs/abide-data-processor
|