Skip to content

Checkmarx SAST Integration

Introduction

This guide walks you through integrating Checkmarx Static Application Security Testing (SAST) scans with AccuKnox using a CI/CD pipeline workflow. The scan results, formatted in SARIF, will be enriched with metadata and code snippets and then integrated with AccuKnox for further analysis.

Pre-requisites

  • GitHub repository with the appropriate permissions.

  • Checkmarx AST API credentials (Client ID, Client Secret, Tenant ID).

  • AccuKnox CSPM credentials (Tenant ID, CSPM URL, Token).

Step 1: Obtain Checkmarx and AccuKnox Credentials

Getting Checkmarx Credentials

  1. Login to the Checkmarx AST Platform.

  2. Navigate to the API Access Management section.

  3. Create a new API client, and note the Client ID, Client Secret, and Tenant ID.

image-20241018-052333.png

image-20241018-051743.png

image-20241018-051851.png

image-20241018-051951.png

image-20241018-052143.png

Getting AccuKnox Credentials

1. Generate the AccuKnox token

The first step is to generate an AccuKnox token. For generating the AccuKnox token, open up the AccuKnox, Go to Settings > Tokens then click on the create button.

image-20241017-062538.png

Give your token a name and click on the Generate button.

image-20241017-062723.png

Once you have generated the the token, click on the copy button and take a note of it. It will be required to configured as a variable in the pipeline. Also copy the Tenant Id and take a note of it.

image-20241017-062925.png

2. Create a label

In AccuKnox, labels are used for grouping the similar types of assets together. For creating a label navigate to the Settings > Labels and click on the create label button.

image-20241017-063446.png

Give your label a name and a filename prefix. Take a note of the label and click on the save button.

Step 2: Configure GitHub Workflow

In your GitHub repository, create a workflow file (e.g., .github/workflows/checkmarx-accuknox.yml) with the following content:

