Module: VRT

Extended by:
CrossVersionMapping
Defined in:
lib/vrt.rb,
lib/vrt/map.rb,
lib/vrt/node.rb,
lib/vrt/mapping.rb,
lib/vrt/cross_version_mapping.rb

Defined Under Namespace

Modules: CrossVersionMapping Classes: Map, Mapping, Node

Constant Summary collapse

DIR =
Pathname.new(__dir__).join('data')
OTHER_OPTION =
{ 'id' => 'other',
'name' => 'Other',
'priority' => nil,
'type' => 'category' }.freeze
MAPPINGS =
i[cvss_v3].freeze

Class Method Summary collapse

Methods included from CrossVersionMapping

cross_version_category_mapping, deprecated_node?, deprecated_node_json, find_deprecated_node, find_valid_parent_node, latest_version_for_deprecated_node

Class Method Details

.all_matching_categories(categories) ⇒ Object

Get all deprecated ids that would match in the given categories from the current version



59
60
61
# File 'lib/vrt.rb', line 59

def all_matching_categories(categories)
  cross_version_category_mapping.select { |key, _value| categories.include?(key) }.values.flatten
end

.current_categoriesObject



54
55
56
# File 'lib/vrt.rb', line 54

def current_categories
  Map.new(current_version).categories
end

.current_versionObject

Get the most recent version of the VRT.



37
38
39
# File 'lib/vrt.rb', line 37

def current_version
  versions.first
end

.current_version?(version) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/vrt.rb', line 41

def current_version?(version)
  version == current_version
end

.find_node(vrt_id:, version: nil, preferred_version: nil, max_depth: 'variant') ⇒ VRT::Node|Nil

Finds the best match valid node. First looks at valid nodes in the given new version or finds the appropriate deprecated mapping. If neither is found it will walk up the tree to find a valid parent node before giving up and returning nil.

Parameters:

  • A (String)

    valid vrt_id

  • (Optional (String)
    • recommended) A valid vrt_version that the vrt_id exists in

  • (Optional) (string)

    The preferred new vrt_version to find a match in

  • (Optional) (String)

    The maximum depth to match in

Returns:

  • (VRT::Node|Nil)

    A valid VRT::Node object or nil if no best match could be found



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/vrt.rb', line 72

def find_node(vrt_id:, version: nil, preferred_version: nil, max_depth: 'variant')
  new_version = preferred_version || current_version
  if Map.new(new_version).valid?(vrt_id)
    Map.new(new_version).find_node(vrt_id, max_depth: max_depth)
  elsif deprecated_node?(vrt_id)
    find_deprecated_node(vrt_id, preferred_version, max_depth)
  else
    return nil unless version
    find_valid_parent_node(vrt_id, version, new_version, max_depth)
  end
end

.get_json(version: nil, other: true) ⇒ Object

Load the VRT from text files, and parse it as JSON. If other: true, we append the OTHER_OPTION hash at runtime (not cached)



86
87
88
89
90
# File 'lib/vrt.rb', line 86

def get_json(version: nil, other: true)
  version ||= current_version
  @version_json[version] ||= json_for_version(version)
  other ? @version_json[version] + [OTHER_OPTION] : @version_json[version]
end

.json_dir_namesObject

Get names of directories matching lib/data/<major>-<minor>/



93
94
95
96
97
98
# File 'lib/vrt.rb', line 93

def json_dir_names
  DIR.entries
     .map(&:basename)
     .map(&:to_s)
     .select { |dirname| dirname =~ /^[0-9]+\.[0-9]/ }.sort
end

.json_for_version(version) ⇒ Object

Load and parse JSON for some VRT version



106
107
108
# File 'lib/vrt.rb', line 106

def json_for_version(version)
  JSON.parse(json_pathname(version).read)['content']
end

.json_pathname(version) ⇒ Object

Get the Pathname for a particular version



101
102
103
# File 'lib/vrt.rb', line 101

def json_pathname(version)
  DIR.join(version, 'vulnerability-rating-taxonomy.json')
end

.last_updated(version = nil) ⇒ Object

Get the last updated timestamp of the VRT data (not schema!) Passing nil for version will return the latest version.



47
48
49
50
51
52
# File 'lib/vrt.rb', line 47

def last_updated(version = nil)
  version ||= current_version
  return @last_update[version] if @last_update[version]
   = JSON.parse(json_pathname(version).read)['metadata']
  @last_update[version] = Date.parse(['release_date'])
end

.mappingsObject



110
111
112
# File 'lib/vrt.rb', line 110

def mappings
  @mappings ||= Hash[MAPPINGS.map { |name| [name, VRT::Mapping.new(name)] }]
end

.reload!Object

Cache the VRT contents in-memory, so we’re not hitting File I/O multiple times per request that needs it.



116
117
118
119
120
121
122
# File 'lib/vrt.rb', line 116

def reload!
  unload!
  versions
  get_json
  last_updated
  mappings
end

.unload!Object

We separate unload! out, as we need to call it in test environments.



125
126
127
128
129
130
# File 'lib/vrt.rb', line 125

def unload!
  @versions = nil
  @version_json = {}
  @last_update = {}
  @mappings = nil
end

.versionsObject

Infer the available versions of the VRT from the names of the files in the repo. The returned list is in semver order with the current version first.



32
33
34
# File 'lib/vrt.rb', line 32

def versions
  @versions ||= json_dir_names.sort_by { |v| Gem::Version.new(v) }.reverse!
end