From ba67e16ddc18f8cdd47cb91c179daea981eb6ed5 Mon Sep 17 00:00:00 2001 From: Aaron Weaver <aaron.weaver2@gmail.com> Date: Tue, 6 Dec 2016 10:02:18 -0500 Subject: [PATCH] Added API examples --- examples/README.rst | 58 ++++++++++++++++++++++++++++++++++ examples/dojo_ci_cd.py | 72 ++++++++++++++++++++++++------------------ 2 files changed, 99 insertions(+), 31 deletions(-) create mode 100644 examples/README.rst diff --git a/examples/README.rst b/examples/README.rst new file mode 100644 index 0000000..2ed7c76 --- /dev/null +++ b/examples/README.rst @@ -0,0 +1,58 @@ +DefectDojo API Examples +======================= + +The following examples are available in this directory: + +- Dojo CI CD (dojo_ci_cd.py): Automatically imports a scanner file into a Dojo Engagement, reports on new issues discovered in the build, total vulnerability count and thresholds can be set to determine if the build should pass or fail. +- Dojo Populate (dojo_populate.py): Populates Dojo with sample data, which includes products, engagements, tests and importing scan files. +- Dojo Product (dojo_product.py): Demonstrates creating and querying Dojo products. + +Quick Start +----------- + +- Install with pip (recommended): :code:`pip install defectdojo_api` +- Clone the repository: :code:`git clone https://github.com/aaronweaver/defectdojo_api` +- CD into examples + +Dojo CI CD (dojo_ci_cd.py) +-------------------------- +A simple example of integrating Dojo in your CI/CD pipeline. + +Pass in the following: +- product: ID of the product in DefectDojo +- file: Path to the scanner output file +- high, medium or low: Maximum number of vulnerabilities allowed to Pass or Fail a build +- host: URL to Defect Dojo +- api_key: Defect Dojo API Key +- User: User associated with the API Key + +.. code-block:: bash + + dojo_ci_cd.py --product=1 --file "/tests/scans/Bodgeit-burp.xml" --scanner="Burp Scan" --high=0 --host=http://localhost:8000 --api_key=<api_key> --user=admin + +Dojo Populate +-------------------------- +Populate Dojo with sample data. *Note it is not recommend to run this on a production server as it will create test data. + +- :code:`export DOJO_API_KEY=<apikey>` +- :code:`python dojo_product.py` + +Dojo Product +-------------------------- +Demonstrates creating and querying Dojo products. + +- :code:`export DOJO_API_KEY=<apikey>` +- :code:`python dojo_populate.py` + + +Supporting information for each method available can be found in the `documentation <https://defectdojo-api.readthedocs.io>`_. + +Bugs and Feature Requests +------------------------- + +Have a bug or a feature request? Please first search for existing and closed issues. If your problem or idea is not addressed yet, `please open a new issue <https://github.com/aaronweaver/defectdojo_api/issues/new>`_. + +Copyright and License +--------------------- + +- `Licensed under MIT <https://github.com/aaronweaver/defectdojo_api/blob/master/LICENSE.txt>`_. diff --git a/examples/dojo_ci_cd.py b/examples/dojo_ci_cd.py index ce8a5bf..f3f1e38 100644 --- a/examples/dojo_ci_cd.py +++ b/examples/dojo_ci_cd.py @@ -9,20 +9,6 @@ from datetime import datetime, timedelta import os import argparse -# Setup DefectDojo connection information -host = 'http://localhost:8000' -api_key = os.environ['DOJO_API_KEY'] -user = 'admin' - -#Optionally, specify a proxy -proxies = { - 'http': 'http://localhost:8080', - 'https': 'http://localhost:8080', -} -""" -proxies=proxies -""" - def sum_severity(findings): severity = [0,0,0,0,0] for finding in findings.data["objects"]: @@ -32,8 +18,10 @@ def sum_severity(findings): severity[3] = severity[3] + 1 if finding["severity"] == "Medium": severity[2] = severity[2] + 1 - if finding["severity"] == "Info": + if finding["severity"] == "Low": severity[1] = severity[1] + 1 + if finding["severity"] == "Info": + severity[0] = severity[0] + 1 return severity @@ -44,7 +32,17 @@ def print_findings(findings): print "Low: " + str(findings[1]) print "Info: " + str(findings[0]) -def create_findings(product_id, user_id, file, scanner, engagement_id=None, max_critical=0, max_high=0, max_medium=0): +def create_findings(host, api_key, user, product_id, file, scanner, engagement_id=None, max_critical=0, max_high=0, max_medium=0): + + #Optionally, specify a proxy + proxies = { + 'http': 'http://localhost:8080', + 'https': 'http://localhost:8080', + } + """ + proxies=proxies + """ + # Instantiate the DefectDojo api wrapper dd = defectdojo.DefectDojoAPI(host, api_key, user, proxies=proxies, timeout=90, debug=False) @@ -57,7 +55,6 @@ def create_findings(product_id, user_id, file, scanner, engagement_id=None, max_ #Specify the product id product_id = product_id engagement_id = None - user_id = 1 # Check for a CI/CD engagement_id engagements = dd.list_engagements(product_in=product_id, status="In Progress") @@ -70,7 +67,10 @@ def create_findings(product_id, user_id, file, scanner, engagement_id=None, max_ if engagement_id == None: start_date = datetime.now() end_date = start_date+timedelta(days=180) - + users = dd.list_users("admin") + user_id = None + if users.success: + user_id = users.data["objects"][0]["id"] engagement_id = dd.create_engagement("Recurring CI/CD Integration", product_id, user_id, "In Progress", start_date.strftime("%Y-%m-%d"), end_date.strftime("%Y-%m-%d")) @@ -107,31 +107,41 @@ def create_findings(product_id, user_id, file, scanner, engagement_id=None, max_ print print"==============================================" - if sum_new_findings[4] > max_critical: - print "Build Failed: Max Critical" - elif sum_new_findings[3] > max_high: - print "Build Failed: Max High" - elif sum_new_findings[2] > max_medium: - print "Build Failed: Max Medium" - else: + strFail = None + if max_critical is not None: + if sum_new_findings[4] > max_critical: + strFail = "Build Failed: Max Critical" + if max_high is not None: + if sum_new_findings[3] > max_high: + strFail = strFail + " Max High" + if max_medium is not None: + if sum_new_findings[2] > max_medium: + strFail = strFail + " Max Medium" + if strFail is None: print "Build Passed!" + else: + print "Build Failed: " + strFail print"==============================================" class Main: if __name__ == "__main__": parser = argparse.ArgumentParser(description='CI/CD integration for DefectDojo') - parser.add_argument('--user', help="Dojo Product ID", required=True) + parser.add_argument('--host', help="Dojo Hostname", required=True) + parser.add_argument('--api_key', help="API Key", required=True) + parser.add_argument('--user', help="User", required=True) parser.add_argument('--product', help="Dojo Product ID", required=True) parser.add_argument('--file', help="Scanner file", required=True) parser.add_argument('--scanner', help="Type of scanner", required=True) parser.add_argument('--engagement', help="Engagement ID (optional)", required=False) - parser.add_argument('--critical', default=0, help="Maximum new critical vulns to pass the build.", required=False) - parser.add_argument('--high', default=0, help="Maximum new high vulns to pass the build.", required=False) - parser.add_argument('--medium', default=0, help="Maximum new medium vulns to pass the build.", required=False) + parser.add_argument('--critical', help="Maximum new critical vulns to pass the build.", required=False) + parser.add_argument('--high', help="Maximum new high vulns to pass the build.", required=False) + parser.add_argument('--medium', help="Maximum new medium vulns to pass the build.", required=False) #Parse out arguments args = vars(parser.parse_args()) - user_id = args["user"] + host = args["host"] + api_key = args["api_key"] + user = args["user"] product_id = args["product"] file = args["file"] scanner = args["scanner"] @@ -140,4 +150,4 @@ class Main: max_high = args["high"] max_medium = args["medium"] - create_findings(product_id, user_id, file, scanner, engagement_id, max_critical, max_high, max_medium) + create_findings(host, api_key, user, product_id, file, scanner, engagement_id, max_critical, max_high, max_medium) -- GitLab