name: Checkmarx Sarif Integration
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: '18 2 * * 5'
permissions:
security-events: write
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Checkmarx scan
uses: checkmarx/ast-github-action@main
with:
base_uri: <https://deu.iam.checkmarx.net/>
cx_client_id: ${{ secrets.CX_CLIENT_ID }}
cx_client_secret: ${{ secrets.CX_CLIENT_SECRET }}
cx_tenant: ${{ secrets.CX_TENANT }}
additional_params: --report-format sarif --output-path .
- name: Fix SARIF file levels
run: |
jq 'walk(if type == "object" and has("level") then .level |= (if . == "none" or . == "note" or . == "warning" or . == "error" then . else "note" end) else . end)' cx_result.sarif > tmp.sarif && mv tmp.sarif cx_result.sarif
- name: Append GitHub metadata to SARIF
env:
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_SHA: ${{ github.sha }}
GITHUB_REF: ${{ github.ref }}
GITHUB_RUN_ID: ${{ github.run_id }}
GITHUB_RUN_NUMBER: ${{ github.run_number }}
SOURCE: "GitHub"
run: |
GITHUB_URL="${{ github.server_url }}/${{ github.repository }}"
GITHUB_RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
jq --arg repo "$GITHUB_REPOSITORY" \
--arg sha "$GITHUB_SHA" \
--arg ref "$GITHUB_REF" \
--arg run_id "$GITHUB_RUN_ID" \
--arg run_number "$GITHUB_RUN_NUMBER" \
--arg github_url "$GITHUB_URL" \
--arg github_run_url "$GITHUB_RUN_URL" \
--arg source "$SOURCE" \
'.runs[0].invocations += [{
"executionSuccessful": true,
"toolExecutionNotifications": [],
"toolConfigurationNotifications": [],
"properties": {
"repository": $repo,
"commit": $sha,
"ref": $ref,
"workflow_run_id": $run_id,
"workflow_run_number": $run_number,
"repository_url": $github_url,
"workflow_run_url": $github_run_url,
"source": $source
}
}]' cx_result.sarif > tmp.sarif && mv tmp.sarif cx_result.sarif
- name: Extract and Embed Code Snippets in SARIF using Python
id: embed_snippets
run: |
python3 <<EOF
import os
import json
def get_code_snippet(lines, start_line, start_column, end_column):
start_line = max(start_line - 3, 0) # Start from 3 lines before or 0
end_line = min(start_line + 5, len(lines)) # End 2 lines after the snippet
snippet_lines = lines[start_line:end_line]
highlighted_snippet = []
for i, line in enumerate(snippet_lines):
line_number = start_line + i + 1 # Correct line number offset
if line_number == start_line: # Highlight the start line
highlighted_snippet.append(
line[:start_column - 1] +
"<<<HIGHLIGHT>>>" +
line[start_column - 1:end_column] +
"<<<END_HIGHLIGHT>>>" +
line[end_column:]
)
else:
highlighted_snippet.append(line)
snippet_with_comments = "// Start of snippet\n"
snippet_with_comments += "".join(highlighted_snippet)
snippet_with_comments += "// End of snippet\n"
return snippet_with_comments
def process_sarif_file(sarif_path):
with open(sarif_path, "r") as sarif_file:
sarif_data = json.load(sarif_file)
for run in sarif_data.get("runs", []):
for result in run.get("results", []):
for location in result.get("locations", []):
physical_location = location.get("physicalLocation", {})
artifact_location = physical_location.get("artifactLocation", {})
region = physical_location.get("region", {})
uri = artifact_location.get("uri")
start_line = region.get("startLine")
start_column = region.get("startColumn")
end_column = region.get("endColumn")
if uri and start_line and start_column and end_column:
file_path = os.path.join(".", uri.lstrip("./"))
try:
with open(file_path, "r") as source_file:
lines = source_file.readlines()
snippet_with_comments = get_code_snippet(
lines, start_line, start_column, end_column
)
region["snippet"] = {
"text": snippet_with_comments
}
except FileNotFoundError:
print(f"Failed to process file {file_path}: File not found.")
except Exception as e:
print(f"Failed to process file {file_path}: {e}")
with open("tmp_sarif_with_snippets.sarif", "w") as output_file:
json.dump(sarif_data, output_file, indent=2)
process_sarif_file("cx_result.sarif")
EOF
- name: Upload SARIF file with code snippets
uses: actions/upload-artifact@v3
with:
name: sarif-results-with-snippets
path: tmp_sarif_with_snippets.sarif
- name: Push SARIF file to AccuKnox
run: |
curl --location '${{ secrets.CSPM_URL }}/api/v1/artifact/?tenant_id=${{ secrets.TENANT_ID }}&data_type=CMX&save_to_s3=true&label_id=${{ secrets.LABEL_ID }}' \
--header 'Tenant-Id: ${{ secrets.TENANT_ID }}' \
--header 'Authorization: Bearer ${{ secrets.CSPM_TOKEN }}' \
--form 'file=@./tmp_sarif_with_snippets.sarif'

Step 3: Set Up GitHub Secrets

Ensure the following secrets are configured in your GitHub repository under Settings > Secrets and Variables:

  • CX_CLIENT_ID: Checkmarx Client ID

  • CX_CLIENT_SECRET: Checkmarx Client Secret

  • CX_TENANT: Checkmarx Tenant ID

  • CSPM_URL: AccuKnox CSPM URL

  • TENANT_ID: AccuKnox Tenant ID

  • LABEL_ID: AccuKnox Label ID

  • CSPM_TOKEN: AccuKnox CSPM API Token

image-20241018-045550.png

Step 4: Running the Workflow

  1. Push changes to the repository's master branch or open a pull request.

  2. The Checkmarx scan runs, generating a SARIF file.

  3. The workflow enriches the SARIF file with metadata and code snippets, then uploads it to AccuKnox for analysis.

Step 5: View findings in AccuKnox

To see your findings navigate to AccuKnox > Issues > Findings and select the CX SAST findings.

image-20241018-051139.png

Click on any finding to get more details. You can also click on the Create Ticket button to create a ticket.

image-20241018-051326.png

Conclusion

By following this guide, you've successfully integrated Checkmarx SAST scans into your CI/CD pipeline and connected them with AccuKnox for further insights. You can now analyze and prioritize vulnerabilities within the AccuKnox dashboard

Was this page helpful?