abide_dev_utils 0.12.2 → 0.13.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e93a77cf4142b06ee4d41863ef2d0b737d21d37306b57082aa316f2731de5e9
4
- data.tar.gz: 9b49e05aa575884d54efed8fd70b5662712845c083a8b59caeccf406a19f5633
3
+ metadata.gz: 863b7f1da9e228c425708434e5adb149a04462c6f9e7a0189799761d9420b6e1
4
+ data.tar.gz: c221c833c4f6b89d80328b3e3bf2de527bb400fe8df5946af2c46d5be45d1b60
5
5
  SHA512:
6
- metadata.gz: 51316ad752020f3b2297acbdc4bb328c5275d03e499721ee12381aaac5da3a6e77ecb9efeb0ffa4b3b6bb512154dbb4b36bf249f4816944a0110d3ceeb871b2b
7
- data.tar.gz: 40b83d7be09ccb1349650617548276f6f34e266fe2e590e8c1b28b8e9c44f4499c93652abf9e254d77469fec9c98e9394a1ae2f4b2d3f0921827c3ce302dfb7e
6
+ metadata.gz: 715413f107df1c3f52269658b124db9bad5b4113042ca9e18eb11cabd73cb3b83a57e3f2adf13591fc168dc841be1fb93d3e972ce74aafe6888b95802b644316
7
+ data.tar.gz: 10eed44e5eb6969974f3426cc65c6c7a00cc988fc5a8ef733df50fafd1c395df44d7afec4b18f51c0ae42d5a36204174a88c42679a6eb3616080deccfb38a86f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- abide_dev_utils (0.12.2)
4
+ abide_dev_utils (0.13.0)
5
5
  amatch (~> 0.4)
6
6
  cmdparse (~> 3.0)
7
7
  facterdb (>= 1.18)
@@ -17,7 +17,7 @@ GEM
17
17
  remote: https://rubygems.org/
18
18
  specs:
19
19
  CFPropertyList (2.3.6)
20
- activesupport (7.0.3)
20
+ activesupport (7.0.4.1)
21
21
  concurrent-ruby (~> 1.0, >= 1.0.2)
22
22
  i18n (>= 1.6, < 2)
23
23
  minitest (>= 5.1)
@@ -60,10 +60,10 @@ GEM
60
60
  diff-lcs (1.5.0)
61
61
  digest-crc (0.6.4)
62
62
  rake (>= 12.0.0, < 14.0.0)
63
- facter (4.2.11)
63
+ facter (4.2.14)
64
64
  hocon (~> 1.3)
65
65
  thor (>= 1.0.1, < 2.0)
66
- facterdb (1.19.0)
66
+ facterdb (1.21.0)
67
67
  facter (< 5.0.0)
68
68
  jgrep
69
69
  faraday (2.3.0)
@@ -84,7 +84,7 @@ GEM
84
84
  octokit (~> 4.6)
85
85
  rainbow (>= 2.2.1)
86
86
  rake (>= 10.0)
87
- google-apis-core (0.7.0)
87
+ google-apis-core (0.10.0)
88
88
  addressable (~> 2.5, >= 2.5.1)
89
89
  googleauth (>= 0.16.2, < 2.a)
90
90
  httpclient (>= 2.8.1, < 3.a)
@@ -93,25 +93,25 @@ GEM
93
93
  retriable (>= 2.0, < 4.a)
94
94
  rexml
95
95
  webrick
96
- google-apis-iamcredentials_v1 (0.13.0)
97
- google-apis-core (>= 0.7, < 2.a)
98
- google-apis-storage_v1 (0.17.0)
99
- google-apis-core (>= 0.7, < 2.a)
96
+ google-apis-iamcredentials_v1 (0.16.0)
97
+ google-apis-core (>= 0.9.1, < 2.a)
98
+ google-apis-storage_v1 (0.19.0)
99
+ google-apis-core (>= 0.9.0, < 2.a)
100
100
  google-cloud-core (1.6.0)
