abide_dev_utils 0.2.1 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.dockerignore +1 -0
- data/Dockerfile +23 -0
- data/README.md +28 -1
- data/abide_dev_utils.gemspec +1 -0
- data/lib/abide_dev_utils/cli.rb +1 -0
- data/lib/abide_dev_utils/cli/puppet.rb +11 -2
- data/lib/abide_dev_utils/cli/test.rb +1 -1
- data/lib/abide_dev_utils/cli/xccdf.rb +7 -3
- data/lib/abide_dev_utils/errors/xccdf.rb +4 -0
- data/lib/abide_dev_utils/ppt.rb +3 -3
- data/lib/abide_dev_utils/ppt/coverage.rb +10 -4
- data/lib/abide_dev_utils/ppt/new_obj.rb +86 -47
- data/lib/abide_dev_utils/resources/generic_spec.erb +13 -0
- data/lib/abide_dev_utils/version.rb +1 -1
- data/lib/abide_dev_utils/xccdf.rb +1 -1
- data/lib/abide_dev_utils/xccdf/cis/hiera.rb +27 -11
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ecd985f39afeac37bf8f2305dc65c782f34722f95a655249d7219b975952012f
|
4
|
+
data.tar.gz: 9123b33054f39149ba2deb34464b56bcac404438ac161f64a02e93fc1d33b340
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 595556633f91088d8b34ac1d17d5f012c9d84ca7c03d45ef31bd59ccc45278b008f967b5e096909fa625c8eac7911163584ac7d0d4cc46caa1bd062b14eb1f7c
|
7
|
+
data.tar.gz: 0dc612075817afeae37820a7c2d097a29af5ed3ee491b7ab2c61743e209b0345e5fd5fff6f5aab53b3d85b9f0e5b9c07cf16cefff5092ec981c679523fd141e2
|
data/.dockerignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/Dockerfile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
FROM ruby:2.7.3-alpine
|
2
|
+
|
3
|
+
ARG version
|
4
|
+
|
5
|
+
RUN mkdir /extvol && \
|
6
|
+
apk update && \
|
7
|
+
apk add git build-base
|
8
|
+
|
9
|
+
VOLUME /extvol
|
10
|
+
|
11
|
+
WORKDIR /usr/src/app
|
12
|
+
|
13
|
+
RUN mkdir -p ./lib/abide_dev_utils/
|
14
|
+
COPY Gemfile abide_dev_utils.gemspec ./
|
15
|
+
COPY lib/abide_dev_utils/version.rb lib/abide_dev_utils
|
16
|
+
RUN bundle install
|
17
|
+
|
18
|
+
COPY . .
|
19
|
+
|
20
|
+
RUN bundle exec rake build && \
|
21
|
+
gem install pkg/abide_dev_utils-${version}.gem
|
22
|
+
|
23
|
+
ENTRYPOINT [ "abide" ]
|
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
Helper library and CLI app for Abide development.
|
4
4
|
|
5
|
+
Issues and pull requests are welcome!
|
6
|
+
|
5
7
|
## Features
|
6
8
|
|
7
9
|
### CLI
|
@@ -125,7 +127,9 @@ Install the gem:
|
|
125
127
|
* `--root-dir`, `-r` - Path to the root directory of your module. Defaults to the current working directory
|
126
128
|
* `--absolute-template-dir`, `-A` - Allows you to specify an absolute path with `--template-dir`. This is useful if your template directory is not relative to your module's root directory
|
127
129
|
* `--template-name`, `-n` - Allows you to specify a template name if it is different than the `TYPE` parameter
|
128
|
-
* `--vars`, `-
|
130
|
+
* `--vars`, `-V` - Comma-separated key=value pairs to pass in to the template renderer. This allows you to pass arbitrary values that can be used in your templates.
|
131
|
+
* `--spec-template`, `-S` - Path to an ERB template to use for rspec test generation instead of the default
|
132
|
+
* `--force`, `-f` - Skips any prompts and executes the command
|
129
133
|
|
130
134
|
`abide puppet new` exposes a few variables for you to use in your templates by default:
|
131
135
|
|
@@ -177,8 +181,10 @@ $ ls manifests
|
|
177
181
|
init.pp
|
178
182
|
$ abide puppet new control_class 'test_module::controls::test_new_control'
|
179
183
|
Created file /Users/the.dude/test_module/manifests/controls/test_new_control.pp
|
184
|
+
Created file /Users/the.dude/test_module/spec/classes/controls/test_new_control_spec.rb
|
180
185
|
$ abide puppet new util_class 'test_module::utils::test_new_util' -v 'testvar1=dude,testvar2=sweet'
|
181
186
|
Created file /Users/the.dude/test_module/manifests/utils/test_new_util.pp
|
187
|
+
Created file /Users/the.dude/test_module/spec/classes/utils/test_new_util_spec.rb
|
182
188
|
$ cat manifests/controls/test_new_control.pp
|
183
189
|
# @api private
|
184
190
|
class test_module::controls::test_new_control (
|
@@ -202,10 +208,22 @@ class test_module::utils::test_new_util (
|
|
202
208
|
|
203
209
|
```
|
204
210
|
|
211
|
+
**NOTE**: You can use two special prefixes on your template files to denote where the rspec test should be generated for that object.
|
212
|
+
If the prefix `c-` is used, the test will be generated in the `spec/classes` directory. If the prefix `d-` is used, the test will be generated in the `spec/defines` directory. For example, to create a template for a defined type, name the template something like this: `d-my_defined_type.pp.erb`.
|
213
|
+
|
205
214
|
### XCCDF Command Reference
|
206
215
|
|
207
216
|
#### to_hiera
|
208
217
|
|
218
|
+
NOTE: When converting XCCDF files to Hiera, control names are sanitized. This means that some characters will be changed to ensure the resulting control names in the Hiera file are valid for both YAML and Puppet class names. Here's what gets changed:
|
219
|
+
|
220
|
+
* All letters are coverted to lower case
|
221
|
+
* The first and last characters of the control name is dropped if they are not letters (a-z)
|
222
|
+
* If a control name has a prefix of `l1_`, `l2_`, or `ng_`, that prefix is dropped
|
223
|
+
* Differentiation between profile level occurs outside of control names
|
224
|
+
* The characters `/` and `\` are deleted. This means that paths are smashed together
|
225
|
+
* Whitespace and the characters `(`, `)`, `.`, and `-` are substituted with underscores (`_`)
|
226
|
+
|
209
227
|
* Required positional parameters:
|
210
228
|
* `XCCDF_FILE` - Path to an XCCDF XML file
|
211
229
|
* Options:
|
@@ -213,6 +231,15 @@ class test_module::utils::test_new_util (
|
|
213
231
|
* `--out-file`, `-o` - A path to a file where you would like to save the generated Hiera
|
214
232
|
* `--parent-key-prefix`, `-p` - Allows you to append a prefix to all top-level Hiera keys
|
215
233
|
|
234
|
+
## Docker
|
235
|
+
|
236
|
+
A Dockerfile has been provided in this repo for convenience since Ruby environments can be painful to deal with. To abide_dev_utils with Docker:
|
237
|
+
|
238
|
+
* Build the Dockerfile: `docker build . -t abide_dev_utils --build-arg version=<semver>`
|
239
|
+
* Run the commands using the container: `docker run -it abide_dev_utils --help`
|
240
|
+
* The container declares a volume for external resources such as files. To use the volume, add the following flag to your `docker run` commands: `-v /path/to/my/files:/extvol`
|
241
|
+
* When using the volume, all paths should be absolute based on the root directory `/extvol`
|
242
|
+
|
216
243
|
## Development
|
217
244
|
|
218
245
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/abide_dev_utils.gemspec
CHANGED
@@ -41,6 +41,7 @@ Gem::Specification.new do |spec|
|
|
41
41
|
# Dev dependencies
|
42
42
|
spec.add_development_dependency 'bundler'
|
43
43
|
spec.add_development_dependency 'rake'
|
44
|
+
spec.add_development_dependency 'console'
|
44
45
|
spec.add_development_dependency 'github_changelog_generator'
|
45
46
|
spec.add_development_dependency 'gem-release'
|
46
47
|
spec.add_development_dependency 'rspec', '~> 3.10'
|
data/lib/abide_dev_utils/cli.rb
CHANGED
@@ -20,6 +20,7 @@ module Abide
|
|
20
20
|
parser.main_options.version = AbideDevUtils::VERSION
|
21
21
|
parser.main_options.banner = ROOT_CMD_BANNER
|
22
22
|
parser.add_command(CmdParse::HelpCommand.new, default: true)
|
23
|
+
parser.add_command(CmdParse::VersionCommand.new(add_switches: true))
|
23
24
|
parser.add_command(PuppetCommand.new)
|
24
25
|
parser.add_command(XccdfCommand.new)
|
25
26
|
parser.add_command(TestCommand.new)
|
@@ -87,6 +87,16 @@ module Abide
|
|
87
87
|
'--vars [VARNAME=VALUE]',
|
88
88
|
'Allows you to specify comma-separated variable names and values that will be converted into a hash that is available for you to use in your templates'
|
89
89
|
) { |v| @data[:vars] = v }
|
90
|
+
options.on(
|
91
|
+
'-S [PATH]',
|
92
|
+
'--spec-template [PATH]',
|
93
|
+
'Path to an ERB template to use for rspec test generation instead of the default'
|
94
|
+
)
|
95
|
+
options.on(
|
96
|
+
'-f',
|
97
|
+
'--force',
|
98
|
+
'Skips any prompts and executes the command'
|
99
|
+
) { |_| @data[:force] = true }
|
90
100
|
end
|
91
101
|
|
92
102
|
def execute(type, name)
|
@@ -97,8 +107,7 @@ module Abide
|
|
97
107
|
opts: @data,
|
98
108
|
vars: @data.fetch(:vars, '').split(',').map { |i| i.split('=') }.to_h # makes the str a hash
|
99
109
|
)
|
100
|
-
|
101
|
-
Abide::CLI::OUTPUT.simple(result)
|
110
|
+
builder.build
|
102
111
|
end
|
103
112
|
end
|
104
113
|
end
|
@@ -35,10 +35,10 @@ module Abide
|
|
35
35
|
@litmus_im = [CMD_LIT_BASE, "'litmus:install_module'"]
|
36
36
|
@litmus_ap = [CMD_LIT_BASE, "'litmus:acceptance:parallel'"]
|
37
37
|
@litmus_td = [CMD_LIT_BASE, "'litmus:tear_down'"]
|
38
|
-
validate_env_and_opts
|
39
38
|
end
|
40
39
|
|
41
40
|
def execute(suite)
|
41
|
+
validate_env_and_opts
|
42
42
|
case suite.downcase
|
43
43
|
when /^a[A-Za-z]*/
|
44
44
|
run_command(@validate)
|
@@ -27,7 +27,12 @@ module Abide
|
|
27
27
|
long_desc(CMD_LONG)
|
28
28
|
options.on('-b [TYPE]', '--benchmark-type [TYPE]', 'XCCDF Benchmark type') { |b| @data[:type] = b }
|
29
29
|
options.on('-o [FILE]', '--out-file [FILE]', 'Path to save file') { |f| @data[:file] = f }
|
30
|
-
options.on('-p [PREFIX]', '--parent-key-prefix [PREFIX]', 'A prefix to append to the parent key')
|
30
|
+
options.on('-p [PREFIX]', '--parent-key-prefix [PREFIX]', 'A prefix to append to the parent key') do |p|
|
31
|
+
@data[:parent_key_prefix] = p
|
32
|
+
end
|
33
|
+
options.on('-N', '--number-fmt', 'Format Hiera control names based off of control number instead of name.') do
|
34
|
+
@data[:num] = true
|
35
|
+
end
|
31
36
|
end
|
32
37
|
|
33
38
|
def execute(xccdf_file)
|
@@ -40,8 +45,7 @@ module Abide
|
|
40
45
|
|
41
46
|
def to_hiera(xccdf_file)
|
42
47
|
xfile = AbideDevUtils::XCCDF.to_hiera(xccdf_file, @data)
|
43
|
-
console
|
44
|
-
Abide::CLI::OUTPUT.yaml(xfile, console: console, file: @data[:file])
|
48
|
+
Abide::CLI::OUTPUT.yaml(xfile, console: @data[:file].nil?, file: @data[:file])
|
45
49
|
end
|
46
50
|
end
|
47
51
|
end
|
@@ -8,5 +8,9 @@ module AbideDevUtils
|
|
8
8
|
class XPathSearchError < GenericError
|
9
9
|
@default = 'XPath seach failed to find anything at:'
|
10
10
|
end
|
11
|
+
|
12
|
+
class StrategyInvalidError < GenericError
|
13
|
+
@default = 'Invalid strategy selected. Should be either \'name\' or \'num\''
|
14
|
+
end
|
11
15
|
end
|
12
16
|
end
|
data/lib/abide_dev_utils/ppt.rb
CHANGED
@@ -9,7 +9,7 @@ module AbideDevUtils
|
|
9
9
|
# the full namespace for all classes in that directory.
|
10
10
|
# @param puppet_class_dir [String] path to a dir containing Puppet manifests
|
11
11
|
# @return [String] The namespace for all classes in manifests in the dir
|
12
|
-
def find_class_namespace(puppet_class_dir)
|
12
|
+
def self.find_class_namespace(puppet_class_dir)
|
13
13
|
path = Pathname.new(puppet_class_dir)
|
14
14
|
mod_root = nil
|
15
15
|
ns_parts = []
|
@@ -34,7 +34,7 @@ module AbideDevUtils
|
|
34
34
|
# metadata.json, if it exists, or by using the parent directory name.
|
35
35
|
# @param pathname [Pathname] A Pathname object of the module's manifests dir
|
36
36
|
# @return [String] The module's namespace root
|
37
|
-
def find_mod_root(pathname)
|
37
|
+
def self.find_mod_root(pathname)
|
38
38
|
metadata_file = nil
|
39
39
|
pathname.entries.each do |e|
|
40
40
|
metadata_file = "#{pathname}/metadata.json" if File.basename(e) == 'metadata.json'
|
@@ -52,7 +52,7 @@ module AbideDevUtils
|
|
52
52
|
|
53
53
|
# @return [Array] An array of frozen arrays where each sub-array's
|
54
54
|
# index 0 is class_name and index 1 is the full path to the file.
|
55
|
-
def find_all_classes_and_paths(puppet_class_dir)
|
55
|
+
def self.find_all_classes_and_paths(puppet_class_dir)
|
56
56
|
all_cap = []
|
57
57
|
Dir.each_child(puppet_class_dir) do |c|
|
58
58
|
path = "#{puppet_class_dir}/#{c}"
|
@@ -13,12 +13,14 @@ module AbideDevUtils
|
|
13
13
|
def self.generate(puppet_class_dir, hiera_path, profile = nil)
|
14
14
|
coverage = {}
|
15
15
|
coverage['classes'] = {}
|
16
|
-
all_cap = find_all_classes_and_paths(puppet_class_dir)
|
16
|
+
all_cap = AbideDevUtils::Ppt.find_all_classes_and_paths(puppet_class_dir)
|
17
17
|
invalid_classes = find_invalid_classes(all_cap)
|
18
|
-
valid_classes = all_cap
|
18
|
+
valid_classes = find_valid_classes(all_cap, invalid_classes)
|
19
19
|
coverage['classes']['invalid'] = invalid_classes
|
20
20
|
coverage['classes']['valid'] = valid_classes
|
21
21
|
hiera = YAML.safe_load(File.open(hiera_path))
|
22
|
+
profile&.gsub!(/^profile_/, '') unless profile.nil?
|
23
|
+
|
22
24
|
matcher = profile.nil? ? /^profile_/ : /^profile_#{profile}/
|
23
25
|
hiera.each do |k, v|
|
24
26
|
key_base = k.split('::')[-1]
|
@@ -50,9 +52,13 @@ module AbideDevUtils
|
|
50
52
|
out_hash
|
51
53
|
end
|
52
54
|
|
53
|
-
def self.find_valid_classes(all_cap)
|
55
|
+
def self.find_valid_classes(all_cap, invalid_classes)
|
54
56
|
all_classes = all_cap.dup.transpose[0]
|
55
|
-
|
57
|
+
return [] if all_classes.nil?
|
58
|
+
|
59
|
+
return all_classes - invalid_classes unless invalid_classes.nil?
|
60
|
+
|
61
|
+
all_classes
|
56
62
|
end
|
57
63
|
|
58
64
|
def self.find_invalid_classes(all_cap)
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'erb'
|
4
4
|
require 'pathname'
|
5
|
+
require 'abide_dev_utils/output'
|
5
6
|
require 'abide_dev_utils/prompt'
|
6
7
|
require 'abide_dev_utils/errors/ppt'
|
7
8
|
|
@@ -9,6 +10,10 @@ module AbideDevUtils
|
|
9
10
|
module Ppt
|
10
11
|
class NewObjectBuilder
|
11
12
|
DEFAULT_EXT = '.pp'
|
13
|
+
VALID_EXT = /(\.pp|\.rb)\.erb$/.freeze
|
14
|
+
TMPL_PATTERN = /^[a-zA-Z][^\s]*\.erb$/.freeze
|
15
|
+
OBJ_PREFIX = /^(c-|d-)/.freeze
|
16
|
+
PREFIX_TEST_PATH = { 'c-' => 'classes', 'd-' => 'defines' }.freeze
|
12
17
|
|
13
18
|
def initialize(obj_type, obj_name, opts: {}, vars: {})
|
14
19
|
@obj_type = obj_type
|
@@ -17,25 +22,17 @@ module AbideDevUtils
|
|
17
22
|
@vars = vars
|
18
23
|
class_vars
|
19
24
|
validate_class_vars
|
25
|
+
@tmpl_data = template_data(@opts.fetch(:tmpl_name, @obj_type))
|
20
26
|
end
|
21
27
|
|
22
|
-
attr_reader :obj_type, :obj_name, :
|
23
|
-
|
24
|
-
def render
|
25
|
-
ERB.new(File.read(@tmpl_path.to_s), 0, '<>-').result(binding)
|
26
|
-
end
|
28
|
+
attr_reader :obj_type, :obj_name, :root_dir, :tmpl_dir, :obj_path, :vars, :tmpl_data
|
27
29
|
|
28
30
|
def build
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
content = render
|
35
|
-
File.open(obj_path, 'w') { |f| f.write(render) } unless content.empty?
|
36
|
-
raise AbideDevUtils::Errors::Ppt::FailedToCreateFileError, obj_path unless File.file?(obj_path)
|
37
|
-
|
38
|
-
"Created file #{obj_path}"
|
31
|
+
force = @opts.fetch(:force, false)
|
32
|
+
obj_cont = force ? true : continue?(obj_path)
|
33
|
+
spec_cont = force ? true : continue?(@tmpl_data[:spec_path])
|
34
|
+
write_file(obj_path, @tmpl_data[:path]) if obj_cont
|
35
|
+
write_file(@tmpl_data[:spec_path], @spec_tmpl) if spec_cont
|
39
36
|
end
|
40
37
|
|
41
38
|
# If a method gets called on the Hiera object which is not defined,
|
@@ -59,42 +56,98 @@ module AbideDevUtils
|
|
59
56
|
|
60
57
|
private
|
61
58
|
|
59
|
+
def continue?(path)
|
60
|
+
continue = if File.exist?(path)
|
61
|
+
AbideDevUtils::Prompt.yes_no('File exists, would you like to overwrite?')
|
62
|
+
else
|
63
|
+
true
|
64
|
+
end
|
65
|
+
AbideDevUtils::Output.simple("Not overwriting file #{path}") unless continue
|
66
|
+
|
67
|
+
continue
|
68
|
+
end
|
69
|
+
|
70
|
+
def write_file(path, tmpl_path)
|
71
|
+
dir, = Pathname.new(path).split
|
72
|
+
Pathname.new(dir).mkpath unless Dir.exist?(dir)
|
73
|
+
content = render(tmpl_path)
|
74
|
+
File.open(path, 'w') { |f| f.write(content) } unless content.empty?
|
75
|
+
raise AbideDevUtils::Errors::Ppt::FailedToCreateFileError, path unless File.file?(path)
|
76
|
+
|
77
|
+
AbideDevUtils::Output.simple("Created file #{path}")
|
78
|
+
end
|
79
|
+
|
80
|
+
def build_obj; end
|
81
|
+
|
62
82
|
def class_vars
|
63
|
-
@tmpl_name = @opts.fetch(:tmpl_name, "#{@obj_type}.erb")
|
64
83
|
@root_dir = Pathname.new(@opts.fetch(:root_dir, Dir.pwd))
|
65
84
|
@tmpl_dir = if @opts.fetch(:absolute_template_dir, false)
|
66
85
|
@opts.fetch(:tmpl_dir)
|
67
86
|
else
|
68
|
-
"#{@
|
87
|
+
"#{@root_dir}/#{@opts.fetch(:tmpl_dir, 'object_templates')}"
|
69
88
|
end
|
70
|
-
@tmpl_path = Pathname.new("#{@tmpl_dir}/#{@opts.fetch(:tmpl_name, "#{@obj_type}.erb")}")
|
71
|
-
@type_path_map = @opts.fetch(:type_path_map, {})
|
72
89
|
@obj_path = new_obj_path
|
90
|
+
@spec_tmpl = @opts.fetch(:spec_template, File.expand_path(File.join(__dir__, '../resources/generic_spec.erb')))
|
73
91
|
end
|
74
92
|
|
75
93
|
def validate_class_vars
|
76
94
|
raise AbideDevUtils::Errors::PathNotDirectoryError, @root_dir unless Dir.exist? @root_dir
|
77
95
|
raise AbideDevUtils::Errors::PathNotDirectoryError, @tmpl_dir unless Dir.exist? @tmpl_dir
|
78
|
-
raise AbideDevUtils::Errors::Ppt::TemplateNotFoundError, @tmpl_path.to_s unless @tmpl_path.file?
|
79
96
|
end
|
80
97
|
|
81
98
|
def basename(obj_name)
|
82
99
|
obj_name.split('::')[-1]
|
83
100
|
end
|
84
101
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
102
|
+
def prefix
|
103
|
+
pfx = basename.match(OBJ_PREFIX)
|
104
|
+
return pfx[1] unless pfx.empty?
|
105
|
+
end
|
106
|
+
|
107
|
+
def templates
|
108
|
+
return [] if Dir.entries(tmpl_dir).empty?
|
109
|
+
|
110
|
+
file_names = Dir.entries(tmpl_dir).select { |f| f.match?(TMPL_PATTERN) }
|
111
|
+
file_names.map { |i| File.join(tmpl_dir, i) }
|
112
|
+
end
|
113
|
+
|
114
|
+
def template_data(query)
|
115
|
+
raise AbideDevUtils::Errors::Ppt::TemplateNotFoundError, @tmpl_dir if Dir.entries(@tmpl_dir).empty?
|
116
|
+
|
117
|
+
data = {}
|
118
|
+
pattern = /#{Regexp.quote(query)}/
|
119
|
+
templates.each do |i|
|
120
|
+
pn = Pathname.new(i)
|
121
|
+
next unless pn.basename.to_s.match?(pattern)
|
122
|
+
|
123
|
+
data[:path] = pn.to_s
|
124
|
+
data[:fname] = pn.basename.to_s
|
90
125
|
end
|
126
|
+
raise AbideDevUtils::Errors::Ppt::TemplateNotFoundError, @tmpl_dir unless data.key?(:fname)
|
127
|
+
|
128
|
+
data[:ext] = data[:fname].match?(VALID_EXT) ? data[:fname].match(VALID_EXT)[1] : '.pp'
|
129
|
+
data[:pfx] = data[:fname].match?(OBJ_PREFIX) ? data[:fname].match(OBJ_PREFIX)[1] : 'c-'
|
130
|
+
data[:spec_base] = PREFIX_TEST_PATH[data[:pfx]]
|
131
|
+
data[:obj_name] = normalize_obj_name(data.dup)
|
132
|
+
data[:spec_name] = "#{@obj_name.split('::')[-1]}_spec.rb"
|
133
|
+
data[:spec_path] = spec_path(data[:spec_base], data[:spec_name])
|
134
|
+
data
|
135
|
+
end
|
136
|
+
|
137
|
+
def normalize_obj_name(data)
|
138
|
+
new_name = data[:fname].slice(/^(?:#{Regexp.quote(data[:pfx])})?(?<name>[^\s.]+)(?:#{Regexp.quote(data[:ext])})?\.erb$/, 'name')
|
139
|
+
"#{new_name}#{data[:ext]}"
|
140
|
+
end
|
141
|
+
|
142
|
+
def render(path)
|
143
|
+
ERB.new(File.read(path), 0, '<>-').result(binding)
|
91
144
|
end
|
92
145
|
|
93
146
|
def namespace_format(name)
|
94
147
|
name.split(':').reject(&:empty?).join('::')
|
95
148
|
end
|
96
149
|
|
97
|
-
def
|
150
|
+
def new_obj_path
|
98
151
|
parts = @obj_name.split('::')[1..-2]
|
99
152
|
parts.insert(0, 'manifests')
|
100
153
|
parts.insert(-1, "#{basename(@obj_name)}#{DEFAULT_EXT}")
|
@@ -102,27 +155,13 @@ module AbideDevUtils
|
|
102
155
|
path.to_s
|
103
156
|
end
|
104
157
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
abs_path = Pathname.new(map_val).absolute? ? map_val : "#{Dir.pwd}/#{map_val}"
|
113
|
-
"#{abs_path}/#{basename(@obj_name)}#{DEFAULT_EXT}"
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def custom_obj_path_from_hash(map_val, obj_name)
|
118
|
-
raise AbideDevUtils::Errors::Ppt::CustomObjPathKeyError, map_val unless map_val.key?(:path)
|
119
|
-
|
120
|
-
abs_path = Pathname.new(map_val[:path]).absolute? ? map_val[:path] : "#{Dir.pwd}/#{map_val[:path]}"
|
121
|
-
if map_val.key?(:extension)
|
122
|
-
"#{abs_path}/#{basename(obj_name)}#{map_val[:extension]}"
|
123
|
-
else
|
124
|
-
"#{abs_path}/#{basename(obj_name)}#{DEFAULT_EXT}"
|
125
|
-
end
|
158
|
+
def spec_path(base_dir, spec_name)
|
159
|
+
parts = @obj_name.split('::')[1..-2]
|
160
|
+
parts.insert(0, 'spec')
|
161
|
+
parts.insert(1, base_dir)
|
162
|
+
parts.insert(-1, spec_name)
|
163
|
+
path = @root_dir + Pathname.new(parts.join('/'))
|
164
|
+
path.to_s
|
126
165
|
end
|
127
166
|
end
|
128
167
|
end
|
@@ -15,7 +15,7 @@ module AbideDevUtils
|
|
15
15
|
type = opts.fetch(:type, 'cis')
|
16
16
|
case type.downcase
|
17
17
|
when 'cis'
|
18
|
-
AbideDevUtils::XCCDF::CIS::Hiera.new(xccdf_file, parent_key_prefix: opts[:parent_key_prefix])
|
18
|
+
AbideDevUtils::XCCDF::CIS::Hiera.new(xccdf_file, parent_key_prefix: opts[:parent_key_prefix], num: opts[:num])
|
19
19
|
else
|
20
20
|
AbideDevUtils::Output.simple("XCCDF type #{type} is unsupported!")
|
21
21
|
end
|
@@ -13,6 +13,7 @@ module AbideDevUtils
|
|
13
13
|
# @!attribute [r] yaml_title
|
14
14
|
class Hiera
|
15
15
|
CONTROL_PREFIX = /^[\d.]+_/.freeze
|
16
|
+
UNDERSCORED = /(\s|\(|\)|-|\.)/.freeze
|
16
17
|
XPATHS = {
|
17
18
|
benchmark: {
|
18
19
|
all: 'xccdf:Benchmark',
|
@@ -34,13 +35,13 @@ module AbideDevUtils
|
|
34
35
|
# @param parent_key_prefix [String] a string to be prepended to the
|
35
36
|
# top-level key in the Hiera structure. Useful for namespacing
|
36
37
|
# the top-level key.
|
37
|
-
def initialize(xccdf_file, parent_key_prefix: nil)
|
38
|
+
def initialize(xccdf_file, parent_key_prefix: nil, num: false)
|
38
39
|
@doc = parse(xccdf_file)
|
39
40
|
@title = xpath(XPATHS[:benchmark][:title]).children.to_s
|
40
41
|
@version = xpath(XPATHS[:benchmark][:version]).children.to_s
|
41
42
|
@profiles = xpath(XPATHS[:profiles][:all])
|
42
43
|
@parent_key = make_parent_key(@doc, parent_key_prefix)
|
43
|
-
@hash = make_hash(@doc, @parent_key)
|
44
|
+
@hash = make_hash(@doc, @parent_key, num)
|
44
45
|
end
|
45
46
|
|
46
47
|
def yaml_title
|
@@ -89,15 +90,18 @@ module AbideDevUtils
|
|
89
90
|
|
90
91
|
private
|
91
92
|
|
92
|
-
attr_accessor :doc, :
|
93
|
+
attr_accessor :doc, :hash, :parent_key, :profiles
|
93
94
|
|
95
|
+
# Accepts a path to an xccdf xml file and returns a parsed Nokogiri object of the file
|
96
|
+
# @param xccdf_file [String] path to an xccdf xml file
|
97
|
+
# @return [Nokogiri::Node] A Nokogiri node object of the XML document
|
94
98
|
def parse(xccdf_file)
|
95
99
|
raise AbideDevUtils::Errors::FileNotFoundError, xccdf_file unless File.file?(xccdf_file)
|
96
100
|
|
97
101
|
Nokogiri.XML(File.open(xccdf_file))
|
98
102
|
end
|
99
103
|
|
100
|
-
def make_hash(doc, parent_key)
|
104
|
+
def make_hash(doc, parent_key, num)
|
101
105
|
hash = { parent_key.to_sym => { title: @title, version: @version } }
|
102
106
|
profiles = doc.xpath('xccdf:Benchmark/xccdf:Profile')
|
103
107
|
profiles.each do |p|
|
@@ -105,7 +109,7 @@ module AbideDevUtils
|
|
105
109
|
hash[parent_key.to_sym][title.to_sym] = []
|
106
110
|
selects = p.xpath('./xccdf:select')
|
107
111
|
selects.each do |s|
|
108
|
-
hash[parent_key.to_sym][title.to_sym] << normalize_ctrl_name(s['idref'].to_s)
|
112
|
+
hash[parent_key.to_sym][title.to_sym] << normalize_ctrl_name(s['idref'].to_s, num)
|
109
113
|
end
|
110
114
|
end
|
111
115
|
hash
|
@@ -113,11 +117,11 @@ module AbideDevUtils
|
|
113
117
|
|
114
118
|
def normalize_str(str)
|
115
119
|
nstr = str.downcase
|
116
|
-
nstr.gsub!(/[^a-
|
120
|
+
nstr.gsub!(/[^a-z0-9]$/, '')
|
117
121
|
nstr.gsub!(/^[^a-z]/, '')
|
118
122
|
nstr.gsub!(/^(l1_|l2_|ng_)/, '')
|
119
|
-
nstr.delete!('
|
120
|
-
nstr.gsub!(
|
123
|
+
nstr.delete!('(/|\\)')
|
124
|
+
nstr.gsub!(UNDERSCORED, '_')
|
121
125
|
nstr
|
122
126
|
end
|
123
127
|
|
@@ -127,9 +131,21 @@ module AbideDevUtils
|
|
127
131
|
prof_name
|
128
132
|
end
|
129
133
|
|
130
|
-
def normalize_ctrl_name(ctrl)
|
131
|
-
|
132
|
-
|
134
|
+
def normalize_ctrl_name(ctrl, num)
|
135
|
+
return num_normalize_ctrl(ctrl) if num
|
136
|
+
|
137
|
+
name_normalize_ctrl(ctrl)
|
138
|
+
end
|
139
|
+
|
140
|
+
def name_normalize_ctrl(ctrl)
|
141
|
+
new_ctrl = ctrl.split('benchmarks_rule_')[-1].gsub(CONTROL_PREFIX, '')
|
142
|
+
normalize_str(new_ctrl)
|
143
|
+
end
|
144
|
+
|
145
|
+
def num_normalize_ctrl(ctrl)
|
146
|
+
part = ctrl.split('benchmarks_rule_')[-1]
|
147
|
+
numpart = CONTROL_PREFIX.match(part).to_s.chop.gsub(UNDERSCORED, '_')
|
148
|
+
"c#{numpart}"
|
133
149
|
end
|
134
150
|
|
135
151
|
def make_parent_key(doc, prefix)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abide_dev_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Heston Snodgrass
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: console
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: github_changelog_generator
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -242,11 +256,13 @@ executables:
|
|
242
256
|
extensions: []
|
243
257
|
extra_rdoc_files: []
|
244
258
|
files:
|
259
|
+
- ".dockerignore"
|
245
260
|
- ".gitignore"
|
246
261
|
- ".rspec"
|
247
262
|
- ".rubocop.yml"
|
248
263
|
- ".rubocop_todo.yml"
|
249
264
|
- CHANGELOG.md
|
265
|
+
- Dockerfile
|
250
266
|
- Gemfile
|
251
267
|
- LICENSE.txt
|
252
268
|
- README.md
|
@@ -278,6 +294,7 @@ files:
|
|
278
294
|
- lib/abide_dev_utils/ppt/coverage.rb
|
279
295
|
- lib/abide_dev_utils/ppt/new_obj.rb
|
280
296
|
- lib/abide_dev_utils/prompt.rb
|
297
|
+
- lib/abide_dev_utils/resources/generic_spec.erb
|
281
298
|
- lib/abide_dev_utils/utils/general.rb
|
282
299
|
- lib/abide_dev_utils/validate.rb
|
283
300
|
- lib/abide_dev_utils/version.rb
|