Skip to content

Commit afabf06

Browse files
update with latest files
1 parent 465fdc5 commit afabf06

File tree

5 files changed

+279
-0
lines changed

5 files changed

+279
-0
lines changed

.github/workflows/nightvision.yml

+13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
1+
## SETUP
2+
3+
## Run before activating pipeline
4+
# nightvision app create -n javaspringvulny-api
5+
# nightvision target create -n javaspringvulny-api -u https://127.0.0.1:9000 --type api
6+
# nightvision auth playwright create -n javaspringvulny-api -u https://127.0.0.1:9000
7+
8+
## Optional steps can be preformed locally or in the pipeline
9+
# nightvision swagger extract ./ -t javaspringvulny-api --lang spring
10+
# nightvision scan -t javaspringvulny-api -a javaspringvulny-api
11+
112
name: Test Case - Java Spring App
213

314
on:
415
push:
16+
branches:
17+
- main
518
workflow_dispatch:
619

720
env:

.gitlab-ci.yml

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
stages:
2+
- test
3+
- convert_sarif_to_gitlab
4+
5+
variables:
6+
NIGHTVISION_TARGET: javaspringvulny-api-gitlab
7+
NIGHTVISION_APP: javaspringvulny-api-gitlab
8+
NIGHTVISION_AUTH: javaspringvulny-api-gitlab
9+
DOCKER_HOST: tcp://docker:2375/
10+
DOCKER_DRIVER: overlay2
11+
# activate container-to-container networking
12+
FF_NETWORK_PER_BUILD: "true"
13+
14+
services:
15+
- docker:dind
16+
17+
test:
18+
stage: test
19+
image: ubuntu:latest
20+
services:
21+
- docker:dind
22+
before_script:
23+
- apt-get update && apt-get install -y wget python3-venv python3-docker python3-pip python3 docker-compose curl gcc musl-dev libffi-dev
24+
- python3 -m venv venv
25+
- source venv/bin/activate
26+
- pip3 install requests urllib3 semgrep
27+
- wget -c https://downloads.nightvision.net/binaries/latest/nightvision_latest_linux_amd64.tar.gz -O - | tar -xz
28+
- mv nightvision /usr/local/bin/
29+
script:
30+
# "Extract API documentation from code"
31+
- nightvision swagger extract ./ --lang spring -t ${NIGHTVISION_APP} || true
32+
- if [ ! -e openapi-spec.yml ]; then cp backup-openapi-spec.yml openapi-spec.yml; fi
33+
# "Starting the app"
34+
- docker-compose up -d
35+
- sleep 60
36+
# "Scanning the API"
37+
- nightvision scan -t ${NIGHTVISION_TARGET} -a ${NIGHTVISION_APP} --auth ${NIGHTVISION_AUTH} > scan-results.txt
38+
- nightvision export sarif -s "$(head -n 1 scan-results.txt)" --swagger-file openapi-spec.yml
39+
artifacts:
40+
paths:
41+
- openapi-spec.yml
42+
- results.sarif
43+
expire_in: 30 days
44+
45+
convert_sarif_to_gitlab:
46+
stage: convert_sarif_to_gitlab
47+
image: python:3.9
48+
script:
49+
- python3 convert_sarif_to_gitlab.py
50+
artifacts:
51+
reports:
52+
sast: gitlab_security_report.json
53+
dependencies:
54+
- test

azure-pipelines.yml

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
## SETUP
2+
3+
## Run before activating pipeline
4+
# nightvision app create -n javaspringvulny-api
5+
# nightvision target create -n javaspringvulny-api -u https://127.0.0.1:9000 --type api
6+
# nightvision auth playwright create -n javaspringvulny-api -u https://127.0.0.1:9000
7+
8+
## Optional steps can be preformed locally or in the pipeline
9+
# nightvision swagger extract ./ -t javaspringvulny-api --lang spring
10+
# nightvision scan -t javaspringvulny-api -a javaspringvulny-api
11+
12+
trigger:
13+
- main
14+
15+
pool:
16+
vmImage: 'ubuntu-latest'
17+
18+
stages:
19+
- stage: Test
20+
jobs:
21+
- job: BuildAndTest
22+
steps:
23+
- checkout: self
24+
displayName: 'Clone Code'
25+
26+
- script: |
27+
wget -c https://downloads.nightvision.net/binaries/latest/nightvision_latest_linux_amd64.tar.gz -O - | tar -xz
28+
sudo mv nightvision /usr/local/bin/
29+
python -m pip install semgrep --user
30+
displayName: 'Install NightVision'
31+
32+
- script: |
33+
nightvision swagger extract ./ -t $NIGHTVISION_TARGET --lang spring || true
34+
if [ ! -e openapi-spec.yml ]; then
35+
cp backup-openapi-spec.yml openapi-spec.yml
36+
fi
37+
displayName: 'Extract API Documentation from Code'
38+
env:
39+
NIGHTVISION_TOKEN: $(NIGHTVISION_TOKEN)
40+
NIGHTVISION_TARGET: javaspringvulny-api
41+
42+
- script: |
43+
docker-compose up -d
44+
sleep 20
45+
curl -k https://localhost:9000
46+
displayName: 'Start the App'
47+
48+
- script: |
49+
nightvision scan -t $NIGHTVISION_TARGET -a $NIGHTVISION_APP --auth $NIGHTVISION_AUTH > scan-results.txt
50+
nightvision export sarif -s "$(head -n 1 scan-results.txt)" --swagger-file openapi-spec.yml
51+
displayName: 'Scan the API'
52+
env:
53+
NIGHTVISION_TOKEN: $(NIGHTVISION_TOKEN)
54+
NIGHTVISION_TARGET: javaspringvulny-api
55+
NIGHTVISION_APP: javaspringvulny-api
56+
NIGHTVISION_AUTH: javaspringvulny-api
57+
58+
# Convert SARIF to Azure DevOps logging commands
59+
- script: |
60+
wget -O sarif_to_azure_devops.py https://gist.githubusercontent.com/alex-nightvision/d2b0813e051d98f623ec8ad3d20df2e8/raw/b6b4d69188c9aa94f0c3993296ba25de553e986d/sarif_to_azure_devops.py
61+
python sarif_to_azure_devops.py
62+
displayName: 'Convert SARIF to Azure DevOps Logging Commands'
63+
env:
64+
PYTHONUNBUFFERED: 1
65+
66+
# Download and prepare nightvision_azure_importer script
67+
- script: |
68+
wget -O nightvision_azure_importer.py https://raw.githubusercontent.com/jxbt/nightvision_azure_importer/main/nightvision_azure_importer.py
69+
wget -O nightvision_azure_importer_requirements.txt https://raw.githubusercontent.com/jxbt/nightvision_azure_importer/main/requirements.txt
70+
sudo apt-get update
71+
sudo apt-get install -y python3-pip
72+
python3 -m pip install -r nightvision_azure_importer_requirements.txt
73+
displayName: 'Prepare Python Script and Dependencies'
74+
75+
# Execute the Python script to import SARIF into Azure DevOps work items
76+
- script: |
77+
python3 nightvision_azure_importer.py --organization $organization --project $project --patoken $pa_token --sarif results.sarif
78+
displayName: 'Import SARIF to Azure DevOps'
79+
env:
80+
organization: "nightvision1"
81+
project: "java-test"
82+
pa_token: $(PERSONAL_ACCESS_TOKEN)
83+

convert_sarif_to_gitlab.py

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import json
2+
from datetime import datetime
3+
4+
5+
def sarif_to_gitlab(sarif_file, output_file):
6+
# Load SARIF data
7+
with open(sarif_file, 'r') as file:
8+
sarif_data = json.load(file)
9+
10+
# Initialize GitLab report structure
11+
gitlab_report = {
12+
"version": "15.0.0",
13+
"vulnerabilities": [],
14+
"remediations": [],
15+
"scan": {
16+
"scanner": {
17+
"id": "custom_sarif_import",
18+
"name": "Custom SARIF Importer",
19+
"version": "1.0",
20+
"vendor": {
21+
"name": "Custom Vendor" # Updated to be an object
22+
}
23+
},
24+
"analyzer": {
25+
"name": "Custom Analyzer",
26+
"version": "1.0",
27+
"id": "custom_analyzer", # Example ID, adjust as needed
28+
"vendor": {
29+
"name": "Custom Analyzer Vendor" # Example vendor, adjust as needed
30+
}
31+
},
32+
"start_time": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
33+
"end_time": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
34+
"status": "success",
35+
"type": "sast"
36+
}
37+
}
38+
39+
# Map SARIF data to GitLab format
40+
for run in sarif_data.get("runs", []):
41+
for result in run.get("results", []):
42+
vulnerability = {
43+
"id": result.get("ruleId"),
44+
"category": "sast",
45+
"name": result.get("message", {}).get("text"),
46+
"message": result.get("message", {}).get("text"),
47+
"description": result.get("message", {}).get("text"),
48+
"severity": map_severity(result.get("properties", {}).get("nightvision-risk")), # Mapping function to ensure correct severity
49+
"confidence": result.get("properties", {}).get("nightvision-confidence"),
50+
"solution": "Please refer to the rule documentation.",
51+
"scanner": gitlab_report["scan"]["scanner"],
52+
"identifiers": [{"type": "cve", "name": result.get("ruleId"), "value": result.get("ruleId")}],
53+
"location": {
54+
"file": result.get("locations", [{}])[0].get("physicalLocation", {}).get("artifactLocation", {}).get("uri"),
55+
}
56+
}
57+
# Conditionally add start and end lines if they are numbers
58+
if isinstance(result.get("locations", [{}])[0].get("physicalLocation", {}).get("region", {}).get("startLine"), int):
59+
vulnerability["location"]["start_line"] = result.get("locations", [{}])[0].get("physicalLocation", {}).get("region", {}).get("startLine")
60+
if isinstance(result.get("locations", [{}])[0].get("physicalLocation", {}).get("region", {}).get("endLine"), int):
61+
vulnerability["location"]["end_line"] = result.get("locations", [{}])[0].get("physicalLocation", {}).get("region", {}).get("endLine")
62+
63+
gitlab_report["vulnerabilities"].append(vulnerability)
64+
65+
# Write GitLab report to file
66+
with open(output_file, 'w') as file:
67+
json.dump(gitlab_report, file, indent=4)
68+
69+
def map_severity(sarif_severity):
70+
"""Map SARIF severity to GitLab severity levels."""
71+
severity_mapping = {
72+
"CRITICAL": "Critical",
73+
"HIGH": "High",
74+
"MEDIUM": "Medium",
75+
"LOW": "Low",
76+
"INFO": "Info",
77+
}
78+
return severity_mapping.get(sarif_severity, "Unknown")
79+
80+
# Example usage
81+
sarif_to_gitlab('results.sarif', 'gitlab_security_report.json')

sarif_to_azure_devops.py

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import json, os
2+
3+
def parse_sarif(sarif_file):
4+
"""Parse the SARIF file and return findings."""
5+
with open(sarif_file, 'r') as file:
6+
sarif_data = json.load(file)
7+
8+
findings = []
9+
for run in sarif_data.get('runs', []):
10+
for result in run.get('results', []):
11+
finding = {
12+
'rule_id': result.get('ruleId'),
13+
'message': result.get('message', {}).get('text'),
14+
'severity': result.get('level'),
15+
'location': result.get('locations', [{}])[0].get('physicalLocation', {}).get('artifactLocation', {}).get('uri'),
16+
'line': result.get('locations', [{}])[0].get('physicalLocation', {}).get('region', {}).get('startLine', 0),
17+
}
18+
findings.append(finding)
19+
return findings
20+
21+
def convert_findings_to_azure_devops_commands(findings, repo_url):
22+
"""Convert findings to Azure DevOps logging commands with clickable links."""
23+
for finding in findings:
24+
# Customize the logging command based on your needs. This example logs a warning.
25+
severity = 'warning' if finding['severity'] == 'warning' else 'error'
26+
27+
# Construct the URL to the file and line in your repository
28+
# This example URL format is for GitHub. Adjust it according to your repo's hosting service.
29+
file_path = finding['location'].replace('\\', '/')
30+
line_number = finding['line']
31+
# Ensure your repo_url does not end with a slash
32+
file_url = f"{repo_url}?path=/{file_path}&version=GBmain&line={line_number+1}&lineEnd={line_number+2}&lineStartColumn=1&lineEndColumn=1&lineStyle=plain&_a=contents"
33+
34+
# Embed the URL in the message
35+
message = f"{finding['rule_id']}: {finding['message']} at {finding['location']}:{finding['line']} | {file_url}"
36+
37+
print(f"##vso[task.logissue type={severity}]{message}")
38+
39+
40+
if __name__ == "__main__":
41+
sarif_file_path = 'results.sarif' # Update this to your SARIF file path
42+
findings = parse_sarif(sarif_file_path)
43+
# Retrieve the repository URL from the Azure DevOps environment variable
44+
repo_url = os.getenv('BUILD_REPOSITORY_URI', 'https://dev.azure.com/nightvision1/_git/java-test')
45+
if "@" in repo_url:
46+
repo_url = "https://" + repo_url.split("@")[1]
47+
48+
convert_findings_to_azure_devops_commands(findings, repo_url)

0 commit comments

Comments
 (0)