fix(netpol): scope datastore-toegang + default-deny in rig-system#75
Conversation
Blokker 1: OPI verliest Postgres-toegangOPI draait in De nieuwe ingress-rule op Fix-opties (kies een): A. Voeg een derde ingress-rule toe voor B. Label A is netter (geen "alsof het een tenant is"-label op de ops-namespace). Blokker 2:
|
Follow-up: Blokker 2 opgelost door author, Blokker 1 augmentation gepushtBlokker 2 (default-deny breekt Keycloak/Redis) is volledig opgelost door author in commit `b28e194c` — de `default-deny-ingress` selecteert nu alleen `cnpg.io/cluster: rig-db` pods, met expliciete comment die de Keycloak/Redis-impact erkent. Mooi gedaan. Blokker 1 (OPI verliest postgres-toegang) persisteerde nog: `rig-prd-operations` heeft geen `created-by: operations-manager` label (OPI genereert zijn eigen namespace niet), dus de tenant-rule miste 'm. Augmentation gepusht (`1fa59764`): derde ingress-rule met expliciete naam-match op `kubernetes.io/metadata.name: rig-prd-operations`. Additief — beperkt niets, dekt alleen de OPI-namespace. Verificatie deep-audit
Pre-merge gate`kustomize build` van `infrastructure/.../postgresql/database/overlays/odcn` schoon. Voor merge: rookproef op staging:
Daarna LGTM voor merge. Aparte opmerking (niet blokkerend)`rig-prd-operations` is conceptueel een door-OPI-bediende namespace; je zou er ook gewoon het label `created-by: operations-manager` op kunnen zetten (in `bootstrap/rig-system/kustomize/overlays/odcn-production/namespace.yaml`), dan dekt rule 2 het al en valt rule 3 weg. Twee mechanismes voor één concept is dan op termijn op te ruimen. Voor nu is de rule duidelijk genoeg en maakt niks stuk. |
Follow-up issues aangemaaktItems uit deze PR die naar follow-ups verschuiven:
Pre-merge gates (staging-validatie) blijven in deze PR. |
1fa5976 to
3c81775
Compare
Productie-realiteit
Wijzigingen
VolgendeArgo dry-run + sync op staging vóór merge. |
a64be27 to
95d083e
Compare
De productie-NetworkPolicies van de gedeelde datastores in rig-system
stonden ingress toe vanuit ALLE namespaces via een lege
`namespaceSelector: {}`, en er was nergens een default-deny. Daardoor kon
elke tenant-pod (rig-prd-{willekeurig project}) TCP openen naar Postgres
(5432), MinIO (9000) en Vault (8200); alleen applicatie-credentials
scheidden tenants nog van elkaar.
Wijzigingen:
- Postgres: lege selector vervangen door een tenant-allowlist op label
`created-by: operations-manager` (stempel die OPI op tenant-namespaces
zet, niet op infra-namespaces). Ongelimiteerde `egress: - {}` van de
DB-pod ingeperkt tot DNS, intra-rig-system (CNPG-replicatie + in-cluster
MinIO-backuptarget) en HTTPS uitgaand (off-cluster backup/WAL).
- MinIO: lege selector vervangen door dezelfde tenant-allowlist voor de
S3 API-poort (9000).
- Vault: de all-namespaces-regel volledig verwijderd. Vault wordt alleen
door OPI in rig-system gebruikt; geen enkele tenant heeft Vault nodig.
- Nieuwe default-deny-ingress NetworkPolicy in rig-system als vangnet,
zodat een toekomstige lege-selector-regressie niet alles heropent.
De default-deny-ingress gebruikte podSelector: {} en selecteerde
daarmee elke pod in rig-system. In de odcn-productiebundel draaien
Keycloak en Redis ook in rig-system zonder eigen NetworkPolicy. Een
cluster-brede deny zou al hun ingress blokkeren (OPI -> Keycloak/Redis,
ingress-nginx -> Keycloak, tenant -> OIDC), een platformbrede storing
die erger is dan de cross-tenant blootstelling die deze PR dicht.
Selector nu beperkt tot de CNPG-postgres-pods (cnpg.io/cluster: rig-db),
conform het gedocumenteerde doel van de policy.
De ingress-rules accepteerden alleen rig-system (intra-namespace) en tenant-namespaces met label 'created-by: operations-manager'. In odcn-production draait OPI echter in 'rig-prd-operations', een bootstrap-gegenereerde namespace die dat label niet draagt (OPI genereert zijn eigen namespace niet). Zonder expliciete naam-match viel OPI's verbinding naar rig-db-rw:5432 onder de default-deny en zou OPI niet meer kunnen starten na deze policy-update. De toegevoegde rule is een namespaceSelector op 'kubernetes.io/metadata.name: rig-prd-operations', dezelfde vorm als de bestaande rig-system-rule. Tenant-toegang via created-by-label en monitoring-toegang via aparte allow-postgres-monitoring policy blijven ongewijzigd.
Voorgaande versie verwees overal naar 'rig-system' en aanverwante labels, maar die namespace bestaat niet op odcn-production. De kustomize-sops CMP plugin schrijft alleen de top-level kustomization.yaml namespace om naar ARGOCD_APP_NAMESPACE (rig-prd-operations); label-selectors binnen NetworkPolicy ingress/egress regels blijven echter letterlijk staan en matchten dus niets, waardoor de cross-tenant lek bleef bestaan. Vier files herzien: - postgresql-networkpolicy.yaml: namespace rig-prd-operations, ingress-rules op kubernetes.io/metadata.name=rig-prd-operations (platform: OPI + Keycloak + co-located) plus created-by=operations-manager (tenant-namespaces; oude pre-label-era tenants zijn handmatig gepatcht). - default-deny-ingress.yaml: namespace rig-prd-operations. - minio-networkpolicy.yaml: zelfde labelmodel; ingress controller bron is openshift-ingress (odcn) ipv ingress-nginx. - vault-networkpolicy.yaml: idem. Vault wordt alleen door OPI consumed in rig-prd-operations. Tenant-namespaces zonder created-by-label (rig-prd-amt, rig-prd-test) zijn met kubectl label gepatcht voor backfill. rig-prd-example was leeg.
8ac22d8 to
c110b88
Compare
Eén NetworkPolicy-file per service, met deny + allow samen. Verwijdert de losse default-deny-ingress.yaml; elke service-file is nu zelfdragend.
K8s NetworkPolicy is allow-only; podSelector + policyTypes maakt pods automatisch deny-by-default. Aparte deny-policy was puur cosmetisch en verwarrend. Header-comment in elke file legt het kort uit.
Vault is niet deployed op productie; barmanObjectStore is niet geconfigureerd. Egress naar 0.0.0.0/0:443 was erfgoed van een originele PR-aanname, niet gebaseerd op werkelijke usage. YAGNI — toevoegen wanneer feature aangezet wordt en het concrete CIDR-bereik bekend is.
…orrigeerd Live productie-verificatie: - minio pod heeft label 'app: minio', niet 'app.kubernetes.io/name: minio' (selector aangepast; oude selector matchte 0 pods). - minio/config/overlays/odcn was uitgecommentarieerd in clusters/odcn — geactiveerd, anders had de minio-policy geen effect op productie. - rig-redis (in rig-prd-operations) had geen NetworkPolicy; tenants en alle cluster-pods konden cross-tenant cache-data benaderen. Policy toegevoegd: alleen rig-prd-operations + tenant-namespaces met created-by-label op port 6379. - Postgres + MinIO + Redis egress beperkt tot DNS + intra-namespace (Postgres CNPG replicatie). Geen speculatieve internet-egress.
Probleem
De productie-NetworkPolicies van de gedeelde datastores in
rig-system(
overlays/odcn) stonden ingress toe vanuit alle namespaces via eenlege
namespaceSelector: {}, en er bestond nergens in de repo eendefault-deny. Concreet:
from: [{namespaceSelector: {}}]-> 5432, plus een volledigongelimiteerde
egress: - {}vanuit de DB-pod.namespaceSelector: {}-> 9000 (S3 API).namespaceSelector: {}-> 8200 (Vault API).Gevolg: elke tenant-pod (
rig-prd-{willekeurig project}) kon een TCP-verbinding opzetten naar elke gedeelde datastore. De enige scheiding
tussen tenants was applicatie-niveau credentials, niet het netwerk. Dit
is cross-tenant bereikbaarheid op de gedeelde dataopslag.
Oplossing
Scoping van de bestaande policies (legitieme consumenten behouden:
de bestaande
rig-system-,ingress-nginx- enmonitoring-regels zijnongewijzigd):
namespaceSelector.matchLabels.created-by: operations-manager.wordt uitsluitend door OPI in
rig-systemgebruikt; geen enkele tenantheeft Vault nodig, dus dit is het strakst gescoped.
egress: - {}ingeperkt tot DNS (kube-dns),intra-
rig-system(CNPG-replicatie/WAL + in-cluster MinIO-backuptarget)en HTTPS uitgaand (off-cluster backup/WAL-archief over TLS). Aanname:
backups gaan naar een HTTPS S3-endpoint; als er uitsluitend een
in-cluster backuptarget is, kan de 0.0.0.0/0:443-regel verder dicht.
Default-deny vangnet:
default-deny-ingressNetworkPolicy (podSelector: {},policyTypes: [Ingress]) inrig-system, gewired viapostgresql/database/overlays/odcn/kustomization.yaml. Dit zorgt dateen datastore-pod zonder matchende allow-policy standaard onbereikbaar
is, zodat een toekomstige lege-selector-regressie niet stilletjes alles
heropent. Egress blijft hier bewust onbeheerd zodat andere
rig-system-workloads niet geraakt worden.Afhankelijkheid: tenant-namespace-label
Tenant-namespaces krijgen vandaag van OPI exact een onderscheidend label:
created-by: operations-manager(zie
operations-manager/python/manifests/namespace.yaml.jinja). Infra-namespaces (
rig-system,monitoring,ingress-nginx) dragen dit labelniet. De scoping gebruikt dit bestaande label - er is geen nieuw,
nog-niet-bestaand label verzonnen. Er is geen per-tenant onderscheidend
label; deze policies isoleren tenants als groep van infra, niet tenants
onderling op netwerkniveau (dat is buiten scope van deze fix en hangt
samen met de per-tenant allow-all policy die OPI genereert - aparte issue).
Pre-merge gate (verplicht)
kustomizeis niet beschikbaar in de werkomgeving en de productie-SOPS-sleutel ontbreekt lokaal, dus een volledige
kustomize buildvan deodcn-overlays kon hier niet draaien. Wel gevalideerd: alle gewijzigde en
toegevoegde YAML-bestanden parsen correct (ruamel) en de pre-commit
check yaml-hook is geslaagd. Voor merge moet eenkustomize buildvan de drie odcn-overlays draaien als gate:infrastructure/bootstrap/infrastructure/postgresql/database/overlays/odcninfrastructure/bootstrap/infrastructure/minio/config/overlays/odcninfrastructure/bootstrap/infrastructure/vault/config/overlays/odcnAard
Pre-existing en onafhankelijk van andere openstaande security-fixes.
Raakt alleen
overlays/odcnNetworkPolicies en een kustomization-resourcelijst.