abide_dev_utils 0.4.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.rubocop.yml +1 -1
  4. data/CODEOWNERS +1 -0
  5. data/README.md +34 -0
  6. data/abide_dev_utils.gemspec +11 -7
  7. data/itests.rb +138 -0
  8. data/lib/abide_dev_utils/cli/abstract.rb +2 -0
  9. data/lib/abide_dev_utils/cli/comply.rb +115 -0
  10. data/lib/abide_dev_utils/cli/jira.rb +2 -2
  11. data/lib/abide_dev_utils/cli/puppet.rb +136 -11
  12. data/lib/abide_dev_utils/cli/xccdf.rb +26 -7
  13. data/lib/abide_dev_utils/cli.rb +2 -0
  14. data/lib/abide_dev_utils/comply.rb +498 -0
  15. data/lib/abide_dev_utils/config.rb +19 -0
  16. data/lib/abide_dev_utils/errors/comply.rb +17 -0
  17. data/lib/abide_dev_utils/errors/gcloud.rb +27 -0
  18. data/lib/abide_dev_utils/errors/general.rb +5 -0
  19. data/lib/abide_dev_utils/errors/ppt.rb +12 -0
  20. data/lib/abide_dev_utils/errors/xccdf.rb +8 -0
  21. data/lib/abide_dev_utils/errors.rb +2 -0
  22. data/lib/abide_dev_utils/gcloud.rb +22 -0
  23. data/lib/abide_dev_utils/jira.rb +15 -0
  24. data/lib/abide_dev_utils/mixins.rb +16 -0
  25. data/lib/abide_dev_utils/output.rb +7 -3
  26. data/lib/abide_dev_utils/ppt/api.rb +219 -0
  27. data/lib/abide_dev_utils/ppt/class_utils.rb +184 -0
  28. data/lib/abide_dev_utils/ppt/coverage.rb +2 -3
  29. data/lib/abide_dev_utils/ppt/score_module.rb +162 -0
  30. data/lib/abide_dev_utils/ppt.rb +138 -49
  31. data/lib/abide_dev_utils/validate.rb +5 -1
  32. data/lib/abide_dev_utils/version.rb +1 -1
  33. data/lib/abide_dev_utils/xccdf.rb +567 -9
  34. data/lib/abide_dev_utils.rb +1 -0
  35. metadata +82 -17
  36. data/lib/abide_dev_utils/utils/general.rb +0 -9
  37. data/lib/abide_dev_utils/xccdf/cis/hiera.rb +0 -161
  38. data/lib/abide_dev_utils/xccdf/cis.rb +0 -3
