abide_dev_utils 0.12.2 → 0.13.0

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