Compare commits
No commits in common. "cfe092df4a9576446dd0655c1e436c0587cd21ae" and "588ffa593ba216263fb1f913260777c9d4da84d3" have entirely different histories.
cfe092df4a
...
588ffa593b
53 changed files with 86 additions and 895 deletions
|
@ -1,92 +0,0 @@
|
||||||
# RPM Pkg Audit
|
|
||||||
This command-line program cn be used to query data against Redhat's Security API.
|
|
||||||
|
|
||||||
## Usage:
|
|
||||||
```
|
|
||||||
Usage: rpm_pkg_audit.rb [options]
|
|
||||||
-p, --pkg PKGNAME Takes a base pkg name and returns cves from redhats security API.
|
|
||||||
-l, --list List packages in the XML datafile.
|
|
||||||
-x, --xmlpkg PKGNAME The pkg name you want to audit from xml file rpm-to-cve.xml
|
|
||||||
-r, --refresh Refresh rpm-to-cve.xml file with latest pkgs and cves
|
|
||||||
-c, --cve CVE-2020-1234 Takes a cve id and returns cve json from redhats security API.
|
|
||||||
-f, --cves-from-file cves.txt Takes a file one cve id per line and sends a batch request to redhat security API
|
|
||||||
-a, --advisory RHSA-2019:0997 Takes a RHSA advisory and sends an API request to redhat RHSA-2015:2155
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### --refresh
|
|
||||||
By default there needs to be a ./data directory in the project where running the script. It needs to have an XML file named rpm-to-cve.xml inside of the data dir. This file is sourced from [here](https://www.redhat.com/security/data/metrics/rpm-to-cve.xml). You can run the --refresh command to download a fresh copy of this file.
|
|
||||||
|
|
||||||
#### --list
|
|
||||||
This will list out all of the packages that are present in the XML file rpm-to-cve.xml. You can pipe the output to grep to search for specific package names.
|
|
||||||
```
|
|
||||||
./rpm_pkg_audit.rb --list | grep ^sudo-devel
|
|
||||||
sudo-devel-0:1.8.19p2-12.el7_4.1
|
|
||||||
sudo-devel-0:1.8.19p2-14.el7_5.1
|
|
||||||
sudo-devel-0:1.8.23-3.el7_6.1
|
|
||||||
sudo-devel-0:1.8.23-4.el7_7.1
|
|
||||||
sudo-devel-0:1.8.23-4.el7_7.2
|
|
||||||
sudo-devel-0:1.8.6p3-12.el6
|
|
||||||
sudo-devel-0:1.8.6p3-12.el6_5.2
|
|
||||||
sudo-devel-0:1.8.6p3-15.el6_6.2
|
|
||||||
sudo-devel-0:1.8.6p3-19.el6
|
|
||||||
sudo-devel-0:1.8.6p3-25.el6_8
|
|
||||||
sudo-devel-0:1.8.6p3-28.el6_9
|
|
||||||
sudo-devel-0:1.8.6p3-29.el6_10.2
|
|
||||||
sudo-devel-0:1.8.6p3-29.el6_10.3
|
|
||||||
sudo-devel-0:1.8.6p3-29.el6_9
|
|
||||||
sudo-devel-0:1.8.6p3-7.el6
|
|
||||||
sudo-devel-0:1.8.6p7-16.el7
|
|
||||||
sudo-devel-0:1.8.6p7-17.el7_2.2
|
|
||||||
sudo-devel-0:1.8.6p7-20.el7
|
|
||||||
sudo-devel-0:1.8.6p7-21.el7_3
|
|
||||||
sudo-devel-0:1.8.6p7-22.el7_3
|
|
||||||
sudo-devel-0:1.8.6p7-23.el7_3
|
|
||||||
sudo-devel-0:1.8.6p7-23.el7_3.2
|
|
||||||
```
|
|
||||||
|
|
||||||
#### --xmlpkg
|
|
||||||
This will parse the XML file rpm-to-cve.xml for the package name given.
|
|
||||||
If there are results, the output will be pretty printed to the screen.
|
|
||||||
|
|
||||||
#### --pkg
|
|
||||||
This will send an API query to Redhat's Security API.
|
|
||||||
`GET /cve.json?package=base_package_name`
|
|
||||||
The output will be pretty printed to the screen.
|
|
||||||
|
|
||||||
#### --cve
|
|
||||||
This will send an API query to Redhat's Security API.
|
|
||||||
`GET /cve/CVE_ID.json`
|
|
||||||
The output will be pretty printed to the screen.
|
|
||||||
|
|
||||||
#### --cves-from-file
|
|
||||||
This command expects a file to be present with one single CVE id per line.
|
|
||||||
This will send X num of batch API query to Redhat's Security API depending how many are in the txt file. 500 CVE IDS per API query
|
|
||||||
`GET /cve/CVE_ID, CVE_ID, CVE_ID, CVE_ID, etc...`
|
|
||||||
The output will be pretty printed to the screen.
|
|
||||||
|
|
||||||
#### --advisory
|
|
||||||
This will send an API query to Redhat's Security API.
|
|
||||||
`GET /cve.json?advisory=ADVISORY_ID`
|
|
||||||
The output will be pretty printed to the screen.
|
|
||||||
|
|
||||||
### helper shellscript
|
|
||||||
To filter out operating system and the package that needs to be upgraded to quickly there is a helper shellscript provided in this repo.
|
|
||||||
It uses `jq` to quickly filter out the package needed to be upgraded from the redhat json api response data. Example usage:
|
|
||||||
|
|
||||||
```
|
|
||||||
./rhel_pkg_upgrade_for_cve.sh CVE-2016-3627 'Red Hat Enterprise Linux 6' [4:28:57]
|
|
||||||
{
|
|
||||||
"cve_id": "CVE-2016-3627",
|
|
||||||
"product_name": "Red Hat Enterprise Linux 6",
|
|
||||||
"package_name": "libxml2-0:2.7.6-21.el6_8.1"
|
|
||||||
}
|
|
||||||
|
|
||||||
./rhel_pkg_upgrade_for_cve.sh CVE-2016-3627 'Red Hat Enterprise Linux 7'
|
|
||||||
{
|
|
||||||
"cve_id": "CVE-2016-3627",
|
|
||||||
"product_name": "Red Hat Enterprise Linux 7",
|
|
||||||
"package_name": "libxml2-0:2.9.1-6.el7_2.3"
|
|
||||||
}
|
|
||||||
|
|
||||||
```a
|
|
|
@ -1,66 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'ox'
|
|
||||||
require 'json'
|
|
||||||
require 'rest-client'
|
|
||||||
|
|
||||||
# This is meant to parse and query data in redhat linux rpm-to-cve.xml file
|
|
||||||
# That is posted on their security API.
|
|
||||||
# Documentation Reference: https://www.redhat.com/security/data/metrics/
|
|
||||||
class RhelRpmToCve
|
|
||||||
# filepath == /path/to/rpm-to-cve.xml
|
|
||||||
attr_accessor :filepath, :file, :xml
|
|
||||||
|
|
||||||
def initialize(filepath: nil)
|
|
||||||
@filepath = filepath
|
|
||||||
@file = File.read(filepath) if filepath
|
|
||||||
@xml = Ox.parse(file) if filepath
|
|
||||||
end
|
|
||||||
|
|
||||||
def list_pkg_names
|
|
||||||
xml.rpms.locate('?/@rpm')
|
|
||||||
end
|
|
||||||
|
|
||||||
def refresh_rpm_to_cve_file(path)
|
|
||||||
r = RestClient::Request.execute(
|
|
||||||
method: :get,
|
|
||||||
url: 'https://www.redhat.com/security/data/metrics/rpm-to-cve.xml'
|
|
||||||
)
|
|
||||||
if r.code == 200
|
|
||||||
File.write(path, r.body)
|
|
||||||
else
|
|
||||||
"Error. HTTP Status code: #{r.code}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def pkg_exists?(pkg_name)
|
|
||||||
list_pkg_names.include? pkg_name
|
|
||||||
end
|
|
||||||
|
|
||||||
def cves_per_pkg_name(pkg_name)
|
|
||||||
if pkg_exists? pkg_name
|
|
||||||
results = find_pkg(pkg_name).locate('*/cve').map(&:text).compact
|
|
||||||
|
|
||||||
cves = results.map { |cve| cve }
|
|
||||||
|
|
||||||
{
|
|
||||||
rhel_package_name: pkg_name,
|
|
||||||
cves: cves,
|
|
||||||
cve_count: cves.count
|
|
||||||
}
|
|
||||||
else 'Package not found.'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_pkg(pkg_name)
|
|
||||||
xml.rpms.locate("rpm[@rpm=#{pkg_name}]").first
|
|
||||||
end
|
|
||||||
|
|
||||||
def convert_to_json
|
|
||||||
pkgs = list_pkg_names
|
|
||||||
pkgs_and_cves = pkgs.map do |pkg_name|
|
|
||||||
cves_per_pkg_name(pkg_name)
|
|
||||||
end
|
|
||||||
pkgs_and_cves.to_json
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,58 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rest-client'
|
|
||||||
require 'json'
|
|
||||||
require 'active_support/core_ext/array/grouping.rb'
|
|
||||||
|
|
||||||
# Documentation link:
|
|
||||||
# https://access.redhat.com/documentation/en-us/red_hat_security_data_api/1.0/html/red_hat_security_data_api/overview
|
|
||||||
class RhelSecurityApiClient
|
|
||||||
attr_accessor :base_url
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
@base_url = 'https://access.redhat.com/hydra/rest/securitydata'
|
|
||||||
end
|
|
||||||
|
|
||||||
# params = {:params => {:key => value}}
|
|
||||||
def request(path, params)
|
|
||||||
r = RestClient::Request.execute(
|
|
||||||
method: :get,
|
|
||||||
url: "#{base_url}#{path}",
|
|
||||||
headers: params
|
|
||||||
)
|
|
||||||
if r.code == 200
|
|
||||||
parse_response(r)
|
|
||||||
else
|
|
||||||
"Error HTTP Code: #{r.code}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse_response(response)
|
|
||||||
JSON.parse(response.body)
|
|
||||||
end
|
|
||||||
|
|
||||||
def cve_pkg_adv(array_of_json_cves)
|
|
||||||
array_of_json_cves.map do |json|
|
|
||||||
{
|
|
||||||
cve_id: json['CVE'],
|
|
||||||
advisories: json['advisories'],
|
|
||||||
affected_packages: json['affected_packages']
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def cve_id(cve_id)
|
|
||||||
params = {}
|
|
||||||
request("/cve/#{cve_id}.json", params)
|
|
||||||
end
|
|
||||||
|
|
||||||
def cve_ids(cve_ids)
|
|
||||||
params = {}
|
|
||||||
responses = []
|
|
||||||
cve_ids.in_groups_of(500, false) do |cve_id_batch|
|
|
||||||
csv_cve_url_str = cve_id_batch.join(',')
|
|
||||||
responses << request('/cve.json?ids=' + csv_cve_url_str, params)
|
|
||||||
end
|
|
||||||
responses.flatten
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,95 +0,0 @@
|
||||||
#!/usr/bin/env ruby
|
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'optparse'
|
|
||||||
require 'json'
|
|
||||||
require 'csv'
|
|
||||||
require './rhel_rpm_to_cve'
|
|
||||||
require './rhel_security_api_client'
|
|
||||||
require 'pry'
|
|
||||||
|
|
||||||
ARGV << '-h' if ARGV.empty?
|
|
||||||
|
|
||||||
data_file = './data/rpm-to-cve.xml'
|
|
||||||
|
|
||||||
options = {}
|
|
||||||
|
|
||||||
# for use with --cves-from-file arg
|
|
||||||
def read_cves_file(filepath)
|
|
||||||
CSV.read(filepath).flatten
|
|
||||||
end
|
|
||||||
|
|
||||||
def json_pp(json)
|
|
||||||
puts JSON.pretty_generate(json)
|
|
||||||
end
|
|
||||||
|
|
||||||
parserr = OptionParser.new do |parser|
|
|
||||||
parser.banner = 'Usage: rpm_pkg_audit.rb [options]'
|
|
||||||
parser.on('-p', '--pkg PKGNAME',
|
|
||||||
'Takes a base pkg name and returns cves from redhats security API.') do |pkg|
|
|
||||||
options[:pkg] = pkg
|
|
||||||
end
|
|
||||||
parser.on('-l', '--list',
|
|
||||||
'List packages in the XML datafile.') do |list|
|
|
||||||
options[:list] = list
|
|
||||||
end
|
|
||||||
parser.on('-x', '--xmlpkg PKGNAME',
|
|
||||||
'The pkg name you want to audit from xml file rpm-to-cve.xml') do |xmlpkg|
|
|
||||||
options[:xmlpkg] = xmlpkg
|
|
||||||
end
|
|
||||||
parser.on('-r', '--refresh',
|
|
||||||
'Refresh rpm-to-cve.xml file with latest pkgs and cves') do |_refresh|
|
|
||||||
options[:refresh] = true
|
|
||||||
end
|
|
||||||
parser.on('-c', '--cve CVE-2020-1234',
|
|
||||||
'Takes a cve id and returns cve json from redhats security API.') do |cve|
|
|
||||||
options[:cve] = cve
|
|
||||||
end
|
|
||||||
parser.on('-f', '--cves-from-file cves.txt',
|
|
||||||
'Takes a file one cve id per line and sends a batch request to redhat security API') do |file|
|
|
||||||
options[:file] = file
|
|
||||||
end
|
|
||||||
parser.on('-a', '--advisory RHSA-2019:0997',
|
|
||||||
'Takes a RHSA advisory and sends an API request to redhat RHSA-2015:2155') do |advisory|
|
|
||||||
options[:advisory] = advisory
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
parserr.parse!
|
|
||||||
|
|
||||||
rpm_auditer = RhelRpmToCve.new(filepath: data_file)
|
|
||||||
rhel_api_client = RhelSecurityApiClient.new
|
|
||||||
|
|
||||||
if options[:xmlpkg_name]
|
|
||||||
pkg = option[:xmlpkg_name]
|
|
||||||
json = rpm_auditer.cves_per_pkg_name(pkg).to_json
|
|
||||||
json_pp(JSON.parse(json))
|
|
||||||
elsif options[:pkg]
|
|
||||||
pkg = options[:pkg]
|
|
||||||
params = { params: { package: pkg } }
|
|
||||||
response = rhel_api_client.request('/cve.json', params)
|
|
||||||
|
|
||||||
json = rhel_api_client.cve_pkg_adv(response)
|
|
||||||
json_pp(json)
|
|
||||||
elsif options[:refresh]
|
|
||||||
rpm_auditer.refresh_rpm_to_cve_file('./data/rpm-to-cve.xml')
|
|
||||||
elsif options[:cve]
|
|
||||||
id = options[:cve]
|
|
||||||
|
|
||||||
json = rhel_api_client.cve_id(id)
|
|
||||||
json_pp(json)
|
|
||||||
elsif options[:file]
|
|
||||||
filepath = options[:file]
|
|
||||||
cve_ids = read_cves_file(filepath)
|
|
||||||
|
|
||||||
json = rhel_api_client.cve_ids(cve_ids)
|
|
||||||
json_pp(json)
|
|
||||||
elsif options[:list]
|
|
||||||
puts rpm_auditer.list_pkg_names.sort
|
|
||||||
elsif options[:advisory]
|
|
||||||
advisory = options[:advisory]
|
|
||||||
params = { params: { advisory: advisory } }
|
|
||||||
|
|
||||||
json = rhel_api_client.request('/cve.json', params)
|
|
||||||
json_pp(json)
|
|
||||||
end
|
|
50
security_tools/rpm_to_cve_parser/rhel_rpm_to_cve.rb
Executable file
50
security_tools/rpm_to_cve_parser/rhel_rpm_to_cve.rb
Executable file
|
@ -0,0 +1,50 @@
|
||||||
|
require 'ox'
|
||||||
|
|
||||||
|
class RhelRpmToCve
|
||||||
|
# filepath == /path/to/rpm-to-cve.xml
|
||||||
|
attr_accessor :filepath, :file, :xml
|
||||||
|
|
||||||
|
def initialize(filepath)
|
||||||
|
@filepath = filepath
|
||||||
|
@file = File.read(filepath)
|
||||||
|
@xml = Ox.parse(file)
|
||||||
|
end
|
||||||
|
|
||||||
|
def list_pkg_names
|
||||||
|
xml.rpms.locate("?/@rpm")
|
||||||
|
end
|
||||||
|
|
||||||
|
def pkg_exists?(pkg_name)
|
||||||
|
list_pkg_names.include? pkg_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def cves_per_pkg_name(pkg_name)
|
||||||
|
if pkg_exists? pkg_name
|
||||||
|
results = find_pkg(pkg_name).locate('*/cve').map do |r|
|
||||||
|
r.text
|
||||||
|
end.compact
|
||||||
|
|
||||||
|
cves = results.map {|cve| cve}
|
||||||
|
|
||||||
|
{
|
||||||
|
:rhel_package_name => pkg_name,
|
||||||
|
:cves => cves,
|
||||||
|
:cve_count => cves.count
|
||||||
|
}
|
||||||
|
else
|
||||||
|
'Package not found.'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_pkg(pkg_name)
|
||||||
|
xml.rpms.locate("rpm[@rpm=#{pkg_name}]").first
|
||||||
|
end
|
||||||
|
|
||||||
|
def convert_to_json
|
||||||
|
pkgs = list_pkg_names
|
||||||
|
pkgs_and_cves = pkgs.map do |pkg_name|
|
||||||
|
cves_per_pkg_name(pkg_name)
|
||||||
|
end
|
||||||
|
pkgs_and_cves.to_json
|
||||||
|
end
|
||||||
|
end
|
File diff suppressed because it is too large
Load diff
32
security_tools/rpm_to_cve_parser/rpm_pkg_audit.rb
Executable file
32
security_tools/rpm_to_cve_parser/rpm_pkg_audit.rb
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'optparse'
|
||||||
|
require 'json'
|
||||||
|
require './rhel_rpm_to_cve'
|
||||||
|
|
||||||
|
data_file = './rpm-to-cve.xml'
|
||||||
|
|
||||||
|
options = {}
|
||||||
|
|
||||||
|
parser = OptionParser.new do |parser|
|
||||||
|
parser.banner = 'Usage: rpm_pkg_audit.rb [options]'
|
||||||
|
parser.on('-p', '--pkg PKGNAME', 'The pkg name you want to audit.') do |pkg|
|
||||||
|
options[:pkg] = pkg
|
||||||
|
end
|
||||||
|
parser.on('-l', '--list', 'List packages in the XML datafile.') do |list|
|
||||||
|
options[:list] = list
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.parse!
|
||||||
|
|
||||||
|
pkg_name = options[:pkg]
|
||||||
|
rpm_auditer = RhelRpmToCve.new(data_file)
|
||||||
|
|
||||||
|
if pkg_name
|
||||||
|
json = rpm_auditer.cves_per_pkg_name(pkg_name).to_json
|
||||||
|
puts JSON.pretty_generate(JSON.parse(json))
|
||||||
|
else options.key?(:list)
|
||||||
|
puts rpm_auditer.list_pkg_names.sort
|
||||||
|
end
|
4
security_tools/rpm_to_cve_parser/update_rpms_to_cve_xml.sh
Executable file
4
security_tools/rpm_to_cve_parser/update_rpms_to_cve_xml.sh
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# refresh the latest rpm to cve xml mapping file from redhat security page
|
||||||
|
|
||||||
|
wget https://www.redhat.com/security/data/metrics/rpm-to-cve.xml .
|
Loading…
Add table
Reference in a new issue