dbotquery 0.9

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.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.idea/.gitignore +10 -0
  3. data/.idea/dbotquery.iml +130 -0
  4. data/.idea/dictionaries/project.xml +9 -0
  5. data/.idea/modules.xml +8 -0
  6. data/.idea/runConfigurations/Specs.xml +33 -0
  7. data/.idea/vcs.xml +6 -0
  8. data/.reek.yml +8 -0
  9. data/CHANGELOG.md +5 -0
  10. data/CODE_OF_CONDUCT.md +10 -0
  11. data/LICENSE.txt +21 -0
  12. data/NOTES.md +38 -0
  13. data/README.md +34 -0
  14. data/Rakefile +32 -0
  15. data/Steepfile +25 -0
  16. data/exe/dbotquery +8 -0
  17. data/lib/d_bot_query/cli.rb +74 -0
  18. data/lib/d_bot_query/commands/command_base.rb +51 -0
  19. data/lib/d_bot_query/commands/package_search_command.rb +40 -0
  20. data/lib/d_bot_query/commands/repo_sla_statistics_command.rb +52 -0
  21. data/lib/d_bot_query/commands/sla_statistics_command.rb +62 -0
  22. data/lib/d_bot_query/commands/summary_command.rb +51 -0
  23. data/lib/d_bot_query/models/alert.rb +40 -0
  24. data/lib/d_bot_query/models/alert_collection.rb +89 -0
  25. data/lib/d_bot_query/models/base.rb +128 -0
  26. data/lib/d_bot_query/models/cvss.rb +11 -0
  27. data/lib/d_bot_query/models/cwe.rb +8 -0
  28. data/lib/d_bot_query/models/data_file.rb +30 -0
  29. data/lib/d_bot_query/models/dependency.rb +12 -0
  30. data/lib/d_bot_query/models/package.rb +23 -0
  31. data/lib/d_bot_query/models/reference.rb +11 -0
  32. data/lib/d_bot_query/models/repository.rb +42 -0
  33. data/lib/d_bot_query/models/security_advisory.rb +22 -0
  34. data/lib/d_bot_query/models/security_vulnerability.rb +19 -0
  35. data/lib/d_bot_query/models/vulnerability_identifier.rb +14 -0
  36. data/lib/d_bot_query/version.rb +6 -0
  37. data/lib/dbotquery.rb +79 -0
  38. data/lib/schema.json +1255 -0
  39. data/rbs_collection.lock.yaml +316 -0
  40. data/rbs_collection.yaml +19 -0
  41. data/sig/d_bot_query/cli.rbs +26 -0
  42. data/sig/d_bot_query/commands/command_base.rbs +18 -0
  43. data/sig/d_bot_query/commands/package_search_command.rbs +11 -0
  44. data/sig/d_bot_query/commands/repo_sla_statistics_command.rbs +9 -0
  45. data/sig/d_bot_query/commands/sla_statistics_command.rbs +11 -0
  46. data/sig/d_bot_query/commands/summary_command.rbs +15 -0
  47. data/sig/d_bot_query/models/alert.rbs +17 -0
  48. data/sig/d_bot_query/models/alert_collection.rbs +41 -0
  49. data/sig/d_bot_query/models/base.rbs +39 -0
  50. data/sig/d_bot_query/models/data_file.rbs +21 -0
  51. data/sig/d_bot_query/models/dependency.rbs +7 -0
  52. data/sig/d_bot_query/models/package.rbs +10 -0
  53. data/sig/d_bot_query/models/repository.rbs +11 -0
  54. data/sig/d_bot_query/models/security_advisory.rbs +9 -0
  55. data/sig/d_bot_query.rbs +14 -0
  56. data/sig/gems/json-schema.rbs +5 -0
  57. metadata +157 -0
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module DBotQuery
5
+ module Commands
6
+ # # Service Level Agreement Stats
7
+ # As part of our vulnerability management program, we need to be able to understand how many
8
+ # open vulnerabilities there are, as well as how long they’ve been open for. For each severity, we
9
+ # have a “service level agreement” (SLA) that states the maximum acceptable time for a
10
+ # vulnerability is allowed to remain unresolved.
11
+ #
12
+ # The SLA for each severity is as follows:
13
+ #
14
+ # | Type | Days |
15
+ # |------|------|
16
+ # | Low | 60|
17
+ # | Medium | 30|
18
+ # | High | 15|
19
+ # | Critical | 5|
20
+ #
21
+ # For this subcommand, we should output the number of vulnerabilities that have been open
22
+ # longer than the SLA allows for, separated by severity.
23
+ #
24
+ # ## Inputs
25
+ # | Command Line Flag | Required? | Description | Example |
26
+ # | :--- | :--- | :--- | :--- |
27
+ # | -f/--file | yes | Path to JSON file exported from Dependabot | dependabot.json |
28
+ # | --time | no | The date/time for which the SLA is being calculated, in ISO8601 format | 2023-01-01T00:00:00Z |
29
+ #
30
+ # ### Example commands
31
+ # * `./your_program sla_stats -f dependabot.json`
32
+ # * A count of all findings that exceed the SLA, separated by severity. The current time is used
33
+ # when calculating age.
34
+ # * `./your_program sla_stats -f dependabot.json -t 2023-01-01T00:00:00Z`
35
+ # * A count of all findings that exceed the SLA, separated by severity. The time specified is
36
+ # used when calculating age.
37
+ #
38
+ # ### Outputs
39
+ # ```json
40
+ # {
41
+ # "low": $count,
42
+ # "medium": $count,
43
+ # "high": $count,
44
+ # "critical": $count,
45
+ # "total": $count
46
+ # }
47
+ # ```
48
+ #
49
+ # Where `$count` represents the number of findings that exceed the SLA for each severity.
50
+ class SLAStatisticsCommand < CommandBase
51
+ def initialize(time: nil)
52
+ super()
53
+
54
+ @time = time || Time.now
55
+ end
56
+
57
+ def perform(input)
58
+ input.alerts.sla_stats @time
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module DBotQuery
5
+ module Commands
6
+ # # Summary
7
+ #
8
+ # This subcommand takes a JSON export from Dependabot and returns the number of findings in
9
+ # the file. This command should take an optional “state” parameter so that the only vulnerabilities
10
+ # that are counted are the ones that match its value (e.g. open, fixed, dismissed)
11
+ #
12
+ # ## Inputs
13
+ #
14
+ # | Command Line Flag | Required | Description | Example |
15
+ # |:--- | :--- | :--- | :--- |
16
+ # | -f/--file | yes | The path to the JSON file to be processed | dependabot.json |
17
+ # | --state | no | The state of the vulnerability to be counted | open, fixed, dismissed |
18
+ # | --severity | no | The severity of the vulnerability to be counted | critical, high, medium, low |
19
+ #
20
+ # ## Example commands
21
+ #
22
+ # * `./your_program summary -f dependabot.json`
23
+ # * Count of all findings in dependabot.json
24
+ # * `./your_program summary -f dependabot.json --state dismissed`
25
+ # * Count of all dismissed findings in dependabot.json
26
+ # * `./your_program summary -f dependabot.json --state open --severity critical`
27
+ # * Count of all open critical vulnerabilities
28
+ #
29
+ # ## Outputs
30
+ #
31
+ # ```json
32
+ # {“count”: $count}
33
+ # ```
34
+ #
35
+ # Where `$count` represents the count of findings in the JSON file. If --state or --severity are specified,
36
+ # the count should only include the findings whose
37
+ class SummaryCommand < CommandBase
38
+ attr_reader :state, :severity
39
+
40
+ def initialize(state: nil, severity: nil)
41
+ super()
42
+ @state = state
43
+ @severity = severity
44
+ end
45
+
46
+ def perform(input)
47
+ input.alerts.summary @state, @severity
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ # A singular dependency alert
6
+ class Alert < Base
7
+ attribute :number, :integer
8
+ alias_attribute :id, :number
9
+ delegate :severity, to: :security_vulnerability
10
+
11
+ attribute :repository, Repository
12
+ attribute :dependency, Dependency
13
+ attribute :security_advisory, SecurityAdvisory
14
+ attribute :security_vulnerability, SecurityVulnerability
15
+
16
+ attribute :created_at, :datetime
17
+ attribute :updated_at, :datetime
18
+ attribute :dismissed_at, :datetime
19
+ attribute :fixed_at, :datetime
20
+ attribute :auto_dismissed_at, :datetime
21
+ attribute :state, :symbol
22
+ attribute :url, :url
23
+ attribute :html_url, :url
24
+ attribute :dismissed_by, :string
25
+ attribute :dismissed_comment, :string
26
+ attribute :dismissed_reason, :string
27
+
28
+ def days_open(as_of)
29
+ as_of = as_of&.to_date || Time.now.to_date
30
+ create_date = created_at.to_date
31
+ if (fix_date = fixed_at)
32
+ fix_date = fix_date.to_date
33
+ fix_date < as_of ? (fix_date - create_date).to_i : (as_of - create_date).to_i
34
+ else
35
+ (as_of - create_date).to_i
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Namespace containing models for DBotQuery when used solely
4
+ # as an API.
5
+ module DBotQuery
6
+ module Models
7
+ # Class representing a collection of alerts. This is usually the
8
+ # result of deserializing JSON data.
9
+ class AlertCollection
10
+ include Enumerable
11
+
12
+ delegate :each, to: :@alerts
13
+
14
+ def initialize(alerts)
15
+ @alerts = alerts.map do |alert|
16
+ case alert
17
+ when Hash
18
+ Alert.new(alert)
19
+ when Alert
20
+ alert
21
+ else
22
+ raise ArgumentError, "Input of type #{alert.class} cannot be converted to Alert\n#{alert.inspect}"
23
+ end
24
+ end
25
+ end
26
+
27
+ def package_search(package_name)
28
+ where_package(package_name).map { |alert| alert.repository.full_name }.uniq
29
+ end
30
+
31
+ def sla_violations(as_of = nil)
32
+ # Here we select only those which are in violation of the SLA.
33
+
34
+ @alerts.select do |finding|
35
+ finding.days_open(as_of) > SLA_DEFINITION[finding.severity]
36
+ end
37
+ end
38
+
39
+ def repo_sla_stats(as_of)
40
+ violation_map = sla_violations(as_of)
41
+
42
+ # And finally group by the repo
43
+ violation_map.group_by(&:repository).to_h do |repo, findings|
44
+ sum_repo(repo, findings)
45
+ end.with_indifferent_access
46
+ end
47
+
48
+ def sla_stats(as_of)
49
+ by_severity = sla_violations(as_of).group_by(&:severity).transform_values(&:size)
50
+ # Because this is just a generalization of the RepoSLAStatisticsCommand, we can gather those results
51
+ # and combine them into a single hash
52
+ base = SLA_DEFINITION.to_h { |severity, _days| [severity, 0] }
53
+ base.merge! by_severity
54
+ totals = { total: base.values.sum } #: { total: Integer }
55
+ base.merge(totals).with_indifferent_access
56
+ end
57
+
58
+ def summary(state, severity)
59
+ findings = severity_filter(severity).state_filter(state)
60
+ { count: findings.count }
61
+ end
62
+
63
+ def sum_repo(repo, findings)
64
+ by_level = findings.select { |alert| alert.repository == repo }.group_by(&:severity)
65
+ by_level = SLA_DEFINITION.to_h { |key, _count| [key, 0] }.merge(by_level.transform_values(&:count))
66
+
67
+ [repo.to_s, { **by_level, total: by_level.values.sum }]
68
+ end
69
+
70
+ def select(&)
71
+ self.class.new(@alerts.select(&))
72
+ end
73
+
74
+ def severity_filter(severity)
75
+ severity ? select { |alert| alert.security_advisory.severity == severity.to_sym } : self
76
+ end
77
+
78
+ def state_filter(state)
79
+ state ? select { |alert| alert.state == state.to_sym } : self
80
+ end
81
+
82
+ def where_package(package_name)
83
+ select do |alert|
84
+ alert.dependency.package == package_name
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ # Generic base class for models. Provides common functionality for all models.
6
+ # This includes additional scalar type support.
7
+ class Base
8
+ # Provides additional scalar type support for casting to symbols
9
+ class SymbolType < ActiveModel::Type::Value
10
+ def cast(value)
11
+ return nil if value.nil?
12
+
13
+ value.to_sym
14
+ end
15
+
16
+ def serialize(value)
17
+ value&.to_s
18
+ end
19
+ end
20
+
21
+ # Provides additional scalar type support for casting to URLs (including those with templates)
22
+ class URLType < ActiveModel::Type::Value
23
+ def cast(value)
24
+ return nil if value.nil?
25
+
26
+ Addressable::Template.new value
27
+ end
28
+
29
+ def serialize(value)
30
+ value.pattern.to_s
31
+ end
32
+ end
33
+
34
+ # Provides additional scalar type support for casting to arrays of objects (with the target class)
35
+ class ObjectArray < ActiveModel::Type::Value
36
+ attr_reader :target_class
37
+
38
+ # Initialize with the specific class you want the array to hold
39
+ def initialize(of:)
40
+ @target_class = of
41
+ super()
42
+ end
43
+
44
+ # Casts raw input data (e.g. an array of hashes) into an array of objects
45
+ def cast(value)
46
+ return [] if value.blank?
47
+
48
+ # Ensure it's handled like an array
49
+ Array(value).map do |item|
50
+ materialize item
51
+ end
52
+ end
53
+
54
+ def serialize(value)
55
+ value.map(&:to_h)
56
+ end
57
+
58
+ private
59
+
60
+ def materialize(item)
61
+ case item
62
+ when Hash
63
+ target_class.new(item)
64
+ when target_class
65
+ item
66
+ else
67
+ raise "Unexpected data (not of target_type #{target_class} or a Hash)"
68
+ end
69
+ end
70
+ end
71
+
72
+ ActiveModel::Type.register(:symbol, SymbolType)
73
+ ActiveModel::Type.register(:url, URLType)
74
+ ActiveModel::Type.register(:array, ObjectArray)
75
+
76
+ include ActiveModel::Model
77
+ include ActiveModel::Attributes
78
+ include ActiveModel::Validations
79
+ include ActiveModel::Serialization
80
+
81
+ # As the models can be modified and re-serialized, we permit the changing of the data.
82
+ def self.mutable?
83
+ true
84
+ end
85
+
86
+ # Run the validations on the model
87
+ def self.assert_valid_value(value)
88
+ case value
89
+ when self
90
+ raise 'value is not valid' unless value.valid?
91
+ when Hash
92
+ invalid = validate_hash_attributes(value)
93
+ raise "#{self} has invalid hash attributes #{invalid.to_a.to_sentence}" unless invalid.empty?
94
+ else
95
+ false
96
+ end
97
+ end
98
+
99
+ # Permit the creation of a model from a hash
100
+ def self.cast(input_hash)
101
+ new input_hash
102
+ end
103
+
104
+ def to_h
105
+ attributes.to_h do |key, value|
106
+ type_for = self.class.type_for_attribute key
107
+ result = type_for.respond_to?(:serialize) ? type_for.serialize(value) : value
108
+ [key, result]
109
+ end
110
+ end
111
+
112
+ # Helper to define multiple attributes of a specific type
113
+ def self.attributes(type, *attributes)
114
+ suffix = type.to_s.downcase
115
+ attributes.each do |attribute|
116
+ self.attribute :"#{attribute}_#{suffix}", type
117
+ end
118
+ end
119
+
120
+ def self.validate_hash_attributes(hash)
121
+ attributes = attribute_names.to_set
122
+ keys = hash.keys.to_set(&:to_s)
123
+ invalid_keys = attributes - keys
124
+ keys <= attributes ? [] : invalid_keys.to_a
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ # CVSS vector and score (Common Vulnerability Scoring System)
6
+ class CVSS < Base
7
+ attribute :vector_string, :string
8
+ attribute :score, :float
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ class CWE < Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ # Data file. Reads and parses JSON data.
6
+ class DataFile
7
+ attr_reader :alerts, :data
8
+
9
+ def initialize(data)
10
+ JSON::Validator.validate!(DBotQuery.schema, data)
11
+ @data = data
12
+ @alerts = AlertCollection.new(data)
13
+ end
14
+
15
+ def self.load(json_data)
16
+ from_data json_data
17
+ end
18
+
19
+ def self.load_file(file_path)
20
+ from_data file_path, loader_method: :load_file
21
+ end
22
+
23
+ def self.from_data(data, loader_method: :load)
24
+ new JSON.send(loader_method, data, freeze: true)
25
+ rescue JSON::ParserError => e
26
+ raise DBotQuery::Error, "File #{data} is not valid JSON: #{e.message}"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ # A single dependency. Describes the package that has or had a vulnerability that triggered the alert.
6
+ class Dependency < Base
7
+ attribute :package, Package
8
+ attribute :manifest_path
9
+ attribute :scope
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ # A singular package (such as a npm package, a gem, or a pip for python) that is the target of a dependency
6
+ # relationship from a repository. This is the code that would have a vulnerability.
7
+ class Package < Base
8
+ attribute :name, :string
9
+ attribute :ecosystem, :string
10
+
11
+ def ==(other)
12
+ case other
13
+ when Package
14
+ name == other.name && ecosystem == other.ecosystem
15
+ when String
16
+ name == other
17
+ else
18
+ false
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ # A reference. This is a link to some information such as a CVE or a security advisory's URL.
6
+ class Reference < Base
7
+ attribute :url, :url
8
+ alias_attribute :id, :url
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ # A repository, or source of a dependency, that is the code that is dependent and vulnerable due to a package
6
+ # on which it depends having a security vulnerability.
7
+ class Repository < Base
8
+ attribute :id, :integer
9
+ attribute :name, :string
10
+ attribute :full_name, :string
11
+ attribute :owner, :string
12
+ attribute :node_id, :string
13
+ attribute :private, :boolean
14
+ attribute :url, :url
15
+ attribute :description, :string
16
+ attribute :fork, :boolean
17
+ attribute :created_at, :datetime
18
+ attribute :updated_at, :datetime
19
+ attributes :url, :teams, :notifications, :deployments, :labels, :releases, :milestones, :pulls
20
+ attributes :url, :issues, :downloads, :compare, :merges, :contents, :issue_comment
21
+ attributes :url, :subscription, :trees, :languages, :stargazers, :contributors, :subscribers
22
+ attributes :url, :git_refs, :git_tags, :tags, :blobs, :events, :branches, :assignees, :hooks
23
+ attributes :url, :issue_events, :html, :forks, :collaborators, :keys, :archive, :comments
24
+ attributes :url, :statuses, :git_commits, :commits
25
+
26
+ def ==(other)
27
+ case other
28
+ when Repository
29
+ full_name == other.full_name
30
+ when String
31
+ full_name == other
32
+ else
33
+ false
34
+ end
35
+ end
36
+
37
+ def to_s
38
+ full_name
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ # The backing security advisory that triggered the alert
6
+ class SecurityAdvisory < Base
7
+ attribute :ghsa_id, :string
8
+ attribute :cve_id, :string
9
+ attribute :summary, :string
10
+ attribute :description, :string
11
+ attribute :severity, :symbol
12
+ attribute :published_at, :datetime
13
+ attribute :updated_at, :datetime
14
+ attribute :withdrawn_at, :datetime
15
+ attribute :identifiers, :array, of: VulnerabilityIdentifier
16
+ attribute :references, :array, of: Reference
17
+ attribute :vulnerabilities, :array, of: SecurityVulnerability
18
+ attribute :cvss, CVSS
19
+ attribute :cwes, :array, of: CWE
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ # A security vulnerability that is discovered in a package. This occurs in a package and has various information
6
+ # such as the package name, severity, published date, updated date, HTML URL, vulnerable version range,
7
+ # and first patched version. It also has any information such as the references to the bulletin.
8
+ class SecurityVulnerability < Base
9
+ attribute :id, :integer
10
+ attribute :package, :string
11
+ attribute :severity, :symbol
12
+ attribute :published_at, :datetime
13
+ attribute :updated_at, :datetime
14
+ attribute :html_url, :url
15
+ attribute :vulnerable_version_range, :string
16
+ attribute :first_patched_version, :string
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DBotQuery
4
+ module Models
5
+ # A singular identifier for a vulnerability to correlate across multiple repos. These identifiers are stable
6
+ # over type and could include a CVE, GHSA, or another unique stable identifier. One vulnerability often has
7
+ # many identifiers (as there are multiple authorities for tracking such).
8
+ class VulnerabilityIdentifier < Base
9
+ attribute :value, :string
10
+ attribute :type, :string
11
+ alias_attribute :id, :value
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module DBotQuery
5
+ VERSION = '0.9'
6
+ end
data/lib/dbotquery.rb ADDED
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ require 'json'
5
+ require 'thor'
6
+ require 'time'
7
+ require 'date'
8
+ require 'uri'
9
+ require 'json-schema'
10
+ require 'active_model'
11
+ require 'active_support/all'
12
+ require 'addressable/template'
13
+ require_relative 'd_bot_query/version'
14
+
15
+ # # Dependabot Data Viewer
16
+ #
17
+ # ## Assignment
18
+ #
19
+ # Dependabot is GitHub’s product for surfacing information about vulnerable dependencies.
20
+ # GitHub maintains a database of known vulnerabilities mapped to specific versions of specific
21
+ # dependencies, and Dependabot compares this to your package manifest (`package.json`,
22
+ # `Gemfile.lock`, etc.).
23
+ #
24
+ # GitHub makes this data available in the web interface, but we want to send this data to be
25
+ # processed elsewhere so non-engineers who don’t have access to GitHub can also see our
26
+ # vulnerabilities. To do this, we want you to write a command line utility that takes an exported
27
+ # JSON file from Dependabot and prints out some basic reports, also in JSON format. The
28
+ # command line tool will not need to talk to GitHub directly. All it needs to do is take the
29
+ # exported Dependabot JSON file as input, some configuration options, and return a JSON
30
+ # document. Please feel free to consult GitHub’s documentation on this file.
31
+ #
32
+ module DBotQuery
33
+ # This is a generic wrapper error for those error types raised specifically by this gem.
34
+ class Error < StandardError; end
35
+
36
+ SCHEMA_PATH = File.join(File.dirname(__FILE__), 'schema.json')
37
+
38
+ SCHEMA = JSON.parse(File.read(SCHEMA_PATH))
39
+
40
+ autoload :CLI, 'd_bot_query/cli'
41
+
42
+ SLA_DEFINITION = {
43
+ low: 60,
44
+ medium: 30,
45
+ high: 15,
46
+ critical: 5
47
+ }.freeze
48
+
49
+ # Module that contains the abstract base class for all commands, as well as the implementations. These
50
+ # are separated in this way to allow for easier testing and maintenance.
51
+ module Commands
52
+ autoload :CommandBase, 'd_bot_query/commands/command_base'
53
+ autoload :PackageSearchCommand, 'd_bot_query/commands/package_search_command'
54
+ autoload :SummaryCommand, 'd_bot_query/commands/summary_command'
55
+ autoload :RepoSLAStatisticsCommand, 'd_bot_query/commands/repo_sla_statistics_command'
56
+ autoload :SLAStatisticsCommand, 'd_bot_query/commands/sla_statistics_command'
57
+ end
58
+
59
+ # Collection of models used by the DBotQuery library providing API access to data files and their contents.
60
+ module Models
61
+ autoload :DataFile, 'd_bot_query/models/data_file'
62
+ autoload :Base, 'd_bot_query/models/base'
63
+ autoload :AlertCollection, 'd_bot_query/models/alert_collection'
64
+ autoload :Alert, 'd_bot_query/models/alert'
65
+ autoload :Dependency, 'd_bot_query/models/dependency'
66
+ autoload :Package, 'd_bot_query/models/package'
67
+ autoload :Repository, 'd_bot_query/models/repository'
68
+ autoload :SecurityAdvisory, 'd_bot_query/models/security_advisory'
69
+ autoload :SecurityVulnerability, 'd_bot_query/models/security_vulnerability'
70
+ autoload :VulnerabilityIdentifier, 'd_bot_query/models/vulnerability_identifier'
71
+ autoload :Reference, 'd_bot_query/models/reference'
72
+ autoload :CVSS, 'd_bot_query/models/cvss'
73
+ autoload :CWE, 'd_bot_query/models/cwe'
74
+ end
75
+
76
+ def self.schema
77
+ SCHEMA
78
+ end
79
+ end