cem_spec_helper 0.1.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 +7 -0
- data/CHANGELOG.md +5 -0
- data/CODEOWNERS +1 -0
- data/LICENSE.txt +21 -0
- data/README.md +16 -0
- data/Rakefile +8 -0
- data/lib/cem_spec_helper/mapping_data_spec.rb +127 -0
- data/lib/cem_spec_helper/resource_data_spec.rb +164 -0
- data/lib/cem_spec_helper/version.rb +5 -0
- data/lib/cem_spec_helper.rb +20 -0
- data/sig/cem_spec_helper.rbs +4 -0
- metadata +57 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 51e588d74479bd14587fff43945c874086cf658ac9527515fa575a99ea066d82
|
4
|
+
data.tar.gz: f9423bb06d63509853cb5245c694b55cdb000a9a900a83bfd0436f75b0b59a2a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 79d0477dffb4aa1ed729761da0660146335652526f0be9abed5ef55bdac601f3df96d0aa6f0125f77355d62d8023315927aa483ca806a4be907c6f5973822f18
|
7
|
+
data.tar.gz: 221401fe507c2cb80f07f7ffde91bc53f508e6e614cf4101ac2e60f7d64926cba5322dd5a6d8a977b85daf6e1fa82955d753b8e30e4e375181a527627fd6327e
|
data/CHANGELOG.md
ADDED
data/CODEOWNERS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* @puppetlabs/abide-team
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 Perforce Software
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# CemSpecHelper
|
2
|
+
|
3
|
+
CemSpecHelper provides methods, classes, modules, etc. to help with RSpec testing the CEM modules.
|
4
|
+
|
5
|
+
Currently, this provides the backing methods for the CEM data tests.
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
Make sure that `cem_spec_helper` is declared as a dependency in the module's `Gemfile`. Then, add this to `spec/spec_helper.rb`:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
require 'cem_spec_helper'
|
13
|
+
include CemSpecHelper
|
14
|
+
```
|
15
|
+
|
16
|
+
Then you're all set.
|
data/Rakefile
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module CemSpecHelper
|
6
|
+
module MappingDataSpec
|
7
|
+
MAP_ROOT = File.join(Dir.pwd, 'spec', 'fixtures', 'data', 'mapping').freeze
|
8
|
+
SYNTHETIC_MAP_ROOT = File.join(Dir.pwd, 'spec', 'fixtures', 'unit', 'puppet_x', 'puppetlabs', 'cem', 'data_processor', 'mapping').freeze
|
9
|
+
|
10
|
+
def load_mapping_data
|
11
|
+
# Get frameworks with maps
|
12
|
+
Dir[File.join(MAP_ROOT, '*')].each_with_object([]) do |fw_dir, arr|
|
13
|
+
framework = File.basename(fw_dir)
|
14
|
+
# Get OS' in frameworks
|
15
|
+
Dir[File.join(fw_dir, '*')].each do |os_dir|
|
16
|
+
os = File.basename(os_dir)
|
17
|
+
# Get major OS versions in OS'
|
18
|
+
Dir[File.join(os_dir, '*')].each do |ver_dir|
|
19
|
+
ver = File.basename(ver_dir)
|
20
|
+
mapping = Mapping.new(framework, os, ver)
|
21
|
+
# Get map names and load map files
|
22
|
+
Dir[File.join(ver_dir, '*.yaml')].each do |map_file|
|
23
|
+
map_type = File.basename(map_file, '.yaml')
|
24
|
+
mapping.add_map(map_type, map_file)
|
25
|
+
end
|
26
|
+
arr << mapping
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def load_synthetic_mapping_data
|
33
|
+
# Get frameworks with maps
|
34
|
+
Dir[File.join(SYNTHETIC_MAP_ROOT, '*')].each_with_object([]) do |fw_dir, arr|
|
35
|
+
framework = File.basename(fw_dir)
|
36
|
+
mapping = Mapping.new(framework, 'Synthetic', '1')
|
37
|
+
# Get map names and load map files
|
38
|
+
Dir[File.join(fw_dir, '*.yaml')].each do |map_file|
|
39
|
+
map_type = File.basename(map_file, '.yaml')
|
40
|
+
mapping.add_map(map_type, map_file)
|
41
|
+
end
|
42
|
+
arr << mapping
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def synthetic_mapping_data
|
47
|
+
@synthetic_mapping_data ||= load_synthetic_mapping_data
|
48
|
+
end
|
49
|
+
|
50
|
+
def mapping_data
|
51
|
+
@mapping_data ||= load_mapping_data
|
52
|
+
end
|
53
|
+
|
54
|
+
class Mapping
|
55
|
+
attr_reader :framework, :os, :majver, :module_name
|
56
|
+
|
57
|
+
def initialize(framework, os, majver, module_name: 'cem_linux')
|
58
|
+
@framework = framework
|
59
|
+
@os = os
|
60
|
+
@majver = majver
|
61
|
+
@module_name = module_name
|
62
|
+
@maps = {}
|
63
|
+
end
|
64
|
+
|
65
|
+
def maps
|
66
|
+
@maps.values
|
67
|
+
end
|
68
|
+
|
69
|
+
def add_map(type, map_file)
|
70
|
+
@maps[type] = YAML.load_file(map_file)
|
71
|
+
end
|
72
|
+
|
73
|
+
def map_types
|
74
|
+
@maps.keys
|
75
|
+
end
|
76
|
+
|
77
|
+
def verify_map_size(keys_with_array_val = find_keys_with_array_val(@maps.dup))
|
78
|
+
result = keys_with_array_val.each_with_object([]) do |(id, map), res|
|
79
|
+
actual_length = 1 + map.length
|
80
|
+
res << id if actual_length != map_types.length
|
81
|
+
end
|
82
|
+
raise "IDs with incorrect map size:\n#{result.join("\n")}" unless result.empty?
|
83
|
+
|
84
|
+
true
|
85
|
+
end
|
86
|
+
|
87
|
+
def verify_one_to_one
|
88
|
+
results = @maps.keys.each_with_object([]) do |t, arr|
|
89
|
+
keys_with_array_val = find_keys_with_array_val(@maps[t])
|
90
|
+
keys_with_array_val.each do |k, v|
|
91
|
+
keys_with_array_val.each do |o_k, o_v|
|
92
|
+
next if o_k == k
|
93
|
+
|
94
|
+
diff = v - o_v
|
95
|
+
arr << k if diff.length < v.length
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
results.compact!
|
100
|
+
results.uniq!
|
101
|
+
raise "IDs with one-to-many or many-to-many relationships:\n#{results.join("\n")}" unless results.empty?
|
102
|
+
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_s
|
107
|
+
"Mapping[#{framework}, #{os}, #{majver}]"
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def top_key(type)
|
113
|
+
[module_name, 'mappings', framework, type].join('::')
|
114
|
+
end
|
115
|
+
|
116
|
+
def find_keys_with_array_val(hsh)
|
117
|
+
results = {}
|
118
|
+
hsh.each do |key, val|
|
119
|
+
results[key] = val if val.is_a?(Array)
|
120
|
+
|
121
|
+
results.merge!(find_keys_with_array_val(val)) if val.is_a?(Hash)
|
122
|
+
end
|
123
|
+
results
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module CemSpecHelper
|
6
|
+
module ResourceDataSpec
|
7
|
+
DATA_ROOT = File.join(Dir.pwd, 'spec', 'fixtures', 'data')
|
8
|
+
REDHAT_FAMILY_ROOT = File.join(DATA_ROOT, 'RedHat')
|
9
|
+
REDHAT_ROOT_DIR = File.join(REDHAT_FAMILY_ROOT, 'RedHat')
|
10
|
+
REDHAT_MAJVER = [7, 8].freeze
|
11
|
+
CENTOS_ROOT_DIR = File.join(REDHAT_FAMILY_ROOT, 'CentOS')
|
12
|
+
CENTOS_MAJVER = [7].freeze
|
13
|
+
ORACLE_ROOT_DIR = File.join(REDHAT_FAMILY_ROOT, 'OracleLinux')
|
14
|
+
ORACLE_MAJVER = [7, 8].freeze
|
15
|
+
ALMA_ROOT_DIR = File.join(REDHAT_FAMILY_ROOT, 'AlmaLinux')
|
16
|
+
ALMA_MAJVER = [8].freeze
|
17
|
+
WINDOWS_ROOT_DIR = File.join(DATA_ROOT, 'windows')
|
18
|
+
WINDOWS_MAJVER = [10, 2016, 2019, 2022].freeze
|
19
|
+
|
20
|
+
SYNTHETIC_DATA_ROOT = File.join(Dir.pwd, 'spec', 'fixtures', 'unit', 'puppet_x', 'puppetlabs', 'cem', 'data_processor')
|
21
|
+
|
22
|
+
SPECIAL_CONTROLS = ['cem_options', 'cem_protected'].freeze
|
23
|
+
|
24
|
+
def find_resource_data(distro, majver = nil, as_objects: false)
|
25
|
+
case distro
|
26
|
+
when 'RedHat'
|
27
|
+
redhat_resource_data(majver, as_objects: as_objects)
|
28
|
+
when 'CentOS'
|
29
|
+
centos_resource_data(majver, as_objects: as_objects)
|
30
|
+
when 'OracleLinux'
|
31
|
+
oracle_resource_data(majver, as_objects: as_objects)
|
32
|
+
when 'AlmaLinux'
|
33
|
+
alma_resource_data(majver, as_objects: as_objects)
|
34
|
+
when 'Windows'
|
35
|
+
windows_resource_data(majver, as_objects: as_objects)
|
36
|
+
when 'Synthetic'
|
37
|
+
load_resource_data(SYNTHETIC_DATA_ROOT, 'test_resource_data', as_objects: as_objects)
|
38
|
+
else
|
39
|
+
raise "Unknown distro: #{distro}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def redhat_resource_data(majver = nil, as_objects: false)
|
44
|
+
raise ArgumentError, "major version #{majver} not found" unless majver.nil? || REDHAT_MAJVER.include?(majver.to_i)
|
45
|
+
|
46
|
+
load_resource_data(REDHAT_ROOT_DIR, majver, as_objects: as_objects)
|
47
|
+
end
|
48
|
+
|
49
|
+
def centos_resource_data(majver = nil, as_objects: false)
|
50
|
+
raise ArgumentError, "major version #{majver} not found" unless majver.nil? || CENTOS_MAJVER.include?(majver.to_i)
|
51
|
+
|
52
|
+
load_resource_data(CENTOS_ROOT_DIR, majver, as_objects: as_objects)
|
53
|
+
end
|
54
|
+
|
55
|
+
def oracle_resource_data(majver = nil, as_objects: false)
|
56
|
+
raise ArgumentError, "major version #{majver} not found" unless majver.nil? || ORACLE_MAJVER.include?(majver.to_i)
|
57
|
+
|
58
|
+
load_resource_data(ORACLE_ROOT_DIR, majver, as_objects: as_objects)
|
59
|
+
end
|
60
|
+
|
61
|
+
def alma_resource_data(majver = nil, as_objects: false)
|
62
|
+
raise ArgumentError, "major version #{majver} not found" unless majver.nil? || ALMA_MAJVER.include?(majver.to_i)
|
63
|
+
|
64
|
+
load_resource_data(ALMA_ROOT_DIR, majver, as_objects: as_objects)
|
65
|
+
end
|
66
|
+
|
67
|
+
def windows_resource_data(majver = nil, as_objects: false)
|
68
|
+
raise ArgumentError, "major version #{majver} not found" unless majver.nil? || WINDOWS_MAJVER.include?(majver.to_i)
|
69
|
+
|
70
|
+
load_resource_data(WINDOWS_ROOT_DIR, majver, as_objects: as_objects)
|
71
|
+
end
|
72
|
+
|
73
|
+
def synthetic_resource_data(as_objects: false)
|
74
|
+
load_resource_data(SYNTHETIC_DATA_ROOT, 'test_resource_data', as_objects: as_objects)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Finds all resources that only implement a single control
|
78
|
+
# @param distro [String]
|
79
|
+
# @param majver [String]
|
80
|
+
# @param benchmark [String] either cis or stig
|
81
|
+
# @return [Hash] A hash of control_name => [resource type, resource title]
|
82
|
+
def single_control_resources(distro, majver = nil, benchmark = 'cis')
|
83
|
+
resources = find_resource_data(distro, majver, as_objects: true)
|
84
|
+
resources.select! { |res| res.controls(include_special: false).length == 1 }
|
85
|
+
resources.map! do |res|
|
86
|
+
[res.controls.first, [res.type, res.title]]
|
87
|
+
end
|
88
|
+
resources = resources.to_h
|
89
|
+
# Reduce to just benchmark-related keypairs
|
90
|
+
case benchmark
|
91
|
+
when 'cis'
|
92
|
+
resources.reject! { |k, _v| k.match?(%r{^V-}) }
|
93
|
+
when 'stig'
|
94
|
+
resources.select! { |k, _v| k.match?(%r{^V-}) }
|
95
|
+
end
|
96
|
+
resources
|
97
|
+
end
|
98
|
+
|
99
|
+
def load_resource_data(root_dir, majver = nil, as_objects: false)
|
100
|
+
raise "root_dir \"#{root_dir}\" is not a valid path" unless File.directory?(root_dir)
|
101
|
+
|
102
|
+
unless majver.nil?
|
103
|
+
file_path = File.join(root_dir, "#{majver}.yaml")
|
104
|
+
raise "Resource data file \"#{file_path}\" not found" unless File.file?(file_path)
|
105
|
+
|
106
|
+
resources = YAML.load_file(file_path)['cem_linux::resources']
|
107
|
+
final_resources = as_objects ? resources.map { |k, v| Resource.new(k, v) } : resources
|
108
|
+
return final_resources
|
109
|
+
end
|
110
|
+
|
111
|
+
Dir[File.join(root_dir, '*')].each_with_object({}) do |rdata, hsh|
|
112
|
+
resources = YAML.load_file(rdata)['cem_linux::resources']
|
113
|
+
final_resources = as_objects ? resources.map { |k, v| Resource.new(k, v) } : resources
|
114
|
+
hsh[File.basename(rdata, '.yaml')] = final_resources
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def duplicate_controls(rdata_objects)
|
119
|
+
all_controls = rdata_objects.map(&:controls).flatten
|
120
|
+
# Lets go O(n^2) solution!
|
121
|
+
all_controls.select { |c| all_controls.count(c) > 1 }.reject { |c| SPECIAL_CONTROLS.include?(c) }.uniq
|
122
|
+
end
|
123
|
+
|
124
|
+
class Resource
|
125
|
+
attr_reader :title, :type
|
126
|
+
|
127
|
+
def initialize(title, data)
|
128
|
+
@title = title
|
129
|
+
@data = data
|
130
|
+
@type = @data['type']
|
131
|
+
@no_params = false
|
132
|
+
@control_data = load_control_data
|
133
|
+
end
|
134
|
+
|
135
|
+
def controls(include_special: true)
|
136
|
+
ctrls = @no_params ? @control_data : @control_data.keys
|
137
|
+
return ctrls if include_special
|
138
|
+
|
139
|
+
ctrls.reject { |c| SPECIAL_CONTROLS.include?(c) }
|
140
|
+
end
|
141
|
+
|
142
|
+
def params
|
143
|
+
# rubocop:disable Style/CollectionMethods
|
144
|
+
control_data.map { |_, v| v if v.is_a?(Hash) }.flatten.compact.uniq.inject(:merge)
|
145
|
+
# rubocop:enable Style/CollectionMethods
|
146
|
+
end
|
147
|
+
|
148
|
+
def verify_no_duplicate_controls
|
149
|
+
controls.uniq == controls
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def load_control_data
|
155
|
+
@no_params = if @data['controls'].is_a?(Array)
|
156
|
+
true
|
157
|
+
else
|
158
|
+
false
|
159
|
+
end
|
160
|
+
@data['controls']
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CemSpecHelper
|
4
|
+
# Makes it so the CemSpecHelper module has to be included in the spec_helper.rb file.
|
5
|
+
def self.included(base)
|
6
|
+
require 'cem_spec_helper/mapping_data_spec'
|
7
|
+
require 'cem_spec_helper/resource_data_spec'
|
8
|
+
require 'cem_spec_helper/version'
|
9
|
+
|
10
|
+
module PuppetX; end
|
11
|
+
module PuppetX::CEM; end
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.include CemSpecHelper::MappingDataSpec
|
15
|
+
config.extend CemSpecHelper::MappingDataSpec
|
16
|
+
config.include CemSpecHelper::ResourceDataSpec
|
17
|
+
config.extend CemSpecHelper::ResourceDataSpec
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cem_spec_helper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- abide-team
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-09-21 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Provides helper methods, classes, modules, etc. for RSpec testing the
|
14
|
+
CEM modules
|
15
|
+
email:
|
16
|
+
- abide-team@perforce.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- CHANGELOG.md
|
22
|
+
- CODEOWNERS
|
23
|
+
- LICENSE.txt
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- lib/cem_spec_helper.rb
|
27
|
+
- lib/cem_spec_helper/mapping_data_spec.rb
|
28
|
+
- lib/cem_spec_helper/resource_data_spec.rb
|
29
|
+
- lib/cem_spec_helper/version.rb
|
30
|
+
- sig/cem_spec_helper.rbs
|
31
|
+
homepage: https://github.com/puppetlabs/cem_spec_helper
|
32
|
+
licenses:
|
33
|
+
- MIT
|
34
|
+
metadata:
|
35
|
+
homepage_uri: https://github.com/puppetlabs/cem_spec_helper
|
36
|
+
source_code_uri: https://github.com/puppetlabs/cem_spec_helper
|
37
|
+
changelog_uri: https://github.com/puppetlabs/cem_spec_helper
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.7.0
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubygems_version: 3.4.18
|
54
|
+
signing_key:
|
55
|
+
specification_version: 4
|
56
|
+
summary: Spec helper for testing the CEM modules
|
57
|
+
test_files: []
|