Skip to content

fix(argocd): beperk productie-Applications met restrictief AppProject#78

Open
anneschuth wants to merge 7 commits into
mainfrom
fix/argocd-appproject-restrict
Open

fix(argocd): beperk productie-Applications met restrictief AppProject#78
anneschuth wants to merge 7 commits into
mainfrom
fix/argocd-appproject-restrict

Conversation

@anneschuth

Copy link
Copy Markdown
Member

Probleem (vooraf bestaand, onafhankelijk)

De twee productie-Applications staan in het ingebouwde default AppProject:

  • argocd-application-production-infrastructure.yaml -> repo RijksICTGilde/RIG-Cluster.git, pad infrastructure/bootstrap/clusters/odcn, prune: true, selfHeal: true
  • argocd-application-user-applications.yaml -> externe repo RijksICTGilde/argo-applications.git, pad odcn-production, prune: true, selfHeal: true

Er bestaat nergens in de repo een AppProject CR die default inperkt. Het ingebouwde default project staat standaard sourceRepos: '*', destinations: '*' en clusterResourceWhitelist: '*' toe.

Supply-chain takeover-pad

Iedereen die naar main van een van beide GitHub-bronrepo's kan pushen, krijgt willekeurige cluster-brede Kubernetes-objecten automatisch toegepast. Met clusterResourceWhitelist: '*' valt daar ook een ClusterRoleBinding onder die een door de aanvaller gecontroleerde ServiceAccount aan cluster-admin bindt. selfHeal: true herstelt elke handmatige terugdraai automatisch binnen seconden. Netto: één git-push = overname van het productiecluster. De externe repo argo-applications vergroot het aanvalsoppervlak buiten dit cluster.

