add working dir as input to step

This commit is contained in:
ada
2026-04-20 18:06:58 -06:00
parent 7f366204a9
commit 5bdf3fe114
9 changed files with 271 additions and 194 deletions
+16 -15
View File
@@ -1,17 +1,18 @@
{{- define "template.enforce-policy" }} {{- define "template.enforce-policy" -}}
- name: enforce-policy - name: enforce-policy
inputs: inputs:
parameters: parameters:
- name: fail-on-cvss - name: fail-on-cvss
container: container:
image: agentguard-tools:latest image: "{{ .Values.pipeline.toolsImage.repository }}:{{ .Values.pipeline.toolsImage.tag }}"
command: imagePullPolicy: {{ .Values.pipeline.toolsImage.pullPolicy }}
- node command:
- /app/dist/enforce-policy.js - node
env: - /app/dist/enforce-policy.js
- name: FAIL_ON_CVSS env:
value: "{{inputs.parameters.fail-on-cvss}}" - name: FAIL_ON_CVSS
volumeMounts: value: {{ `{{inputs.parameters.fail-on-cvss}}` | quote }}
- name: workspace volumeMounts:
mountPath: /workspace - name: workspace
mountPath: /workspace
{{- end }} {{- end }}
+23 -20
View File
@@ -1,22 +1,25 @@
{{- define "template.scan-kics" }} {{- define "template.scan-kics" -}}
- name: scan-kics - name: scan-kics
container: inputs:
image: checkmarx/kics:1.7.14 parameters:
command: - name: working-dir
- sh container:
- -c image: {{ .Values.images.kics | quote }}
args: command:
- | - sh
set -eu - -c
mkdir -p /workspace/reports args:
kics scan -p /workspace -o /workspace/reports --report-formats sarif,json --output-name kics || true - |
if [ -f /workspace/reports/kics.sarif ]; then set -eu
exit 0 mkdir -p /workspace/reports
fi kics scan -p "/workspace/{{ `{{inputs.parameters.working-dir}}` }}" -o /workspace/reports --report-formats sarif,json --output-name kics || true
if [ -f /workspace/reports/kics.json ]; then if [ -f /workspace/reports/kics.sarif ]; then
cp /workspace/reports/kics.json /workspace/reports/kics.sarif exit 0
fi fi
volumeMounts: if [ -f /workspace/reports/kics.json ]; then
- name: workspace cp /workspace/reports/kics.json /workspace/reports/kics.sarif
mountPath: /workspace fi
volumeMounts:
- name: workspace
mountPath: /workspace
{{- end }} {{- end }}
+17 -14
View File
@@ -1,16 +1,19 @@
{{- define "template.scan-semgrep" }} {{- define "template.scan-semgrep" -}}
- name: scan-semgrep - name: scan-semgrep
container: inputs:
image: returntocorp/semgrep:1.85.0 parameters:
command: - name: working-dir
- sh container:
- -c image: {{ .Values.images.semgrep | quote }}
args: command:
- | - sh
set -eu - -c
mkdir -p /workspace/reports args:
semgrep scan --config auto --sarif --output /workspace/reports/semgrep.sarif /workspace || true - |
volumeMounts: set -eu
- name: workspace mkdir -p /workspace/reports
mountPath: /workspace semgrep scan --config auto --sarif --output /workspace/reports/semgrep.sarif "/workspace/{{ `{{inputs.parameters.working-dir}}` }}" || true
volumeMounts:
- name: workspace
mountPath: /workspace
{{- end }} {{- end }}
+23 -20
View File
@@ -1,22 +1,25 @@
{{- define "template.scan-socketdev" }} {{- define "template.scan-socketdev" -}}
- name: scan-socketdev - name: scan-socketdev
container: inputs:
image: socketdev/socketcli:latest parameters:
env: - name: working-dir
- name: SOCKET_DEV_API_KEY container:
valueFrom: image: {{ .Values.images.socketdev | quote }}
secretKeyRef: env:
name: amp-security-pipeline-secrets - name: SOCKET_DEV_API_KEY
key: SOCKET_DEV_API_KEY valueFrom:
command: secretKeyRef:
- sh name: amp-security-pipeline-secrets
- -c key: SOCKET_DEV_API_KEY
args: command:
- | - sh
set -eu - -c
mkdir -p /workspace/reports args:
socketdev scan /workspace --format json --output /workspace/reports/socketdev.json || true - |
volumeMounts: set -eu
- name: workspace mkdir -p /workspace/reports
mountPath: /workspace socketdev scan "/workspace/{{ `{{inputs.parameters.working-dir}}` }}" --format json --output /workspace/reports/socketdev.json || true
volumeMounts:
- name: workspace
mountPath: /workspace
{{- end }} {{- end }}
+18 -15
View File
@@ -1,17 +1,20 @@
{{- define "template.scan-syft-grype" }} {{- define "template.scan-syft-grype" -}}
- name: scan-syft-grype - name: scan-syft-grype
container: inputs:
image: anchore/syft:latest parameters:
command: - name: working-dir
- sh container:
- -c image: {{ .Values.images.syftGrype | quote }}
args: command:
- | - sh
set -eu - -c
mkdir -p /workspace/reports args:
syft scan dir:/workspace -o cyclonedx-json=/workspace/reports/sbom.json || true - |
grype sbom:/workspace/reports/sbom.json -o sarif=/workspace/reports/grype.sarif || true set -eu
volumeMounts: mkdir -p /workspace/reports
- name: workspace syft scan dir:/workspace/{{ `{{inputs.parameters.working-dir}}` }} -o cyclonedx-json=/workspace/reports/sbom.json || true
mountPath: /workspace grype sbom:/workspace/reports/sbom.json -o sarif=/workspace/reports/grype.sarif || true
volumeMounts:
- name: workspace
mountPath: /workspace
{{- end }} {{- end }}
+17 -14
View File
@@ -1,16 +1,19 @@
{{- define "template.scan-trufflehog" }} {{- define "template.scan-trufflehog" -}}
- name: scan-trufflehog - name: scan-trufflehog
container: inputs:
image: trufflesecurity/trufflehog:latest parameters:
command: - name: working-dir
- sh container:
- -c image: {{ .Values.images.trufflehog | quote }}
args: command:
- | - sh
set -eu - -c
mkdir -p /workspace/reports args:
trufflehog filesystem /workspace --json > /workspace/reports/trufflehog.json || true - |
volumeMounts: set -eu
- name: workspace mkdir -p /workspace/reports
mountPath: /workspace trufflehog filesystem "/workspace/{{ `{{inputs.parameters.working-dir}}` }}" --json > /workspace/reports/trufflehog.json || true
volumeMounts:
- name: workspace
mountPath: /workspace
{{- end }} {{- end }}
+37 -20
View File
@@ -1,22 +1,39 @@
{{- define "template.upload-defectdojo" }} {{- define "template.upload-defectdojo" -}}
- name: upload-defectdojo - name: upload-defectdojo
container: container:
image: agentguard-tools:latest image: "{{ .Values.pipeline.toolsImage.repository }}:{{ .Values.pipeline.toolsImage.tag }}"
env: imagePullPolicy: {{ .Values.pipeline.toolsImage.pullPolicy }}
- name: DEFECTDOJO_URL env:
valueFrom: - name: DEFECTDOJO_URL
secretKeyRef: valueFrom:
name: amp-security-pipeline-secrets secretKeyRef:
key: DEFECTDOJO_URL name: amp-security-pipeline-secrets
- name: DEFECTDOJO_API_TOKEN key: DEFECTDOJO_URL
valueFrom: - name: DEFECTDOJO_API_TOKEN
secretKeyRef: valueFrom:
name: amp-security-pipeline-secrets secretKeyRef:
key: DEFECTDOJO_API_TOKEN name: amp-security-pipeline-secrets
command: key: DEFECTDOJO_API_TOKEN
- node - name: DEFECTDOJO_PRODUCT_TYPE_NAME
- /app/dist/upload-defectdojo.js value: {{ .Values.defectdojo.productTypeName | quote }}
volumeMounts: - name: DEFECTDOJO_PRODUCT_NAME
- name: workspace value: {{ .Values.defectdojo.productName | quote }}
mountPath: /workspace - name: DEFECTDOJO_ENGAGEMENT_NAME
value: {{ .Values.defectdojo.engagementName | quote }}
- name: DEFECTDOJO_MINIMUM_SEVERITY
value: {{ .Values.defectdojo.minimumSeverity | quote }}
- name: DEFECTDOJO_ACTIVE
value: {{ .Values.defectdojo.active | quote }}
- name: DEFECTDOJO_VERIFIED
value: {{ .Values.defectdojo.verified | quote }}
- name: DEFECTDOJO_CLOSE_OLD_FINDINGS
value: {{ .Values.defectdojo.closeOldFindings | quote }}
- name: DEFECTDOJO_AUTO_CREATE_CONTEXT
value: {{ .Values.defectdojo.autoCreateContext | quote }}
command:
- node
- /app/dist/upload-defectdojo.js
volumeMounts:
- name: workspace
mountPath: /workspace
{{- end }} {{- end }}
+47 -37
View File
@@ -1,39 +1,49 @@
{{- define "template.upload-storage" }} {{- define "template.upload-storage" -}}
- name: upload-storage - name: upload-storage
container: container:
image: amazon/aws-cli:2.15.40 image: {{ .Values.images.awsCli | quote }}
env: env:
- name: AWS_ACCESS_KEY_ID - name: AWS_ACCESS_KEY_ID
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: amp-security-pipeline-secrets name: amp-security-pipeline-secrets
key: AWS_ACCESS_KEY_ID key: AWS_ACCESS_KEY_ID
- name: AWS_SECRET_ACCESS_KEY - name: AWS_SECRET_ACCESS_KEY
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: amp-security-pipeline-secrets name: amp-security-pipeline-secrets
key: AWS_SECRET_ACCESS_KEY key: AWS_SECRET_ACCESS_KEY
- name: MINIO_ROOT_USER - name: MINIO_ROOT_USER
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: amp-security-pipeline-secrets name: amp-security-pipeline-secrets
key: MINIO_ROOT_USER key: MINIO_ROOT_USER
- name: MINIO_ROOT_PASSWORD - name: MINIO_ROOT_PASSWORD
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: amp-security-pipeline-secrets name: amp-security-pipeline-secrets
key: MINIO_ROOT_PASSWORD key: MINIO_ROOT_PASSWORD
command: - name: REPORTS_BUCKET
- sh value: {{ .Values.storage.reportsBucket | quote }}
- -c - name: REPO_NAME
args: value: {{ .Values.pipeline.repoName | quote }}
- | - name: STORAGE_ENDPOINT
set -eu value: {{ .Values.storage.endpoint | quote }}
repo_name="${REPO_NAME:-repo}" command:
commit_sha="${GIT_COMMIT_SHA:-unknown}" - sh
report_date="$(date -u +%F)" - -c
aws s3 sync /workspace/reports "s3://${REPORTS_BUCKET:-security-reports}/${repo_name}/${report_date}/${commit_sha}/" args:
volumeMounts: - |
- name: workspace set -eu
mountPath: /workspace commit_sha="${GIT_COMMIT_SHA:-unknown}"
report_date="$(date -u +%F)"
sync_target="s3://${REPORTS_BUCKET}/${REPO_NAME}/${report_date}/${commit_sha}/"
if [ -n "${STORAGE_ENDPOINT}" ]; then
aws --endpoint-url "${STORAGE_ENDPOINT}" s3 sync /workspace/reports "${sync_target}"
else
aws s3 sync /workspace/reports "${sync_target}"
fi
volumeMounts:
- name: workspace
mountPath: /workspace
{{- end }} {{- end }}
+69 -35
View File
@@ -1,68 +1,102 @@
import * as fs from 'node:fs'; import { promises as fs } from 'node:fs';
import * as path from 'node:path'; import * as path from 'node:path';
import { fileURLToPath } from 'node:url'; import { fileURLToPath } from 'node:url';
export async function uploadReports() { function resolveScanType(fileName: string): string | undefined {
const baseUrl = (process.env.DEFECTDOJO_URL || "").replace(/\/$/, ""); if (fileName.endsWith('.sarif')) {
return 'SARIF';
}
if (fileName === 'generic-findings.json') {
return 'Generic Findings Import';
}
return undefined;
}
export async function uploadReports(): Promise<void> {
const baseUrl = (process.env.DEFECTDOJO_URL || '').replace(/\/$/, '');
const apiToken = process.env.DEFECTDOJO_API_TOKEN; const apiToken = process.env.DEFECTDOJO_API_TOKEN;
const productName = process.env.DEFECTDOJO_PRODUCT_NAME || "agentguard-ci"; const productTypeName = process.env.DEFECTDOJO_PRODUCT_TYPE_NAME || 'Homelab Security';
const productName = process.env.DEFECTDOJO_PRODUCT_NAME || 'agentguard-ci';
const engagementName = process.env.DEFECTDOJO_ENGAGEMENT_NAME || 'Default Pipeline';
const minimumSeverity = process.env.DEFECTDOJO_MINIMUM_SEVERITY || 'Info';
const active = process.env.DEFECTDOJO_ACTIVE || 'true';
const verified = process.env.DEFECTDOJO_VERIFIED || 'true';
const closeOldFindings = process.env.DEFECTDOJO_CLOSE_OLD_FINDINGS || 'false';
const autoCreateContext = process.env.DEFECTDOJO_AUTO_CREATE_CONTEXT || 'true';
if (!baseUrl || !apiToken) { if (!baseUrl || !apiToken) {
console.error("DEFECTDOJO_URL and DEFECTDOJO_API_TOKEN must be set."); console.error('DEFECTDOJO_URL and DEFECTDOJO_API_TOKEN must be set.');
process.exit(1); process.exit(1);
} }
const scanMap: Record<string, string> = { const reportsDir = '/workspace/reports';
".sarif": "SARIF", let fileNames: string[];
".json": "Generic Findings Import",
};
const reportsDir = "/workspace/reports"; try {
if (!fs.existsSync(reportsDir)) { fileNames = (await fs.readdir(reportsDir)).sort();
console.log("No reports directory found."); } catch {
console.log('No reports directory found.');
return; return;
} }
const files = fs.readdirSync(reportsDir).sort(); for (const fileName of fileNames) {
const fullPath = path.join(reportsDir, fileName);
const stats = await fs.stat(fullPath);
if (!stats.isFile()) {
continue;
}
for (const file of files) { const scanType = resolveScanType(fileName);
const fullPath = path.join(reportsDir, file); if (!scanType) {
if (!fs.statSync(fullPath).isFile()) continue; console.log(`Skipping ${fileName}: no DefectDojo importer is configured for this file yet.`);
continue;
}
const ext = path.extname(file); const reportContents = await fs.readFile(fullPath);
const scanType = scanMap[ext]; const form = new FormData();
if (!scanType) continue; form.append('scan_type', scanType);
form.append('product_type_name', productTypeName);
form.append('product_name', productName);
form.append('engagement_name', engagementName);
form.append('test_title', fileName);
form.append('minimum_severity', minimumSeverity);
form.append('active', active);
form.append('verified', verified);
form.append('close_old_findings', closeOldFindings);
form.append('auto_create_context', autoCreateContext);
form.append('file', new Blob([reportContents]), fileName);
console.log(`Uploading ${file} as ${scanType}...`); console.log(`Uploading ${fileName} to DefectDojo as ${scanType}...`);
try { try {
const response = await fetch(`${baseUrl}/api/v2/import-scan/`, { const response = await fetch(`${baseUrl}/api/v2/reimport-scan/`, {
method: "POST", method: 'POST',
headers: { headers: {
"Authorization": `Token ${apiToken}`, Authorization: `Token ${apiToken}`,
"Content-Type": "application/json",
}, },
body: JSON.stringify({ body: form,
scan_type: scanType,
product_name: productName,
file_name: file,
})
}); });
if (!response.ok) { if (!response.ok) {
const text = await response.text(); const text = await response.text();
console.error(`Failed to upload ${file}: ${response.status} ${response.statusText} - ${text}`); console.error(`Failed to upload ${fileName}: ${response.status} ${response.statusText} - ${text}`);
process.exitCode = 1; process.exitCode = 1;
} else { continue;
console.log(`Successfully uploaded ${file}`);
} }
} catch (e) {
console.error(`Network error uploading ${file}:`, e); console.log(`Successfully uploaded ${fileName}`);
} catch (error) {
console.error(`Network error uploading ${fileName}:`, error);
process.exitCode = 1; process.exitCode = 1;
} }
} }
} }
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) { if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
uploadReports(); uploadReports().catch((error: unknown) => {
console.error('Unexpected upload failure:', error);
process.exit(1);
});
} }