@@ -0,0 +1,498 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'yaml'
5
+ require 'selenium-webdriver'
6
+ require 'abide_dev_utils/errors/comply'
7
+ require 'abide_dev_utils/gcloud'
8
+ require 'abide_dev_utils/output'
9
+ require 'abide_dev_utils/prompt'
10
+ require 'pry'
11
+
12
+ module AbideDevUtils
13
+ # Holds module methods and a class for dealing with Puppet Comply
14
+ module Comply
15
+ include AbideDevUtils::Errors::Comply
16
+
17
+ def self.build_report(url, password, config = nil, **opts)
18
+ ReportScraper.new(url, config, **opts).build_report(password)
19
+ end
20
+
21
+ def self.compare_reports(report_a, report_b, **opts)
22
+ report_name = opts.fetch(:report_name, nil)
23
+ current_report = ScanReport.new.from_yaml(report_a)
24
+ last_report = if opts.fetch(:remote_storage, '') == 'gcloud'
25
+ report_name = report_b if report_name.nil?
26
+ ScanReport.new.from_yaml(ScanReport.fetch_report(name: report_b))
27
+ else
28
+ report_name = File.basename(report_b) if report_name.nil?
29
+ ScanReport.new.from_yaml(File.read(report_b))
30
+ end
31
+ result, details = current_report.report_comparison(last_report, check_goodness: true)
32
+ if result
33
+ AbideDevUtils::Output.simple('No negative differences detected...')
34
+ AbideDevUtils::Output.simple(JSON.pretty_generate(details))
35
+ else
36
+ AbideDevUtils::Output.simple('Negative differences detected!', stream: $stderr)
37
+ AbideDevUtils::Output.simple(JSON.pretty_generate(details), stream: $stderr)
38
+ end
39
+ if opts.fetch(:upload, false) && !opts.fetch(:remote_storage, '').empty? && !report_name.nil?
40
+ AbideDevUtils::Output.simple('Uploading current report...')
41
+ ScanReport.upload_report(File.expand_path(report_a), name: report_name)
42
+ AbideDevUtils::Output.simple('Successfully uploaded report.')
43
+ end
44
+ result
45
+ end
46
+
47
+ # Class that uses Selenium WebDriver to gather scan reports from Puppet Comply
48
+ class ReportScraper
49
+ attr_reader :timeout,
50
+ :username,
51
+ :status,
52
+ :ignorelist,
53
+ :onlylist,
54
+ :max_pagination,
55
+ :screenshot_on_error,
56
+ :page_source_on_error
57
+
58
+ def initialize(url, config = nil, **opts)
59
+ @url = url
60
+ @config = config
61
+ @opts = opts
62
+ @timeout = fetch_option(:timeout, 10).to_i
63
+ @username = fetch_option(:username, 'comply')
64
+ @status = fetch_option(:status)
65
+ @ignorelist = fetch_option(:ignorelist, [])
66
+ @onlylist = fetch_option(:onlylist, [])
67
+ @max_pagination = fetch_option(:max_pagination, 5).to_i
68
+ @screenshot_on_error = fetch_option(:screenshot_on_error, false)
69
+ @page_source_on_error = fetch_option(:page_source_on_error, false)
70
+ end
71
+
72
+ def build_report(password)
73
+ connect(password)
74
+ scrape_report
75
+ ensure
76
+ driver.quit
77
+ end
78
+
79
+ def file_dir
80
+ @file_dir ||= File.expand_path('~/abide_dev_utils')
81
+ end
82
+
83
+ def file_dir=(path)
84
+ @file_dir = new_file_dir(path)
85
+ end
86
+
87
+ private
88
+
89
+ attr_reader :progress
90
+
91
+ def fetch_option(option, default = nil)
92
+ return @opts.fetch(option, default) if @config.nil?
93
+
94
+ @opts.key?(option) ? @opts[option] : @config.fetch(option, default)
95
+ end
96
+
97
+ def node_report_links
98
+ @node_report_links ||= find_node_report_links
99
+ end
100
+
101
+ def driver
102
+ @driver ||= new_driver
103
+ end
104
+
105
+ def output
106
+ AbideDevUtils::Output
107
+ end
108
+
109
+ def prompt
110
+ AbideDevUtils::Prompt
111
+ end
112
+
113
+ def new_progress(node_name)
114
+ @progress = AbideDevUtils::Output.progress title: "Building report for #{node_name}", total: nil
115
+ end
116
+
117
+ def new_driver
118
+ options = Selenium::WebDriver::Chrome::Options.new
119
+ options.args = @opts.fetch(:driveropts, %w[
120
+ --headless
121
+ --test-type
122
+ --disable-gpu
123
+ --no-sandbox
124
+ --no-first-run
125
+ --no-default-browser-check
126
+ --ignore-certificate-errors
127
+ --start-maximized
128
+ ])
129
+ output.simple 'Starting headless Chrome...'
130
+ Selenium::WebDriver.for(:chrome, options: options)
131
+ end
132
+
133
+ def find_element(subject = driver, **kwargs)
134
+ driver.manage.window.resize_to(1920, 1080)
135
+ subject.find_element(**kwargs)
136
+ end
137
+
138
+ def wait_on(timeout: @timeout,
139
+ ignore_nse: false,
140
+ quit_driver: true,
141
+ quiet: false,
142
+ ignore: [Selenium::WebDriver::Error::NoSuchElementError],
143
+ &block)
144
+ raise 'wait_on must be passed a block' unless block
145
+
146
+ value = nil
147
+ if ignore_nse
148
+ begin
149
+ Selenium::WebDriver::Wait.new(ignore: [], timeout: timeout, interval: 1).until do
150
+ value = yield
151
+ end
152
+ rescue Selenium::WebDriver::Error::NoSuchElementError
153
+ return value
154
+ rescue StandardError => e
155
+ raise_error(e, AbideDevUtils::Comply::WaitOnError, quit_driver: quit_driver, quiet: quiet)
156
+ end
157
+ else
158
+ begin
159
+ Selenium::WebDriver::Wait.new(ignore: ignore, timeout: timeout, interval: 1).until do
160
+ value = yield
161
+ end
162
+ rescue StandardError => e
163
+ raise_error(e, AbideDevUtils::Comply::WaitOnError, quit_driver: quit_driver, quiet: quiet)
164
+ end
165
+ end
166
+ value
167
+ end
168
+
169
+ def new_file_dir(path)
170
+ return File.expand_path(path) if Dir.exist?(File.expand_path(path))
171
+
172
+ create_dir = prompt.yes_no("Directory #{path} does not exist. Create directory?")
173
+ return unless create_dir
174
+
175
+ require 'fileutils'
176
+ FileUtils.mkdir_p path
177
+ end
178
+
179
+ def raise_error(original, err_class = nil, quit_driver: true, quiet: false)
180
+ output.simple 'Something went wrong!' unless quiet
181
+ if screenshot_on_error
182
+ output.simple 'Taking a screenshot of current page state...' unless quiet
183
+ screenshot
184
+ end
185
+
186
+ if page_source_on_error
187
+ output.simple 'Saving page source of current page...' unless quiet
188
+ page_source
189
+ end
190
+
191
+ driver.quit if quit_driver
192
+ actual_err_class = err_class.nil? ? original.class : err_class
193
+ raise actual_err_class, original.message
194
+ end
195
+
196
+ def screenshot
197
+ driver.save_screenshot(File.join(file_dir, "comply_error_#{Time.now.to_i}.png"))
198
+ rescue Errno::ENOENT
199
+ save_default = prompt.yes_no(
200
+ "Directory #{file_dir} does not exist. Save screenshot to current directory?"
201
+ )
202
+ driver.save_screenshot(File.join(File.expand_path('.'), "comply_error_#{Time.now.to_i}.png")) if save_default
203
+ end
204
+
205
+ def page_source
206
+ File.open(File.join(file_dir, "comply_error_#{Time.now.to_i}.txt"), 'w') { |f| f.write(driver.page_source) }
207
+ rescue Errno::ENOENT
208
+ save_default = prompt.yes_no(
209
+ "Directory #{file_dir} does not exist. Save page source to current directory?"
210
+ )
211
+ if save_default
212
+ File.open(File.join(File.expand_path('.'), "comply_error_#{Time.now.to_i}.html"), 'w') do |f|
213
+ f.write(driver.page_source)
214
+ end
215
+ end
216
+ end
217
+
218
+ def bypass_ssl_warning_page
219
+ wait_on(ignore_nse: true) do
220
+ find_element(id: 'details-button').click
221
+ find_element(id: 'proceed-link').click
222
+ end
223
+ end
224
+
225
+ def login_to_comply(password)
226
+ output.simple "Logging into Comply at #{@url}..."
227
+ wait_on { driver.find_element(id: 'username') }
228
+ find_element(id: 'username').send_keys username
229
+ find_element(id: 'password').send_keys password
230
+ find_element(id: 'kc-login').click
231
+ error_text = wait_on(ignore_nse: true) { find_element(class: 'kc-feedback-text').text }
232
+ return if error_text.nil? || error_text.empty?
233
+
234
+ raise ComplyLoginFailedError, error_text
235
+ end
236
+
237
+ def filter_node_report_links(node_report_links)
238
+ if onlylist.empty? && ignorelist.empty?
239
+ output.simple 'No filters set, using all node reports...'
240
+ return node_report_links
241
+ end
242
+
243
+ unless onlylist.empty?
244
+ output.simple 'Onlylist found, filtering node reports...'
245
+ return node_report_links.select { |l| onlylist.include?(l[:name]) }
246
+ end
247
+
248
+ output.simple 'Ignorelist found, filtering node reports...'
249
+ node_report_links.reject { |l| ignorelist.include?(l[:name]) }
250
+ end
251
+
252
+ def find_node_report_table(subject)
253
+ wait_on { find_element(subject, class: 'metric-containers-failed-hosts-count') }
254
+ hosts = find_element(subject, class: 'metric-containers-failed-hosts-count')
255
+ table = find_element(hosts, class: 'rc-table')
256
+ wait_on { find_element(table, tag_name: 'tbody') }
257
+ find_element(table, tag_name: 'tbody')
258
+ end
259
+
260
+ def wait_for_node_report_links(table_body)
261
+ wait_on(timeout: 2, quit_driver: false, quiet: true) { table_body.find_element(tag_name: 'a') }
262
+ output.simple 'Found node report links...'
263
+ table_body.find_elements(tag_name: 'a')
264
+ rescue AbideDevUtils::Comply::WaitOnError
265
+ []
266
+ end
267
+
268
+ def find_node_report_links
269
+ output.simple 'Finding nodes with scan reports...'
270
+ node_report_links = []
271
+ (1..max_pagination).each do |page|
272
+ output.simple "Trying page #{page}..."
273
+ driver.get("#{@url}/dashboard?page=#{page}&limit=50")
274
+ table_body = find_node_report_table(driver)
275
+ elems = wait_for_node_report_links(table_body)
276
+ if elems.empty?
277
+ output.simple "No links found on page #{page}, stopping search..."
278
+ break
279
+ end
280
+
281
+ elems.each do |elem|
282
+ node_report_links << { name: elem.text, url: elem.attribute('href') }
283
+ end
284
+ end
285
+ driver.get(@url)
286
+ filter_node_report_links(node_report_links)
287
+ end
288
+
289
+ def connect(password)
290
+ output.simple "Connecting to #{@url}..."
291
+ driver.get(@url)
292
+ bypass_ssl_warning_page
293
+ login_to_comply(password)
294
+ end
295
+
296
+ def normalize_cis_rec_name(name)
297
+ nstr = name.downcase
298
+ nstr.delete!('(/|\\|\+|:|\'|")')
299
+ nstr.gsub!(/(\s|\(|\)|-|\.)/, '_')
300
+ nstr.strip!
301
+ nstr
302
+ end
303
+
304
+ def scrape_report
305
+ output.simple 'Building scan reports, this may take a while...'
306
+ all_checks = {}
307
+ original_window = driver.window_handle
308
+ node_report_links.each do |link|
309
+ node_name = link[:name]
310
+ link_url = link[:url]
311
+ new_progress(node_name)
312
+ driver.manage.new_window(:tab)
313
+ progress.increment
314
+ wait_on { driver.window_handles.length == 2 }
315
+ progress.increment
316
+ driver.switch_to.window driver.window_handles[1]
317
+ driver.get(link_url)
318
+ wait_on { find_element(class: 'details-scan-info') }
319
+ progress.increment
320
+ wait_on { find_element(class: 'details-table') }
321
+ progress.increment
322
+ report = { 'scan_results' => {} }
323
+ scan_info_table = find_element(class: 'details-scan-info')
324
+ scan_info_table_rows = scan_info_table.find_elements(tag_name: 'tr')
325
+ progress.increment
326
+ check_table_body = find_element(tag_name: 'tbody')
327
+ check_table_rows = check_table_body.find_elements(tag_name: 'tr')
328
+ progress.increment
329
+ scan_info_table_rows.each do |row|
330
+ key = find_element(row, tag_name: 'h5').text
331
+ value = find_element(row, tag_name: 'strong').text
332
+ report[key.downcase.tr(':', '').tr(' ', '_')] = value
333
+ progress.increment
334
+ end
335
+ check_table_rows.each do |row|
336
+ chk_objs = row.find_elements(tag_name: 'td')
337
+ chk_objs.map!(&:text)
338
+ if status.nil? || status.include?(chk_objs[1].downcase)
339
+ name_parts = chk_objs[0].match(/^([0-9.]+) (.+)$/)
340
+ key = normalize_cis_rec_name(name_parts[2])
341
+ unless report['scan_results'].key?(chk_objs[1])
342
+ report['scan_results'][chk_objs[1]] = {}
343
+ end
344
+ report['scan_results'][chk_objs[1]][key] = {
345
+ 'name' => name_parts[2].chomp,
346
+ 'number' => name_parts[1].chomp
347
+ }
348
+ end
349
+ progress.increment
350
+ end
351
+ all_checks[node_name] = report
352
+ driver.close
353
+ output.simple "Created report for #{node_name}"
354
+ rescue ::StandardError => e
355
+ raise_error(e)
356
+ ensure
357
+ driver.switch_to.window original_window
358
+ end
359
+ all_checks
360
+ end
361
+ end
362
+
363
+ # Contains multiple NodeScanReport objects
364
+ class ScanReport
365
+ attr_reader :node_scan_reports
366
+
367
+ def from_yaml(report)
368
+ @scan_report = if report.is_a? Hash
369
+ report
370
+ elsif File.file?(report)
371
+ File.open(report.to_s, 'r') { |f| YAML.safe_load(f.read) }
372
+ else
373
+ YAML.safe_load(report)
374
+ end
375
+ @node_scan_reports = build_node_scan_reports
376
+ self
377
+ end
378
+
379
+ def to_h
380
+ node_scan_reports.each_with_object({}) do |node, h|
381
+ h[node.name] = node.hash
382
+ end
383
+ end
384
+
385
+ def to_yaml
386
+ to_h.to_yaml
387
+ end
388
+
389
+ def self.storage_bucket
390
+ @storage_bucket ||= AbideDevUtils::GCloud.storage_bucket
391
+ end
392
+
393
+ def self.fetch_report(name: 'comply_report.yaml')
394
+ report = storage_bucket.file(name)
395
+ report.download.read
396
+ end
397
+
398
+ def self.upload_report(report, name: 'comply_report.yaml')
399
+ storage_bucket.create_file(report, name)
400
+ end
401
+
402
+ def report_comparison(other, check_goodness: false)
403
+ comparison = []
404
+ node_scan_reports.zip(other.node_scan_reports).each do |cr, lr|
405
+ comparison << { cr.name => { diff: {}, node_presense: :new } } if lr.nil?
406
+ comparison << { lr.name => { diff: {}, node_presense: :dropped } } if cr.nil?
407
+ comparison << { cr.name => { diff: cr.diff(lr), node_presence: :same } } unless cr.nil? || lr.nil?
408
+ end
409
+ comparison.inject(&:merge)
410
+ return good_comparison?(comparison) if check_goodness
411
+
412
+ compairison
413
+ end
414
+
415
+ def good_comparison?(report_comparison)
416
+ good = true
417
+ not_good = {}
418
+ report_comparison.each do |node_report|
419
+ node_name = node_report.keys[0]
420
+ report = node_report[node_name]
421
+ next if report[:diff].empty?
422
+
423
+ not_good[node_name] = {}
424
+ unless report.dig(:diff, :passing, :other).nil?
425
+ good = false
426
+ not_good[node_name][:new_not_passing] = report[:diff][:passing][:other]
427
+ end
428
+ unless report.dig(:diff, :failing, :self).nil?
429
+ good = false
430
+ not_good[node_name][:new_failing] = report[:diff][:failing][:self]
431
+ end
432
+ end
433
+ [good, not_good]
434
+ end
435
+
436
+ private
437
+
438
+ def build_node_scan_reports
439
+ node_scan_reports = []
440
+ @scan_report.each do |node_name, node_hash|
441
+ node_scan_reports << NodeScanReport.new(node_name, node_hash)
442
+ end
443
+ node_scan_reports.sort_by(&:name)
444
+ end
445
+ end
446
+
447
+ # Class representation of a Comply node scan report
448
+ class NodeScanReport
449
+ attr_reader :name, :passing, :failing, :error, :not_checked, :informational, :benchmark, :last_scan, :profile
450
+
451
+ DIFF_PROPERTIES = %i[passing failing error not_checked informational].freeze
452
+
453
+ def initialize(node_name, node_hash)
454
+ @name = node_name
455
+ @hash = node_hash
456
+ @passing = node_hash.dig('scan_results', 'Pass') || {}
457
+ @failing = node_hash.dig('scan_results', 'Fail') || {}
458
+ @error = node_hash.dig('scan_results', 'Error') || {}
459
+ @not_checked = node_hash.dig('scan_results', 'Not checked') || {}
460
+ @informational = node_hash.dig('scan_results', 'Informational') || {}
461
+ @benchmark = node_hash['benchmark']
462
+ @last_scan = node_hash['last_scan']
463
+ @profile = node_hash.fetch('custom_profile', nil) || node_hash.fetch('profile', nil)
464
+ create_equality_methods
465
+ end
466
+
467
+ def diff(other)
468
+ diff = {}
469
+ DIFF_PROPERTIES.each do |prop|
470
+ diff[prop] = send("#{prop.to_s}_equal?".to_sym, other.send(prop)) ? {} : property_diff(prop, other)
471
+ end
472
+ diff
473
+ end
474
+
475
+ private
476
+
477
+ def create_equality_methods
478
+ DIFF_PROPERTIES.each do |prop|
479
+ meth_name = "#{prop.to_s}_equal?"
480
+ self.class.define_method(meth_name) do |other|
481
+ property_equal?(prop, other)
482
+ end
483
+ end
484
+ end
485
+
486
+ def property_diff(property, other)
487
+ {
488
+ self: send(property).keys - other.send(property).keys,
489
+ other: other.send(property).keys - send(property).keys
490
+ }
491
+ end
492
+
493
+ def property_equal?(property, other_property)
494
+ send(property) == other_property
495
+ end
496
+ end
497
+ end
498
+ end
@@ -13,6 +13,13 @@ module AbideDevUtils
13
13
  h.transform_keys(&:to_sym)
