abide_dev_utils 0.2.0 → 0.2.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/README.md +189 -6
- data/lib/abide_dev_utils/cli/abstract.rb +1 -1
- data/lib/abide_dev_utils/cli/puppet.rb +3 -3
- data/lib/abide_dev_utils/ppt/new_obj.rb +47 -32
- data/lib/abide_dev_utils/version.rb +1 -1
- data/lib/abide_dev_utils/xccdf/cis/hiera.rb +15 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9e993f8a435b4be58831bc98cf1658533c8c1084f14c96c1a12ecd73ff89da6
|
4
|
+
data.tar.gz: 1120b6cc91eac28ff8168e808f13c16cf6c6d844b5928f04f4f4bb6d7cda0bcb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bcf0b6aa95f003e5402be98cc797202949368ceff62e6cdb778f4002e452716ef5ef833bc0bcd34bb797f628997e1c807d88f191048a5afec767bd8bcb7dc7a3
|
7
|
+
data.tar.gz: 2ca0b4fb33d0329f13e3ce04d317427b4ba67c9937b4df739d991a1692871d19c17d1eeb24d5035573a676560795ae466e6df65148693258718aeda115c9e1d8
|
data/README.md
CHANGED
@@ -2,15 +2,48 @@
|
|
2
2
|
|
3
3
|
Helper library and CLI app for Abide development.
|
4
4
|
|
5
|
+
## Features
|
6
|
+
|
7
|
+
### CLI
|
8
|
+
|
9
|
+
* Type `abide -h` to see the CLI help menu
|
10
|
+
* All commands have help menus
|
11
|
+
* Tested on MacOS, should also work on Linux
|
12
|
+
|
13
|
+
### PDK-like manifest generation from local ERB templates
|
14
|
+
|
15
|
+
* Create a directory in your module called `object_templates` to hold ERB files
|
16
|
+
* Generate manifests from those ERB files
|
17
|
+
|
18
|
+
### XCCDF to Hiera conversion
|
19
|
+
|
20
|
+
* Convert the contents of an XCCDF XML file to Hiera
|
21
|
+
|
22
|
+
### Coverage Reporting
|
23
|
+
|
24
|
+
* Generate a coverage report (i.e. how many CIS controls are covered by classes in your module)
|
25
|
+
|
26
|
+
### Jira Integration
|
27
|
+
|
28
|
+
* Create Jira issues in bulk from coverage reports
|
29
|
+
|
30
|
+
### Supports Configuration via Local YAML file
|
31
|
+
|
32
|
+
* Fully configurable via the `~/.abide_dev.yaml` file
|
33
|
+
|
5
34
|
## Installation
|
6
35
|
|
7
36
|
### CLI app
|
8
37
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
38
|
+
Install from RubyGems:
|
39
|
+
|
40
|
+
`gem install abide_dev_utils`
|
41
|
+
|
42
|
+
Then to access the help menu:
|
43
|
+
|
44
|
+
`abide -h`
|
45
|
+
|
46
|
+
### As a dependency
|
14
47
|
|
15
48
|
Add this line to your application's Gemfile:
|
16
49
|
|
@@ -26,9 +59,159 @@ Or install it yourself as:
|
|
26
59
|
|
27
60
|
`$ gem install abide_dev_utils`
|
28
61
|
|
62
|
+
### Build it yourself
|
63
|
+
|
64
|
+
Clone this repo:
|
65
|
+
|
66
|
+
`git clone <this repo>`
|
67
|
+
|
68
|
+
Build the gem:
|
69
|
+
|
70
|
+
`bundle exec rake build`
|
71
|
+
|
72
|
+
The gem will be located at `pkg/<gem file>`
|
73
|
+
|
74
|
+
Install the gem:
|
75
|
+
|
76
|
+
`gem install pkg/<gem file>`
|
77
|
+
|
29
78
|
## Usage
|
30
79
|
|
31
|
-
|
80
|
+
* `abide -h` - CLI top-level help menu
|
81
|
+
* `abide <command> -h` - Command-specific help menu
|
82
|
+
|
83
|
+
### Overview of Commands
|
84
|
+
|
85
|
+
* `abide jira` - Command namespace for Jira commands
|
86
|
+
* `abide jira auth` - Authenticate with Jira. Only useful as a stand-alone command to test authentication
|
87
|
+
* `abide jira from_coverage` - Creates a parent issue with subtasks from a Puppet coverage report
|
88
|
+
* `abide jira get_issue` - Gets a specific Jira issue
|
89
|
+
* `abide jira new_issue` - Creates a new Jira issue
|
90
|
+
* `abide puppet` - Command namespace for Puppet commands
|
91
|
+
* `abide puppet coverage` - Generate a "coverage" report. This examines how many manifests you have in your Puppet module versus how many CIS controls exist in the local Hiera data and gives you a breakdown of what percentage of the selected CIS benchmark / profile you have successfully covered.
|
92
|
+
* `abide puppet new` - Generate a new manifest from a local ERB template. Functions similar to `pdk new` except you can create arbitrary manifests.
|
93
|
+
* `abide test` - **BUGGED** Runs a module's test suite. Currently has issues with local gem environments.
|
94
|
+
* `abide xccdf` - Command namespace for XCCDF commands
|
95
|
+
* `abide xccdf to_hiera` - Converts a benchmark XCCDF file to a Hiera yaml file
|
96
|
+
|
97
|
+
### Jira Command Reference
|
98
|
+
|
99
|
+
#### from_coverage
|
100
|
+
|
101
|
+
* Required positional parameters:
|
102
|
+
* `REPORT` - A path to a JSON file generated by the `abide puppet coverage` command
|
103
|
+
* `PROJECT` - A Jira project code. This is typically an all-caps abbreviation of a Jira project
|
104
|
+
* Options:
|
105
|
+
* `--dry-run`, `-d` - Prints the results of this command to the console instead of actually creating Jira issues
|
106
|
+
|
107
|
+
### Puppet Command Reference
|
108
|
+
|
109
|
+
#### coverage
|
110
|
+
|
111
|
+
* Required positional parameters:
|
112
|
+
* `CLASS_DIR` - The path to the directory in your module that holds manifests named after the benchmark controls
|
113
|
+
* `HIERA_FILE` - The path to the Hiera file generated by the `abide xccdf to_hiera` command
|
114
|
+
* Options:
|
115
|
+
* `--out-file`, `-o` - The path to save the coverage report JSON file
|
116
|
+
* `--profile`, `-p` - A benchmark profile to generate the report for. By default, generates the report for all profiles
|
117
|
+
|
118
|
+
#### new
|
119
|
+
|
120
|
+
* Required positional parameters:
|
121
|
+
* `TYPE` - The type of object you would like to generate. This value is the name of an ERB template without `.erb` located in your template directory
|
122
|
+
* `NAME` - The fully namespaced name of the new object. Subdirectories will be automatically created within `manifests` based on the namespacing of this parameter if the directories do not exist.
|
123
|
+
* Options:
|
124
|
+
* `--template-dir`, `-t` - Name of the template directory relative to your module's root directory. Defaults to `object_templates`
|
125
|
+
* `--root-dir`, `-r` - Path to the root directory of your module. Defaults to the current working directory
|
126
|
+
* `--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
|
+
* `--template-name`, `-n` - Allows you to specify a template name if it is different than the `TYPE` parameter
|
128
|
+
* `--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.
|
129
|
+
|
130
|
+
`abide puppet new` exposes a few variables for you to use in your templates by default:
|
131
|
+
|
132
|
+
* `@obj_name` - The value of the `NAME` parameter passed into the command
|
133
|
+
* `@vars` - A hash of any key=value pairs you passed into the command using `--vars`
|
134
|
+
|
135
|
+
Examples:
|
136
|
+
|
137
|
+
Lets assume we have a module at `~/test_module` and we have a directory in that module called `object_templates`. In the template directory, we have two ERB template files: `control_class.erb` and `util_class.erb`.
|
138
|
+
|
139
|
+
* control_class.erb
|
140
|
+
|
141
|
+
```text
|
142
|
+
# @api private
|
143
|
+
class <%= @obj_name %> (
|
144
|
+
Boolean $enforce = true,
|
145
|
+
Hash $config = {},
|
146
|
+
) {
|
147
|
+
if $enforce {
|
148
|
+
warning('Class not implemented yet')
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
```
|
153
|
+
|
154
|
+
* util_class.erb
|
155
|
+
|
156
|
+
```text
|
157
|
+
class <%= @obj_name %> (
|
158
|
+
<% if @vars.key?('testvar1') -%>
|
159
|
+
$testparam1 = '<%= @vars['testvar1'] %>',
|
160
|
+
<% else -%>
|
161
|
+
$testparam1 = undef,
|
162
|
+
<% end -%>
|
163
|
+
) {
|
164
|
+
file { $testparam1:
|
165
|
+
ensure => file,
|
166
|
+
mode => '<%= @vars.fetch('testvar2', '0644') %>',
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
```
|
171
|
+
|
172
|
+
```text
|
173
|
+
$ cd ~/test_module
|
174
|
+
$ ls object_templates
|
175
|
+
control_class.erb util_class.erb
|
176
|
+
$ ls manifests
|
177
|
+
init.pp
|
178
|
+
$ abide puppet new control_class 'test_module::controls::test_new_control'
|
179
|
+
Created file /Users/the.dude/test_module/manifests/controls/test_new_control.pp
|
180
|
+
$ abide puppet new util_class 'test_module::utils::test_new_util' -v 'testvar1=dude,testvar2=sweet'
|
181
|
+
Created file /Users/the.dude/test_module/manifests/utils/test_new_util.pp
|
182
|
+
$ cat manifests/controls/test_new_control.pp
|
183
|
+
# @api private
|
184
|
+
class test_module::controls::test_new_control (
|
185
|
+
Boolean $enforce = true,
|
186
|
+
Hash $config = {},
|
187
|
+
) {
|
188
|
+
if $enforce {
|
189
|
+
warning('Class not implemented yet')
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
$ cat manifests/utils/test_new_util.pp
|
194
|
+
class test_module::utils::test_new_util (
|
195
|
+
$testparam1 = 'dude',
|
196
|
+
) {
|
197
|
+
file { 'dude':
|
198
|
+
ensure => file,
|
199
|
+
mode => 'sweet',
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
```
|
204
|
+
|
205
|
+
### XCCDF Command Reference
|
206
|
+
|
207
|
+
#### to_hiera
|
208
|
+
|
209
|
+
* Required positional parameters:
|
210
|
+
* `XCCDF_FILE` - Path to an XCCDF XML file
|
211
|
+
* Options:
|
212
|
+
* `--benchmark-type`, `-b` - The type of benchmark. Defaults to `cis`
|
213
|
+
* `--out-file`, `-o` - A path to a file where you would like to save the generated Hiera
|
214
|
+
* `--parent-key-prefix`, `-p` - Allows you to append a prefix to all top-level Hiera keys
|
32
215
|
|
33
216
|
## Development
|
34
217
|
|
@@ -4,7 +4,7 @@ require 'abide_dev_utils/cli/abstract'
|
|
4
4
|
|
5
5
|
module Abide
|
6
6
|
module CLI
|
7
|
-
class PuppetCommand <
|
7
|
+
class PuppetCommand < AbideCommand
|
8
8
|
CMD_NAME = 'puppet'
|
9
9
|
CMD_SHORT = 'Commands related to Puppet code'
|
10
10
|
CMD_LONG = 'Namespace for commands related to Puppet code'
|
@@ -15,7 +15,7 @@ module Abide
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
class PuppetCoverageCommand <
|
18
|
+
class PuppetCoverageCommand < AbideCommand
|
19
19
|
CMD_NAME = 'coverage'
|
20
20
|
CMD_SHORT = 'Generates control coverage report'
|
21
21
|
CMD_LONG = 'Generates report of valid Puppet classes that match with Hiera controls'
|
@@ -53,7 +53,7 @@ module Abide
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
class PuppetNewCommand <
|
56
|
+
class PuppetNewCommand < AbideCommand
|
57
57
|
CMD_NAME = 'new'
|
58
58
|
CMD_SHORT = 'Generates a new Puppet object from templates'
|
59
59
|
CMD_LONG = 'Generates a new Puppet object (class, test, etc.) from templates stored in the module repo'
|
@@ -12,36 +12,16 @@ module AbideDevUtils
|
|
12
12
|
|
13
13
|
def initialize(obj_type, obj_name, opts: {}, vars: {})
|
14
14
|
@obj_type = obj_type
|
15
|
-
@obj_name = obj_name
|
16
|
-
@
|
17
|
-
@root_dir = Pathname.new(opts.fetch(:root_dir, Dir.pwd))
|
18
|
-
@tmpl_dir = if opts.fetch(:absolute_template_dir, false)
|
19
|
-
opts.fetch(:tmpl_dir)
|
20
|
-
else
|
21
|
-
"#{@root_dir}/#{opts.fetch(:tmpl_dir, 'object_templates')}"
|
22
|
-
end
|
23
|
-
@tmpl_name = opts.fetch(:tmpl_name, "#{@obj_type}.erb")
|
24
|
-
@tmpl_path = Pathname.new("#{@tmpl_dir}/#{@tmpl_name}")
|
25
|
-
@type_path_map = opts.fetch(:type_path_map, {})
|
15
|
+
@obj_name = namespace_format(obj_name)
|
16
|
+
@opts = opts
|
26
17
|
@vars = vars
|
18
|
+
class_vars
|
19
|
+
validate_class_vars
|
27
20
|
end
|
28
21
|
|
29
|
-
|
30
|
-
case @obj_type
|
31
|
-
when 'class'
|
32
|
-
obj_path_from_name
|
33
|
-
else
|
34
|
-
custom_obj_path
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def template?
|
39
|
-
@tmpl_path.file?
|
40
|
-
end
|
22
|
+
attr_reader :obj_type, :obj_name, :tmpl_name, :root_dir, :tmpl_dir, :tmpl_path, :type_path_map, :obj_path, :vars
|
41
23
|
|
42
24
|
def render
|
43
|
-
raise AbideDevUtils::Errors::Ppt::TemplateNotFoundError, @tmpl_path.to_s unless template?
|
44
|
-
|
45
25
|
ERB.new(File.read(@tmpl_path.to_s), 0, '<>-').result(binding)
|
46
26
|
end
|
47
27
|
|
@@ -79,34 +59,69 @@ module AbideDevUtils
|
|
79
59
|
|
80
60
|
private
|
81
61
|
|
62
|
+
def class_vars
|
63
|
+
@tmpl_name = @opts.fetch(:tmpl_name, "#{@obj_type}.erb")
|
64
|
+
@root_dir = Pathname.new(@opts.fetch(:root_dir, Dir.pwd))
|
65
|
+
@tmpl_dir = if @opts.fetch(:absolute_template_dir, false)
|
66
|
+
@opts.fetch(:tmpl_dir)
|
67
|
+
else
|
68
|
+
"#{@opts.fetch(:root_dir, Dir.pwd)}/#{@opts.fetch(:tmpl_dir, 'object_templates')}"
|
69
|
+
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
|
+
@obj_path = new_obj_path
|
73
|
+
end
|
74
|
+
|
75
|
+
def validate_class_vars
|
76
|
+
raise AbideDevUtils::Errors::PathNotDirectoryError, @root_dir unless Dir.exist? @root_dir
|
77
|
+
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
|
+
end
|
80
|
+
|
81
|
+
def basename(obj_name)
|
82
|
+
obj_name.split('::')[-1]
|
83
|
+
end
|
84
|
+
|
85
|
+
def new_obj_path
|
86
|
+
if obj_type == 'class'
|
87
|
+
obj_path_from_name
|
88
|
+
else
|
89
|
+
custom_obj_path
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def namespace_format(name)
|
94
|
+
name.split(':').reject(&:empty?).join('::')
|
95
|
+
end
|
96
|
+
|
82
97
|
def obj_path_from_name
|
83
98
|
parts = @obj_name.split('::')[1..-2]
|
84
99
|
parts.insert(0, 'manifests')
|
85
|
-
parts.insert(-1, "#{@
|
100
|
+
parts.insert(-1, "#{basename(@obj_name)}#{DEFAULT_EXT}")
|
86
101
|
path = @root_dir + Pathname.new(parts.join('/'))
|
87
102
|
path.to_s
|
88
103
|
end
|
89
104
|
|
90
105
|
def custom_obj_path
|
91
|
-
map_val =
|
106
|
+
map_val = type_path_map.fetch(@obj_type.to_sym, nil)
|
92
107
|
return obj_path_from_name if map_val.nil?
|
93
108
|
|
94
109
|
if map_val.respond_to?(:key?)
|
95
|
-
custom_obj_path_from_hash(map_val)
|
110
|
+
custom_obj_path_from_hash(map_val, @obj_name)
|
96
111
|
else
|
97
112
|
abs_path = Pathname.new(map_val).absolute? ? map_val : "#{Dir.pwd}/#{map_val}"
|
98
|
-
"#{abs_path}/#{@
|
113
|
+
"#{abs_path}/#{basename(@obj_name)}#{DEFAULT_EXT}"
|
99
114
|
end
|
100
115
|
end
|
101
116
|
|
102
|
-
def custom_obj_path_from_hash(map_val)
|
117
|
+
def custom_obj_path_from_hash(map_val, obj_name)
|
103
118
|
raise AbideDevUtils::Errors::Ppt::CustomObjPathKeyError, map_val unless map_val.key?(:path)
|
104
119
|
|
105
120
|
abs_path = Pathname.new(map_val[:path]).absolute? ? map_val[:path] : "#{Dir.pwd}/#{map_val[:path]}"
|
106
121
|
if map_val.key?(:extension)
|
107
|
-
"#{abs_path}/#{
|
122
|
+
"#{abs_path}/#{basename(obj_name)}#{map_val[:extension]}"
|
108
123
|
else
|
109
|
-
"#{abs_path}/#{
|
124
|
+
"#{abs_path}/#{basename(obj_name)}#{DEFAULT_EXT}"
|
110
125
|
end
|
111
126
|
end
|
112
127
|
end
|
@@ -25,6 +25,7 @@ module AbideDevUtils
|
|
25
25
|
relative_select: './xccdf:select'
|
26
26
|
}
|
27
27
|
}.freeze
|
28
|
+
NEXT_GEN_WINDOWS = /(next_generation_windows_security)/.freeze
|
28
29
|
|
29
30
|
attr_reader :title, :version
|
30
31
|
|
@@ -111,11 +112,19 @@ module AbideDevUtils
|
|
111
112
|
end
|
112
113
|
|
113
114
|
def normalize_str(str)
|
114
|
-
str.
|
115
|
+
nstr = str.downcase
|
116
|
+
nstr.gsub!(/[^a-z]$/, '')
|
117
|
+
nstr.gsub!(/^[^a-z]/, '')
|
118
|
+
nstr.gsub!(/^(l1_|l2_|ng_)/, '')
|
119
|
+
nstr.delete!('-')
|
120
|
+
nstr.gsub!(/(\s|\(|\))/, '_')
|
121
|
+
nstr
|
115
122
|
end
|
116
123
|
|
117
124
|
def normalize_profile_name(prof)
|
118
|
-
normalize_str("profile_#{prof}")
|
125
|
+
prof_name = normalize_str("profile_#{prof}")
|
126
|
+
prof_name.gsub!(NEXT_GEN_WINDOWS, 'ngws')
|
127
|
+
prof_name
|
119
128
|
end
|
120
129
|
|
121
130
|
def normalize_ctrl_name(ctrl)
|
@@ -125,12 +134,10 @@ module AbideDevUtils
|
|
125
134
|
|
126
135
|
def make_parent_key(doc, prefix)
|
127
136
|
doc_title = normalize_str(doc.xpath(XPATHS[:benchmark][:title]).children.to_s)
|
128
|
-
if prefix.nil?
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
"#{sepped_prefix.chomp}#{doc_title}"
|
133
|
-
end
|
137
|
+
return doc_title if prefix.nil?
|
138
|
+
|
139
|
+
sepped_prefix = prefix.end_with?('::') ? prefix : "#{prefix}::"
|
140
|
+
"#{sepped_prefix.chomp}#{doc_title}"
|
134
141
|
end
|
135
142
|
end
|
136
143
|
end
|
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.2.
|
4
|
+
version: 0.2.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-03-
|
11
|
+
date: 2021-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|