Mit der Veröffentlichung der Beta-Version von PostgreSQL 18 wurde eine spannende neue Funktion eingeführt: native Unterstützung für OAuth2. Da ich im Netz weder eine Anleitung noch einen Blogbeitrag gefunden habe, der zeigt, wie man diese Funktion nutzt, habe ich aus Neugier beschlossen, es selbst auszuprobieren.
Ich habe ein neues Projektverzeichnis angelegt und mit dem Experimentieren begonnen.
Umgebung und Zielsetzung
Ziel war es, PostgreSQL 18 Beta mit OAuth2-Authentifizierung einzurichten, für den Identity Provider habe ich Keycloak gewählt.
Ich habe mich dazu entschieden Docker Compose zu verwenden, um beide Dienste schnell und unkompliziert hoch fahren zu können.
Docker-Compose-Konfiguration
Hier ist das docker-compose.yml, das ich verwendet habe:
services:
mock-oauth2:
image: quay.io/keycloak/keycloak:24.0
command: start --https-port=8080 --https-key-store-file=/etc/x509/https/localhost.p12 --https-key-store-password=changeit --import-realm --hostname-strict=false --hostname-url=https://mock-oauth2:8080
ports:
- "8080:8080"
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
volumes:
- ./certs:/etc/x509/https
- ./keycloak-realm.json:/opt/keycloak/data/import/realm.json
networks:
- pgnet
postgres18:
build: .
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: postgres
volumes:
- ./postgres/postgresql.conf:/etc/postgresql/postgresql.conf
- ./postgres/pg_hba.conf:/etc/postgresql/pg_hba.conf
command: ["-c", "config_file=/etc/postgresql/postgresql.conf"]
networks:
- pgnet
networks:
pgnet:
driver: bridgePostgreSQL erwartet eine Verbindung zum OAuth2-Issuer über HTTPS. Dieselbe URL muss auch über den Host erreichbar sein, etwa bei der Nutzung des Keycloak-UI. Das bedeutet: Das Zertifikat muss sowohl auf dem Host als auch im Container gültig und vertrauenswürdig sein.
Der verwendete Hostname (z. B. https://mock-oauth2:8080) muss in beiden Umgebungen korrekt auflösbar sein.
Dazu habe ich folgende Zeile in meiner /etc/hosts-Datei auf dem Host ergänzt:
127.0.0.1 mock-oauth2So konnten sowohl der PostgreSQL-Container als auch mein Host den Keycloak-Service unter https://mock-oauth2:8080 erreichen.
TLS-Zertifikat für Keycloak
Keycloak benötigt zwingend einen HTTPS-Endpunkt, damit die OAuth2-Issuer-URL von PostgreSQL akzeptiert wird.
Dafür habe ich ein selbstsigniertes Zertifikat erstellt und es in ein .p12-Keystore-Paket umgewandelt, das Keycloak verwenden kann.
Das .p12-Zertifikat wird über folgenden Mount in den Container eingebunden:
volumes:
- ./certs:/etc/x509/httpsIm certs-Verzeichnis liegt die Datei localhost.p12, welche ich aus meinem selbstsignierten Schlüssel und Zertifikat folgendermaßen erstellt habe:
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout server.key \
-out server.crt \
-subj "/CN=mock-oauth2" \
-addext "subjectAltName = DNS:mock-oauth2,DNS:localhost,IP:127.0.0.1"Keycloak-Realm-Konfiguration
Ich habe eine minimalistische Realm-Datei für Keycloak erstellt. Sie enthält einen Client namens postgres und einen Benutzer mit entsprechenden Anmeldedaten.
Inhalt von keycloak-realm.json:
{
"realm": "pg",
"enabled": true,
"clients": [
{
"clientId": "postgres",
"enabled": true,
"publicClient": false,
"redirectUris": ["*"],
"protocol": "openid-connect",
"secret": "postgres",
"directAccessGrantsEnabled": true,
"standardFlowEnabled": true
}
],
"users": [
{
"username": "postgres",
"enabled": true,
"credentials": [
{
"type": "password",
"value": "postgres"
}
]
}
]
}Nach dem Import des Realms war Keycloak bereit und der Standard-Scope im UI sichtbar.
Installation von libpq-oauth und oauth_validator
Die offizielle PostgreSQL-Image musste ich erweitern, um zusätzliche Abhängigkeiten wie die Erweiterung libpq-oauth sowie den Validator oauth_validator zu installieren.
PostgreSQL 18 unterstützt OAuth2-Authentifizierung experimentell. Allerdings liefert PostgreSQL keine eigene Validator-Bibliothek mit. In der offiziellen Dokumentation heißt es:
Die PostgreSQL-Distribution enthält keine Bibliotheken zur Validierung von OAuth2-Token. Benutzer müssen eine eigene Lösung bereitstellen oder selbst kompilieren.
PostgreSQL
Docs –oauth_validator_libraries
Für Tests habe ich folgende Open-Source-Implementierung verwendet:
Diese minimalistische C-Bibliothek kann kompiliert und als oauth_validator_library in PostgreSQL verwendet werden.
Verwendetes Dockerfile
FROM postgres:18beta1
USER root
RUN apt-get update \
&& apt-get install -y libpq-oauth build-essential libkrb5-dev \
libsasl2-dev libcurl4-openssl-dev postgresql-server-dev-18 git \
&& git clone https://github.com/TantorLabs/oauth_validator.git /tmp/oauth_validator \
&& cd /tmp/oauth_validator \
&& make && make install \
&& rm -rf /tmp/oauth_validator \
&& apt-get remove -y build-essential git \
&& apt-get autoremove -y && rm -rf /var/lib/apt/lists/*Dieses Image habe ich dann für den `postgres18`-Service in meinem Docker-Compose-Setup verwendet.
PostgreSQL mit der Keycloak-CA vertrauen lassen
PostgreSQL muss dem von Keycloak präsentierten Zertifikat vertrauen, sonst wird die Verbindung zum OAuth2-Issuer abgelehnt.
Dazu habe ich die Datei `mock-oauth.crt` in den PostgreSQL-Container kopiert und im typischen CA-Pfad abgelegt:
/usr/local/share/ca-certificates/Dann habe ich innerhalb des Containers folgendes Kommando ausgeführt:
update-ca-certificatesDanach wurde das Zertifikat akzeptiert und PostgreSQL konnte die Verbindung zum HTTPS-Issuer erfolgreich überprüfen.
PostgreSQL-Konfiguration
In pg_hba.conf habe ich folgende Zeile ergänzt:
host all all all oauth scope="profile" issuer="https://mock-oauth2:8080/realms/pg" map="oauthmap"In pg_ident.conf habe ich die vom Token bereitgestellte Identität dem PostgreSQL-Benutzer zugeordnet:
oauthmap "postgresID" "postgres"Diese Zuordnung muss ggf. angepasst werden – abhängig davon, wie dein Keycloak-Client konfiguriert ist und welches Feld (z. B.
preferred_username oder sub) im Token übergeben wird.
Verbindungstest mit OAuth2
Zum Testen der Verbindung habe ich folgenden `psql`-Befehl verwendet:
psql "host=localhost \
port=5432 \
dbname=postgres \
user=postgres \
oauth_issuer=https://mock-oauth2:8080/realms/pg \
oauth_client_id=postgres \
oauth_client_secret=changeme \
oauth_scope=profile"Nach dem Aufruf erscheint eine Device-Code-Meldung wie:
Besuchen Sie `https://mock-oauth2:8080/realms/pg/device` und geben Sie den Code FBAD-XXYZ ein.
Nach Anmeldung mit den Benutzeranmeldedaten stellt `psql` erfolgreich eine Verbindung zu PostgreSQL über OAuth2 her.
Erkenntnisse und Tipps
- PostgreSQL 18 verlangt HTTPS für die OAuth2-Issuer-URL – selbst im lokalen Setup.
pg_hba.confist empfindlich gegenüber Formatierungsfehlern. Ich musste die Konfiguration mehrfach neu laden (SELECT pg_reload_conf();) und die Logs genau analysieren.- Um einer lokalen Zertifizierungsstelle zu vertrauen, reicht es, das
.crt-Zertifikat in den Container zu kopieren und mitupdate-ca-certificateszu registrieren. - Keycloak eignet sich gut für Tests mit OAuth2, aber man muss evtl. mit Scopes, Claims und Secrets experimentieren, bis alles mit PostgreSQL zusammenpasst.
Fazit
Das war ein spannendes, praxisnahes Experiment mit einer vielversprechenden neuen Funktion in PostgreSQL. OAuth2-Integration bringt PostgreSQL näher an moderne Identity-Management-Lösungen heran und vereinfacht den Betrieb in Umgebungen mit zentralisierter Authentifizierung.