14
14
  end
15
15
 
16
+ def to_h(path = DEFAULT_PATH)
17
+ return {} unless File.file?(path)
18
+
19
+ h = YAML.safe_load(File.open(path), [Symbol])
20
+ h.transform_keys(&:to_sym)
21
+ end
22
+
16
23
  def self.config_section(section, path = DEFAULT_PATH)
17
24
  h = to_h(path)
18
25
  s = h.fetch(section.to_sym, nil)
@@ -21,8 +28,20 @@ module AbideDevUtils
21
28
  s.transform_keys(&:to_sym)
22
29
  end
23
30
 
31
+ def config_section(section, path = DEFAULT_PATH)
32
+ h = to_h(path)
33
+ s = h.fetch(section.to_sym, nil)
34
+ return {} if s.nil?
35
+
36
+ s.transform_keys(&:to_sym)
37
+ end
38
+
24
39
  def self.fetch(key, default = nil, path = DEFAULT_PATH)
25
40
  to_h(path).fetch(key, default)
26
41
  end
42
+
43
+ def fetch(key, default = nil, path = DEFAULT_PATH)
44
+ to_h(path).fetch(key, default)
45
+ end
27
46
  end
28
47
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/errors/base'
4
+
5
+ module AbideDevUtils
6
+ module Errors
7
+ module Comply
8
+ class ComplyLoginFailedError < GenericError
9
+ @default = 'Failed to login to Comply:'
10
+ end
11
+
12
+ class WaitOnError < GenericError
13
+ @default = 'wait_on failed due to error:'
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'abide_dev_utils/errors/base'
4
+
5
+ module AbideDevUtils
6
+ module Errors
7
+ module GCloud
8
+ class MissingCredentialsError < GenericError
9
+ @default = <<~EOERR
10
+ Storage credentials not given. Please set environment variable ABIDE_GCLOUD_CREDENTIALS.
11
+ EOERR
12
+ end
13
+
14
+ class MissingProjectError < GenericError
15
+ @default = <<~EOERR
16
+ Storage project not given. Please set the environment variable ABIDE_GCLOUD_PROJECT.
17
+ EOERR
18
+ end
19
+
20
+ class MissingBucketNameError < GenericError
21
+ @default = <<~EOERR
22
+ Storage bucket name not given. Please set the environment variable ABIDE_GCLOUD_BUCKET.
23
+ EOERR
24
+ end
25
+ end
26
+ end
27
+ end
@@ -29,6 +29,11 @@ module AbideDevUtils
29
29
  @default = 'Path is not a directory:'
30
30
  end
31
31
 
32
+ # Raised when a file extension is not correct
33
+ class FileExtensionIncorrectError < GenericError
34
+ @default = 'File extension does not match specified extension:'
35
+ end
36
+
32
37
  # Raised when a searched for service is not found in the parser
33
38
  class ServiceNotFoundError < GenericError
34
39
  @default = 'Service not found:'
@@ -24,6 +24,18 @@ module AbideDevUtils
24
24
  class FailedToCreateFileError < GenericError
25
25
  @default = 'Failed to create file:'
26
26
  end
27
+
28
+ class ClassFileNotFoundError < GenericError
29
+ @default = 'Class file was not found:'
30
+ end
31
+
32
+ class ClassDeclarationNotFoundError < GenericError
33
+ @default = 'Class declaration was not found:'
34
+ end
35
+
36
+ class InvalidClassNameError < GenericError
37
+ @default = 'Not a valid Puppet class name:'
38
+ end
27
39
  end
28
40
  end
29
41
  end
@@ -12,5 +12,13 @@ module AbideDevUtils
12
12
  class StrategyInvalidError < GenericError
13
13
  @default = 'Invalid strategy selected. Should be either \'name\' or \'num\''
14
14
  end
15
+
16
+ class ControlPartsError < GenericError
17
+ @default = 'Failed to extract parts from control name:'
18
+ end
19
+
20
+ class ProfilePartsError < GenericError
21
+ @default = 'Failed to extract parts from profile name:'
22
+ end
15
23
  end
