Compare commits
6 Commits
1e849976aa
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f2b5c1b47 | |||
| 43d6ad6d6c | |||
| 2d246bd95c | |||
| 0d80215207 | |||
| e0e7018a55 | |||
| 3676ccf990 |
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
|
||||
"${repo_root}/scripts/check-chart.sh"
|
||||
@@ -23,3 +23,5 @@ reports/
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
.amp-usage.db
|
||||
|
||||
@@ -44,18 +44,30 @@ The rendered reference reflects the default values in `helm/values.yaml`, so opt
|
||||
|
||||
For fast validation while wiring up infrastructure, use these tools together:
|
||||
|
||||
- `helm lint ./helm`
|
||||
- `helm template agentguard-ci ./helm`
|
||||
- `helm template agentguard-ci ./helm | kubectl apply --dry-run=client -f -`
|
||||
- `helm template agentguard-ci ./helm | kubectl apply --dry-run=server -f -`
|
||||
- `argo lint rendered.yaml`
|
||||
- `./scripts/check-chart.sh`
|
||||
- `RUN_KUBECTL_CLIENT_CHECK=1 ./scripts/check-chart.sh`
|
||||
- `RUN_KUBECTL_SERVER_CHECK=1 ./scripts/check-chart.sh`
|
||||
|
||||
What each mode does:
|
||||
|
||||
- `./scripts/check-chart.sh` runs the fast offline checks used by the repo-managed pre-commit hook: `helm lint`, `helm template`, and `argo lint --offline`.
|
||||
- `RUN_KUBECTL_CLIENT_CHECK=1 ./scripts/check-chart.sh` adds a client-side `kubectl` dry-run. This is optional because CRD-heavy manifests can still be environment-sensitive here.
|
||||
- `RUN_KUBECTL_SERVER_CHECK=1 ./scripts/check-chart.sh` adds a server-side dry-run against your current cluster context, which is the strongest validation once the Argo and Infisical CRDs are installed.
|
||||
|
||||
Install the shared git hook once per clone:
|
||||
|
||||
```bash
|
||||
git config core.hooksPath .githooks
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- `helm lint` catches Helm chart problems.
|
||||
- `kubectl --dry-run=client` catches basic Kubernetes schema issues without talking to the cluster.
|
||||
- `kubectl --dry-run=server` is better once the cluster already has the Argo and Infisical CRDs installed.
|
||||
- `argo lint` is the most useful Argo-specific check once you have the Argo CLI installed.
|
||||
- `helm template` proves the chart renders successfully with the current values.
|
||||
- `argo lint --offline` is the most useful Argo-specific local check because it validates the rendered `ClusterWorkflowTemplate` without needing cluster access.
|
||||
- `kubectl --dry-run=client` is weaker for CRDs than Argo lint, so it is included as an optional extra check instead of the default hook behavior.
|
||||
- `kubectl --dry-run=server` is best once the cluster already has the Argo and Infisical CRDs installed.
|
||||
- CI should still rerun the same baseline checks even if pre-commit already passed, because hooks are local and bypassable. The usual CI extra is the server-side `kubectl` dry-run once a cluster with the needed CRDs is available.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -101,6 +113,12 @@ If you do not use Infisical, create the `amp-security-pipeline-secrets` secret y
|
||||
helm upgrade --install agentguard-ci ./helm -n argo
|
||||
```
|
||||
|
||||
## Scope and boundaries
|
||||
|
||||
This repository is intentionally focused on **source, IaC, and dependency scanning** before deployment.
|
||||
|
||||
It does **not** try to be the full build-signing, deploy-admission, or runtime-security stack. For the explicit boundary, missing controls, and recommended sibling pipeline responsibilities, read [`docs/security-scope.md`](docs/security-scope.md).
|
||||
|
||||
## DefectDojo integration
|
||||
|
||||
DefectDojo is not installed by this repository.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
Nuclei - https://github.com/projectdiscovery/nuclei
|
||||
|
||||
cli tester with embedded chromium
|
||||
sandyaa - https://github.com/securelayer7/sandyaa
|
||||
|
||||
pipeline vuln tester, very comprehensive
|
||||
darwis-taka - https://hub.docker.com/r/cysecurity/darwis-taka
|
||||
@@ -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
|
||||
@@ -0,0 +1,207 @@
|
||||
# Security Scope and Boundaries
|
||||
|
||||
This repository is intentionally a **source, IaC, and dependency scanning pipeline**.
|
||||
It is not a complete software supply chain or runtime security platform.
|
||||
|
||||
The goal of this document is to make the scope explicit so users understand:
|
||||
|
||||
- what this repository is designed to secure
|
||||
- what it does not secure
|
||||
- what additional controls are still required for a production or homelab deployment pipeline
|
||||
- what requirements a sibling pipeline should meet if you want to fill the gaps
|
||||
|
||||
## What this repository covers
|
||||
|
||||
This repository provides a reusable pre-deploy security gate that scans a repository before deployment proceeds.
|
||||
|
||||
Today it covers:
|
||||
|
||||
- **Secret scanning** with TruffleHog in the pipeline and Gitleaks in local development guidance.
|
||||
- **First-party code scanning** with Semgrep.
|
||||
- **Infrastructure-as-code scanning** with KICS.
|
||||
- **Dependency risk scanning** with Socket.dev.
|
||||
- **SBOM generation and vulnerability scanning** with Syft and Grype.
|
||||
- **Policy-pack validation** with Pulumi CrossGuard.
|
||||
- **Finding export and triage plumbing** through optional DefectDojo and object storage uploads.
|
||||
- **Dependency update automation support** through the Renovate preset and Renovate bot chart in this repository.
|
||||
|
||||
In practical terms, this repository is strongest at:
|
||||
|
||||
- stopping known-bad or suspicious changes before deploy
|
||||
- reducing the chance that AI-generated insecure code or dependencies reach production
|
||||
- creating visibility into code, IaC, dependency, and package vulnerability risk
|
||||
|
||||
## What this repository does not cover
|
||||
|
||||
This repository does **not** attempt to be responsible for every security control in a modern delivery system.
|
||||
|
||||
It does not provide:
|
||||
|
||||
- **Artifact signing** for container images, packages, or release bundles.
|
||||
- **Build provenance / attestations** proving which trusted builder produced an artifact from which source revision.
|
||||
- **Admission control verification** that only signed or attested artifacts may deploy.
|
||||
- **Runtime threat detection** inside the cluster or host.
|
||||
- **Network segmentation or runtime isolation** for the deployed applications.
|
||||
- **DAST** or other black-box testing against a live running application.
|
||||
- **Repository hosting configuration enforcement** such as branch protection, required reviews, CODEOWNERS, or token restrictions.
|
||||
- **Application deployment hardening enforcement** such as checking whether deployed workloads run as non-root, drop capabilities, use read-only root filesystems, or have network policies.
|
||||
- **Secure secret delivery for the scanned application** beyond the pipeline's own runtime secret needs.
|
||||
- **Incident response, rollback, backup, disaster recovery, or patch SLAs**.
|
||||
|
||||
Those areas still matter. They are simply outside the intended scope of this repository.
|
||||
|
||||
## Why the scope stops here
|
||||
|
||||
The security boundary for this repository is:
|
||||
|
||||
1. clone a source repository
|
||||
2. scan source, IaC, dependencies, and generated SBOM data
|
||||
3. publish findings
|
||||
4. fail or pass based on policy
|
||||
|
||||
That boundary is useful because it keeps this repository focused, fast, and reusable.
|
||||
If artifact build security, deploy admission, and runtime controls are mixed directly into this pipeline, the repository stops being a clear pre-deploy scanner and turns into a broader platform.
|
||||
|
||||
This repository should remain the **shift-left scanning gate**, not the entire delivery architecture.
|
||||
|
||||
## What a complete deployment pipeline still needs
|
||||
|
||||
If you are deploying software after this pipeline passes, you still need additional controls elsewhere.
|
||||
|
||||
At a minimum, a production-grade or public homelab deployment flow should also have:
|
||||
|
||||
### 1. Repository and change-management controls
|
||||
|
||||
These controls protect the trustworthiness of the source before scanning even begins.
|
||||
|
||||
Recommended controls:
|
||||
|
||||
- branch protection on default and release branches
|
||||
- required pull request reviews for sensitive paths
|
||||
- `CODEOWNERS` for pipeline, deployment, and policy files
|
||||
- restricted direct pushes to protected branches
|
||||
- minimal repository admin access
|
||||
- mandatory CI status checks before merge
|
||||
- protected tags or release branches if releases are tag-driven
|
||||
|
||||
This repository can document those requirements, but enforcement belongs in the source control platform.
|
||||
|
||||
### 2. Build pipeline controls
|
||||
|
||||
These controls establish that build outputs came from a trusted process.
|
||||
|
||||
Recommended controls:
|
||||
|
||||
- isolated build environment
|
||||
- pinned builder images and actions
|
||||
- least-privilege credentials for the build system
|
||||
- artifact signing for produced container images or release assets
|
||||
- provenance / attestation generation for builds
|
||||
- immutable artifact storage or registry retention controls
|
||||
|
||||
If you want image signing or provenance, that should usually live in the **build pipeline**, because that is where artifacts are actually created.
|
||||
|
||||
### 3. Deploy pipeline controls
|
||||
|
||||
These controls ensure only approved artifacts and manifests reach the cluster.
|
||||
|
||||
Recommended controls:
|
||||
|
||||
- verification of image signatures or attestations before deploy
|
||||
- enforcement that deployment pulls only from approved registries
|
||||
- promotion between environments using immutable digests rather than floating tags
|
||||
- deployment-time policy checks for manifests and workload security settings
|
||||
- manual approval or staged rollout where risk justifies it
|
||||
|
||||
### 4. Runtime and cluster controls
|
||||
|
||||
These controls reduce blast radius after deployment.
|
||||
|
||||
Recommended controls:
|
||||
|
||||
- namespace isolation and least-privilege RBAC
|
||||
- workload security contexts
|
||||
- non-root containers where possible
|
||||
- dropped Linux capabilities
|
||||
- read-only root filesystems where possible
|
||||
- Kubernetes network policies
|
||||
- admission control for workload standards
|
||||
- runtime threat detection / alerting
|
||||
- centralized logs, metrics, and alerts
|
||||
- secrets delivery from a vault or equivalent system
|
||||
|
||||
### 5. Recovery and resilience controls
|
||||
|
||||
These controls matter because modern guidance assumes prevention will sometimes fail.
|
||||
|
||||
Recommended controls:
|
||||
|
||||
- tested rollback procedures
|
||||
- backups and restore testing
|
||||
- credential rotation procedures
|
||||
- vulnerability remediation SLAs
|
||||
- incident response playbooks
|
||||
- inventory of critical services and owners
|
||||
|
||||
## Recommended sibling pipeline responsibilities
|
||||
|
||||
If you build a second pipeline to fill the gaps, keep the separation of concerns explicit.
|
||||
|
||||
A sibling **build and deploy security pipeline** should be responsible for:
|
||||
|
||||
- building artifacts in a trusted environment
|
||||
- generating SBOMs tied to the built artifact
|
||||
- signing artifacts
|
||||
- generating provenance / attestations
|
||||
- verifying signatures or attestations before deploy
|
||||
- enforcing deploy-time policy on manifests and workloads
|
||||
- optionally running DAST or post-deploy validation outside the fast PR loop
|
||||
|
||||
That keeps this repository focused on source scanning while the sibling pipeline owns artifact trust and deployment trust.
|
||||
|
||||
## Mapping this repository to modern security guidance
|
||||
|
||||
A concise way to think about the split is:
|
||||
|
||||
- **Assume compromise:** this repo helps by enforcing checks before deploy, but recovery and runtime containment live elsewhere.
|
||||
- **Defense in depth:** this repo is one layer, not the whole system.
|
||||
- **Blast-radius reduction:** this repo can reduce risky changes reaching production, but runtime RBAC, isolation, and network controls are outside its scope.
|
||||
- **Zero trust / verified supply chain:** this repo contributes source and dependency scrutiny, but full artifact trust also needs build signing and deploy verification in another pipeline.
|
||||
- **Prevention plus detection and recovery:** this repo is primarily a prevention and early-detection layer.
|
||||
|
||||
## Minimum expectations for users of this repository
|
||||
|
||||
If you adopt this repository, you should assume it is only one part of the security architecture.
|
||||
|
||||
At minimum, you should also have:
|
||||
|
||||
- repository branch protection and required reviews
|
||||
- a secure build pipeline
|
||||
- a deployment path that uses immutable artifacts
|
||||
- workload hardening standards for deployed applications
|
||||
- secret management outside Git
|
||||
- logging/monitoring and a plan for response when a scanner finds something important
|
||||
|
||||
## Non-goals
|
||||
|
||||
To avoid scope creep, the following are non-goals for this repository:
|
||||
|
||||
- becoming the authoritative runtime security platform
|
||||
- becoming the artifact signing system
|
||||
- becoming the deployment admission controller
|
||||
- replacing source control platform protections
|
||||
- replacing cluster hardening or incident response processes
|
||||
|
||||
## Summary
|
||||
|
||||
This repository is the **source-side security gate**.
|
||||
It helps answer: "Is this code, IaC, dependency set, and generated SBOM safe enough to continue?"
|
||||
|
||||
It does **not** answer the full downstream questions:
|
||||
|
||||
- "Was the artifact built by a trusted builder?"
|
||||
- "Should the cluster admit this artifact?"
|
||||
- "Is the running workload isolated and monitored correctly?"
|
||||
- "Can we detect, contain, and recover if prevention fails?"
|
||||
|
||||
Those controls should exist, but they should live in adjacent repository, build, deploy, and runtime systems rather than being forced into this repository.
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
|
||||
chart_dir="${repo_root}/helm"
|
||||
rendered_manifest="$(mktemp --suffix=.yaml)"
|
||||
release_name="${RELEASE_NAME:-agentguard-ci}"
|
||||
|
||||
cleanup() {
|
||||
rm -f "${rendered_manifest}"
|
||||
}
|
||||
|
||||
require_command() {
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
printf 'Missing required command: %s\n' "$1" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_kubectl_client_check() {
|
||||
require_command kubectl
|
||||
if ! kubectl apply --dry-run=client --validate=false -f "${rendered_manifest}" >/dev/null 2>&1; then
|
||||
cat <<'EOF' >&2
|
||||
kubectl client dry-run failed.
|
||||
For Argo CRDs, this check can still be environment-sensitive and is optional here.
|
||||
Re-run without RUN_KUBECTL_CLIENT_CHECK=1, or use RUN_KUBECTL_SERVER_CHECK=1 against a cluster with the CRDs installed.
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_kubectl_server_check() {
|
||||
require_command kubectl
|
||||
kubectl apply --dry-run=server -f "${rendered_manifest}" >/dev/null
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
require_command helm
|
||||
require_command argo
|
||||
|
||||
printf '==> helm lint\n'
|
||||
helm lint "${chart_dir}"
|
||||
|
||||
printf '==> helm template\n'
|
||||
helm template "${release_name}" "${chart_dir}" > "${rendered_manifest}"
|
||||
|
||||
printf '==> argo lint --offline\n'
|
||||
argo lint --offline --kinds=clusterworkflowtemplates "${rendered_manifest}"
|
||||
|
||||
if [[ "${RUN_KUBECTL_CLIENT_CHECK:-0}" == "1" ]]; then
|
||||
printf '==> kubectl apply --dry-run=client\n'
|
||||
run_kubectl_client_check
|
||||
fi
|
||||
|
||||
if [[ "${RUN_KUBECTL_SERVER_CHECK:-0}" == "1" ]]; then
|
||||
printf '==> kubectl apply --dry-run=server\n'
|
||||
run_kubectl_server_check
|
||||
fi
|
||||
Reference in New Issue
Block a user