101
101
  google-cloud-env (~> 1.0)
102
102
  google-cloud-errors (~> 1.0)
103
103
  google-cloud-env (1.6.0)
104
104
  faraday (>= 0.17.3, < 3.0)
105
- google-cloud-errors (1.2.0)
106
- google-cloud-storage (1.38.0)
105
+ google-cloud-errors (1.3.0)
106
+ google-cloud-storage (1.44.0)
107
107
  addressable (~> 2.8)
108
108
  digest-crc (~> 0.4)
109
109
  google-apis-iamcredentials_v1 (~> 0.1)
110
- google-apis-storage_v1 (~> 0.17.0)
110
+ google-apis-storage_v1 (~> 0.19.0)
111
111
  google-cloud-core (~> 1.6)
112
112
  googleauth (>= 0.16.2, < 2.a)
113
113
  mini_mime (~> 1.0)
114
- googleauth (1.2.0)
114
+ googleauth (1.3.0)
115
115
  faraday (>= 0.17.3, < 3.a)
116
116
  jwt (>= 1.4, < 3.0)
117
117
  memoist (~> 0.16)
@@ -119,31 +119,36 @@ GEM
119
119
  os (>= 0.9, < 2.0)
120
120
  signet (>= 0.16, < 2.a)
121
121
  hashdiff (1.0.1)
122
- hiera (3.10.0)
122
+ hashie (5.0.0)
123
+ hiera (3.11.0)
123
124
  hocon (1.3.1)
124
125
  httpclient (2.8.3)
125
- i18n (1.10.0)
126
+ i18n (1.12.0)
126
127
  concurrent-ruby (~> 1.0)
127
128
  jgrep (1.5.4)
128
- jira-ruby (2.2.0)
129
+ jira-ruby (2.3.0)
129
130
  activesupport
130
131
  atlassian-jwt
131
132
  multipart-post
132
133
  oauth (~> 0.5, >= 0.5.0)
133
- jwt (2.4.1)
134
+ jwt (2.7.0)
134
135
  locale (2.1.3)
135
136
  memoist (0.16.2)
136
137
  method_source (1.0.0)
137
138
  mini_mime (1.1.2)
138
- minitest (5.15.0)
139
- mize (0.4.0)
139
+ minitest (5.17.0)
140
+ mize (0.4.1)
140
141
  protocol (~> 2.0)
141
142
  multi_json (1.15.0)
142
- multipart-post (2.2.3)
143
+ multipart-post (2.3.0)
143
144
  nio4r (2.5.8)
144
- nokogiri (1.13.8-x86_64-darwin)
145
+ nokogiri (1.14.1-x86_64-darwin)
145
146
  racc (~> 1.4)
146
- oauth (0.5.10)
147
+ nokogiri (1.14.1-x86_64-linux)
148
+ racc (~> 1.4)
149
+ oauth (0.6.2)
150
+ snaky_hash (~> 2.0)
151
+ version_gem (~> 1.1)
147
152
  octokit (4.25.0)
148
153
  faraday (>= 1, < 3)
149
154
  sawyer (~> 0.9)
@@ -164,9 +169,20 @@ GEM
164
169
  coderay (~> 1.1)
165
170
  method_source (~> 1.0)
166
171
  public_suffix (4.0.7)
167
- puppet (7.18.0-universal-darwin)
172
+ puppet (7.22.0)
173
+ concurrent-ruby (~> 1.0, < 1.2.0)
174
+ deep_merge (~> 1.0)
175
+ facter (> 2.0.1, < 5)
176
+ fast_gettext (>= 1.1, < 3)
177
+ hiera (>= 3.2.1, < 4)
178
+ locale (~> 2.1)
179
+ multi_json (~> 1.10)
180
+ puppet-resource_api (~> 1.5)
181
+ scanf (~> 1.0)
182
+ semantic_puppet (~> 1.0)
183
+ puppet (7.22.0-universal-darwin)
168
184
  CFPropertyList (~> 2.2)
169
- concurrent-ruby (~> 1.0)
185
+ concurrent-ruby (~> 1.0, < 1.2.0)
170
186
  deep_merge (~> 1.0)
171
187
  facter (> 2.0.1, < 5)
172
188
  fast_gettext (>= 1.1, < 3)
@@ -178,7 +194,7 @@ GEM
178
194
  semantic_puppet (~> 1.0)
179
195
  puppet-resource_api (1.8.14)
180
196
  hocon (>= 1.0)
181
- racc (1.6.0)
197
+ racc (1.6.2)
182
198
  rainbow (3.1.1)
183
199
  rake (13.0.6)
184
200
  regexp_parser (2.5.0)
@@ -221,7 +237,7 @@ GEM
221
237
  rubocop (~> 1.19)
222
238
  ruby-progressbar (1.11.0)
223
239
  ruby2_keywords (0.0.5)
224
- ruby_parser (3.19.1)
240
+ ruby_parser (3.19.2)
225
241
  sexp_processor (~> 4.16)
226
242
  rubyzip (2.3.2)
227
243
  sawyer (0.9.2)
@@ -239,18 +255,22 @@ GEM
239
255
  faraday (>= 0.17.5, < 3.a)
240
256
  jwt (>= 1.5, < 3.0)
241
257
  multi_json (~> 1.10)
258
+ snaky_hash (2.0.1)
259
+ hashie
260
+ version_gem (~> 1.1, >= 1.1.1)
242
261
  sync (0.5.0)
243
262
  thor (1.2.1)
244
263
  timers (4.3.3)
245
- tins (1.31.1)
264
+ tins (1.32.1)
246
265
  sync
247
266
  traces (0.4.1)
248
267
  trailblazer-option (0.1.2)
249
- tzinfo (2.0.4)
268
+ tzinfo (2.0.5)
250
269
  concurrent-ruby (~> 1.0)
251
270
  uber (0.1.0)
252
271
  unicode-display_width (2.1.0)
253
- webrick (1.7.0)
272
+ version_gem (1.1.1)
273
+ webrick (1.8.1)
254
274
 
255
275
  PLATFORMS
256
276
  x86_64-darwin-19
@@ -123,8 +123,9 @@ module Abide
123
123
  super(CMD_NAME, takes_commands: false)
124
124
  short_desc(CMD_SHORT)
125
125
  long_desc(CMD_LONG)
126
- argument_desc(PATH: 'An XCCDF file from the abide puppet ticket coverage command', PROJECT: 'A Jira project')
126
+ argument_desc(PATH: 'An XCCDF file', PROJECT: 'A Jira project')
127
127
  options.on('-d', '--dry-run', 'Print to console instead of saving objects') { |_| @data[:dry_run] = true }
128
+ options.on('-e [EPIC]', '--epic [EPIC]', 'If given, tasks will be created and assigned to this epic. Takes form <PROJECT>-<NUM>') { |e| @data[:epic] = e }
128
129
  end
129
130
 
130
131
  def execute(path, project)
@@ -132,7 +133,7 @@ module Abide
132
133
  @data[:dry_run] = false if @data[:dry_run].nil?
133
134
  client = JIRA.client(options: {})
134
135
  proj = JIRA.project(client, project)
135
- JIRA.new_issues_from_xccdf(client, proj, path, dry_run: @data[:dry_run])
136
+ JIRA.new_issues_from_xccdf(client, proj, path, epic: @data[:epic], dry_run: @data[:dry_run])
136
137
  end
137
138
  end
138
139
  end
@@ -9,6 +9,10 @@ module AbideDevUtils
9
9
  @default = 'Failed to create Jira issue:'
10
10
  end
11
11
 
12
+ class CreateEpicError < GenericError
13
+ @default = 'Failed to create Jira epic:'
14
+ end
15
+
12
16
  class CreateSubtaskError < GenericError
13
17
  @default = 'Failed to create Jira subtask for issue:'
14
18
  end
@@ -11,6 +11,7 @@ module AbideDevUtils
11
11
  ERRORS = AbideDevUtils::Errors::Jira
12
12
  COV_PARENT_SUMMARY_PREFIX = '::BENCHMARK:: '
13
13
  COV_CHILD_SUMMARY_PREFIX = '::CONTROL:: '
14
+ PROGRESS_BAR_FORMAT = '%a %e %P% Created: %c of %C'
14
15
 
15
16
  def self.project(client, project)
16
17
  client.Project.find(project)
@@ -18,6 +19,11 @@ module AbideDevUtils
18
19
 
19
20
  def self.issue(client, issue)
20
21
  client.Issue.find(issue)
22
+ rescue URI::InvalidURIError
23
+ iss = client.Issue.all.find { |i| i.summary == issue }
24
+ raise ERRORS::FindIssueError, issue unless iss
25
+
26
+ iss
21
27
  end
22
28
 
23
29
  def self.myself(client)
@@ -25,11 +31,19 @@ module AbideDevUtils
25
31
  end
26
32
 
27
33
  def self.issuetype(client, id)
28
- client.Issuetype.find(id)
34
+ if id.match?(%r{^\d+$})
35
+ client.Issuetype.find(id)
36
+ else
37
+ client.Issuetype.all.find { |i| i.name == id }
38
+ end
29
39
  end
30
40
 
31
41
  def self.priority(client, id)
32
- client.Priority.find(id)
42
+ if id.match?(%r{^\d+$})
43
+ client.Priority.find(id)
44
+ else
45
+ client.Priority.all.find { |i| i.name == id }
46
+ end
33
47
  end
34
48
 
35
49
  def self.all_project_issues_attrs(project)
@@ -37,21 +51,50 @@ module AbideDevUtils
37
51
  raw_issues.collect(&:attrs)
38
52
  end
39
53
 
40
- def self.new_issue(client, project, summary, dry_run: false)
54
+ def self.add_issue_label(iss, label, dry_run: false)
55
+ return if dry_run || iss.labels.include?(label)
56
+
57
+ iss.labels << profile_summary
58
+ iss.save
59
+ end
60
+
61
+ def self.new_issue(client, project, summary, labels: ['abide_dev_utils'], epic: nil, dry_run: false)
41
62
  if dry_run
42
63
  sleep(0.2)
43
- return Dummy.new
64
+ return Dummy.new(summary)
44
65
  end
45
66
  fields = {}
46
67
  fields['summary'] = summary
47
68
  fields['project'] = project(client, project)
48
69
  fields['reporter'] = myself(client)
49
- fields['issuetype'] = issuetype(client, '3')
70
+ fields['issuetype'] = issuetype(client, 'Task')
50
71
  fields['priority'] = priority(client, '6')
51
- issue = client.Issue.build
52
- raise ERRORS::CreateIssueError, issue.attrs unless issue.save({ 'fields' => fields })
72
+ fields['labels'] = labels
73
+ epic = issue(client, epic) if epic && !epic.is_a?(JIRA::Resource::Issue)
74
+ fields['customfield_10006'] = epic.key if epic # Epic_Link
75
+ iss = client.Issue.build
76
+ raise ERRORS::CreateIssueError, iss.attrs unless iss.save({ 'fields' => fields })
53
77
 
54
- issue
78
+ iss
79
+ end
80
+
81
+ def self.new_epic(client, project, summary, dry_run: false)
82
+ AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Creating epic '#{summary}'")
83
+ if dry_run
84
+ sleep(0.2)
85
+ return Dummy.new(summary)
86
+ end
87
+ fields = {
88
+ 'summary' => summary,
89
+ 'project' => project(client, project),
90
+ 'reporter' => myself(client),
91
+ 'issuetype' => issuetype(client, 'Epic'),
92
+ 'customfield_10007' => summary, # Epic Name
93
+ }
94
+ iss = client.Issue.build
95
+ raise ERRORS::CreateEpicError, iss.attrs unless iss.save({ 'fields' => fields })
96
+
97
+ iss
55
98
  end
56
99
 
57
100
  # This should probably be threaded in the future
@@ -135,46 +178,55 @@ module AbideDevUtils
135
178
  end
136
179
  end
137
180
 
138
- def self.new_issues_from_xccdf(client, project, xccdf_path, dry_run: false)
139
- dr_prefix = dry_run ? 'DRY RUN: ' : ''
181
+ def self.new_issues_from_xccdf(client, project, xccdf_path, epic: nil, dry_run: false)
140
182
  i_attrs = all_project_issues_attrs(project)
141
-
142
183
  xccdf = AbideDevUtils::XCCDF::Benchmark.new(xccdf_path)
143
-
144
- summaries = summaries_from_xccdf(xccdf)
145
- summaries.each do |profile_summary, control_summaries|
146
- if summary_exist?(profile_summary, i_attrs)
147
- AbideDevUtils::Output.simple("#{dr_prefix}Skipping #{profile_summary} as it already exists")
148
- next
184
+ # We need to get the actual epic Issue object, or create it if it doesn't exist
185
+ epic = if epic.nil?
186
+ new_epic_summary = "#{COV_PARENT_SUMMARY_PREFIX}#{xccdf.title}"
187
+ if summary_exist?(new_epic_summary, i_attrs)
188
+ issue(client, new_epic_summary)
189
+ else
190
+ unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create new epic '#{new_epic_summary}'?")
191
+ AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Aborting")
192
+ exit(0)
193
+ end
194
+ new_epic(client, project.key, new_epic_summary, dry_run: dry_run)
195
+ end
196
+ else
197
+ issue(client, epic)
198
+ end
199
+ # Now we need to find out which issues we need to create for the benchmark
200
+ # The profiles that the control belongs to will be added as an issue label
201
+ to_create = {}
202
+ summaries_from_xccdf(xccdf).each do |profile_summary, control_summaries|
203
+ control_summaries.reject { |s| summary_exist?(s, i_attrs) }.each do |control_summary|
204
+ if to_create.key?(control_summary)
205
+ to_create[control_summary] << profile_summary.split.join('_').downcase
206
+ else
207
+ to_create[control_summary] = [profile_summary.split.join('_').downcase]
208
+ end
149
209
  end
210
+ end
150
211
 
151
- parent = new_issue(client, project.attrs['key'], profile_summary, dry_run: dry_run)
152
- AbideDevUtils::Output.simple("#{dr_prefix}Created parent issue #{profile_summary}")
153
- parent_issue = issue(client, parent.attrs['key']) unless parent.respond_to?(:dummy)
154
- AbideDevUtils::Output.simple("#{dr_prefix}Creating subtasks, this can take a while...")
155
- progress = AbideDevUtils::Output.progress(title: "#{dr_prefix}Creating Subtasks", total: nil)
156
- control_summaries.each do |control_summary|
157
- next if summary_exist?(control_summary, i_attrs)
212
+ unless AbideDevUtils::Prompt.yes_no("#{dr_prefix(dry_run)}Create #{to_create.keys.count} new Jira issues?")
213
+ AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Aborting")
214
+ exit(0)
215
+ end
158
216
 
