Dette dokument beskriver arkitekturen af de etablerede Keycloak instanser i NSP og hvorledes de sammen udgør et keycloak cluster i NSP.
Nedenstående tegning viser 1 instans af Keycloak (node) i clusteret. Noden består af en virtuel maskine hvorpå der afvikles en Keycloak server vha. Docker Compose. Dvs. clusteret vil bestå af f.eks. 3 tilsvarende virtuelle maskiner.
Databasen og NSP netværkskomponenten (LB) er fælles for det samlede Keycloak cluster. Databasen er en MariaDB.
Som det også fremgår på tegningen ovenfor, vil kald til Keycloak gå igennem en loadbalancer som ikke terminere TLS forbindelserne. Loadbalanceren foretager udelukkende loadbalancing og etablerer ”sticky” sessioner til de enkelte instanser baseret på klientens IP adresser.
På hver instans kører der en NGINX reverse proxy sammen med Keycloak. Formålet med denne NGINX er
- Terminere (m)TLS forbindelse
- Verificere trust til mTLS klientcertifikater (OCES3)
- Indsætte mTLS klientcertifikat i http header i kald som proxies videre til Keycloak.
- Begrænse adgang til forskellige administrative områder i Keycloak til whitelistede IP-adresser.
NSP Keycloak image
Der anvendes et Keycloak image som indeholder specifikke komponenter specielt udviklet til NSP. Dette image er baseret på det officielle Keycloak Docker image (se https://quay.io/repository/keycloak/keycloak). Dvs. al konfiguration og drift af Keycloak som Docker container beskrevet på https://www.keycloak.org/ er stadig aktuel. Der er dog truffet specifikke konfigurationsvalg i NSP Keycloak, og de specialudviklede komponenter har ligeledes specifikke konfigurationsparametre. Disse er beskrevet i installationsvejledningen.
TLS og mTLS
Adgangen til Keycloak sker udelukkende via enten TLS eller mTLS. Server certifikaterne udstedes af generelt trustede CA'er som anvendes i NSP.
Validering af mTLS klientcertifikater
Opgaven med at validerer mTLS klientcertifikater er delt mellem NGINX (se diagram nedenfor) og Keycloak.
Validering af trust i NSP Netværkskomponenten
NGINX terminerer TLS forbindelse. Dette betyder at server certifikatet er installeret i denne komponent.
Der laves optionelt klient autentifikation hvis klienten sender certifikater med ved etablering at TLS forbindelsen. NGINX verificerer at klient certifikatet er trusted. Trust er konfigureret med OCES3 Rod certifikatet (produktion eller test) og det forventes at klienten medsender intermediate (udstedende) CA certifikat sammen med klient certifikatet. Hvis der ikke medsendes intermediate certifikat så der kan etableres en trusted kæde til rod CA'en skal NSP Netværkskomponenten afvise klienten.
Hvis der etables en mTLS forbindelse med et trusted klientcertifikat, indsætter NSP Netværkskomponenten klientcertifikatet som http headers i request til Keycloak. Navngivning af denne header er gjort i både NSP Netværkskomponentens konfigurationen og i konfigurationen af Keycloak.
Validering i Keycloak
Når en request skal autoriseres via klientcertifikater i Keycloak gøres det på følgende vis:
- Klientcertifikat hentes fra http header.
- Revokeringsstatus for klientcertifikatet chekkes ved at slå certifikatets serienummer op i CRA databasen for certifikatets spærreliste URL ("X509v3 CRL Distribution Points" extension). Hvis der ikke findes en spærreliste i CRA for den pågældende URL, antages det at
- Den udstedende CA er ukendt i CRA, eller
- Den udstedende CA er selv spærret (dermed vil den ikke kunne udstede (og signere) CRL'er
- Gyldighed checkes - altså at certifikatet ikke er udløbet.
OCES 3 mTLS klientcertifikater
Klientcertifikater skal være OCES3 certifikater.
Format af Subject på mTLS klientcertifikater
Ved registrering af klienter skal certifikat subject dn angives i format som specificeret i RFC4514 (se https://datatracker.ietf.org/doc/html/rfc8705#section-2.1.2).
Dette er beklageligvis ikke det format som vises af f.eks. openssl. Eksempelvis vises subject dn for et OCES 3 test certifikat som følgende tekst streng af openssl's x509 kommando:
openssl x509 -in system-1.crt -subject -nocert
subject=CN=System 1, serialNumber=UI:DK-O:G:7bd0d84a-c1f3-4650-a351-4235c482ebeb, O=Testorganisation nr. 96024140, organizationIdentifier=NTRDK-96024140, C=DK
Den korrekte repræsentation af dette DN er jf. RFC4514 :
C=DK,2.5.4.97=#0c0e4e5452444b2d3936303234313430,O=Testorganisation nr. 96024140,2.5.4.5=#132e55493a444b2d4f3a473a37626430643834612d633166332d343635302d613335312d343233356334383265626562,CN=System 1
Keycloak benytter Java metoden
X509Certificate.getSubjectX500Principal().getName(X500Principal.RFC2253, CUSTOM_OIDS)
hvor
Map<String, String> CUSTOM_OIDS = new HashMap<>();
CUSTOM_OIDS.put("2.5.4.5", "serialNumber".toUpperCase());
CUSTOM_OIDS.put("2.5.4.15", "businessCategory".toUpperCase());
CUSTOM_OIDS.put("1.3.6.1.4.1.311.60.2.1.3", "jurisdictionCountryName".toUpperCase());
CUSTOM_OIDS.put("1.2.840.113549.1.9.1", "emailAddress".toUpperCase());
til at finde en streng repræsentation af det anvendte klientcertifikat og benytter denne streng til at verificerer den specificerede tls_client_auth_subject_dn i metadata.
Det betyder at Subject (fra openssl)
CN=System 1, serialNumber=UI:DK-O:G:7bd0d84a-c1f3-4650-a351-4235c482ebeb, O=Testorganisation nr. 96024140, organizationIdentifier=NTRDK-96024140, C=DK
Skal angives i metadata filerne med følgende værdi:
"tls_client_auth_subject_dn": "C=DK,2.5.4.97=#0c0e4e5452444b2d3936303234313430,O=Testorganisation nr. 96024140,SERIALNUMBER=UI:DK-O:G:7bd0d84a-c1f3-4650-a351-4235c482ebeb,CN=System 1"
Forskellen er
- De 5 værdier skal stå i omvendt rækkefølge
- Mellemrum efter komma mellem værdierne fjernes
- "serialNumber" → "SERIALNUMBER"
- "organizationIdentifier" → "2.5.4.97"
- Værdien af organizationIdentifier skal angives som
# + Hex værdien af UTF8String (ASN1) encoding
NSP specifikke komponenter i Keycloak
I dette afsnit er formål og funktionalitet i de forskellige NSP specfikke udvidelser af Keycloak dokumenteret.
NSP CRA Service
Integrationen til CRA er implementeret som en Keycloak SPI "NspCraSpi". Denne service loader en cachet version af CRA databasen i et memory map, og benytter dette til at lave revokeringscheck.
Indlæsning af CRA
Alle CRL'er i CRA databasen indlæses i et map fra CRL url til et sæt af serienumre.
Derefter indlæses alle ICA'er. For hver ICA verificeres det om ICA er spærret via de netop indlæste CRL'er. ICA's revokeringsstatus gennes i et map fra ICA subject DN til en boolean som indikerer om ICA er spærret eller ej.
Revokeringscheck
Revokeringscheck af et certifikat i servicen verificerer følgende:
- Findes certifikates crl distribution point i CRA
- Hvis ikke betragtes certifikat som spærret
- Check om certifikatets serienummer står på spærrelisten i CRA.
- Check om certifikatets issuer er kendt i CRA.
- Hvis ikke betragtes ICA som spærret.
- Check om certifikatets issuer er spærret.
Revokeringscheck returnerer kun true hvis hverken certifikat eller ICA ikke er spærret.

