diff --git a/src/ENV-python b/src/ENV-python index 3455cee..74140fd 100644 --- a/src/ENV-python +++ b/src/ENV-python @@ -1,2 +1,5 @@ export PYTHONPATH=./locallibs/defectdojo-client:./locallibs/dependencytrack-client + + + diff --git a/src/converter.py b/src/converter.py index f20146c..9e5eba4 100644 --- a/src/converter.py +++ b/src/converter.py @@ -9,6 +9,7 @@ from cyclonedx.model.bom import Bom from cyclonedx.model.component import Component, ComponentType from cyclonedx.model.contact import OrganizationalEntity from cyclonedx.model import XsUri +from cyclonedx.model import ExternalReference from cyclonedx.output.json import JsonV1Dot5 class MyLocalConverterException(Exception): pass @@ -54,7 +55,9 @@ def minimalSbomFormatConverter(minimalSbom, classifier): minimalSbomObject = yaml.safe_load(minimalSbom) logger.debug(f"{minimalSbomObject=}") - bom = Bom() + bom = Bom( + version=minimalSbomObject['sbomVersion'] + ) bom.metadata.tools.components.add(cdx_lib_component()) bom.metadata.tools.components.add(Component( name='sbom-dt-dd', diff --git a/src/prepare-local-env.sh b/src/prepare-local-env.sh index 648fe92..8aef2a4 100755 --- a/src/prepare-local-env.sh +++ b/src/prepare-local-env.sh @@ -1,10 +1,11 @@ #!/bin/bash +set -e + +. ./ENV + LOCALLBIS=./locallibs -DTRACK_API_URL=https://dtrack-api-rd.krohne.com -DEFECTDOJO_API_URL=https://defectdojo-rd.krohne.com OPENAPI_GENERATOR=openapitools/openapi-generator-cli:v7.12.0 -UID=$(id -u) mkdir $LOCALLBIS && cd $LOCALLBIS @@ -16,8 +17,8 @@ docker run -v $PWD:/work -u $UID $OPENAPI_GENERATOR \ -g python \ -o /work/dependencytrack-openapi-custom-template -sed -i 's/import re/import regex as re/' dependencytrack-openapi-custom-template/model_anyof.mustache -sed -i 's/import re/import regex as re/' dependencytrack-openapi-custom-template/model_generic.mustache +sed -i -e 's/import re/import regex as re/' dependencytrack-openapi-custom-template/model_anyof.mustache +sed -i -e 's/import re/import regex as re/' dependencytrack-openapi-custom-template/model_generic.mustache docker run -v $PWD:/work -u $UID $OPENAPI_GENERATOR \ generate \ @@ -28,7 +29,7 @@ docker run -v $PWD:/work -u $UID $OPENAPI_GENERATOR \ -t /work/dependencytrack-openapi-custom-template # --- Defectdojo Client Library ---------------------------------------------------------- -curl ${DEFECTDOJO_API_URL}/api/v2/oa3/schema/?format=json >defectdojo-openapi.json +curl ${DEFECTDOJO_URL}/api/v2/oa3/schema/?format=json >defectdojo-openapi.json docker run -v $PWD:/work -u $UID $OPENAPI_GENERATOR \ generate \ diff --git a/src/sbom-dt-dd.py b/src/sbom-dt-dd.py index beaf36b..83cbab1 100644 --- a/src/sbom-dt-dd.py +++ b/src/sbom-dt-dd.py @@ -102,6 +102,11 @@ parser.add_argument('--overwritemetadata', '-O', parser.add_argument('--target', '-T', help='Target to scan, either path name for sources or docker image tag', required=False) +parser.add_argument('--reimport', '-R', + help='Import the SBOM for an existing project/product once again', + required=False, + action='store_true', + default=False) parser.add_argument('--verbose', '-V', help='A lot of debug output', required=False, @@ -113,6 +118,7 @@ projectVersion = args.version projectDescription = args.description productType = args.type projectClassifier = args.classifier +reImport = args.reimport uploadSbomFlag = args.uploadsbom if uploadSbomFlag: @@ -158,44 +164,46 @@ else: # ------- create product and engagement in DefectDojo ------- -defectdojo_configuration = defectdojo_api.Configuration( - host = DEFECTDOJO_URL -) -defectdojo_configuration.api_key['tokenAuth'] = DEFECTDOJO_TOKEN -defectdojo_configuration.api_key_prefix['tokenAuth'] = 'Token' +if not reImport: + # in case of a reimport no modification on DefectDojo are required + defectdojo_configuration = defectdojo_api.Configuration( + host = DEFECTDOJO_URL + ) + defectdojo_configuration.api_key['tokenAuth'] = DEFECTDOJO_TOKEN + defectdojo_configuration.api_key_prefix['tokenAuth'] = 'Token' -with defectdojo_api.ApiClient(defectdojo_configuration) as defectdojo_api_client: - print("Create product in DefectDojo") - productName = f"{projectName}:{projectVersion}" - product_response = \ - executeApiCall( - defectdojo_api_client, - defectdojo_api.ProductsApi, - defectdojo_api.ProductsApi.products_create, - defectdojo_api.ProductRequest, - { 'name': productName, 'description': projectDescription, 'prod_type': productType }, - [] - ) + with defectdojo_api.ApiClient(defectdojo_configuration) as defectdojo_api_client: + print("Create product in DefectDojo") + productName = f"{projectName}:{projectVersion}" + product_response = \ + executeApiCall( + defectdojo_api_client, + defectdojo_api.ProductsApi, + defectdojo_api.ProductsApi.products_create, + defectdojo_api.ProductRequest, + { 'name': productName, 'description': projectDescription, 'prod_type': productType }, + [] + ) - product_id = product_response.id - print(f"{product_id=}") + product_id = product_response.id + print(f"{product_id=}") - print("Create engagement in DefectDojo") - start_time = datetime.date.today() - end_time = start_time + relativedelta(years=10) - engagementName = f"{productName} DTrack Link" - engagement_response = \ - executeApiCall( - defectdojo_api_client, - defectdojo_api.EngagementsApi, - defectdojo_api.EngagementsApi.engagements_create, - defectdojo_api.EngagementRequest, - { 'name': engagementName, 'target_start': start_time, 'target_end': end_time, 'status': 'In Progress', 'product': product_id }, - [] - ) - - engagement_id = engagement_response.id - print(f"{engagement_id=}") + print("Create engagement in DefectDojo") + start_time = datetime.date.today() + end_time = start_time + relativedelta(years=10) + engagementName = f"{productName} DTrack Link" + engagement_response = \ + executeApiCall( + defectdojo_api_client, + defectdojo_api.EngagementsApi, + defectdojo_api.EngagementsApi.engagements_create, + defectdojo_api.EngagementRequest, + { 'name': engagementName, 'target_start': start_time, 'target_end': end_time, 'status': 'In Progress', 'product': product_id }, + [] + ) + + engagement_id = engagement_response.id + print(f"{engagement_id=}") # ------- create project in DependencyTrack, connect project to engagement in DefectDojo, upload SBOM -------- @@ -206,36 +214,38 @@ dependencytrack_configuration.debug = False dependencytrack_configuration.api_key['ApiKeyAuth'] = DTRACK_TOKEN with dependencytrack_api.ApiClient(dependencytrack_configuration) as dependencytrack_api_client: - project_response = \ - executeApiCall( - dependencytrack_api_client, - dependencytrack_api.ProjectApi, - dependencytrack_api.ProjectApi.create_project, - dependencytrack_api.Project, - { 'name': projectName, 'version': projectVersion, 'classifier': projectClassifier, 'uuid': "", 'last_bom_import': 0 }, - [] - ) - - project_uuid = project_response.uuid - print(f"{project_uuid=}") - - properties = [ - { 'group_name': "integrations", 'property_name': "defectdojo.engagementId", - 'property_value': str(engagement_id), 'property_type': "STRING" }, - { 'group_name': "integrations", 'property_name': "defectdojo.doNotReactivate", - 'property_value': "true", 'property_type': "BOOLEAN" }, - { 'group_name': "integrations", 'property_name': "defectdojo.reimport", - 'property_value': "true", 'property_type': "BOOLEAN" } - ] - for property in properties: - executeApiCall( + if not reImport: + # in case of a reimport it is not necessary to create the project + project_response = \ + executeApiCall( dependencytrack_api_client, - dependencytrack_api.ProjectPropertyApi, - dependencytrack_api.ProjectPropertyApi.create_property1, - dependencytrack_api.ProjectProperty, - property, - [ project_uuid ] - ) + dependencytrack_api.ProjectApi, + dependencytrack_api.ProjectApi.create_project, + dependencytrack_api.Project, + { 'name': projectName, 'version': projectVersion, 'classifier': projectClassifier, 'uuid': "", 'last_bom_import': 0 }, + [] + ) + + project_uuid = project_response.uuid + print(f"{project_uuid=}") + + properties = [ + { 'group_name': "integrations", 'property_name': "defectdojo.engagementId", + 'property_value': str(engagement_id), 'property_type': "STRING" }, + { 'group_name': "integrations", 'property_name': "defectdojo.doNotReactivate", + 'property_value': "true", 'property_type': "BOOLEAN" }, + { 'group_name': "integrations", 'property_name': "defectdojo.reimport", + 'property_value': "true", 'property_type': "BOOLEAN" } + ] + for property in properties: + executeApiCall( + dependencytrack_api_client, + dependencytrack_api.ProjectPropertyApi, + dependencytrack_api.ProjectPropertyApi.create_property1, + dependencytrack_api.ProjectProperty, + property, + [ project_uuid ] + ) bom_response = \ executeApiCall(