16
24
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'abide_dev_utils/errors/base'
4
+ require 'abide_dev_utils/errors/comply'
5
+ require 'abide_dev_utils/errors/gcloud'
4
6
  require 'abide_dev_utils/errors/general'
5
7
  require 'abide_dev_utils/errors/jira'
6
8
  require 'abide_dev_utils/errors/xccdf'
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'abide_dev_utils/errors/gcloud'
5
+
6
+ module AbideDevUtils
7
+ module GCloud
8
+ include AbideDevUtils::Errors::GCloud
9
+
10
+ def self.storage_bucket(name: nil, project: nil, credentials: nil)
11
+ raise MissingProjectError if project.nil? && ENV['ABIDE_GCLOUD_PROJECT'].nil?
12
+ raise MissingCredentialsError if credentials.nil? && ENV['ABIDE_GCLOUD_CREDENTIALS'].nil?
13
+ raise MissingBucketNameError if name.nil? && ENV['ABIDE_GCLOUD_BUCKET'].nil?
14
+
15
+ require 'google/cloud/storage'
16
+ @bucket = Google::Cloud::Storage.new(
17
+ project_id: project || ENV['ABIDE_GCLOUD_PROJECT'],
18
+ credentials: credentials || JSON.parse(ENV['ABIDE_GCLOUD_CREDENTIALS'])
19
+ ).bucket(name || ENV['ABIDE_GCLOUD_BUCKET'])
20
+ end
21
+ end
22
+ end
@@ -135,6 +135,16 @@ module AbideDevUtils
135
135
  end
136
136
  end
137
137
 
138
+ # def self.new_issues_from_comply_report(client, project, report, dry_run: false)
139
+ # dr_prefix = dry_run ? 'DRY RUN: ' : ''
140
+ # i_attrs = all_project_issues_attrs(project)
141
+ # rep_sums = summaries_from_coverage_report(report)
142
+ # rep_sums.each do |k, v|
143
+ # next if summary_exist?(k, i_attrs)
144
+
145
+ # progress = AbideDevUtils::Output.progress(title: "#{dr_prefix}Creating Tasks", total: nil)
146
+ # v.each do |s|
147
+
138
148
  def self.merge_options(options)
139
149
  config.merge(options)
140
150
  end
@@ -167,6 +177,11 @@ module AbideDevUtils
167
177
  summaries.transform_keys { |k| "#{COV_PARENT_SUMMARY_PREFIX}#{benchmark}-#{k}"}
168
178
  end
169
179
 
180
+ # def self.summaries_from_comply_report(report)
181
+ # summaries = {}
182
+ # report.each do |_, v|
183
+ # end
184
+
170
185
  class Dummy
171
186
  def attrs
172
187
  { 'fields' => {