Skip to content

Commit

Permalink
cvecheck: Support web-only results without a subscription
Browse files Browse the repository at this point in the history
  • Loading branch information
mgpb committed Dec 5, 2017
1 parent e64ea23 commit 5d6762e
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 22 deletions.
87 changes: 70 additions & 17 deletions scripts/checkcves.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,71 @@
#!/usr/bin/env python

from datetime import datetime
import os
import sys
import json

from lib import llapi

NVD_BASE_URL = 'https://nvd.nist.gov/vuln/detail/'
API_DOC = '%s/docs/wiki/engineering/LinuxLink_Key_File' % llapi.LINUXLINK_SERVER
INFO_PAGE = 'https://www.timesys.com/open-source-embedded/security-update-management/'


def print_usage():
apidoc = '%s/docs/wiki/engineering/LinuxLink_Key_File' % llapi.LINUXLINK_SERVER
print('This script sends a json manifest file for an image to LinuxLink '
print('Usage: %s <manifest file>\n\n'
'This script sends a json manifest file for an image to LinuxLink '
'to check the CVE status of the recipes.\n\n'
'It requires a LinuxLink API keyfile, and an active LinuxLink '
'subscription. See this document for keyfile information:\n'
'Subscribing to notifications requires a LinuxLink API keyfile, and '
'an active LinuxLink subscription.\n\n'
'See this document for keyfile information:\n'
'%s\n\n'
'Usage: %s <manifestfile>'
% (apidoc, sys.argv[0]))
% (sys.argv[0], API_DOC))


def print_demo_notice(bad_key=False):
if bad_key:
print('\nWarning: No API keyfile was found, or the contents were '
'invalid.\n\n'
'If you do have a LinuxLink subscription, please see this '
'document for API key information:\n'
'%s\n'
% API_DOC)
else:
print('\nWarning: No active subscription for this account.\n')

print('The script will continue in demo mode, which will link you to '
'temporarily available online results only.\n'
'You will not be able to subscribe for notifications!\n\n'
'For more information on the security notification service, visit:\n'
'%s\n'
% INFO_PAGE)


def read_manifest(manifest_file):
with open(manifest_file, 'rb') as f:
manifest = ''.join(line.rstrip() for line in f)
try:
with open(manifest_file, 'rb') as f:
manifest = ''.join(line.rstrip() for line in f)
except (OSError, IOError, UnicodeDecodeError) as e:
print('Error: Could not open manifest: %s' % e)
sys.exit(1)
return manifest


def print_cves(result):
for pkg,info in result.iteritems():
def print_cves(result, demo=False):
if demo:
report_url = '%s%s' % (llapi.LINUXLINK_SERVER, result['report_path'])
print('CVE Summary:\n'
' Unfixed: %d\n'
' Fixed: %d\n\n'
'View complete report online at:\n'
'%s\n\n'
'Note: The above URL will expire after one day.'
% (result['unfixed_count'],
result['fixed_count'],
report_url))
return

for pkg, info in result.iteritems():
for cve in info:
print('\nRecipe: %s' % pkg)
print('Version: %s' % cve['version'])
Expand All @@ -49,6 +86,7 @@ def print_cves(result):
resource = '/api/cves/reports/yocto/'
home_dir = os.path.expanduser('~')
key_file = os.getenv('KEY_FILE', '%s/timesys/linuxlink_key' % home_dir)
demo = False

try:
manifest_file = sys.argv[1]
Expand All @@ -63,16 +101,31 @@ def print_cves(result):
print_usage()
sys.exit(1)

# If there was no proper API keyfile, operate in demo mode.
if not email or not key:
demo = True
resource += 'demo/'
print_demo_notice(bad_key=True)

manifest = read_manifest(manifest_file)
manifest_json=json.loads(manifest)
manifest_json = json.loads(manifest)
if len(manifest_json['packages']) > 0:
print('Requesting image analysis from LinuxLink ...')
result = llapi.api_post(email, key, resource, {'manifest': manifest})
result = result.get('cves', [])
if not result:
cves = result.get('cves', [])
print('--------')
print('Date: %s\n' % result['date'])
if not cves:
print('No results.')
else:
print('Date: %s' % datetime.utcnow())
print_cves(result)
# If no subscription or bogus user/key, it will have fallen back to
# demo mode to give results
demo_result = result.get('demo', False)
if not demo and demo_result:
print_demo_notice()
demo = demo_result
print_cves(cves, demo=demo)
else:
print('No packages found in manifest.\nPlease confirm %s is a valid image' % manifest_json["image"])
print('No packages found in manifest.\n'
'Please confirm that "%s" is a valid image'
% manifest_json["image"])
13 changes: 8 additions & 5 deletions scripts/lib/llapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,20 @@ def create_hmac(key, msg):
return base64.b64encode(sig)


# This raises an error if it can't read or decode a file that's present, but
# leaves it to the caller to decide what to do with empty values.
def read_keyfile(key_file):
try:
with open(key_file, 'r') as f:
key_info = json.load(f, encoding='utf-8')
except (OSError, IOError, UnicodeDecodeError):
email, key = (None, None)
except Exception:
raise Exception("Unable to read key file: %s" % key_file)
raise Exception("Unable to parse key file: %s" % key_file)
else:
email = key_info.get('email', '').strip()
key = key_info.get('key', '').strip()

email = key_info.get('email', '').strip()
key = key_info.get('key', '').strip()
if not email or not key:
raise Exception("Invalid or missing data in key file")
return (email, key)


Expand Down

0 comments on commit 5d6762e

Please sign in to comment.