|
| 1 | +# Cutover — uitvraag naar de cluster-interne outway |
| 2 | + |
| 3 | +> Draaiboek voor het omzetten van `berichtenuitvraag` van de publieke ingress-URL van de outway |
| 4 | +> naar zijn cluster-interne Service-adres. Hoort bij de wijziging die `LISTEN_HTTPS` op |
| 5 | +> `logius-fscoutway` zet; achtergrond in `docs/plans/2026-08-19-outway-https-clusterip.md`. |
| 6 | +
|
| 7 | +Doeladres: |
| 8 | + |
| 9 | +``` |
| 10 | +https://fsc-logius-logius-fscoutway.rig-prd-mpfb-8wh.svc.cluster.local:8443 |
| 11 | +``` |
| 12 | + |
| 13 | +De Service heet `<deployment>-<component>` en leeft in namespace `rig-prd-<project>`. Let op dat |
| 14 | +`zadctl deployment describe` `mpfb-8wh` als "Namespace" toont; dat is het project-id. |
| 15 | + |
| 16 | +## Dit is een cutover, geen toevoeging |
| 17 | + |
| 18 | +Twee dingen maken dat de stappen in één venster horen en niet los uitgerold kunnen worden. |
| 19 | + |
| 20 | +**De bestaande ingress-route breekt zodra de outway TLS spreekt.** De gerenderde Ingress |
| 21 | +(`logius-fscoutway-ingress.yaml`) termineert TLS aan de rand (`tls: - {}`) en praat plain HTTP |
| 22 | +naar poort 8443; er staat geen `backend-protocol: HTTPS`-annotatie op. Zet je `LISTEN_HTTPS=true`, |
| 23 | +dan spreekt de pod TLS en levert de publieke route 502. |
| 24 | + |
| 25 | +**Het trust-anker vervangt de JVM-default trust-store, het vult die niet aan.** Zodra |
| 26 | +`quarkus.tls.outway` bestaat valideert élk magazijn-endpoint tegen de interne CA — ook een |
| 27 | +endpoint dat nog op de publieke ingress staat, met een publiek certificaat. Vandaar dat het anker |
| 28 | +per deployment gaat zolang niet elke deployment mee is. |
| 29 | + |
| 30 | +## Voorwaarden |
| 31 | + |
| 32 | +- `ZAD_API_KEY` voor project `mpfb-8wh` staat in de omgeving (`.env.zadctl`); `zadctl deployment |
| 33 | + list` werkt. |
| 34 | +- De wijziging is uitgerold, zodat de app de TLS-configuratie kent. |
| 35 | + |
| 36 | +## Stap 0 — netwerktoegang tussen de twee deployments |
| 37 | + |
| 38 | +Deployments van hetzelfde project mogen elkaar standaard niet bereiken. De platform-service |
| 39 | +`cross-domain-access` heft dat gericht op, en vraagt **twee** regels: een `outbound` bij de |
| 40 | +bellende kant en een `inbound` bij de gebelde kant. Eén van de twee is niet genoeg — de ontvanger |
| 41 | +geeft de toestemming. |
| 42 | + |
| 43 | +`zadctl service config set` schrijft het hele document; een veld dat je niet noemt wordt |
| 44 | +verwijderd. Lees dus eerst wat er staat (`zadctl --json service config get cross-domain-access`) |
| 45 | +en stuur het complete beeld terug: |
| 46 | + |
| 47 | +```yaml |
| 48 | +# cross-domain-access.yaml |
| 49 | +inbound: |
| 50 | + - name: uitvraag-naar-logius-fscoutway |
| 51 | + from: { project: mpfb-8wh, deployment: test, component: uitvraag } |
| 52 | + to: { component: logius-fscoutway, port: 8443 } |
| 53 | +outbound: |
| 54 | + - name: uitvraag-naar-logius-fscoutway |
| 55 | + from: { component: uitvraag } |
| 56 | + to: { project: mpfb-8wh, deployment: fsc-logius, component: logius-fscoutway, port: 8443 } |
| 57 | +``` |
| 58 | +
|
| 59 | +```bash |
| 60 | +zadctl service config set cross-domain-access --target project -f cross-domain-access.yaml --dry-run |
| 61 | +zadctl service config set cross-domain-access --target project -f cross-domain-access.yaml |
| 62 | +``` |
| 63 | + |
| 64 | +**`from.deployment` op de inbound-regel is niet optioneel in de praktijk.** Het schema zegt dat je |
| 65 | +'m open mag laten, en de API accepteert dat ook — maar er verschijnt dan géén NetworkPolicy voor |
| 66 | +de ontvangende kant, zonder waarschuwing. Logisch achteraf: de renderer bouwt een `podSelector` |
| 67 | +op het label `app: <deployment>-<component>`, en zonder deployment valt dat label niet te maken. |
| 68 | +Elke bellende deployment heeft dus zijn eigen inbound-regel nodig; PR-previews die ook op de |
| 69 | +interne route moeten, komen er los bij. |
| 70 | + |
| 71 | +Controleer de uitkomst aan de gerenderde manifests, niet aan de API-respons: onder |
| 72 | +`rig-cluster-application-test/odcn-production/mpfb-8wh/` horen nu |
| 73 | +`test/test-cross-domain-access-uitvraag-network-policy.yaml` (Egress) én |
| 74 | +`fsc-logius/fsc-logius-cross-domain-access-logius-fscoutway-network-policy.yaml` (Ingress) te |
| 75 | +staan, elkaars spiegelbeeld op poort 8443. |
| 76 | + |
| 77 | +## Stappen |
| 78 | + |
| 79 | +**1. De outway laat TLS toe op zijn serve-poort.** |
| 80 | + |
| 81 | +Niet via `upsert-peer.sh apply`: ZAD past `env_vars` uit een component-body alleen toe bij |
| 82 | +component-*creatie*, dus een re-POST verandert niets. De user-env-laag werkt wel op een bestaande |
| 83 | +component: |
| 84 | + |
| 85 | +```bash |
| 86 | +zadctl env add -c logius-fscoutway \ |
| 87 | + LISTEN_HTTPS=true \ |
| 88 | + TLS_SERVER_CERT=/etc/fsc/internal/logius/outway/cert.pem \ |
| 89 | + TLS_SERVER_KEY=/etc/fsc/internal/logius/outway/key.pem |
| 90 | +``` |
| 91 | + |
| 92 | +Beide certificaat-paden zijn de bijlagen die er al hangen (`cert-manifest.md`); er hoeft niets |
| 93 | +geüpload te worden. Vanaf hier is de publieke route stuk — de rest van de stappen hoort direct |
| 94 | +achter deze aan. |
| 95 | + |
| 96 | +**2. De uitvraag krijgt de interne CA als bestand.** |
| 97 | + |
| 98 | +De bijlage staat al in de catalogus van het project (`logius-internal-ca-root-cert`), alleen nog |
| 99 | +niet gekoppeld aan `uitvraag`: |
| 100 | + |
| 101 | +```bash |
| 102 | +zadctl attachment assign logius-internal-ca-root-cert uitvraag \ |
| 103 | + --provide-as file \ |
| 104 | + --mount-path /etc/fsc/internal/logius/ca/root.pem |
| 105 | +``` |
| 106 | + |
| 107 | +**3. De uitvraag krijgt het anker en de URL's, in één stap.** |
| 108 | + |
| 109 | +Per deployment, zodat de PR-previews op hun eigen (nog publieke) adres blijven werken tot ze mee |
| 110 | +verhuizen: |
| 111 | + |
| 112 | +```bash |
| 113 | +OUTWAY=https://fsc-logius-logius-fscoutway.rig-prd-mpfb-8wh.svc.cluster.local:8443 |
| 114 | + |
| 115 | +zadctl env add -c uitvraag --deployment test \ |
| 116 | + QUARKUS_TLS_OUTWAY_TRUST_STORE_PEM_CERTS=/etc/fsc/internal/logius/ca/root.pem \ |
| 117 | + QUARKUS_REST_CLIENT_PROFIEL_SERVICE_TLS_CONFIGURATION_NAME=outway |
| 118 | + |
| 119 | +zadctl env set -c uitvraag --deployment test \ |
| 120 | + MAGAZIJN_A_URL="$OUTWAY" \ |
| 121 | + PROFIEL_SERVICE_URL="$OUTWAY" |
| 122 | +``` |
| 123 | + |
| 124 | +`add` voor de twee nieuwe sleutels, `set` voor de twee die al bestaan — `add` op een bestaande |
| 125 | +sleutel is een conflict, geen overschrijving. Beide rollen standaard uit; met `--no-rollout` kun |
| 126 | +je ze stapelen en daarna één keer `zadctl deployment refresh test` doen. |
| 127 | + |
| 128 | +**4. Verifiëren.** |
| 129 | + |
| 130 | +```bash |
| 131 | +zadctl logs fsc-logius -c logius-fscoutway | grep -i "HTTPS server" # verwacht: starting HTTPS server |
| 132 | +zadctl logs test -c uitvraag | grep -iE "PKIX|SSLHandshake" # verwacht: niets |
| 133 | +``` |
| 134 | + |
| 135 | +**De outway logt vanaf nu elke twee seconden een TLS-fout, en dat hoort zo.** De readinessProbe |
| 136 | +is een `tcpSocket`-probe op 8443 met `periodSeconds: 2`; die opent een verbinding en sluit 'm |
| 137 | +meteen, wat een TLS-server als een afgebroken handshake ziet: |
| 138 | + |
| 139 | +``` |
| 140 | +ERROR ... "http: TLS handshake error from 10.x.x.x:39xxx: EOF" |
| 141 | +``` |
| 142 | + |
| 143 | +De probe slaagt gewoon (hij toetst alleen of de poort verbindingen aanneemt) en de deployment |
| 144 | +blijft Healthy. Filter erop bij het lezen van deze logs, en trap er niet in als je een écht |
| 145 | +handshake-probleem zoekt: dat komt van het adres van de uitvraag-pod en staat aan die kant als |
| 146 | +`PKIX path building failed`. |
| 147 | + |
| 148 | +Daarna de functionele smoke: een ophaal-request door de keten |
| 149 | +`berichtenuitvraag → logius-fscoutway → magazijna-fscinway → berichtenmagazijn`, met een verse BSN |
| 150 | +zodat de sessiecache de keten niet maskeert. Let op dat de inway aan de overkant die van |
| 151 | +**magazijn-a** is (project `mpfm-w3h`, deployment `fsc-magazijna`): magazijn-a is een eigen peer. |
| 152 | +`logius-fscinway` is de ingang voor de diensten die logius zélf publiceert, zoals de |
| 153 | +profiel-service, en komt in dit pad niet voor. Een nieuwe transactie in beide txlogs is het bewijs |
| 154 | +dat het verkeer écht door de outway liep. |
| 155 | + |
| 156 | +**5. De publieke ingress intrekken — punt van geen terugkeer.** |
| 157 | + |
| 158 | +Werkt de interne route, haal dan "Publicatie op het web" van `logius-fscoutway` weg in de ZAD-UI. |
| 159 | +Hij is dan niet meer in gebruik, en een outway met een publiek adres is oppervlak dat niemand |
| 160 | +nodig heeft. Werk `verify-zad.md` bij als dit gebeurd is. |
| 161 | + |
| 162 | +Doe deze stap pas als je de terugrol niet meer nodig denkt te hebben: het korte recept hieronder |
| 163 | +leunt op precies dat adres. |
| 164 | + |
| 165 | +## Terugrollen |
| 166 | + |
| 167 | +**Vóór stap 5.** Stap 1 en 3 zijn elkaars tegenhanger; draai ze samen terug: |
| 168 | + |
| 169 | +```bash |
| 170 | +zadctl env unset -c logius-fscoutway LISTEN_HTTPS TLS_SERVER_CERT TLS_SERVER_KEY |
| 171 | +zadctl env unset -c uitvraag --deployment test \ |
| 172 | + QUARKUS_TLS_OUTWAY_TRUST_STORE_PEM_CERTS QUARKUS_REST_CLIENT_PROFIEL_SERVICE_TLS_CONFIGURATION_NAME |
| 173 | +zadctl env set -c uitvraag --deployment test \ |
| 174 | + MAGAZIJN_A_URL=https://logius-fscoutway-fsc-logius-mpfb-8wh.rig.prd1.gn2.quattro.rijksapps.nl \ |
| 175 | + PROFIEL_SERVICE_URL=https://logius-fscoutway-fsc-logius-mpfb-8wh.rig.prd1.gn2.quattro.rijksapps.nl |
| 176 | +``` |
| 177 | + |
| 178 | +**Ná stap 5 werkt dat recept niet meer.** Die ingress-URL bestaat dan niet, dus je rolt terug naar |
| 179 | +een dood adres — en een terugrol draai je onder tijdsdruk. Zet in dat geval eerst "Publicatie op |
| 180 | +het web" op `logius-fscoutway` weer aan (ZAD-UI, `tls: standard`) en wacht tot de route antwoordt; |
| 181 | +pas daarna de commando's hierboven. Wil je die omweg vermijden, dan is de snellere terugval de |
| 182 | +env-vars leeghalen en `MAGAZIJN_A_URL`/`PROFIEL_SERVICE_URL` helemaal `unset`-en: de app valt dan |
| 183 | +terug op de component-aliassen, die rechtstreeks naar magazijn-a en de profiel-stub wijzen. Dat |
| 184 | +werkt zonder ingress, maar levert verkeer buiten de mesh om — zonder transactielogboek en zonder |
| 185 | +contractcontrole. |
| 186 | + |
| 187 | +De bijlage uit stap 2 mag blijven hangen: zonder de env-var uit stap 3 doet een gemount |
| 188 | +CA-bestand niets. Laat 'm staan, dan is een tweede poging één commando korter. |
0 commit comments