Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🎉 Add Trivy Operator clustercompliance report #11279

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions dojo/tools/trivy_operator/clustercompliance_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from dojo.models import Finding

TRIVY_SEVERITIES = {
"CRITICAL": "Critical",
"HIGH": "High",
"MEDIUM": "Medium",
"LOW": "Low",
"UNKNOWN": "Info",
}


class TrivyClusterComplianceHandler:
def handle_clustercompliance(self, controls, clustercompliance, test):
findings = []
for result in clustercompliance.get("controlCheck"):
if int(result.get("totalFail", 0)) > 0:
description = ""
result_id = result.get("id", "")
vulnerabilityids = []
for control in controls:
if control.get("id") == result_id:
vulnids = control.get("checks", [])
for vulnid in vulnids:
vulnerabilityids.append(vulnid.get("id"))
description += "**description:** " + control.get("description") + "\n"
result_name = result.get("name", "")
result_severity = result.get("severity", "")
result_totalfail = str(result.get("totalFail", ""))
severity = TRIVY_SEVERITIES[result_severity]
description += "**id:** " + result_id + "\n"
description += "**name:** " + result_name + "\n"
description += "**totalfail:** " + result_totalfail + "\n"
title = "TrivyClusterCompliance " + result_id + " totalFail: " + result_totalfail
finding = Finding(
test=test,
title=title,
description=description,
severity=severity,
static_finding=False,
dynamic_finding=True,
)
if vulnerabilityids != []:
finding.unsaved_vulnerability_ids = vulnerabilityids
findings.append(finding)
return findings
17 changes: 11 additions & 6 deletions dojo/tools/trivy_operator/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import json

from dojo.tools.trivy_operator.checks_handler import TrivyChecksHandler
from dojo.tools.trivy_operator.clustercompliance_handler import TrivyClusterComplianceHandler
from dojo.tools.trivy_operator.compliance_handler import TrivyComplianceHandler
from dojo.tools.trivy_operator.secrets_handler import TrivySecretsHandler
from dojo.tools.trivy_operator.vulnerability_handler import TrivyVulnerabilityHandler
Expand Down Expand Up @@ -38,6 +39,7 @@ def get_findings(self, scan_file, test):
return findings

def output_findings(self, data, test):
findings = []
if data is None:
return []
metadata = data.get("metadata", None)
Expand All @@ -47,10 +49,6 @@ def output_findings(self, data, test):
if labels is None:
return []
report = data.get("report", None)
benchmark = data.get("status", None)
if benchmark is not None:
benchmarkreport = benchmark.get("detailReport", None)
findings = []
if report is not None:
vulnerabilities = report.get("vulnerabilities", None)
if vulnerabilities is not None:
Expand All @@ -61,6 +59,13 @@ def output_findings(self, data, test):
secrets = report.get("secrets", None)
if secrets is not None:
findings += TrivySecretsHandler().handle_secrets(labels, secrets, test)
elif benchmarkreport is not None:
findings += TrivyComplianceHandler().handle_compliance(benchmarkreport, test)
status = data.get("status", None)
if status is not None:
benchmarkreport = status.get("detailReport", None)
if benchmarkreport is not None:
findings += TrivyComplianceHandler().handle_compliance(benchmarkreport, test)
clustercompliance = status.get("summaryReport", None)
if clustercompliance is not None:
if int(status.get("summary").get("failCount", 0)) > 0:
findings += TrivyClusterComplianceHandler().handle_clustercompliance(controls=data.get("spec").get("compliance").get("controls"), clustercompliance=clustercompliance, test=test)
return findings
105 changes: 105 additions & 0 deletions unittests/scans/trivy_operator/clustercompliancereport.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
[
{
"apiVersion": "aquasecurity.github.io/v1alpha1",
"kind": "ClusterComplianceReport",
"metadata": {
"annotations": {
"meta.helm.sh/release-name": "trivy-operator-asdf",
"meta.helm.sh/release-namespace": "asdf"
},
"creationTimestamp": "2021-1-1T10:10:10Z",
"generation": 1,
"labels": {
"app.kubernetes.io/instance": "trivy-operator",
"app.kubernetes.io/managed-by": "Helm",
"app.kubernetes.io/name": "trivy-operator",
"app.kubernetes.io/version": "0.17.1"
},
"name": "cis",
"resourceVersion": "asdf",
"uid": "afsewfwefwfw"
},
"spec": {
"compliance": {
"controls": [
{
"checks": [
{
"id": "AVD-KCV-0087"
}
],
"description": "Security relevant information should be captured. The --event-qps flag on the Kubelet can be used to limit the rate at which events are gathered",
"id": "4.2.9",
"name": "Ensure that the --event-qps argument is set to 0 or a level which ensures appropriate event capture",
"severity": "HIGH"
},
{
"checks": [
{
"id": "AVD-KCV-0088"
},
{
"id": "AVD-KCV-0089"
}
],
"description": "Setup TLS connection on the Kubelets",
"id": "4.2.10",
"name": "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate",
"severity": "CRITICAL"
},
{
"checks": [
{
"id": "AVD-KCV-0090"
}
],
"description": "Enable kubelet client certificate rotation",
"id": "4.2.11",
"name": "Ensure that the --rotate-certificates argument is not set to false",
"severity": "CRITICAL"
}
],
"description": "CIS Kubernetes Benchmarks",
"id": "cis",
"relatedResources": [
"https://www.cisecurity.org/benchmark/kubernetes"
],
"title": "CIS Kubernetes Benchmarks v1.23",
"version": "1.0"
},
"cron": "0 */6 * * *",
"reportType": "summary"
},
"status": {
"summary": {
"failCount": 2,
"passCount": 1
},
"summaryReport": {
"controlCheck": [
{
"id": "4.2.9",
"name": "Ensure that the --event-qps argument is set to 0 or a level which ensures appropriate event capture",
"severity": "HIGH",
"totalFail": 0
},
{
"id": "4.2.10",
"name": "Ensure that the --tls-cert-file and --tls-private-key-file arguments are set as appropriate",
"severity": "CRITICAL",
"totalFail": 10
},
{
"id": "4.2.11",
"name": "Ensure that the --rotate-certificates argument is not set to false",
"severity": "CRITICAL",
"totalFail": 5
}
],
"id": "cis",
"title": "CIS Kubernetes Benchmarks v1.23"
},
"updateTimestamp": "2021-1-1T10:10:10Z"
}
}
]
6 changes: 6 additions & 0 deletions unittests/tools/test_trivy_operator_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,9 @@ def test_findings_all_reports_in_dict(self):
parser = TrivyOperatorParser()
findings = parser.get_findings(test_file, Test())
self.assertEqual(len(findings), 43)

def test_findings_clustercompliancereport(self):
with open(sample_path("clustercompliancereport.json"), encoding="utf-8") as test_file:
parser = TrivyOperatorParser()
findings = parser.get_findings(test_file, Test())
self.assertEqual(len(findings), 2)