diff --git a/.gitignore b/.gitignore index 06d28ca38..1fa4f258d 100644 --- a/.gitignore +++ b/.gitignore @@ -103,3 +103,6 @@ ENV/ # PyCharm .idea/ + +# Database +*.sqlite3* diff --git a/.travis.yml b/.travis.yml index 606ad44a2..e358372d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,12 @@ install: before_script: - pycodestyle --exclude=migrations,settings.py,lib,tests --max-line-length=100 . + - cd app/ + - python3 manage.py migrate script: - python3.6 -m pytest -v tests/ + - python3.6 manage.py test notifications: email: false diff --git a/README.md b/README.md index dd46f26bd..f7deaa486 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,13 @@ Clone the source code: git clone https://github.com/nexB/vulnerablecode.git && cd vulnerablecode ``` -Activate a virtualenv and install dependencies: +Activate a virtualenv, install dependencies, and run the database migrations: ``` python3.6 -m venv . source bin/activate pip install -r requirements.txt +app/manage.py migrate ``` Tests @@ -28,18 +29,28 @@ pycodestyle --exclude=migrations,settings.py,lib,tests --max-line-length=100 . cd app/ python3.6 -m pytest -v tests/ ``` + For Django based tests ``` cd app/ -python3 manage.py test +./manage.py test ``` -Scrape ------- +Scrape and save to the database +------------------------------- + +``` +cd app/ +./manage.py shell +``` ``` from scraper import debian, ubuntu +from vulncode_app.data_dump import debian_dump, ubuntu_dump + +debian_vulnerabilities = debian.scrape_vulnerabilities() +ubuntu_cves = ubuntu.scrape_cves() -debian.scrape_cves() -ubuntu.scrape_cves() +debian_dump(debian_vulnerabilities) +ubuntu_dump(ubuntu_cves) ``` diff --git a/app/app/settings.py b/app/app/settings.py index 384dae1ea..157066daa 100644 --- a/app/app/settings.py +++ b/app/app/settings.py @@ -31,6 +31,7 @@ # Application definition INSTALLED_APPS = [ + 'vulncode_app.apps.VulncodeAppConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', diff --git a/app/app/urls.py b/app/app/urls.py index 9a30fd723..37fd405a7 100644 --- a/app/app/urls.py +++ b/app/app/urls.py @@ -13,10 +13,9 @@ 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ + from django.conf.urls import url, include -from django.contrib import admin urlpatterns = [ url(r'^vulncode_app/', include('vulncode_app.urls')), - url(r'^admin/', admin.site.urls), ] diff --git a/scraper/debian.py b/app/scraper/debian.py similarity index 78% rename from scraper/debian.py rename to app/scraper/debian.py index 5cd6c1080..74a93fe58 100644 --- a/scraper/debian.py +++ b/app/scraper/debian.py @@ -24,25 +24,16 @@ import json from urllib.request import urlopen - DEBIAN_TRACKER_URL = 'https://security-tracker.debian.org/tracker/data/json' -def json_data(url=DEBIAN_TRACKER_URL): - """ - Return Debian vulnerabilities data fetched from `url`. - """ - debian_data = urlopen(url).read() - return json.loads(debian_data) - - -def extract_data(debian_data, base_release='jessie'): +def extract_vulnerabilities(debian_data, base_release='jessie'): """ Return a sequence of mappings for each existing combination of package and vulnerability from a mapping of Debian vulnerabilities data. """ - package_vulns = [] + package_vulnerabilities = [] for package_name, vulnerabilities in debian_data.items(): if not vulnerabilities or not package_name: @@ -57,11 +48,21 @@ def extract_data(debian_data, base_release='jessie'): if not release: continue - package_vulns.append({ + package_vulnerabilities.append({ 'package_name': package_name, 'vulnerability_id': vulnerability, - 'status': release.get('status'), - 'urgency': release.get('urgency'), - 'fixed_version': release.get('fixed_version') + 'description': details.get('description', ''), + 'status': release.get('status', ''), + 'urgency': release.get('urgency', ''), + 'fixed_version': release.get('fixed_version', '') }) - return package_vulns + + return package_vulnerabilities + + +def scrape_vulnerabilities(): + """ + Scrape debian' security tracker. + """ + json_content = urlopen(DEBIAN_TRACKER_URL).read() + return extract_vulnerabilities(json.loads(json_content)) diff --git a/scraper/ubuntu.py b/app/scraper/ubuntu.py similarity index 100% rename from scraper/ubuntu.py rename to app/scraper/ubuntu.py diff --git a/tests/test_api_data.py b/app/tests/test_api_data.py similarity index 98% rename from tests/test_api_data.py rename to app/tests/test_api_data.py index 5ea514e07..9f1a4bc54 100644 --- a/tests/test_api_data.py +++ b/app/tests/test_api_data.py @@ -23,7 +23,7 @@ import json -from api_data import extract_fields +from vulncode_app.api_data import extract_fields test_data = """ diff --git a/tests/test_data/debian.json b/app/tests/test_data/debian.json similarity index 88% rename from tests/test_data/debian.json rename to app/tests/test_data/debian.json index d9aaef2e5..843d43842 100644 --- a/tests/test_data/debian.json +++ b/app/tests/test_data/debian.json @@ -3,7 +3,7 @@ "CVE-2009-2458": { "scope": "remote", "debianbug": 537254, - "description": "Multiple stack-based buffer overflows in mimetex.cgi in mimeTeX, when downloaded before 20090713, allow remote attackers to execute arbitrary code via a TeX file with long (1) picture, (2) circle, or (3) input tags.", + "description": "Multiple stack-based buffer overflows in mimetex.cgi in mimeTeX", "releases": {"stretch": {"status": "resolved", @@ -34,7 +34,7 @@ "CVE-2009-2459": {"scope": "un-remote", "debianbug": 537254, - "description": "Multiple unspecified vulnerabilities in mimeTeX, when downloaded before 20090713, have unknown impact and attack vectors related to the (1) \\environ, (2) \\input, and (3) \\counter TeX directives.", + "description": "Multiple unspecified vulnerabilities in mimeTeX.", "releases": {"stretch": {"status": "resolved", diff --git a/tests/ubuntu/main.html b/app/tests/test_data/ubuntu_main.html similarity index 100% rename from tests/ubuntu/main.html rename to app/tests/test_data/ubuntu_main.html diff --git a/tests/test_scrapers.py b/app/tests/test_scrapers.py similarity index 82% rename from tests/test_scrapers.py rename to app/tests/test_scrapers.py index 45a1a75cf..13cf4e96b 100644 --- a/tests/test_scrapers.py +++ b/app/tests/test_scrapers.py @@ -30,7 +30,7 @@ def test_ubuntu_extract_cves(): - ubuntu_testfile = join(dirname(__file__), 'ubuntu', 'main.html') + ubuntu_testfile = join(dirname(__file__), 'test_data', 'ubuntu_main.html') with open(ubuntu_testfile) as f: test_input = f.read() @@ -59,7 +59,7 @@ def test_ubuntu_extract_cves(): assert expected == cves[-1] -def test_debian_extract_data(): +def test_debian_extract_vulnerabilities(): debian_test_file = join(dirname(__file__), 'test_data', 'debian.json') with open(debian_test_file) as f: @@ -71,22 +71,25 @@ def test_debian_extract_data(): 'package_name': 'mimetex', 'status': 'resolved', 'urgency': 'medium', - 'vulnerability_id': 'CVE-2009-2458' + 'vulnerability_id': 'CVE-2009-2458', + 'description': 'Multiple stack-based buffer overflows in mimetex.cgi in mimeTeX' }, { 'fixed_version': '1.50-1.1', 'package_name': 'mimetex', 'status': 'not-resolved', 'urgency': 'medium', - 'vulnerability_id': 'CVE-2009-2459' + 'vulnerability_id': 'CVE-2009-2459', + 'description': 'Multiple unspecified vulnerabilities in mimeTeX.' }, { - 'fixed_version': None, 'package_name': 'git-repair', + 'vulnerability_id': 'TEMP-0807341-84E914', + 'description': '', 'status': 'open', 'urgency': 'unimportant', - 'vulnerability_id': 'TEMP-0807341-84E914' + 'fixed_version': '' } ] - assert expected == debian.extract_data(test_data) + assert expected == debian.extract_vulnerabilities(test_data) diff --git a/app/vulncode_app/admin.py b/app/vulncode_app/admin.py deleted file mode 100644 index 13be29d96..000000000 --- a/app/vulncode_app/admin.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.contrib import admin - -# Register your models here. diff --git a/api_data.py b/app/vulncode_app/api_data.py similarity index 100% rename from api_data.py rename to app/vulncode_app/api_data.py diff --git a/app/vulncode_app/data_dump.py b/app/vulncode_app/data_dump.py new file mode 100644 index 000000000..71bcd44bc --- /dev/null +++ b/app/vulncode_app/data_dump.py @@ -0,0 +1,61 @@ +# +# Copyright (c) 2017 nexB Inc. and others. All rights reserved. +# http://nexb.com and https://github.com/nexB/vulnerablecode/ +# The VulnerableCode software is licensed under the Apache License version 2.0. +# Data generated with VulnerableCode require an acknowledgment. +# +# You may not use this software except in compliance with the License. +# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# +# When you publish or redistribute any data created with VulnerableCode or any VulnerableCode +# derivative work, you must accompany this data with the following acknowledgment: +# +# Generated with VulnerableCode and provided on an "AS IS" BASIS, WITHOUT WARRANTIES +# OR CONDITIONS OF ANY KIND, either express or implied. No content created from +# VulnerableCode should be considered or used as legal advice. Consult an Attorney +# for any legal advice. +# VulnerableCode is a free software code scanning tool from nexB Inc. and others. +# Visit https://github.com/nexB/vulnerablecode/ for support and download. + +from vulncode_app.models import Vulnerability +from vulncode_app.models import VulnerabilityReference +from vulncode_app.models import Package + + +def debian_dump(extract_data): + """ + Save data scraped from Debian' security tracker. + """ + for data in extract_data: + vulnerability = Vulnerability.objects.create( + summary=data.get('description', ''), + ) + VulnerabilityReference.objects.create( + vulnerability=vulnerability, + reference_id=data.get('vulnerability_id', ''), + ) + Package.objects.create( + name=data.get('package_name', ''), + version=data.get('fixed_version', ''), + ) + + +def ubuntu_dump(html): + """ + Dump data scraped from Ubuntu's security tracker. + """ + for data in html: + vulnerability = Vulnerability.objects.create( + summary='', + ) + VulnerabilityReference.objects.create( + vulnerability=vulnerability, + reference_id=data.get('cve_id'), + ) + Package.objects.create( + name=data.get('package_name'), + ) diff --git a/app/vulncode_app/migrations/0001_initial.py b/app/vulncode_app/migrations/0001_initial.py new file mode 100644 index 000000000..2b500623d --- /dev/null +++ b/app/vulncode_app/migrations/0001_initial.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-08-08 09:11 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='ImpactedPackage', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + ), + migrations.CreateModel( + name='Package', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('platform', models.CharField(blank=True, help_text='Package platform eg:maven', max_length=50)), + ('name', models.CharField(blank=True, help_text='Package name', max_length=50)), + ('version', models.CharField(blank=True, help_text='Package version', max_length=50)), + ], + ), + migrations.CreateModel( + name='PackageReference', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('repository', models.CharField(blank=True, help_text='Repository URL eg:http://central.maven.org', max_length=50)), + ('platform', models.CharField(blank=True, help_text='Platform eg:maven', max_length=50)), + ('name', models.CharField(blank=True, help_text='Package reference name eg:org.apache.commons.io', max_length=50)), + ('version', models.CharField(blank=True, help_text='Reference version', max_length=50)), + ('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='vulncode_app.Package')), + ], + ), + migrations.CreateModel( + name='ResolvedPackage', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='vulncode_app.Package')), + ], + ), + migrations.CreateModel( + name='Vulnerability', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('summary', models.CharField(blank=True, help_text='Summary of the vulnerability', max_length=50)), + ('cvss', models.FloatField(help_text='CVSS Score', max_length=50, null=True)), + ], + ), + migrations.CreateModel( + name='VulnerabilityReference', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('source', models.CharField(blank=True, help_text="Source's name eg:NVD", max_length=50)), + ('reference_id', models.CharField(blank=True, help_text='Reference ID, eg:CVE-ID', max_length=50)), + ('url', models.URLField(blank=True, help_text='URL of Vulnerability data', max_length=1024)), + ('vulnerability', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='vulncode_app.Vulnerability')), + ], + ), + migrations.AddField( + model_name='resolvedpackage', + name='vulnerability', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='vulncode_app.Vulnerability'), + ), + migrations.AddField( + model_name='impactedpackage', + name='package', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='vulncode_app.Package'), + ), + migrations.AddField( + model_name='impactedpackage', + name='vulnerability', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='vulncode_app.Vulnerability'), + ), + migrations.AlterUniqueTogether( + name='vulnerabilityreference', + unique_together=set([('vulnerability', 'source', 'reference_id')]), + ), + ] diff --git a/app/vulncode_app/models.py b/app/vulncode_app/models.py index 914142645..713423555 100644 --- a/app/vulncode_app/models.py +++ b/app/vulncode_app/models.py @@ -21,7 +21,6 @@ # VulnerableCode is a free software code scanning tool from nexB Inc. and others. # Visit https://github.com/nexB/vulnerablecode/ for support and download. -from __future__ import unicode_literals from django.db import models @@ -30,9 +29,11 @@ class Vulnerability(models.Model): A software vulnerability with minimal information. Identifiers are stored as VulnerabilityReference. """ - summary = models.TextField(max_length=1024, - help_text="Summary of the vulnerability") - cvss = models.FloatField(help_text="CVSS Score") + summary = models.CharField(max_length=50, help_text='Summary of the vulnerability', blank=True) + cvss = models.FloatField(max_length=50, help_text='CVSS Score', null=True) + + def __str__(self): + return self.summary class VulnerabilityReference(models.Model): @@ -42,12 +43,9 @@ class VulnerabilityReference(models.Model): at the NVD, a bug id and similar references. """ vulnerability = models.ForeignKey('Vulnerability') - source = models.CharField(max_length=50, - help_text="Source's name eg:NVD") - reference_id = models.CharField(max_length=50, - help_text="Reference ID, eg:CVE-ID") - url = models.URLField(max_length=1024, - help_text="URL of Vulnerability data") + source = models.CharField(max_length=50, help_text='Source(s) name eg:NVD', blank=True) + reference_id = models.CharField(max_length=50, help_text='Reference ID, eg:CVE-ID', blank=True) + url = models.URLField(max_length=1024, help_text='URL of Vulnerability data', blank=True) class Meta: unique_together = ('vulnerability', 'source', 'reference_id') @@ -75,13 +73,12 @@ class Package(models.Model): A software package with minimal identifying information. Other identifiers are stored as PackageReference. """ - platform = models.CharField(max_length=50, - help_text="Package platform eg:maven") - name = models.CharField(max_length=50, help_text="Package name") - version = models.CharField(max_length=50, help_text="Pacakge version") + platform = models.CharField(max_length=50, help_text='Package platform eg:maven', blank=True) + name = models.CharField(max_length=50, help_text='Package name', blank=True) + version = models.CharField(max_length=50, help_text='Package version', blank=True) - class Meta: - unique_together = ('platform', 'name', 'version') + def __str__(self): + return self.name class PackageReference(models.Model): @@ -90,11 +87,26 @@ class PackageReference(models.Model): in a package repository, such as a Debian, Maven or NPM repository. """ package = models.ForeignKey('Package') - repository = models.CharField(max_length=1024, - help_text="Repository URL eg:http://central.maven.org") - platform = models.CharField(max_length=50, - help_text="Platform eg:maven") - name = models.CharField(max_length=50, - help_text="Package reference name eg:org.apache.commons.io") - version = models.CharField(max_length=50, - help_text="Reference version") + repository = models.CharField( + max_length=50, + help_text='Repository URL eg:http://central.maven.org', + blank=True, + ) + platform = models.CharField( + max_length=50, + help_text='Platform eg:maven', + blank=True, + ) + name = models.CharField( + max_length=50, + help_text='Package reference name eg:org.apache.commons.io', + blank=True, + ) + version = models.CharField( + max_length=50, + help_text='Reference version', + blank=True, + ) + + def __str__(self): + return self.platform diff --git a/app/vulncode_app/test_data_dump.py b/app/vulncode_app/test_data_dump.py new file mode 100644 index 000000000..cb359ece4 --- /dev/null +++ b/app/vulncode_app/test_data_dump.py @@ -0,0 +1,82 @@ +# +# Copyright (c) 2017 nexB Inc. and others. All rights reserved. +# http://nexb.com and https://github.com/nexB/vulnerablecode/ +# The VulnerableCode software is licensed under the Apache License version 2.0. +# Data generated with VulnerableCode require an acknowledgment. +# +# You may not use this software except in compliance with the License. +# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# +# When you publish or redistribute any data created with VulnerableCode or any VulnerableCode +# derivative work, you must accompany this data with the following acknowledgment: +# +# Generated with VulnerableCode and provided on an "AS IS" BASIS, WITHOUT WARRANTIES +# OR CONDITIONS OF ANY KIND, either express or implied. No content created from +# VulnerableCode should be considered or used as legal advice. Consult an Attorney +# for any legal advice. +# VulnerableCode is a free software code scanning tool from nexB Inc. and others. +# Visit https://github.com/nexB/vulnerablecode/ for support and download. + +import json + +from django.test import TestCase + +from vulncode_app.models import Vulnerability +from vulncode_app.models import VulnerabilityReference +from vulncode_app.models import Package +from vulncode_app.data_dump import debian_dump +from vulncode_app.data_dump import ubuntu_dump +from scraper import debian +from scraper import ubuntu + + +class TestDataDump(TestCase): + def test_debian_data_dump(self): + """ + Scrape data from Debian' main tracker, save it + in the database and verify entries. + """ + with open('tests/test_data/debian.json') as f: + test_data = json.loads(f.read()) + + extract_data = debian.extract_vulnerabilities(test_data) + debian_dump(extract_data) + + self.assertEqual(3, Vulnerability.objects.count()) + self.assertEqual(3, VulnerabilityReference.objects.count()) + self.assertEqual(3, Package.objects.count()) + + self.assertTrue(Vulnerability.objects.get( + summary='Multiple stack-based buffer overflows in mimetex.cgi in mimeTeX')) + + self.assertTrue(Vulnerability.objects.get( + summary='Multiple unspecified vulnerabilities in mimeTeX.')) + + self.assertTrue(VulnerabilityReference.objects.get(reference_id='CVE-2009-2458')) + + self.assertTrue(VulnerabilityReference.objects.get(reference_id='CVE-2009-2459')) + + self.assertTrue(VulnerabilityReference.objects.get(reference_id='TEMP-0807341-84E914')) + + self.assertEqual(Package.objects.filter(name='mimetex')[0].name, 'mimetex') + self.assertTrue(Package.objects.get(name='git-repair')) + self.assertEqual(Package.objects.filter(version='1.50-1.1')[0].version, '1.50-1.1') + + def test_ubuntu_data_dump(self): + """ + Scrape data from Ubuntu' main tracker, save it + in the database and verify entries. + """ + with open('tests/test_data/ubuntu_main.html') as f: + test_data = f.read() + + data = ubuntu.extract_cves(test_data) + ubuntu_dump(data) + + reference = VulnerabilityReference.objects.filter(reference_id='CVE-2002-2439')[0] + self.assertEqual(reference.reference_id, 'CVE-2002-2439') + self.assertTrue(Package.objects.filter(name='gcc-4.6')[0].name, 'gcc-4.6') diff --git a/app/vulncode_app/test_models.py b/app/vulncode_app/test_models.py new file mode 100644 index 000000000..2f5fe0cac --- /dev/null +++ b/app/vulncode_app/test_models.py @@ -0,0 +1,83 @@ +# +# Copyright (c) 2017 nexB Inc. and others. All rights reserved. +# http://nexb.com and https://github.com/nexB/vulnerablecode/ +# The VulnerableCode software is licensed under the Apache License version 2.0. +# Data generated with VulnerableCode require an acknowledgment. +# +# You may not use this software except in compliance with the License. +# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# +# When you publish or redistribute any data created with VulnerableCode or any VulnerableCode +# derivative work, you must accompany this data with the following acknowledgment: +# +# Generated with VulnerableCode and provided on an "AS IS" BASIS, WITHOUT WARRANTIES +# OR CONDITIONS OF ANY KIND, either express or implied. No content created from +# VulnerableCode should be considered or used as legal advice. Consult an Attorney +# for any legal advice. +# VulnerableCode is a free software code scanning tool from nexB Inc. and others. +# Visit https://github.com/nexB/vulnerablecode/ for support and download. + +from django.test import TestCase + +from vulncode_app.models import Vulnerability +from vulncode_app.models import VulnerabilityReference +from vulncode_app.models import Package +from vulncode_app.models import PackageReference + + +class TestVulnerability(TestCase): + def test_vulnerability(self): + Vulnerability.objects.create( + summary="Affected package xyz", + cvss="7.8" + ) + + self.assertTrue(Vulnerability.objects.get(summary="Affected package xyz")) + self.assertTrue(Vulnerability.objects.get(cvss="7.8")) + + +class TestVulnerabilityReference(TestCase): + def test_vulnerability_reference(self): + VulnerabilityReference.objects.create( + vulnerability=Vulnerability.objects.create(summary="XYZ"), + reference_id="CVE-2017-8564", + source="NVD", + url="http://mitre.com" + ) + + self.assertTrue(VulnerabilityReference.objects.get(reference_id="CVE-2017-8564")) + self.assertTrue(VulnerabilityReference.objects.get(source="NVD")) + self.assertTrue(VulnerabilityReference.objects.get(url="http://mitre.com")) + + +class TestPackage(TestCase): + def test_package(self): + Package.objects.create( + name="Firefox", + platform="Maven", + version="1.5.4" + ) + + self.assertTrue(Package.objects.get(name="Firefox")) + self.assertTrue(Package.objects.get(platform="Maven")) + self.assertTrue(Package.objects.get(version="1.5.4")) + + +class TestPackageReference(TestCase): + def test_package_reference(self): + PackageReference.objects.create( + package=Package.objects.create(name="Iceweasel"), + platform="Maven", + repository="http://central.maven.org", + name="org.apache.commons.io", + version="7.6.5" + ) + + self.assertTrue(PackageReference.objects.get(platform="Maven")) + self.assertTrue(PackageReference.objects.get(repository="http://central.maven.org")) + self.assertTrue(PackageReference.objects.get(name="org.apache.commons.io")) + self.assertTrue(PackageReference.objects.get(version="7.6.5")) diff --git a/app/vulncode_app/tests.py b/app/vulncode_app/tests.py deleted file mode 100644 index 5982e6bcd..000000000 --- a/app/vulncode_app/tests.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.test import TestCase - -# Create your tests here. diff --git a/app/vulncode_app/urls.py b/app/vulncode_app/urls.py index e6f5b6da7..6eec081f6 100644 --- a/app/vulncode_app/urls.py +++ b/app/vulncode_app/urls.py @@ -22,10 +22,11 @@ # Visit https://github.com/nexB/vulnerablecode/ for support and download. from django.conf.urls import url + from . import views -urlpatterns = [ - url(r'(?P[a-z]+)/(?P[0-9]+)', views.package_version, name="package_version"), - url(r'^(?P[a-z]+)', views.package, name="package"), +urlpatterns = [ + url(r'(?P[a-z]+)/(?P[0-9]+)', views.package_version, name='package_version'), + url(r'^(?P[a-z]+)', views.package, name='package'), ] diff --git a/app/vulncode_app/views.py b/app/vulncode_app/views.py index 62066303c..254b8b311 100644 --- a/app/vulncode_app/views.py +++ b/app/vulncode_app/views.py @@ -21,21 +21,21 @@ # VulnerableCode is a free software code scanning tool from nexB Inc. and others. # Visit https://github.com/nexB/vulnerablecode/ for support and download. -from __future__ import unicode_literals -from django.http import HttpResponse -from django.shortcuts import render -import vulncode_app.api_data as api import json +from django.http import HttpResponse + +from vulncode_app import api_data + def package(request, name): """ Queries the cve-search api with just a package name. """ - raw_data = api.data_cve_circl(name=name) + raw_data = api_data.data_cve_circl(name=name) fields_names = ['id', 'summary', 'cvss'] - extracted_data = api.extract_fields(raw_data, fields_names) + extracted_data = api_data.extract_fields(raw_data, fields_names) return HttpResponse(json.dumps(extracted_data)) @@ -45,8 +45,8 @@ def package_version(request, name, version): Queries the cve-search api with a package name and version. """ - raw_data = api.data_cve_circl(name=name, version=version) + raw_data = api_data.data_cve_circl(name=name, version=version) fields_names = ['id', 'summary', 'cvss'] - extracted_data = api.extract_fields(raw_data, fields_names, version=True) + extracted_data = api_data.extract_fields(raw_data, fields_names, version=True) return HttpResponse(json.dumps(extracted_data)) diff --git a/requirements.txt b/requirements.txt index 6b087fe22..889b545db 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ beautifulsoup4==4.6.0 lxml==3.8.0 +django==1.11.4 # Tests pytest==3.1.3