Commit 8096d83
committed
GitOps drift detection + Argo CD API deep diff
Two coordinated capabilities for the "drift between deployments and GitOps"
ask, credential-free detection plus a hardened connected deep-diff view.
## Detection (no credentials)
- Manual-sync Applications continuously OutOfSync for >24h reach the issues
stream (gitops_out_of_sync, warning). Drift onset is tracked Radar-side per
app UID on the ResourceCache (Argo records no sync-status transition time);
a restart resets the clock — deliberately conservative.
- New gitops_stale category: a down application-controller emits one critical
rollup ("sync verdicts are frozen"), a majority-stale fleet (>=3 apps) one
warning rollup, isolated stale apps per-app warnings. Threshold max(30m,
10x argocd-cm timeout.reconciliation); controller pods found by label across
all namespaces.
- Cluster Audit: gitops-unmanaged-workload / gitops-helm-only-workload flag
top-level workloads outside GitOps via the pkg/subject overlay tiers. Gated
on real GitOps root objects existing (not just CRDs); ownerRef'd workloads
skipped; Argo label-tracking recognized by cross-referencing app names.
- GitOps detail page discloses spec.ignoreDifferences as comparison coverage
(rule/jq/managed-fields counts + kinds).
## Argo CD API deep diff (connected)
- pkg/argoapi: pure REST client for argocd-server (filtered managed-resources,
session/userinfo probe, version reachability, CLI-config token extraction);
no internal/ imports, so radar-hub can reuse it.
- internal/argocd: discovery by service label, argocd-owned port-forward for
out-of-cluster runs, 15s TTL cache, lazy self-reconnect, context-switch reset.
- GET /api/argo/applications/{ns}/{name}/resource-diff: dual RBAC gate
(Application namespace access + per-kind get SAR) before any upstream call;
Git-rendered desired vs normalized live YAML + field entries.
- UI: Settings "Argo CD" card (URL/token/insecure-TLS/CLI-session), inline
unified diff on the expanded change row with a full-screen maximize, and a
"Connect Argo CD" hint when disconnected.
## Security model (3 review rounds, all findings fixed)
- Token bound to its origin AND kubeconfig context: changing the URL or
switching context requires re-entering it; the probe runs off an immutable
snapshot (URL + token + TLS + frozen k8s client/config), fails closed if a
switch races the capture, and commits only under a generation check — the
token never reaches a different cluster's argocd-server.
- Secret redaction is fail-closed: data/stringData/binaryData masked in any
shape, annotation values masked, last-applied/managedFields/status stripped
before serialization. No un-redact.
- No credential or secret in responses or logs: token redacted from GET
/api/config and probe logs; upstream Argo error bodies never reach responses.
Verified: full Go suite + tsc green both modules; real-cluster validation
against nonprod GKE Argo (discovery/port-forward/token-verify round-trip);
diff render + redaction + UI verified on the gitops-demo kind cluster.1 parent a582c01 commit 8096d83
57 files changed
Lines changed: 8319 additions & 55 deletions
File tree
- docs
- internal
- argocd
- audit
- config
- issues
- k8s
- server
- packages/k8s-ui/src
- components
- gitops/insights
- issues
- types
- pkg
- argoapi
- audit
- gitops/insights
- issuesapi
- scratchpad
- scripts
- gitops-demo
- web/src
- api
- components
- gitops
- settings
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
0 commit comments