cem_spec_helper 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|