From 24725eaf10195dfaf9a5d99844f6ec0144c1f7d7 Mon Sep 17 00:00:00 2001 From: David Herring Date: Fri, 31 Dec 2021 14:14:53 +0100 Subject: [PATCH 1/5] feature/added bom upload function --- VERSION | 2 +- dependencytrack/__init__.py | 39 ++++++++++++++++---------------- dependencytrack/bom.py | 45 +++++++++++++++++++++++++++++++++++++ setup.py | 2 +- 4 files changed, 67 insertions(+), 21 deletions(-) create mode 100644 dependencytrack/bom.py diff --git a/VERSION b/VERSION index bbdeab6..1750564 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.0.5 +0.0.6 diff --git a/dependencytrack/__init__.py b/dependencytrack/__init__.py index 9db6e07..6f4a62b 100644 --- a/dependencytrack/__init__.py +++ b/dependencytrack/__init__.py @@ -7,12 +7,13 @@ from .projects import Projects from .components import Components from .licenses import Licenses +from .bom import Bom from .exceptions import AuthenticationError, DependencyTrackApiError logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) -class DependencyTrack(Projects, Components, Licenses): +class DependencyTrack(Projects, Components, Licenses, Bom): """Main DependencyTrack API class @@ -24,7 +25,7 @@ class DependencyTrack(Projects, Components, Licenses): >>> dt = DependencyTrack(url, api_key) .. note:: - + The class instantiation exits if the session with the DependencyTrack server can't be established @@ -52,18 +53,18 @@ def __init__(self, url, api_key): logger.info( f"DependencyTrack instance against {self.host} using {self.api}" ) - + def close(self): self.session.close() def search(self, query): """Search from the server - + API endpoint: GET /search/{query} - + :Example: >>> dt.search('dnsmasq-2.78')['results']['component'] - + :return: the seatch result :rtype: dict {'license': [], 'project': [], 'component': [], 'vulnerability': []} :raises DependencyTrackApiError: if the REST call failed @@ -74,15 +75,15 @@ def search(self, query): else: description = f"Error while searching" raise DependencyTrackApiError(description, response) - + def search_component(self, query): """Search component from the server - + API endpoint: GET /component/?searchText={query} - + :Example: >>> dt.search_component('dnsmasq-2.78') - + :return: the seatch result :rtype: dict :raises DependencyTrackApiError: if the REST call failed @@ -96,12 +97,12 @@ def search_component(self, query): def search_project(self, query): """Search project from the server - + API endpoint: GET /project/?searchText={query} - + :Example: >>> dt.search_project('my project')['results']['component'] - + :return: the seatch result :rtype: dict :raises DependencyTrackApiError: if the REST call failed @@ -115,12 +116,12 @@ def search_project(self, query): def search_vulnerability(self, query): """Search vulnerability from the server - + API endpoint: GET /vulnerability/?searchText={query} - + :Example: >>> dt.search_vulnerability('my vulnerability') - + :return: the seatch result :rtype: dict :raises DependencyTrackApiError: if the REST call failed @@ -134,12 +135,12 @@ def search_vulnerability(self, query): def search_license(self, query): """Search license from the server - + API endpoint: GET /license/?searchText={query} - + :Example: >>> dt.search_license('my license') - + :return: the seatch result :rtype: dict :raises DependencyTrackApiError: if the REST call failed diff --git a/dependencytrack/bom.py b/dependencytrack/bom.py new file mode 100644 index 0000000..691b505 --- /dev/null +++ b/dependencytrack/bom.py @@ -0,0 +1,45 @@ +# Copyright 2020 Alvin Chen sonoma001@gmail.com +# SPDX-License-Identifier: GPL-2.0+ + +import logging + +from .exceptions import DependencyTrackApiError + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + + +class Bom: + """Class dedicated to all "projects" related endpoints""" + + def upload_bom(self, file_name, project_id=None, project_name=None, project_version=None, auto_create=False): + """Upload a supported bill of material format document + + API Endpoint: POST /bom + + :return: UUID-Token + :rtype: string + :raises DependencyTrackApiError: if the REST call failed + """ + multipart_form_data = {} + multipart_form_data['bom']=('bom', open(file_name, 'r')) + + if project_id: + multipart_form_data['project']=project_id + if project_name: + multipart_form_data['projectName']=project_name + if project_version: + multipart_form_data['projectVersion']=project_version + multipart_form_data['autoCreate']=auto_create + response = self.session.post(self.api + "/bom", params=self.paginated_param_payload, files=multipart_form_data) + if response.status_code == 200: + return response.json() + else: + description = f"Unable to upload BOM file" + raise DependencyTrackApiError(description, response) + + + + + + diff --git a/setup.py b/setup.py index bdbceeb..418ba5e 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="dependency-track", - version="0.0.4", + version="0.0.6", author="Alvin Chen", author_email="sonoma001@gmail.com", description="A simple wrapper for the Dependency Track REST API.", From a1a10ac8e64f0ed155666cb98105cb20e6b70b46 Mon Sep 17 00:00:00 2001 From: David Herring Date: Fri, 31 Dec 2021 14:26:33 +0100 Subject: [PATCH 2/5] updated documentation --- dependencytrack/bom.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/dependencytrack/bom.py b/dependencytrack/bom.py index 691b505..958fd61 100644 --- a/dependencytrack/bom.py +++ b/dependencytrack/bom.py @@ -1,16 +1,9 @@ -# Copyright 2020 Alvin Chen sonoma001@gmail.com # SPDX-License-Identifier: GPL-2.0+ -import logging - from .exceptions import DependencyTrackApiError -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) - - class Bom: - """Class dedicated to all "projects" related endpoints""" + """Class dedicated to all "bom" related endpoints""" def upload_bom(self, file_name, project_id=None, project_name=None, project_version=None, auto_create=False): """Upload a supported bill of material format document From ea70492115a232726b53750b5c18a5b14a554fd1 Mon Sep 17 00:00:00 2001 From: David Herring Date: Fri, 31 Dec 2021 14:28:05 +0100 Subject: [PATCH 3/5] updated documentation --- README.rst | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index af60129..a3aaecf 100644 --- a/README.rst +++ b/README.rst @@ -5,10 +5,10 @@ .. |Python Version| image:: https://img.shields.io/badge/python-3.6%2C3.7%2C3.8-blue?logo=python :target: https://www.python.org/doc/versions/ - + .. |Downloads| image:: https://pypip.in/download/dependency-track/badge.svg?period=week :target: https://pypi.python.org/pypi/dependency-track/ - + A simple wrapper for the Dependency Track REST API. Usage @@ -41,17 +41,19 @@ Using the API dt = DependencyTrack(url, api_key) dt.list_projects() - + dt.get_project_property('ab36ead0-c7b0-47f5-89ac-7f92a0bbe12e') - + dt.list_components() dt.get_project_dependency('ab36ead0-c7b0-47f5-89ac-7f92a0bbe12e') - + dt.get_component_dependency('db6157c2-f0a3-447c-902d-aecd360958bd') - + dt.list_concise_licenses()[0] - + dt.get_license('MIT') dt.search('dnsmasq-2.0') + + dt.upload_bom('bom.xml') \ No newline at end of file From 48219b0cabef764d6240e1c31e637864d0723485 Mon Sep 17 00:00:00 2001 From: David Herring Date: Fri, 31 Dec 2021 14:34:08 +0100 Subject: [PATCH 4/5] removed trailing whitespace --- dependencytrack/bom.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/dependencytrack/bom.py b/dependencytrack/bom.py index 958fd61..f049b53 100644 --- a/dependencytrack/bom.py +++ b/dependencytrack/bom.py @@ -29,10 +29,4 @@ def upload_bom(self, file_name, project_id=None, project_name=None, project_vers return response.json() else: description = f"Unable to upload BOM file" - raise DependencyTrackApiError(description, response) - - - - - - + raise DependencyTrackApiError(description, response) \ No newline at end of file From 6ef7991098060a045895aa9b8790b014fdf13728 Mon Sep 17 00:00:00 2001 From: David Herring Date: Fri, 31 Dec 2021 14:37:39 +0100 Subject: [PATCH 5/5] ran black for formatting --- dependencytrack/bom.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/dependencytrack/bom.py b/dependencytrack/bom.py index f049b53..d87e5d6 100644 --- a/dependencytrack/bom.py +++ b/dependencytrack/bom.py @@ -2,10 +2,18 @@ from .exceptions import DependencyTrackApiError + class Bom: """Class dedicated to all "bom" related endpoints""" - def upload_bom(self, file_name, project_id=None, project_name=None, project_version=None, auto_create=False): + def upload_bom( + self, + file_name, + project_id=None, + project_name=None, + project_version=None, + auto_create=False, + ): """Upload a supported bill of material format document API Endpoint: POST /bom @@ -15,18 +23,22 @@ def upload_bom(self, file_name, project_id=None, project_name=None, project_vers :raises DependencyTrackApiError: if the REST call failed """ multipart_form_data = {} - multipart_form_data['bom']=('bom', open(file_name, 'r')) + multipart_form_data["bom"] = ("bom", open(file_name, "r")) if project_id: - multipart_form_data['project']=project_id + multipart_form_data["project"] = project_id if project_name: - multipart_form_data['projectName']=project_name + multipart_form_data["projectName"] = project_name if project_version: - multipart_form_data['projectVersion']=project_version - multipart_form_data['autoCreate']=auto_create - response = self.session.post(self.api + "/bom", params=self.paginated_param_payload, files=multipart_form_data) + multipart_form_data["projectVersion"] = project_version + multipart_form_data["autoCreate"] = auto_create + response = self.session.post( + self.api + "/bom", + params=self.paginated_param_payload, + files=multipart_form_data, + ) if response.status_code == 200: return response.json() else: description = f"Unable to upload BOM file" - raise DependencyTrackApiError(description, response) \ No newline at end of file + raise DependencyTrackApiError(description, response)