DevSecOps with DefectDojo

The Early Bird

Integration with Atlassian Jira

DefectDojo thrives on integration. The Atlassian Jira [2] tool is used in many companies and can be integrated easily. Connections are possible in both directions: You can import Jira elements and return the changes to Jira. To integrate, you first need to define a webhook in Jira:

1. First open the https://<Jita-URL>/plugins/servlet/webhooks page in your browser.

2. Click Create a webhook .

3. Enter the value in the URL field: https://<DefectDojo Domain>/jira/webhook/<Webhook Secret> . You will find the value under Configuration | System Settings in DefectDojo.

4. Below Comments, enable Created and choose the Updated setting for Issues.

Next, go to the System Settings menu in DefectDojo and click Enable Jira integration and Submit . Finally, select Enable JIRA webhook and press Submit again. You just need the granular configuration now:

1. Click JIRA in the menu on the left.

2. Select Add Configuration from the selection list.

3. Enter a username and a password. If you use JIRA Cloud, you will need the email address and an API token, as well.

4. Open https://<Jira-URL>/rest/api/latest/issue/<any-valid issue key>/transitions?expand=transitions.fields- .

5. Enter open status key as the Todo id.

6. Enter closed status key as the Done id.

7. For admin access to Jira, open https://<Jira-URL>/secure/admin/ViewCustomFields.jspa ; click next to Epic Name and then on View . You will then see the numerical value for the epic name id in the URL.

Working with the API

If your system is not integrated, you can work with the API. Typical use cases include automated uploading of reports from continuous integration and continuous delivery (CI/CD) pipelines (see the "Uploading from GitLab CI" box). To access the documentation, click on the user avatar in the top right-hand corner of the GUI.

Uploading from GitLab CI

In many organizations, security tools are integrated into CI/CD pipelines. For this reason, it makes sense to publish findings directly in DefectDojo, as shown with Hadolint [3] in this example. As a rule, you will always define the configuration settings in a CI script at the outset:

DEFECTDOJO_DIR: "."
DEFECTDOJO_HADOLINT_REPORTS: "hadolint-json-*.json reports/docker-hadolint-*.native.json"
DEFECTDOJO_BASE_IMAGE: "registry.hub.docker.com/library/node:alpine3.11"
DEFECTDOJO_NOTIFICATION_SEVERITIES: "Critical,High"
DEFECTDOJO_TIMEZONE: "Europe/Paris"
# default production ref name (pattern)
PROD_REF: '/^(master|main)$/'
DEFECTDOJO_NOPROD_ENABLED: "false"

Later in the script, the results from the Hadolint scan are collected:

# Hadolint
     # template: docker
     hadolint_nb_reports=0
     for file in ${DEFECTDOJO_HADOLINT_REPORTS}
     do
          if [[ $(expr "$file" : '.*\*.*') == 0 ]] && [[ -f "$file" ]]; then
               log_info "hadolint report found: $file"
               hadolint_nb_reports=$((hadolint_nb_reports + 1))
               nb_reports=$((nb_reports + 1))
          fi
done

You then send these to the DefectDojo API and write the engagements:

_engname="Engagement ${_today_time} $CI_COMMIT_REF_NAME $CI_COMMIT_SHORT_SHA"_end=${_today}
     branch_tag=$CI_COMMIT_TAG
     branch_tag_info="[${CI_COMMIT_TAG}](${CI_PROJECT_URL}/-/tags/${CI_COMMIT_TAG})"
     # if there is no tag, then use branch
     if [[ -z "$CI_COMMIT_TAG" ]]; then
          branch_tag=$CI_COMMIT_REF_NAME
          branch_tag_info="[${CI_COMMIT_REF_NAME}](${CI_PROJECT_URL}/-/tree/${CI_COMMIT_REF_NAME})"
     fi
     dashboard_template_version=$(get_tpl_version_in_use "to-be-continuous/defectdojo")
     commit_info="[commit ${CI_COMMIT_SHORT_SHA}](${CI_PROJECT_URL}/-/commit/${CI_COMMIT_SHA})\n${branch_tag_info}\ncreated with dashboard-template ${dashboard_template_version}"
     echo "{\"engagement_type\": \"CI/CD\", \"product\": \"${dd_product_pk}\", \"name\": \"${_engname}\", \"source_code_management_uri\": \"${CI_PROJECT_URL}\", \"commit_hash\": \"${CI_COMMIT_SHA}\", \"branch_tag\": \"${branch_tag}\", \"status\": \"In Progress\", \"target_start\": \"${_today}\", \"target_end\": \"${_end}\", \"description\": \"${commit_info}\"}" > api_input.json
     # post request to create engagement
     curl -LX POST -d @api_input.json "${DEFECTDOJO_SERVER_URL}/api/v2/engagements/" --header "Content-Type: application/json" --header "Authorization: Token $DEFECTDOJO_API_KEY" --verbose 1> api_output.txt
     engagement_id=$(jq ".id" api_output.txt)
     echo "engagement_id: $engagement_id"
