Skip to content
This repository was archived by the owner on Jan 24, 2025. It is now read-only.

Commit dc849ef

Browse files
authored
Update pkg_vuln.py
1 parent 7b56a56 commit dc849ef

File tree

1 file changed

+105
-39
lines changed

1 file changed

+105
-39
lines changed

entrypoint/entrypoint/pkg_vuln.py

+105-39
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,123 @@
11
import json
22
import logging
3+
import requests
34
from typing import List
45

56
class Vulnerability:
7+
"""
8+
Vulnerability is an object for marshalling vulnerability findings
9+
from Inspector's JSON into a Python object that can be queried and manipulated.
10+
"""
611
def __init__(self):
7-
"""
8-
Vulnerability is an object for marshalling vulnerability findings
9-
from Inspector's JSON into a Python object that can be queried and manipulated.
10-
"""
1112
self.vuln_id = "null"
1213
self.severity = "null"
13-
self.cvss_score = "null"
1414
self.description = "null"
1515
self.resource_type = "null"
1616
self.resource_id = "null"
1717

18-
def vulns_to_obj(inspector_findings_json) -> List[Vulnerability]:
19-
"""
20-
Parses JSON from Inspector's API and returns a list of vulnerability objects.
21-
"""
22-
vuln_list = []
23-
24-
findings = inspector_findings_json.get("findings", [])
25-
for finding in findings:
26-
vuln_obj = Vulnerability()
27-
vuln_obj.vuln_id = finding.get("arn", "null")
28-
vuln_obj.severity = finding.get("severity", "null")
29-
vuln_obj.cvss_score = finding.get("attributes", {}).get("cvss", "null")
30-
vuln_obj.description = finding.get("description", "null")
31-
vuln_obj.resource_type = finding.get("resource", {}).get("type", "null")
32-
vuln_obj.resource_id = finding.get("resource", {}).get("id", "null")
33-
vuln_list.append(vuln_obj)
34-
35-
return vuln_list
36-
37-
def process_findings_to_json(findings) -> str:
38-
"""
39-
Converts findings to a formatted JSON string.
40-
"""
41-
findings_detail = json.dumps(findings, indent=4)
42-
return findings_detail
18+
def get_json_value(key: str, inspector_scan_json: dict):
19+
value = inspector_scan_json.get(key)
20+
return value
21+
22+
def get_json_value_or_throw_fatal_error(key: str, inspector_scan_json: dict):
23+
value = get_json_value(key, inspector_scan_json)
24+
if not value:
25+
logging.fatal(f"expected JSON with key '{key}' but it was not found")
26+
return value
27+
28+
def get_inspector_scan_body(inspector_scan_json):
29+
scan_json = json.loads(inspector_scan_json)
30+
scan_body = get_json_value("findings", scan_json)
31+
if not scan_body:
32+
logging.fatal("expected JSON with key 'findings' but none was found")
33+
return scan_body
34+
35+
def parse_vulns(inspector_scan_json: str) -> List[Vulnerability]:
36+
scan_body = get_inspector_scan_body(inspector_scan_json)
37+
vulnerabilities = []
38+
39+
for finding in scan_body:
40+
vuln = Vulnerability()
41+
vuln.vuln_id = finding.get("arn", "null")
42+
vuln.severity = finding.get("severity", "null")
43+
vuln.description = finding.get("description", "null")
44+
vuln.resource_type = finding.get("resource", {}).get("type", "null")
45+
vuln.resource_id = finding.get("resource", {}).get("id", "null")
46+
vulnerabilities.append(vuln)
47+
48+
return vulnerabilities
4349

44-
def set_github_actions_output(name: str, value: str):
50+
def generate_csv_report(vulnerabilities: List[Vulnerability]) -> str:
51+
csv_output = "ID,SEVERITY,DESCRIPTION,RESOURCE_TYPE,RESOURCE_ID\n"
52+
53+
for vuln in vulnerabilities:
54+
clean_description = vuln.description.replace(',', '')
55+
csv_row = f"{vuln.vuln_id},{vuln.severity},{clean_description},{vuln.resource_type},{vuln.resource_id}\n"
56+
csv_output += csv_row
57+
58+
return csv_output
59+
60+
def write_csv_report(inspector_scan_path: str, dst_file: str) -> bool:
61+
with open(inspector_scan_path, 'r') as file:
62+
inspector_scan_json = file.read()
63+
64+
vulnerabilities = parse_vulns(inspector_scan_json)
65+
if not vulnerabilities:
66+
logging.info("No vulnerabilities found, skipping CSV report")
67+
return False
68+
69+
csv_output = generate_csv_report(vulnerabilities)
70+
logging.info(f"Writing vulnerability CSV report to: {dst_file}")
71+
with open(dst_file, "w") as file:
72+
file.write(csv_output)
73+
74+
return True
75+
76+
def create_jira_ticket(jira_url, jira_username, jira_api_token, jira_project_key, vulnerability):
4577
"""
46-
Sets the GitHub Actions output.
78+
Creates a Jira ticket for a given vulnerability.
79+
:param jira_url: Jira URL
80+
:param jira_username: Jira Username
81+
:param jira_api_token: Jira API Token
82+
:param jira_project_key: Jira Project Key
83+
:param vulnerability: Vulnerability object
84+
:return: Response from Jira API
4785
"""
48-
logging.info(f"Setting GitHub Actions output - {name}: {value}")
49-
print(f"::set-output name={name}::{value}")
86+
url = f"{jira_url}/rest/api/2/issue"
87+
headers = {
88+
"Content-Type": "application/json"
89+
}
90+
auth = (jira_username, jira_api_token)
91+
payload = {
92+
"fields": {
93+
"project": {
94+
"key": jira_project_key
95+
},
96+
"summary": f"Vulnerability: {vulnerability.vuln_id} - {vulnerability.severity}",
97+
"description": f"{vulnerability.description}\n\nResource Type: {vulnerability.resource_type}\nResource ID: {vulnerability.resource_id}",
98+
"issuetype": {
99+
"name": "Bug"
100+
}
101+
}
102+
}
103+
104+
response = requests.post(url, headers=headers, auth=auth, json=payload)
105+
106+
if response.status_code == 201:
107+
logging.info(f"Successfully created Jira ticket for vulnerability {vulnerability.vuln_id}")
108+
else:
109+
logging.error(f"Failed to create Jira ticket for vulnerability {vulnerability.vuln_id}: {response.text}")
110+
111+
return response
50112

51-
def fatal_assert(expr: bool, msg: str):
113+
def create_jira_tickets(jira_url, jira_username, jira_api_token, jira_project_key, vulnerabilities: List[Vulnerability]):
52114
"""
53-
Asserts a condition and logs an error message if the condition is not met.
115+
Creates Jira tickets for a list of vulnerabilities.
116+
:param jira_url: Jira URL
117+
:param jira_username: Jira Username
118+
:param jira_api_token: Jira API Token
119+
:param jira_project_key: Jira Project Key
120+
:param vulnerabilities: List of Vulnerability objects
54121
"""
55-
if not expr:
56-
logging.error(msg)
57-
exit(1)
122+
for vulnerability in vulnerabilities:
123+
create_jira_ticket(jira_url, jira_username, jira_api_token, jira_project_key, vulnerability)

0 commit comments

Comments
 (0)