diff --git a/docs/rendered/default-clusterworkflowtemplate.yaml b/docs/rendered/default-clusterworkflowtemplate.yaml new file mode 100644 index 0000000..d779817 --- /dev/null +++ b/docs/rendered/default-clusterworkflowtemplate.yaml @@ -0,0 +1,268 @@ +# Rendered reference for the default chart values in helm/values.yaml. +# This is intended for reading and review, so you can inspect the final Argo object +# without also mentally evaluating Helm templates. +# +# Notes: +# - Optional storage, DefectDojo, and Infisical resources are omitted because they are +# disabled by default. +# - Argo placeholders such as {{workflow.parameters.repo-url}} are expected and remain +# in the rendered object because Argo resolves them at workflow runtime. +apiVersion: argoproj.io/v1alpha1 +kind: ClusterWorkflowTemplate +metadata: + name: amp-security-pipeline-v1.0.0 +spec: + serviceAccountName: default + entrypoint: security-pipeline + onExit: pipeline-exit-hook + volumeClaimTemplates: + - metadata: + name: workspace + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + arguments: + parameters: + - name: working-dir + value: "." + - name: fail-on-cvss + value: "7.0" + - name: repo-url + - name: git-revision + value: "main" + templates: + - name: security-pipeline + dag: + tasks: + - name: clone + template: clone-repo + arguments: + parameters: + - name: repo-url + value: "{{workflow.parameters.repo-url}}" + - name: git-revision + value: "{{workflow.parameters.git-revision}}" + - name: scanners + dependencies: + - clone + template: parallel-scanners + arguments: + parameters: + - name: working-dir + value: "{{workflow.parameters.working-dir}}" + - name: enforce-policy + dependencies: + - scanners + template: enforce-policy + arguments: + parameters: + - name: fail-on-cvss + value: "{{workflow.parameters.fail-on-cvss}}" + - name: clone-repo + inputs: + parameters: + - name: repo-url + - name: git-revision + container: + image: alpine/git:2.45.2 + command: + - sh + - -c + args: + - git clone --branch "{{inputs.parameters.git-revision}}" --single-branch "{{inputs.parameters.repo-url}}" /workspace + volumeMounts: + - name: workspace + mountPath: /workspace + - name: parallel-scanners + inputs: + parameters: + - name: working-dir + dag: + tasks: + - name: trufflehog + template: scan-trufflehog + arguments: + parameters: + - name: working-dir + value: "{{inputs.parameters.working-dir}}" + - name: semgrep + template: scan-semgrep + arguments: + parameters: + - name: working-dir + value: "{{inputs.parameters.working-dir}}" + - name: kics + template: scan-kics + arguments: + parameters: + - name: working-dir + value: "{{inputs.parameters.working-dir}}" + - name: socketdev + template: scan-socketdev + arguments: + parameters: + - name: working-dir + value: "{{inputs.parameters.working-dir}}" + - name: syft-grype + template: scan-syft-grype + arguments: + parameters: + - name: working-dir + value: "{{inputs.parameters.working-dir}}" + - name: pulumi-crossguard + template: scan-pulumi-crossguard + arguments: + parameters: + - name: working-dir + value: "{{inputs.parameters.working-dir}}" + - name: pipeline-exit-hook + container: + image: curlimages/curl:8.8.0 + command: + - sh + - -c + args: + - | + set -eu + echo "Pipeline completed with status: {{workflow.status}}" + - name: scan-trufflehog + inputs: + parameters: + - name: working-dir + container: + image: trufflesecurity/trufflehog:latest + command: + - sh + - -c + args: + - | + set -eu + mkdir -p /workspace/reports + trufflehog filesystem "/workspace/{{inputs.parameters.working-dir}}" --json > /workspace/reports/trufflehog.json || true + volumeMounts: + - name: workspace + mountPath: /workspace + - name: scan-semgrep + inputs: + parameters: + - name: working-dir + container: + image: returntocorp/semgrep:1.85.0 + command: + - sh + - -c + args: + - | + set -eu + mkdir -p /workspace/reports + semgrep scan --config auto --sarif --output /workspace/reports/semgrep.sarif "/workspace/{{inputs.parameters.working-dir}}" || true + volumeMounts: + - name: workspace + mountPath: /workspace + - name: scan-kics + inputs: + parameters: + - name: working-dir + container: + image: checkmarx/kics:1.7.14 + command: + - sh + - -c + args: + - | + set -eu + mkdir -p /workspace/reports + kics scan -p "/workspace/{{inputs.parameters.working-dir}}" -o /workspace/reports --report-formats sarif,json --output-name kics || true + if [ -f /workspace/reports/kics.sarif ]; then + exit 0 + fi + if [ -f /workspace/reports/kics.json ]; then + cp /workspace/reports/kics.json /workspace/reports/kics.sarif + fi + volumeMounts: + - name: workspace + mountPath: /workspace + - name: scan-socketdev + inputs: + parameters: + - name: working-dir + container: + image: socketdev/socketcli:latest + env: + - name: SOCKET_DEV_API_KEY + valueFrom: + secretKeyRef: + name: amp-security-pipeline-secrets + key: SOCKET_DEV_API_KEY + command: + - sh + - -c + args: + - | + set -eu + mkdir -p /workspace/reports + socketdev scan "/workspace/{{inputs.parameters.working-dir}}" --format json --output /workspace/reports/socketdev.json || true + volumeMounts: + - name: workspace + mountPath: /workspace + - name: scan-syft-grype + inputs: + parameters: + - name: working-dir + container: + image: anchore/syft:latest + command: + - sh + - -c + args: + - | + set -eu + mkdir -p /workspace/reports + syft scan dir:/workspace/{{inputs.parameters.working-dir}} -o cyclonedx-json=/workspace/reports/sbom.json || true + grype sbom:/workspace/reports/sbom.json -o sarif=/workspace/reports/grype.sarif || true + volumeMounts: + - name: workspace + mountPath: /workspace + - name: scan-pulumi-crossguard + inputs: + parameters: + - name: working-dir + container: + image: pulumi/pulumi:3.154.0 + env: + - name: PULUMI_ACCESS_TOKEN + valueFrom: + secretKeyRef: + name: amp-security-pipeline-secrets + key: PULUMI_ACCESS_TOKEN + command: + - sh + - -c + args: + - | + set -eu + mkdir -p /workspace/reports + cd "/workspace/{{inputs.parameters.working-dir}}" + pulumi preview --policy-pack "policy-pack" > /workspace/reports/pulumi-crossguard.json 2>&1 || true + volumeMounts: + - name: workspace + mountPath: /workspace + - name: enforce-policy + inputs: + parameters: + - name: fail-on-cvss + container: + image: agentguard-tools:latest + imagePullPolicy: IfNotPresent + command: + - node + - /app/dist/enforce-policy.js + env: + - name: FAIL_ON_CVSS + value: "{{inputs.parameters.fail-on-cvss}}" + volumeMounts: + - name: workspace + mountPath: /workspace diff --git a/helm/values.schema.json b/helm/values.schema.json new file mode 100644 index 0000000..e87186c --- /dev/null +++ b/helm/values.schema.json @@ -0,0 +1,234 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema#", + "type": "object", + "additionalProperties": false, + "properties": { + "pipeline": { + "type": "object", + "additionalProperties": false, + "description": "Core Argo workflow settings.", + "properties": { + "enabled": { + "type": "boolean", + "description": "Render the ClusterWorkflowTemplate when true." + }, + "name": { + "type": "string", + "description": "Name of the ClusterWorkflowTemplate resource.", + "minLength": 1 + }, + "serviceAccountName": { + "type": "string", + "description": "Service account used by workflow pods.", + "minLength": 1 + }, + "workingDir": { + "type": "string", + "description": "Repository path scanned inside the cloned workspace.", + "minLength": 1 + }, + "gitRevision": { + "type": "string", + "description": "Default git revision to clone when the workflow caller does not override it.", + "minLength": 1 + }, + "failOnCvss": { + "type": "string", + "description": "CVSS threshold passed to the policy enforcement utility.", + "pattern": "^[0-9]+(\\.[0-9]+)?$" + }, + "workspace": { + "type": "object", + "additionalProperties": false, + "description": "PVC configuration for the shared workspace volume.", + "properties": { + "storage": { + "type": "string", + "description": "Requested workspace PVC size, for example 1Gi.", + "minLength": 1 + } + }, + "required": [ + "storage" + ] + }, + "repoName": { + "type": "string", + "description": "Repository name used in storage upload paths.", + "minLength": 1 + }, + "scanners": { + "type": "array", + "description": "Ordered list of scanner templates wired into the scanner fan-out DAG.", + "minItems": 1, + "items": { + "type": "string", + "enum": [ + "trufflehog", + "semgrep", + "kics", + "socketdev", + "syft-grype", + "pulumi-crossguard" + ] + }, + "uniqueItems": true + }, + "toolsImage": { + "type": "object", + "additionalProperties": false, + "description": "Custom image that packages the Node utilities used by the workflow.", + "properties": { + "repository": { + "type": "string", + "minLength": 1 + }, + "tag": { + "type": "string", + "minLength": 1 + }, + "pullPolicy": { + "type": "string", + "enum": [ + "Always", + "IfNotPresent", + "Never" + ] + } + }, + "required": [ + "repository", + "tag", + "pullPolicy" + ] + } + }, + "required": [ + "enabled", + "name", + "serviceAccountName", + "workingDir", + "gitRevision", + "failOnCvss", + "workspace", + "repoName", + "scanners", + "toolsImage" + ] + }, + "images": { + "type": "object", + "additionalProperties": false, + "description": "Container images used by each workflow step.", + "properties": { + "git": { "type": "string", "minLength": 1 }, + "trufflehog": { "type": "string", "minLength": 1 }, + "semgrep": { "type": "string", "minLength": 1 }, + "kics": { "type": "string", "minLength": 1 }, + "socketdev": { "type": "string", "minLength": 1 }, + "syftGrype": { "type": "string", "minLength": 1 }, + "pulumiCrossguard": { "type": "string", "minLength": 1 }, + "awsCli": { "type": "string", "minLength": 1 }, + "curl": { "type": "string", "minLength": 1 } + }, + "required": [ + "git", + "trufflehog", + "semgrep", + "kics", + "socketdev", + "syftGrype", + "pulumiCrossguard", + "awsCli", + "curl" + ] + }, + "storage": { + "type": "object", + "additionalProperties": false, + "description": "Optional raw report upload configuration.", + "properties": { + "enabled": { + "type": "boolean" + }, + "reportsBucket": { + "type": "string", + "minLength": 1 + }, + "endpoint": { + "type": "string", + "description": "Optional custom S3 endpoint for MinIO or another compatible store." + } + }, + "required": [ + "enabled", + "reportsBucket", + "endpoint" + ] + }, + "pulumi": { + "type": "object", + "additionalProperties": false, + "description": "Pulumi CrossGuard scanner settings.", + "properties": { + "policyPackPath": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "policyPackPath" + ] + }, + "defectdojo": { + "type": "object", + "additionalProperties": false, + "description": "Optional DefectDojo upload step configuration.", + "properties": { + "enabled": { "type": "boolean" }, + "productTypeName": { "type": "string", "minLength": 1 }, + "productName": { "type": "string", "minLength": 1 }, + "engagementName": { "type": "string", "minLength": 1 }, + "minimumSeverity": { "type": "string", "minLength": 1 }, + "active": { "type": "boolean" }, + "verified": { "type": "boolean" }, + "closeOldFindings": { "type": "boolean" }, + "autoCreateContext": { "type": "boolean" } + }, + "required": [ + "enabled", + "productTypeName", + "productName", + "engagementName", + "minimumSeverity", + "active", + "verified", + "closeOldFindings", + "autoCreateContext" + ] + }, + "infisical": { + "type": "object", + "additionalProperties": false, + "description": "Optional Infisical operator integration.", + "properties": { + "enabled": { "type": "boolean" }, + "workspaceSlug": { "type": "string" }, + "projectSlug": { "type": "string" } + }, + "required": [ + "enabled", + "workspaceSlug", + "projectSlug" + ] + } + }, + "required": [ + "pipeline", + "images", + "storage", + "pulumi", + "defectdojo", + "infisical" + ] +}