if [ "$hadolint_nb_reports" -gt 0 ]; then
          docker_tpl_version=$(get_tpl_version_in_use "to-be-continuous/docker")
          log_info "Docker template version: $docker_tpl_version"
          for file in ${DEFECTDOJO_HADOLINT_REPORTS}
          do
               if [[ $(expr "$file" : '.*\*.*') == 0 ]] && [[ -f "$file" ]]; then
                    import_scan "$file" "Hadolint Dockerfile check" "$engagement_id" "to-be-continuous/docker ${docker_tpl_version}"
               fi
          done
     fi
# Close the engagement
     curl -L -X POST "${DEFECTDOJO_SERVER_URL}/api/v2/engagements/$engagement_id/close/" --header "Authorization: Token $DEFECTDOJO_API_KEY" -d ''
     curl -L
     "${DEFECTDOJO_SERVER_URL}/api/v2/findings/?test__engagement__product=${dd_product_pk}&severity=$DEFECTDOJO_NOTIFICATION_SEVERITIES&limit=100&false_p=false&duplicate=false&active=true" --header "Content-Type: application/json" --header "Authorization: Token $DEFECTDOJO_API_KEY" --verbose 1> api_final_findings.json

Swagger definitions are also available. Before you can work with the API, it first needs to authenticate itself. The API uses an authentication header with the format Authorization: Token <api.key> . For example, a header token can look like:

Authorization: Token 80749f64ae120c27e504088d8c2ce29a0fa7f85c

The example code in Listing 2 uses Python to demonstrate how to use the API to retrieve user information. To begin, import the Python Requests API and define the URL. In the header variable, code the authorization token to call the API, and display all the elements in a for loop. The results will then look something like Listing 3. It is not always useful to display all the available elements in the output. Luckily, you can use filters (Listing 4).

Listing 2

Retrieving User Information

01 import requests
02 url = 'http://127.0.0.1:8000/api/v2/users'
03 headers = {'content-type': 'application/json', 'Authorization': 'Token 80749f64ae120c27e504088d8c2ce29a0fa7f85c'}
04 r = requests.get(url, headers=headers, verify=True) # set verify to False if ssl cert is self-signed
05 for key, value in r.__dict__.items():
06       print(f"'{key}': '{value}'")
07       print('------------------')

Listing 3

Return User Info as JSON

01 [
02       {
03            "first_name": "Tyagi",
04            "id": 22,
05            "last_login": "2019-06-18T08:05:51.925743",
06            "last_name": "Paz",
07            "username": "dev7958"
08       },
09       {
10            "first_name": "saurabh",
11            "id": 31,
12            "last_login": "2019-06-06T11:44:32.533035",
13            "username": "saurabh.paz"
14      }
15 ]

Listing 4

Filter with for Loop

01 import requests
02 url = 'http://127.0.0.1:8000/api/v2/users/?username__contains=jay'
03 headers = {'content-type': 'application/json', 'Authorization': 'Token 80749f64ae120c27e504088d8c2ce29a0fa7f85c'}
04 r = requests.get(url, headers=headers, verify=True) # set verify to False if ssl cert is self-signed
05 for key, value in r.__dict__.items():
06       print(f"'{key}': '{value}'")
07       print('------------------')

Conclusions

DefectDojo is a useful tool for centralized vulnerability management. The rich feature set and large number of plugins are major advantages. If required, you can use the API or extend the product. The orchestration options with CI pipelines make it possible to publish vulnerabilities directly (e.g., when building containers). DefectDojo's scalability is also noteworthy and offers good support for large teams.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus