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.
| Kind | Scope | Cardinality | Owning operator |
|---|---|---|---|
BackupVerifyRun | Namespaced | per run | backup-verify |
BackupVerifyResult | Namespaced | per run | backup-verify |
ComplianceScanRun | Namespaced | per run | compliance-scan |
ComplianceScanResult | Namespaced | per run | compliance-scan |
BackupVerifyRun
Section titled “BackupVerifyRun”Namespace-scoped, one CR per verification. Owned by backup-verify.
Spec
backend(enum) -velerooretcd-snapshot.backupRef.name(string) - upstreamBackup(Velero) or snapshot filename (etcd-snapshot).backupRef.namespace(string) - empty foretcd-snapshot.backupRef.storageLocation(string) - overrideBackupStorageLocation(Velero only).mode(enum) -checksum-only(default) orfull-restore.sandboxNamespace(string) - required whenmode=full-restore, must end with-bvsandbox(admission policy).timeout(Duration) - default15m, bounded at1h.
Status
phase(enum) -Pending,Running,Succeeded,Failed.startTime,completionTime.resultRef-BackupVerifyResultproduced (empty untilSucceeded).conditions[].
Example
apiVersion: security.ugallu.io/v1alpha1kind: BackupVerifyRunmetadata: { 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: 10mBackupVerifyResult
Section titled “BackupVerifyResult”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 forchecksum-only).findings[]- per-finding records:{code, message, severity, detail}. An empty list withphase=Succeededmeans a healthy backup.
Status
worstSeverity(enum) -critical,high,medium,low,info. The maximum acrossfindings.
Retained 30 days by ugallu-ttl.
Example (controller-produced)
apiVersion: security.ugallu.io/v1alpha1kind: BackupVerifyResultmetadata: { 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: lowComplianceScanRun
Section titled “ComplianceScanRun”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) - default10m, bounded at30m.
Status
phase(enum) -Pending,Running,Succeeded,Failed.startTime,completionTime.resultRef.conditions[].
Example
apiVersion: security.ugallu.io/v1alpha1kind: ComplianceScanRunmetadata: { 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: 5mComplianceScanResult
Section titled “ComplianceScanResult”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/v1alpha1kind: ComplianceScanResultmetadata: { 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: 4status: worstSeverity: high