159
- progress.title = "#{dr_prefix}#{control_summary}"
160
- new_subtask(client, parent_issue, control_summary, dry_run: dry_run)
161
- progress.increment
162
- end
163
- final_text = "#{dr_prefix}Created #{control_summaries.count} subtasks for #{profile_summary}"
164
- puts "\r\033[K#{final_text}\n"
217
+ progress = AbideDevUtils::Output.progress(title: "#{dr_prefix(dry_run)}Creating issues",
218
+ total: to_create.keys.count,
219
+ format: PROGRESS_BAR_FORMAT)
220
+ to_create.each do |control_summary, labels|
221
+ abrev = control_summary.length > 40 ? control_summary[0..60] : control_summary
222
+ progress.log("#{dr_prefix(dry_run)}Creating #{abrev}...")
223
+ new_issue(client, project.key, control_summary, labels: labels, epic: epic, dry_run: dry_run)
224
+ progress.increment
165
225
  end
226
+ progress.finish
227
+ AbideDevUtils::Output.simple("#{dr_prefix(dry_run)}Done creating tasks in Epic '#{epic.summary}'")
166
228
  end
167
229
 
168
- # def self.new_issues_from_comply_report(client, project, report, dry_run: false)
169
- # dr_prefix = dry_run ? 'DRY RUN: ' : ''
170
- # i_attrs = all_project_issues_attrs(project)
171
- # rep_sums = summaries_from_coverage_report(report)
172
- # rep_sums.each do |k, v|
173
- # next if summary_exist?(k, i_attrs)
174
-
175
- # progress = AbideDevUtils::Output.progress(title: "#{dr_prefix}Creating Tasks", total: nil)
176
- # v.each do |s|
177
-
178
230
  def self.merge_options(options)
179
231
  config.merge(options)
180
232
  end
@@ -209,25 +261,30 @@ module AbideDevUtils
209
261
 
210
262
  def self.summaries_from_xccdf(xccdf)
211
263
  summaries = {}
212
- facter_os = xccdf.facter_benchmark.join('-')
213
264
  xccdf.profiles.each do |profile|
214
- summaries["#{COV_PARENT_SUMMARY_PREFIX}#{facter_os} - #{profile.level} #{profile.title}"] = profile.controls.collect do |control|
215
- summary = "#{COV_CHILD_SUMMARY_PREFIX}#{control.vulnid} - #{control.title}"
216
- if summary.length > 255
217
- summary = summary[0..251] + '...'
218
- end
265
+ sum_key = "#{profile.level}_#{profile.title}".split.join('_').downcase
266
+ summaries[sum_key] = profile.controls.collect do |control|
267
+ control_id = control.respond_to?(:vulnid) ? control.vulnid : control.number
268
+ summary = "#{control_id} - #{control.title}"
269
+ summary = "#{summary[0..251]}..." if summary.length > 255
219
270
  summary
220
271
  end
221
272
  end
222
273
  summaries
223
274
  end
224
275
 
225
- # def self.summaries_from_comply_report(report)
226
- # summaries = {}
227
- # report.each do |_, v|
228
- # end
276
+ def self.dr_prefix(dry_run)
277
+ dry_run ? 'DRY RUN: ' : ''
278
+ end
229
279
 
230
280
  class Dummy
281
+ attr_reader :summary, :key
282
+
283
+ def initialize(summary = 'dummy summary')
284
+ @summary = summary
285
+ @key = 'DUM-111'
286
+ end
287
+
231
288
  def attrs
232
289
  { 'fields' => {
233
290
  'project' => 'dummy',
@@ -41,8 +41,8 @@ module AbideDevUtils
41
41
  FWRITER.write_yml(yml_out, file: file) unless file.nil?
42
42
  end
43
43
 
44
- def self.progress(title: 'Progress', start: 0, total: 100)
45
- ProgressBar.create(title: title, starting_at: start, total: total)
44
+ def self.progress(title: 'Progress', start: 0, total: 100, format: nil)
45
+ ProgressBar.create(title: title, starting_at: start, total: total, format: format)
46
46
  end
47
47
  end
48
48
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbideDevUtils
4
- VERSION = "0.12.2"
4
+ VERSION = "0.13.0"
5
5
  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.12.2
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - abide-team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-17 00:00:00.000000000 Z
11
+ date: 2023-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri