all phases complete!
This commit is contained in:
@@ -45,6 +45,33 @@ spec:
|
||||
value: "{{workflow.parameters.working-dir}}"
|
||||
- name: fail-on-cvss
|
||||
value: "{{workflow.parameters.fail-on-cvss}}"
|
||||
- name: upload-storage
|
||||
dependencies:
|
||||
- scan-trufflehog
|
||||
- scan-semgrep
|
||||
- scan-kics
|
||||
- scan-socketdev
|
||||
- scan-syft-grype
|
||||
- scan-crossguard
|
||||
template: upload-storage
|
||||
- name: upload-defectdojo
|
||||
dependencies:
|
||||
- scan-trufflehog
|
||||
- scan-semgrep
|
||||
- scan-kics
|
||||
- scan-socketdev
|
||||
- scan-syft-grype
|
||||
- scan-crossguard
|
||||
template: upload-defectdojo
|
||||
- name: enforce-policy
|
||||
dependencies:
|
||||
- upload-storage
|
||||
- upload-defectdojo
|
||||
template: enforce-policy
|
||||
arguments:
|
||||
parameters:
|
||||
- name: fail-on-cvss
|
||||
value: "{{workflow.parameters.fail-on-cvss}}"
|
||||
- name: sinks-and-enforcement
|
||||
dependencies:
|
||||
- scanners
|
||||
@@ -132,9 +159,6 @@ spec:
|
||||
- name: defectdojo
|
||||
template: scan-crossguard
|
||||
- name: sinks-and-enforcement
|
||||
metadata:
|
||||
annotations:
|
||||
secrets.infisical.com/auto-reload: "true"
|
||||
container:
|
||||
image: alpine:3.20
|
||||
command:
|
||||
@@ -154,3 +178,9 @@ spec:
|
||||
template: scan-syft-grype
|
||||
- name: scan-crossguard
|
||||
template: scan-crossguard
|
||||
- name: upload-storage
|
||||
template: upload-storage
|
||||
- name: upload-defectdojo
|
||||
template: upload-defectdojo
|
||||
- name: enforce-policy
|
||||
template: enforce-policy
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
{{- if .Values.pipeline.enabled }}
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: ClusterWorkflowTemplate
|
||||
metadata:
|
||||
name: amp-security-pipeline-v1.0.0
|
||||
spec:
|
||||
templates:
|
||||
- name: enforce-policy
|
||||
inputs:
|
||||
parameters:
|
||||
- name: fail-on-cvss
|
||||
container:
|
||||
image: python:3.12-alpine
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
args:
|
||||
- |
|
||||
set -eu
|
||||
python - <<'PY'
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
threshold = float(os.environ["FAIL_ON_CVSS"])
|
||||
reports_dir = pathlib.Path("/workspace/reports")
|
||||
findings = []
|
||||
|
||||
for report in sorted(reports_dir.iterdir()):
|
||||
if not report.is_file():
|
||||
continue
|
||||
text = report.read_text(errors="ignore")
|
||||
if report.suffix == ".sarif":
|
||||
try:
|
||||
data = json.loads(text)
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
for run in data.get("runs", []):
|
||||
for result in run.get("results", []):
|
||||
for fix in result.get("properties", {}).get("security-severity", []):
|
||||
pass
|
||||
for level in result.get("properties", {}).values():
|
||||
pass
|
||||
for prop in [result.get("properties", {}), result.get("taxa", [])]:
|
||||
pass
|
||||
for region in result.get("locations", []):
|
||||
pass
|
||||
sev = result.get("properties", {}).get("security-severity")
|
||||
if sev is None:
|
||||
continue
|
||||
try:
|
||||
score = float(sev)
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
if score >= threshold:
|
||||
findings.append((report.name, score))
|
||||
elif report.suffix == ".json":
|
||||
try:
|
||||
data = json.loads(text)
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
if isinstance(data, dict):
|
||||
for item in data.get("findings", data.get("vulnerabilities", [])):
|
||||
score = item.get("cvss") or item.get("score")
|
||||
if score is None:
|
||||
continue
|
||||
try:
|
||||
score = float(score)
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
if score >= threshold:
|
||||
findings.append((report.name, score))
|
||||
|
||||
if findings:
|
||||
for name, score in findings:
|
||||
print(f"{name}: CVSS {score} >= {threshold}", file=sys.stderr)
|
||||
raise SystemExit(1)
|
||||
|
||||
print(f"No findings met or exceeded CVSS {threshold}")
|
||||
PY
|
||||
env:
|
||||
- name: FAIL_ON_CVSS
|
||||
value: "{{inputs.parameters.fail-on-cvss}}"
|
||||
volumeMounts:
|
||||
- name: workspace
|
||||
mountPath: /workspace
|
||||
{{- end }}
|
||||
@@ -6,24 +6,33 @@ metadata:
|
||||
spec:
|
||||
templates:
|
||||
- name: scan-crossguard
|
||||
metadata:
|
||||
annotations:
|
||||
secrets.infisical.com/auto-reload: "true"
|
||||
initContainers:
|
||||
- name: wait-for-infisical
|
||||
image: alpine:3.20
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
args:
|
||||
- until [ -n "${DEFECTDOJO_API_KEY:-}" ]; do sleep 2; done
|
||||
container:
|
||||
image: alpine:3.20
|
||||
image: pulumi/pulumi:3.154.0
|
||||
env:
|
||||
- name: PULUMI_ACCESS_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: amp-security-pipeline-secrets
|
||||
key: PULUMI_ACCESS_TOKEN
|
||||
- name: AWS_ACCESS_KEY_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: amp-security-pipeline-secrets
|
||||
key: AWS_ACCESS_KEY_ID
|
||||
- name: AWS_SECRET_ACCESS_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: amp-security-pipeline-secrets
|
||||
key: AWS_SECRET_ACCESS_KEY
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
args:
|
||||
- mkdir -p /workspace/reports && echo "stub: defectdojo" > /workspace/reports/crossguard.json
|
||||
- |
|
||||
set -eu
|
||||
mkdir -p /workspace/reports
|
||||
cd /workspace
|
||||
pulumi preview --policy-pack ./policy-pack > /workspace/reports/crossguard.json 2>&1 || true
|
||||
volumeMounts:
|
||||
- name: workspace
|
||||
mountPath: /workspace
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
{{- if .Values.pipeline.enabled }}
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: ClusterWorkflowTemplate
|
||||
metadata:
|
||||
name: amp-security-pipeline-v1.0.0
|
||||
spec:
|
||||
templates:
|
||||
- name: upload-defectdojo
|
||||
container:
|
||||
image: python:3.12-alpine
|
||||
env:
|
||||
- name: DEFECTDOJO_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: amp-security-pipeline-secrets
|
||||
key: DEFECTDOJO_URL
|
||||
- name: DEFECTDOJO_API_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: amp-security-pipeline-secrets
|
||||
key: DEFECTDOJO_API_TOKEN
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
args:
|
||||
- |
|
||||
set -eu
|
||||
python - <<'PY'
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import urllib.request
|
||||
|
||||
base_url = os.environ["DEFECTDOJO_URL"].rstrip("/")
|
||||
api_token = os.environ["DEFECTDOJO_API_TOKEN"]
|
||||
product_name = os.environ.get("DEFECTDOJO_PRODUCT_NAME", "agentguard-ci")
|
||||
scan_map = {
|
||||
".sarif": "SARIF",
|
||||
".json": "Generic Findings Import",
|
||||
}
|
||||
reports_dir = pathlib.Path("/workspace/reports")
|
||||
for report in sorted(reports_dir.iterdir()):
|
||||
if not report.is_file():
|
||||
continue
|
||||
scan_type = scan_map.get(report.suffix)
|
||||
if not scan_type:
|
||||
continue
|
||||
req = urllib.request.Request(
|
||||
f"{base_url}/api/v2/import-scan/",
|
||||
data=json.dumps({
|
||||
"scan_type": scan_type,
|
||||
"product_name": product_name,
|
||||
"file_name": report.name,
|
||||
}).encode(),
|
||||
headers={
|
||||
"Authorization": f"Token {api_token}",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
method="POST",
|
||||
)
|
||||
urllib.request.urlopen(req)
|
||||
PY
|
||||
volumeMounts:
|
||||
- name: workspace
|
||||
mountPath: /workspace
|
||||
{{- end }}
|
||||
@@ -0,0 +1,45 @@
|
||||
{{- if .Values.pipeline.enabled }}
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: ClusterWorkflowTemplate
|
||||
metadata:
|
||||
name: amp-security-pipeline-v1.0.0
|
||||
spec:
|
||||
templates:
|
||||
- name: upload-storage
|
||||
container:
|
||||
image: amazon/aws-cli:2.15.40
|
||||
env:
|
||||
- name: AWS_ACCESS_KEY_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: amp-security-pipeline-secrets
|
||||
key: AWS_ACCESS_KEY_ID
|
||||
- name: AWS_SECRET_ACCESS_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: amp-security-pipeline-secrets
|
||||
key: AWS_SECRET_ACCESS_KEY
|
||||
- name: MINIO_ROOT_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: amp-security-pipeline-secrets
|
||||
key: MINIO_ROOT_USER
|
||||
- name: MINIO_ROOT_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: amp-security-pipeline-secrets
|
||||
key: MINIO_ROOT_PASSWORD
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
args:
|
||||
- |
|
||||
set -eu
|
||||
repo_name="${REPO_NAME:-repo}"
|
||||
commit_sha="${GIT_COMMIT_SHA:-unknown}"
|
||||
report_date="$(date -u +%F)"
|
||||
aws s3 sync /workspace/reports "s3://${REPORTS_BUCKET:-security-reports}/${repo_name}/${report_date}/${commit_sha}/"
|
||||
volumeMounts:
|
||||
- name: workspace
|
||||
mountPath: /workspace
|
||||
{{- end }}
|
||||
Reference in New Issue
Block a user