Wijziging

  • Nieuw AppProject rig-platform in de odcn-production overlay:
    • sourceRepos gepind op exact de twee legitieme repo-URL's, geen wildcard. Dit alleen al sluit de takeover via een willekeurige andere repo uit.
    • destinations gepind op https://kubernetes.default.svc plus uitsluitend de namespaces waar deze apps legitiem deployen: rig-prd-operations (de destination.namespace van beide Applications) en rig-system (waar de infrastructuur-overlay aantoonbaar resources plaatst).
    • clusterResourceWhitelist conservatief: Namespace, ClusterRole, ClusterRoleBinding (external-dns levert aantoonbaar een ClusterRole + ClusterRoleBinding). Géén *.
    • namespaceResourceWhitelist bewust breed (*/*): de blast radius is al ingeperkt door de destination-namespace-pinning; een strakke namespaced-whitelist zou de platform-sync stilletjes breken zonder extra winst.
  • Beide Applications van project: default naar project: rig-platform.
  • AppProject toegevoegd aan de odcn-production kustomization.yaml.

VERPLICHTE validatie op staging vóór merge

kustomize is lokaal niet beschikbaar en de productie-SOPS-sleutel ontbreekt, dus lokaal is alleen geverifieerd dat de YAML parst en dat de kustomization-referenties kloppen. Voor merge is het volgende verplicht op staging:

  1. kustomize build van de odcn-production overlay (met SOPS-plugin) moet slagen.
  2. ArgoCD dry-run / sync van beide Applications onder het nieuwe project moet slagen.
  3. Specifiek controleren dat geen legitieme resource geblokkeerd wordt. Delen van de infrastructuur-overlay zijn SOPS-versleuteld; daardoor zijn niet alle namespaces en cluster-brede kinds statisch te enumereren. Als de versleutelde overlays naar een andere namespace deployen, of een ander cluster-breed kind aanmaken dan in de whitelist staat, faalt de sync. Dat is dan zichtbaar op staging en de whitelist wordt daar uitgebreid met het concrete kind/de concrete namespace — niet met *.

Een te strakke whitelist breekt de productie-GitOps. Niet mergen zonder groene staging-validatie.

Aanbeveling

Branch protection inschakelen op main van zowel RijksICTGilde/RIG-Cluster als RijksICTGilde/argo-applications (verplichte review, geen force-push). Het AppProject perkt de schade in; branch protection adresseert het instappunt.

@uittenbroekrobbert

Copy link
Copy Markdown
Contributor

LGTM met restjes. Statische platform-AppProject die default vervangt is de juiste hef; sourceRepos op exacte URL's (incl. credential-prefix) sluit de supply-chain-takeover-route.

Geverifieerd

  • Geen overlap met fix: dicht systemische template-injectie in OPI-manifesten #77. fix: dicht systemische template-injectie in OPI-manifesten #77 raakt operations-manager/python/manifests/argocd-appproject.yaml.jinja (per-tenant template, gerenderd door OPI per ZAD-project); deze PR raakt alleen het platform-niveau AppProject (bootstrap/rig-system/.../argocd-appproject-rig-platform.yaml). Verschillende controllers, onafhankelijke merge-volgorde.
  • Destinations dekken de actieve namespaces. Cross-check tegen infrastructure/bootstrap/clusters/odcn/kustomization.yaml: keycloak/controller, keycloak/config, postgresql/database, redis/controller zetten namespace: rig-system; minio/controller, prometheus/controller, external-dns/controller zetten rig-prd-operations. Allebei in de whitelist. backup-destination (zou rig-prd-backup raken) staat uitgecommentarieerd, niet relevant nu.
  • clusterResourceWhitelist-set is voldoende. ClusterRole+ClusterRoleBinding worden gegenereerd door prometheus/controller/overlays/odcn/ (external-dns, kube-state-metrics). Geen andere cluster-scoped kinds in de actieve odcn-paths.

Twee kleinigheden

1. Comment/config mismatch

argocd-appproject-rig-platform.yaml:71-73: comment zegt "alleen waarschuwen" maar warn: false doet juist géén waarschuwing. Comment in lijn brengen óf warn: true zetten.

2. Namespace in clusterResourceWhitelist

Lijn 51-52 staat Namespace toe, maar geen enkele actieve odcn-path produceert een kind: Namespace-resource (backup-destination/controller/base/namespace.yaml is uitgecommentarieerd). Defense-in-depth-argument om te laten staan; alternatief is verwijderen tot daadwerkelijk benodigd. Niet kritiek.

Verplichte staging-validatie vóór merge

De PR-omschrijving noemt dit terecht. De inhoud van de externe repo RijksICTGilde/argo-applications (path odcn-production) is hier niet statisch te verifiëren. Als die repo manifesten bevat met metadata.namespace buiten rig-prd-operations/rig-system, of cluster-scoped kinds buiten {Namespace, ClusterRole, ClusterRoleBinding}, faalt de sync. Dus:

SOPS_AGE_KEY="$(sed -n '3p' security/key.txt)" kustomize build \
  --enable-alpha-plugins --enable-exec --load-restrictor LoadRestrictionsNone \
  bootstrap/rig-system/kustomize/overlays/odcn-production/

en ArgoCD dry-run/sync op staging op zowel production-infrastructure als user-applications onder rig-platform.

Apart, niet-blokkerend

De sandboxed-local overlay blijft op default-AppProject (*/*/*). Buiten scope, maar verdient als parallel task ook deze restrictie te krijgen — anders is er een tweede instap-pad met platform-wide blast radius.

@uittenbroekrobbert

Copy link
Copy Markdown
Contributor

Follow-up: kleine augmentation (`fac878c7`) + LGTM voor merge

Eén kleinigheid uit de eerdere review gefixt: `orphanedResources.warn: false` paste niet bij de comment "alleen waarschuwen". Flipped naar `warn: true` — manueel toegepaste cluster-resources die niet in git staan worden nu zichtbaar in de Argo UI. Nuttig detectiemechanisme bovenop de project-scoping, geen destructieve auto-prune.

De `Namespace` in `clusterResourceWhitelist` (defense-in-depth, nog niet actief gebruikt) blijft staan zoals voorgesteld. Geen actie nodig.

Verificatie deep-audit (sinds initial review)

  • Geen nieuwe commits van author; PR-shape onveranderd
  • Geen overlap met fix: dicht systemische template-injectie in OPI-manifesten #77 (verschillend AppProject, verschillende controller)
  • Destinations dekken alle actieve odcn-namespaces (kruisgecheckt tegen `infrastructure/bootstrap/clusters/odcn/kustomization.yaml`)
  • `clusterResourceWhitelist` dekt de cluster-scoped kinds uit `prometheus/controller/overlays/odcn` (external-dns ClusterRole/ClusterRoleBinding)

Pre-merge gate (verplicht, zoals PR-tekst noemt)

```bash
SOPS_AGE_KEY="$(sed -n '3p' security/key.txt)" kustomize build \
--enable-alpha-plugins --enable-exec --load-restrictor LoadRestrictionsNone \
bootstrap/rig-system/kustomize/overlays/odcn-production/
```

Plus Argo dry-run op staging voor zowel `production-infrastructure` als `user-applications` onder `rig-platform`. Als de SOPS-versleutelde overlays of de externe `argo-applications`-repo cluster-scoped kinds buiten `{Namespace, ClusterRole, ClusterRoleBinding}` blijken te bevatten, faalt de sync zichtbaar daar — uitbreiding van de whitelist daar, niet `*`.

Apart (sandbox-overlay, niet-blokkerend)

`sandboxed-local` blijft op `default`-AppProject met ``/``/`*`. Tweede instap-pad met platform-wide blast radius. Verdient een parallelle PR met dezelfde restrictie (eenvoudiger qua scope, geen SOPS-overlay onbekenden). Schrijf ik op als follow-up.

LGTM voor merge na staging-gate.

@uittenbroekrobbert

Copy link
Copy Markdown
Contributor

Follow-up issues aangemaakt

@uittenbroekrobbert uittenbroekrobbert force-pushed the fix/argocd-appproject-restrict branch from fac878c to ccc2bac Compare May 19, 2026 20:39
@uittenbroekrobbert

Copy link
Copy Markdown
Contributor

Veiligheidsupdate: clusterResourceWhitelist leeg

Na overleg: onze Argo ServiceAccount heeft op productie geen rechten om cluster-scoped resources aan te maken (ClusterRole, ClusterRoleBinding, Namespace, etc.). Die worden out-of-band door het ODCN-platformteam beheerd. De eerdere whitelist met Namespace, ClusterRole, ClusterRoleBinding was misleidend — Argo kon ze toch niet maken.

Augmentation 53bc94cb: clusterResourceWhitelist: [] (leeg). Effecten:

  • Elke poging om cluster-scoped resources via deze AppProject te syncen wordt expliciet geblokkeerd
  • Bestaande cluster-scoped resources (door ODCN beheerd) worden niet aangeraakt — Argo claimt geen ownership over kinds die niet in de whitelist staan
  • prune: true op de Applications (al actief op main, geen wijziging) raakt alleen resources die in git staan en daar verdwijnen; lege whitelist verandert dat gedrag niet

Restrictie is daarmee strakker dan eerst: voorheen claimde Argo dat het 3 cluster-kinds mocht beheren (zonder de rechten), nu is het expliciet null.

anneschuth and others added 4 commits May 26, 2026 08:29
De twee productie-Applications (production-infrastructure en
user-applications) draaiden in het ingebouwde 'default' AppProject met
prune + selfHeal. 'default' staat sourceRepos '*', destinations '*' en
clusterResourceWhitelist '*' toe. Gevolg: iedereen die naar 'main' van
een van de twee GitHub-bronrepo's kan pushen krijgt willekeurige
cluster-brede objecten (inclusief ClusterRoleBindings) automatisch
toegepast én self-healed. Dat is een volledige overname van het
productiecluster via een git-push.

Wijziging:
- Nieuw AppProject 'rig-platform' met sourceRepos gepind op exact de
  twee legitieme repo-URL's, destinations gepind op de in-cluster API
  server plus uitsluitend rig-prd-operations en rig-system, en een
  conservatieve clusterResourceWhitelist.
- Beide Applications van project 'default' naar 'rig-platform' verplaatst.
- AppProject toegevoegd aan de odcn-production kustomization.

Vooraf bestaand en onafhankelijk van andere wijzigingen.
De comment beschreef "alleen waarschuwen" maar warn stond op false, wat
juist géén waarschuwing geeft. Op true gezet zodat manueel toegepaste
ClusterRoleBindings of andere resources die niet in git staan zichtbaar
worden in de Argo UI — nuttig detectiemechanisme bovenop de
project-scoping, zonder destructieve auto-prune toe te voegen.
Onze Argo ServiceAccount heeft op productie geen rechten om cluster-scoped
resources aan te maken; die worden out-of-band door ODCN beheerd. Een
whitelist met ClusterRole/ClusterRoleBinding/Namespace was misleidend
(deed in praktijk niks omdat Argo ze toch niet kan maken).

Lege whitelist blokkeert nu expliciet elke cluster-scoped sync-poging,
zonder bestaande resources te raken.
Live verificatie: production-infrastructure en user-applications Apps
syncen uitsluitend naar rig-prd-operations. De rig-system destination
was overgekomen van een sandbox-context en is op odcn-production dood.
@uittenbroekrobbert uittenbroekrobbert force-pushed the fix/argocd-appproject-restrict branch from 53bc94c to 07cd904 Compare May 26, 2026 06:30
Sandbox krijgt dezelfde restrictie als odcn-production maar gepin op
Forgejo in-cluster repos en rig-system namespace. Maakt het mogelijk
het AppProject-patroon op sandbox te valideren voordat we naar productie
syncen.
rig-prd-operations / rig-system bevatten bootstrap-resources (Argo, OPI,
Keycloak, etc.) die niet door Argo gemanaged worden — die zouden tientallen
ruis-warnings genereren zonder actie. Namespace-opsplitsing als follow-up.
@uittenbroekrobbert

Copy link
Copy Markdown
Contributor

Deze PR mergen we als laatste in de security-batch — om volledige controle te houden over de productie-rollout.

Sandbox-validatie geslaagd: AppProject + Application project-switch toegepast op kind-rig-sandbox, beide Apps blijven Synced + Healthy, geen resources verloren of geblokt.

Productie-resource-audit (live): 170 resources totaal, 0 cluster-scoped, 0 buiten rig-prd-operations. Alles past binnen de nieuwe namespaceResourceWhitelist: */*. Per-tenant AppProjects/Applications die door user-applications aangemaakt worden hebben eigen project: references — die worden niet door deze restrictie geraakt.

Rollback-pad: revert PR + task update-operations-manager CLUSTER_TYPE=odcn-production → terug naar project: default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants