Skip to content

Backup & compliance CRDs

backup-verify and compliance-scan follow the same shape: an immutable *Run declares what to do, the controller produces a *Result with per-finding detail, and status.worstSeverity is the single field downstream consumers use to decide whether to alert.

KindScopeCardinalityOwning operator
BackupVerifyRunNamespacedper runbackup-verify
BackupVerifyResultNamespacedper runbackup-verify
ComplianceScanRunNamespacedper runcompliance-scan
ComplianceScanResultNamespacedper runcompliance-scan

Namespace-scoped, one CR per verification. Owned by backup-verify.

Spec

  • backend (enum) - velero or etcd-snapshot.
  • backupRef.name (string) - upstream Backup (Velero) or snapshot filename (etcd-snapshot).
  • backupRef.namespace (string) - empty for etcd-snapshot.
  • backupRef.storageLocation (string) - override BackupStorageLocation (Velero only).
  • mode (enum) - checksum-only (default) or full-restore.
  • sandboxNamespace (string) - required when mode=full-restore, must end with -bvsandbox (admission policy).
  • timeout (Duration) - default 15m, bounded at 1h.

Status

  • phase (enum) - Pending, Running, Succeeded, Failed.
  • startTime, completionTime.
  • resultRef - BackupVerifyResult produced (empty until Succeeded).
  • conditions[].

Example

apiVersion: security.ugallu.io/v1alpha1
kind: BackupVerifyRun
metadata: { name: nightly-velero, namespace: ugallu-system }
spec:
backend: velero
backupRef:
name: nightly-2026-04-29
namespace: velero
mode: full-restore
sandboxNamespace: nightly-2026-04-29-bvsandbox
timeout: 10m

Namespace-scoped, one CR per run.

Spec

  • derivedFromRun (LocalProfileRef).
  • backend, mode - mirror the run.
  • checksum (string) - SHA-256 of the backup payload (lowercase hex; empty when there is no single payload, e.g. multi-volume).
  • restoredObjectCount (int) - K8s objects produced by the full-restore (zero for checksum-only).
  • findings[] - per-finding records: {code, message, severity, detail}. An empty list with phase=Succeeded means a healthy backup.

Status

  • worstSeverity (enum) - critical, high, medium, low, info. The maximum across findings.

Retained 30 days by ugallu-ttl.

Example (controller-produced)

apiVersion: security.ugallu.io/v1alpha1
kind: BackupVerifyResult
metadata: { name: nightly-velero-result, namespace: ugallu-system }
spec:
derivedFromRun: { name: nightly-velero }
backend: velero
mode: full-restore
checksum: "" # full-restore mode does not compute a single checksum
restoredObjectCount: 412
findings:
- code: velero-restore-completed
severity: info
message: "Restore reached phase=Completed in 1m24s"
- code: object-count-diff
severity: low
message: "412 restored vs 414 in manifest (2 ConfigMaps purposely excluded)"
status:
worstSeverity: low

Namespace-scoped, one CR per scan. Owned by compliance-scan.

Spec

  • backend (enum) - kube-bench, falco, cel-custom.
  • profile (string) - backend-specific identifier (kube-bench benchmark version; falco source name; cel rule pack name).
  • controlMappings[] - SOC2 / ISO27001 mapping the reporter stamps on results (so a single scan can populate multiple frameworks without re-running).
  • timeout (Duration) - default 10m, bounded at 30m.

Status

  • phase (enum) - Pending, Running, Succeeded, Failed.
  • startTime, completionTime.
  • resultRef.
  • conditions[].

Example

apiVersion: security.ugallu.io/v1alpha1
kind: ComplianceScanRun
metadata: { name: cis-control-plane, namespace: ugallu-system }
spec:
backend: kube-bench
profile: cis-1.9
controlMappings:
- framework: SOC2
control: CC7.1
- framework: ISO27001
control: A.12.4
timeout: 5m

Namespace-scoped, one CR per run.

Spec

  • derivedFromRun (LocalProfileRef).
  • backend, profile - mirror the run.
  • checks[] - per-check records: {checkID, title, outcome (pass/fail/warn/skip), severity, detail, frameworks[]}.
  • summary (map) - {pass: N, fail: N, warn: N, skip: N}.

Status

  • worstSeverity (enum) - same as backup-verify.

Retained 365 days by ugallu-ttl.

Example (controller-produced)

apiVersion: security.ugallu.io/v1alpha1
kind: ComplianceScanResult
metadata: { name: cis-control-plane-result, namespace: ugallu-system }
spec:
derivedFromRun: { name: cis-control-plane }
backend: kube-bench
profile: cis-1.9
checks:
- checkID: 1.1.1
title: "Ensure that the API server pod specification file permissions are set to 600 or more restrictive"
outcome: pass
severity: info
frameworks: [SOC2, ISO27001]
- checkID: 1.2.6
title: "Ensure that the --kubelet-certificate-authority argument is set as appropriate"
outcome: fail
severity: high
detail: "kubelet-certificate-authority is unset on apiserver"
frameworks: [SOC2]
summary:
pass: 142
fail: 3
warn: 7
skip: 4
status:
worstSeverity: high