How drift detection works
Cloudkeel-DD compares desired state against actual state on every scan.
desired (what you declared) actual (what's really running)───────────────────────────── ──────────────────────────────Terraform Cloud workspace ┐raw .tfstate in S3/GCS/Blob ├──► live cloud read (Azure/AWS/GCP APIs)Helm release record (k8s) ┘ live Kubernetes API read │ │ └──────────► diff ◄──────┘ │ drift · unmanaged · policyThe two halves
Section titled “The two halves”Most clouds need two integrations working together:
- A state source — Terraform Cloud, or raw
.tfstatein cloud storage — supplies the desired state. - A cross-check credential — a read-only Azure/AWS/GCP identity — lets Cloudkeel-DD read the actual live resources.
With only the state source, resources are discovered but tagged “no live comparison available”: you get inventory, not drift. With only the credential, there’s nothing to compare against. Connect both, per cloud.
Kubernetes is the exception — one kubeconfig integration is self-contained: desired = Helm’s own stored release manifest, actual = a live read of the Kubernetes API.
What a scan does
Section titled “What a scan does”- Ingest desired state — parse the workspace /
.tfstate/ Helm release. - Read actual state — call the cloud or Kubernetes API for each resource, using the read-only credential and its enabled scopes.
- Diff — per-resource, field by field, through type-specific normalizers that focus on security-relevant fields.
- Detect unmanaged — anything live in an enabled scope that no state declares.
- Evaluate policy — run the finding through the policy set (best-effort; a broken policy engine never fails the scan).
- Record — open, refresh, or auto-resolve drift events with full history.
Scopes
Section titled “Scopes”A scope is an account / subscription / project / cluster that a credential can see. Live verification only runs against enabled scopes:
- AWS and GCP auto-enable the scope from the account ID / project ID you enter.
- Azure discovers your subscriptions and leaves each disabled until you opt in — a common “connected but no drift shows” cause. See troubleshooting.
By-design behaviours (not bugs)
Section titled “By-design behaviours (not bugs)”- Tag/label-only changes aren’t flagged. A changed cloud tag, GCP label, or Kubernetes label is low-signal; the normalizers focus on security-relevant fields (firewall/security-group rules, replica counts, images).
- Adding a brand-new field the chart never declared isn’t Kubernetes drift — changing a field the manifest owns is. The API server defaults dozens of fields no chart declares; without this every resource would “drift” the moment it was created.