mirror of
https://github.com/morten-olsen/homelab-operator.git
synced 2026-02-08 01:36:28 +01:00
remove argo
This commit is contained in:
3
security/trivy-report/.gitignore
vendored
Normal file
3
security/trivy-report/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/security_report.pdf
|
||||
/transformed_data.json
|
||||
/all_data.json
|
||||
0
security/trivy-report/README.md
Normal file
0
security/trivy-report/README.md
Normal file
24
security/trivy-report/fetch-data.sh
Executable file
24
security/trivy-report/fetch-data.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Data Extraction Function
|
||||
extract_data() {
|
||||
crd_type="$1"
|
||||
|
||||
kubectl get "$crd_type" -A -o json | jq -r '.items[] | {
|
||||
namespace: .metadata.namespace,
|
||||
name: .metadata.name,
|
||||
report: .report
|
||||
}'
|
||||
}
|
||||
|
||||
# Vulnerability Reports
|
||||
vulnerability_data=$(extract_data vulnerabilityreports)
|
||||
|
||||
# Example of capturing ConfigAuditReports (adjust jq filter as needed)
|
||||
config_audit_data=$(extract_data configauditreports)
|
||||
|
||||
# Combine the data into a proper JSON array using jq
|
||||
{
|
||||
echo "$vulnerability_data"
|
||||
echo "$config_audit_data"
|
||||
} | jq -s '.' > all_data.json
|
||||
82
security/trivy-report/generate_report.py
Normal file
82
security/trivy-report/generate_report.py
Normal file
@@ -0,0 +1,82 @@
|
||||
import json
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
import weasyprint
|
||||
|
||||
|
||||
def generate_pdf_report(transformed_data, template_file, output_file):
|
||||
"""Generates a PDF report from the transformed data and Jinja2 template."""
|
||||
|
||||
env = Environment(
|
||||
loader=FileSystemLoader(".")
|
||||
) # Load templates from the current directory
|
||||
template = env.get_template(template_file)
|
||||
html_output = template.render(transformed_data) # Render the template with the data
|
||||
|
||||
# Generate PDF using WeasyPrint
|
||||
weasyprint.HTML(string=html_output).write_pdf(output_file)
|
||||
|
||||
|
||||
# Load the already transformed JSON data
|
||||
with open("transformed_data.json", "r") as f:
|
||||
raw_data = json.load(f)
|
||||
|
||||
# Sort by severity (CRITICAL, HIGH, MEDIUM, LOW)
|
||||
severity_order = {"CRITICAL": 0, "HIGH": 1, "MEDIUM": 2, "LOW": 3}
|
||||
|
||||
# Group vulnerabilities by CVE ID
|
||||
vuln_groups = {}
|
||||
for vuln in raw_data["vulnerabilities"]:
|
||||
cve_id = vuln["vulnerabilityID"]
|
||||
if cve_id not in vuln_groups:
|
||||
vuln_groups[cve_id] = {
|
||||
"vulnerabilityID": vuln["vulnerabilityID"],
|
||||
"severity": vuln["severity"],
|
||||
"title": vuln["title"],
|
||||
"packagePURL": vuln.get("packagePURL"),
|
||||
"installedVersion": vuln.get("installedVersion"),
|
||||
"fixedVersion": vuln.get("fixedVersion"),
|
||||
"affected_resources": [],
|
||||
}
|
||||
|
||||
vuln_groups[cve_id]["affected_resources"].append(
|
||||
{"namespace": vuln["namespace"], "resource": vuln["resource"]}
|
||||
)
|
||||
|
||||
# Convert to list and sort by severity
|
||||
grouped_vulnerabilities = sorted(
|
||||
list(vuln_groups.values()), key=lambda x: severity_order.get(x["severity"], 4)
|
||||
)
|
||||
|
||||
# Group config issues by checkID
|
||||
config_groups = {}
|
||||
for issue in raw_data["config_issues"]:
|
||||
check_id = issue["checkID"]
|
||||
if check_id not in config_groups:
|
||||
config_groups[check_id] = {
|
||||
"checkID": issue["checkID"],
|
||||
"severity": issue["severity"],
|
||||
"title": issue["title"],
|
||||
"description": issue["description"],
|
||||
"remediation": issue["remediation"],
|
||||
"affected_resources": [],
|
||||
}
|
||||
|
||||
config_groups[check_id]["affected_resources"].append(
|
||||
{"namespace": issue["namespace"], "resource": issue["resource"]}
|
||||
)
|
||||
|
||||
# Convert to list and sort by severity
|
||||
grouped_config_issues = sorted(
|
||||
list(config_groups.values()), key=lambda x: severity_order.get(x["severity"], 4)
|
||||
)
|
||||
|
||||
transformed_data = {
|
||||
"vulnerabilities": grouped_vulnerabilities,
|
||||
"config_issues": grouped_config_issues,
|
||||
}
|
||||
|
||||
|
||||
# Generate the PDF report
|
||||
generate_pdf_report(transformed_data, "report_template.html", "security_report.pdf")
|
||||
|
||||
print("PDF report generated successfully: security_report.pdf")
|
||||
6
security/trivy-report/main.py
Normal file
6
security/trivy-report/main.py
Normal file
@@ -0,0 +1,6 @@
|
||||
def main():
|
||||
print("Hello from trivy-report!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
10
security/trivy-report/pyproject.toml
Normal file
10
security/trivy-report/pyproject.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[project]
|
||||
name = "trivy-report"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"jinja2>=3.1.6",
|
||||
"weasyprint>=66.0",
|
||||
]
|
||||
136
security/trivy-report/report_template.html
Normal file
136
security/trivy-report/report_template.html
Normal file
@@ -0,0 +1,136 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Kubernetes Security Report</title>
|
||||
<style>
|
||||
@page {
|
||||
size: A4;
|
||||
margin: 0.5in;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 10px;
|
||||
line-height: 1.3;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
margin: 15px 0 8px 0;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
font-size: 8px;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #ccc;
|
||||
padding: 4px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
word-wrap: break-word;
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #f5f5f5;
|
||||
font-weight: bold;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.severity-critical { background-color: #ffebee; color: #c62828; font-weight: bold; }
|
||||
.severity-high { background-color: #fff3e0; color: #ef6c00; font-weight: bold; }
|
||||
.severity-medium { background-color: #fff8e1; color: #f57f17; }
|
||||
.severity-low { background-color: #f3e5f5; color: #7b1fa2; }
|
||||
|
||||
.resource-col { max-width: 120px; }
|
||||
.vuln-id-col { max-width: 80px; }
|
||||
.severity-col { max-width: 60px; text-align: center; }
|
||||
.namespace-col { max-width: 80px; }
|
||||
.description-col { max-width: 200px; font-size: 7px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Kubernetes Security Report</h1>
|
||||
|
||||
<h2>Vulnerabilities ({{ vulnerabilities|length }})</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="vuln-id-col">CVE ID</th>
|
||||
<th class="severity-col">Severity</th>
|
||||
<th style="max-width: 180px;">Title</th>
|
||||
<th style="max-width: 100px;">Package</th>
|
||||
<th style="max-width: 60px;">Count</th>
|
||||
<th style="max-width: 250px;">Affected Resources</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for vuln in vulnerabilities %}
|
||||
<tr>
|
||||
<td class="vuln-id-col">{{ vuln.vulnerabilityID }}</td>
|
||||
<td class="severity-col severity-{{ vuln.severity|lower }}">{{ vuln.severity }}</td>
|
||||
<td style="max-width: 180px;">{{ vuln.title }}</td>
|
||||
<td style="max-width: 100px;">{{ vuln.packagePURL or 'N/A' }}</td>
|
||||
<td style="max-width: 60px; text-align: center;">{{ vuln.affected_resources|length }}</td>
|
||||
<td style="max-width: 250px; font-size: 7px;">
|
||||
{% for resource in vuln.affected_resources[:10] %}
|
||||
{{ resource.namespace }}/{{ resource.resource }}{% if not loop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{% if vuln.affected_resources|length > 10 %}
|
||||
<br/><em>... and {{ vuln.affected_resources|length - 10 }} more</em>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>Configuration Issues ({{ config_issues|length }})</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="vuln-id-col">Check ID</th>
|
||||
<th class="severity-col">Severity</th>
|
||||
<th style="max-width: 180px;">Title</th>
|
||||
<th style="max-width: 200px;">Remediation</th>
|
||||
<th style="max-width: 60px;">Count</th>
|
||||
<th style="max-width: 200px;">Affected Resources</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for issue in config_issues %}
|
||||
<tr>
|
||||
<td class="vuln-id-col">{{ issue.checkID }}</td>
|
||||
<td class="severity-col severity-{{ issue.severity|lower }}">{{ issue.severity }}</td>
|
||||
<td style="max-width: 180px;">{{ issue.title }}</td>
|
||||
<td style="max-width: 200px; font-size: 7px;">{{ issue.remediation }}</td>
|
||||
<td style="max-width: 60px; text-align: center;">{{ issue.affected_resources|length }}</td>
|
||||
<td style="max-width: 200px; font-size: 7px;">
|
||||
{% for resource in issue.affected_resources[:8] %}
|
||||
{{ resource.namespace }}/{{ resource.resource }}{% if not loop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{% if issue.affected_resources|length > 8 %}
|
||||
<br/><em>... and {{ issue.affected_resources|length - 8 }} more</em>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
56
security/trivy-report/transform.py
Normal file
56
security/trivy-report/transform.py
Normal file
@@ -0,0 +1,56 @@
|
||||
import json
|
||||
|
||||
|
||||
def transform_data(json_data):
|
||||
"""Transforms the raw JSON data into a structured format for reporting."""
|
||||
reports = json.loads(json_data)
|
||||
all_vulnerabilities = []
|
||||
all_config_audit_issues = []
|
||||
|
||||
for report in reports:
|
||||
if "vulnerabilities" in report["report"]:
|
||||
for vuln in report["report"]["vulnerabilities"]:
|
||||
all_vulnerabilities.append(
|
||||
{
|
||||
"namespace": report["namespace"],
|
||||
"resource": report["name"],
|
||||
"vulnerabilityID": vuln["vulnerabilityID"],
|
||||
"severity": vuln["severity"],
|
||||
"title": vuln["title"],
|
||||
"packagePURL": vuln.get("packagePURL"),
|
||||
"installedVersion": vuln.get("installedVersion"),
|
||||
"fixedVersion": vuln.get("fixedVersion"),
|
||||
}
|
||||
)
|
||||
elif "checks" in report["report"]: # ConfigAuditReports have "checks"
|
||||
for check in report["report"]["checks"]:
|
||||
all_config_audit_issues.append(
|
||||
{
|
||||
"namespace": report["namespace"],
|
||||
"resource": report["name"],
|
||||
"checkID": check["checkID"],
|
||||
"severity": check["severity"],
|
||||
"title": check["title"],
|
||||
"description": check["description"],
|
||||
"remediation": check["remediation"],
|
||||
"success": check["success"],
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
"vulnerabilities": all_vulnerabilities,
|
||||
"config_issues": all_config_audit_issues,
|
||||
}
|
||||
|
||||
|
||||
# Load the JSON data
|
||||
with open("all_data.json", "r") as f:
|
||||
raw_data = f.read()
|
||||
|
||||
transformed_data = transform_data(raw_data)
|
||||
|
||||
# Print the transformed data (for verification)
|
||||
print(json.dumps(transformed_data, indent=2)) # print for check
|
||||
# Save it for the next step:
|
||||
with open("transformed_data.json", "w") as f:
|
||||
json.dump(transformed_data, f, indent=2)
|
||||
Reference in New Issue
Block a user