PostgreSQL – Řízení přístupu prostřednictvím externího autentizačního providera

PostgreSQL nabízí několik různých metod ověřování klientů a tentokrát si ukážeme, jak nastavit ověřování pomocí metody GSSAPI, která se obvykle používá pro přístup k Microsoft Active Directory nebo FreeIPA.

Základní požadavky

Zde je výčet základních požadavků pro funkční nastavení ověřování uživatelů z Active Directory v PostgreSQL pomocí Kerberos (GSS):

  1. nainstalovaný server PostgreSQL
  2. nainstalovou podporu a nastavení pro Kerberos na DB serveru
  3. uživatelský účet v Active Directory pro PostgreSQL
  4. vytvořený Kerberos keytab pro uživatele v Active Directory
  5. nastavený PostgreSQL pro Kerberos a GSSAPI
  6. uživatelský účet v PostgreSQL totožný s účtem v Active Directory (nebo ldap2pg)
  7. ověřovací Kerberos ticket pro DB uživatele v Active Directory

Instalace a konfigurace Kerberos

Nejprve na databázovém serveru nainstalujeme základní balíčky, které obsahují knihovny, a binární i konfigurační soubory pro podporu Kerberos.

dnf install krb5-server krb5-workstation

V případě, že chceme používat k autentizaci Kerberos i na samotném klientu (potažmo serveru), je potřeba mít zde i správně nastavený Kerberos.

Ovšem PostgreSQL samotný toto nastavení pro funkční ověřování uživatelů nepotřebuje.

Kerberos se na úrovni OS nastavuje v konfiguračním souboru /etc/krb5.conf a tento soubor může upravovat pouze privilegovaný uživatel root.

Vzorová konfigurace může kupříkladu vypadat následovně:

[logging]
default = /var/log/krb5libs.log
kdc = /var/log/krb5kdc.log
admin_server = /var/log/kadmind.log

[libdefaults]
default_realm = DEMO.INITMAX.CZ
dns_lookup_realm = false
# ticket_lifetime = 24h
# renew_lifetime = 7d
forwardable = true
udp_preference_limit = 1
default_ccache_name = KEYRING:persistent:%{uid}

[realms]
DEMO.INITMAX.CZ = {
kdc = demo.initmax.cz
admin_server = demo.initmax.cz
}

[domain_realm]
.demo.initmax.cz = DEMO.INITMAX.CZ
demo.initmax.cz = DEMO.INITMAX.CZ

Uživatelský účet v Active Directory

Na úrovni Active Directory běžným způsobem vytvoříme servisní účet, který v našem případě nazveme pg_db_srv01.

A následně vytvoříme níže zobrazeným příkazem tzv. Kerberos keytab, který k tomuto servisnímu účtu přiřadíme.

ktpass –princ POSTGRES/pgsql.demo.initmax.cz@DEMO.INITMAX.CZ -pass %heslo% -mapuser pg_db_srv01 -crypto ALL -ptype KRB5_NT_Principal -out pgsql.demo.initmax.cz.keytab

Takto vzniklý Kerberos keytab si zkopírujeme a přesuneme ho na klienta, v našem případě tedy na databázový server, například do složky /etc.

Přímo na databázovém serveru si pak můžeme ověřit, že vytvořený keytab skutečně funguje, a to následujícím příkazem:

kinit -k -t /etc/pgsql.demo.initmax.cz.keytab POSTGRES/pgsql.demo.initmax.cz@DEMO.INITMAX.CZ -V

Pokud nám příkaz kinit na konci svého běhu ve výstupu zobrazí hlášku Authenticated to Kerberos, pak je keytab funkční a my můžeme překročit ke konfiguraci samotného PostgreSQL.

Vzorový výstup výše zmíněného příkazu kinit s funkčním souborem keytab můžete vidět zde:

Using existing cache: 0
Using principal: POSTGRES/pgsql.demo.initmax.cz@DEMO.INITMAX.CZ
Using keytab: /etc/pgsql.demo.initmax.cz.keytab
Authenticated to Kerberos v5

Konfigurace PostgreSQL

Nejprve upravíme konfigurační soubor PostgreSQL (postgresql.conf) tak, aby věděl, kde mu leží náš Kerberos keytab a tudíž ho korektně načetl a použil.

K tomu slouží následující konfigurační direktiva krb_server_keyfile, jejíž hodnotu naplníme absolutní cestou ke Kerberos keytabu.

V našem případě tedy /etc/pgsql.demo.initmax.cz.keytab.

krb_server_keyfile=/etc/pgsql.demo.initmax.cz.keytab

Následně v konfiguračním souboru nastavujícím přístupy, tedy pg_hba.conf povolíme lokální i vzdálené ověřování pomocí metody GSSAPI se správně nastaveným Kerberos realm.

# IPv4 local connections:
#host all all 127.0.0.1/32 ident
host all all 0.0.0.0/0 gss include_realm=0 krb_realm=DEMO.INITMAX.CZ

Poté se připojíme k serveru pomocí psql a vytvoříme uživatele na úrovní samotného PostgreSQL a nastavíme mu požadováná oprávnění.

Pozor! Tento uživatel musí odpovídat skutečnému uživatli v Active Directory!

create user "ad_user" superuser;

Jako další krok můžeme konzoli psql opustit a příkazem kinit získáme (po zadání správného hesla) ověřovací ticket pro našeho uživatele z Active Directory serveru:

kinit ad_user

A v tuto chvíli se již pod tímto uživatelem můžeme přihlásit přímo do PostgreSQL bez nutnosti zadání hesla, jelikož se pro ověření použije ticket, získaný výše.

psql -U "ad_user" -h csas-pgsql.win.initmax.cz postgres

Nespornou nevýhodou tohoto nativního řešení pak (v závislosti na velikosti prostředí) zůstává nutnost uživatele ručně vytvářet na úrovni PostgreSQL.

Tyto činnosti je však možné zautomatizovat, a to pomocí ldap2pg, na což se podíváme v následující kapitole.

ldap2pg

Toto je nástroj, který na základě předem nastavených parametrů automatizuje vytváření, aktualizaci i odebírání rolí na PostgreSQL podle nastavení v LDAP.

ldap2pg je skript napsaný v jazyku Python, a pro svůj běh vyžaduje kromě Pythonu samotného (v2.6+ nebo v3.4+) i další závislé balíčky.

Konkrétně to jsou Pyyaml, python-ldappython-psycopg2.

Instalace

Doporučovaná metoda instalace je v případě RHEL přímo z oficiálního repozitáře PostgreSQL (PGDG) a v případě Debian pak pomocí pip.

Pokud chceme balíčky co nejaktuálnější, pak využijeme přímo repozitář Dalibo labs.

V našem případě používáme Rocky Linux 9 a tudíž si oficiální repozitář Dalibo labs přidáme následujícím příkazem a následně obnovíme dnf cache.

dnf install -y https://yum.dalibo.org/labs/dalibo-labs-4-1.noarch.rpm
dnf makecache fast

Další možností je vytvoření repozitáře ručně. To uděláme tak, že vytvoříme nový soubor /etc/yum.repos.d/dalibolabs.repo a ten naplníme následujícím obsahem:

[dalibolabs]
name = Dalibo Labs - RHEL/CentOS/Rockylinux $releasever - $basearch
baseurl = https://yum.dalibo.org/labs/RHEL$releasever-$basearch
gpgcheck = 1
enabled = 1

Soubor uložíme a zaktualizujeme dnf cache:

dnf makecache fast

Potom, co máme přidaný repozitář, můžeme přejít k samotné instalaci ldap2pg a všech jeho závislostí:

dnf install ldap2pg

Jakmile máme ldap2pg úspěšně nainstalován, tak můžeme překročit k jeho konfiguraci.

Nastavení

ldap2pg standardně vyhledává svůj konfigurační soubor v těchto cestách:

  • ldap2pg.yml v aktuálním pracovním adresáři
  • ~/.config/ldap2pg.yml
  • /etc/ldap2pg.yml

Lze však nastavit i cestu vlastní a to spuštění ldap2pg s parametrem --config, toto lze využít například pro spuštění několika instancí ldap2pg s různými konfiguračními soubory.

Zde můžete pro ukázku vidět příklad takové konfigurace:

postgres:
  dsn: postgres://alfa@csas-pgsql.win.initmax.cz:5432/postgres
  roles_blacklist_query:
  - postgres
  - "pg_*"
  - "rds_*"

ldap:
  uri: ldap://dc1.win.initmax.cz
  binddn: CN=Test User Alfa,OU=Users,OU=testAcounts,DC=win,DC=initmax,DC=cz
  password: "%heslo%"

sync_map:
- role:
  name: alfa
  options: LOGIN SUPERUSER
  names:
  - ad_roles
  comment: "LDAP role managed by ldap2pg."

- ldapsearch:
    base: CN=pg_DBA_users,OU=Groups,OU=testAcounts,DC=win,DC=initmax,DC=cz
  role:
    name: 'dba_{member.samaccountname}'
    options: LOGIN SUPERUSER
    parent: ad_roles
    comment: "Synced from AD: {dn}"

- ldapsearch:
    base: CN=pg_RO_users,OU=Groups,OU=testAcounts,DC=win,DC=initmax,DC=cz
  role:
    name: '{member.samaccountname}'
    options: LOGIN
    parent: ad_roles
    comment: "Synced from AD: {dn}"

Tento ukázkový konfigurační soubor obsahuje několik částí.

V části postgres: definujeme připojení k databázovému serveru a k databázi, včetně přihlašovacích údajů. Z bezpečnostních důvodů doporučujeme přihlašovací heslo v konfiguračním souboru nepoužívat, ale namísto toho uživatele ověřovat přes Kerberos ticket, jak je ukázáno právě v tomto návodu. Součástí této sekce je i direktiva roles_blacklist_query: nám určuje seznam lokálních rolí v PostgreSQL, které bude ldap2pg ignorovat. Povšimněte si možnosti využití zástupných znaků.

V části ldap: definujeme připojení k Active Directory, nebo jinému LDAP serveru. Tato sekce je v tomto konfiguračním souboru volitelná a informace o nastavení LDAP si nástroj ldap2pg umí načíst i z jakéhokoliv standardního umístění těchto systémových konfiguračních souborů (např. /etc/ldap.conf), kde je záhodno mít případně uloženo i heslo pro bind uživatel v LDAP.

Poslední sekci sync_map: pak používáme k mapování uživatelů a rolí. Na jejím začátku definujeme příklad lokální, statické role pro admin uživatele „alfa“ s právém přihlásit se a rolí SUPER USER. Zároveň v této sekci vytváříme uživatelskou roli ad_roles, do které následně přiřazujeme další, automaticky vytvořené uživatele pomocí ldap2pg (a této roli je vytvořen i takto formulovaný komentář). V podsekcích ldapsearch: pak definujeme jednotlivá BaseDN, tedy cesty ve struktuře LDAP, kde má ldap2pg uživatele hledat. Vzorově zde vytváříme databázové administrátory (ze skupiny pg_DBA_users) a uživatele pro čtení (ze skupiny pg_RO_users) s jejich příslušnými oprávěními a komentáři. Jako nadřazenou roli mají ad_roles, kterou jsme si definovali v předchozí podsekci.

Testování a spuštění

Nespornou výhodou nástoje ldap2pg je rovněž možnost si vytvořené nastavení nanečisto otestovat (tzv. dry run), a to pomocí spouštěcího parametru --dry, jehož výstup s naší vzorovou konfigurací můžete vidět zde:

Starting ldap2pg 5.8.
Using /root/ldap2pg.yml.
Connecting to LDAP server ldap://dc1.win.initmax.cz.
Trying simple bind.
Running in dry mode. Postgres will be untouched.
Inspecting roles in Postgres cluster...
Querying LDAP CN=pg_DBA_users,OU=Group... (objectClass...
Missing 'member' from CN=pg_DBA_users,OU=Groups,OU=testAcounts,DC=win,DC=initmax,DC=cz.
Considering it as an empty list.
Querying LDAP CN=pg_RO_users,OU=Groups... (objectClass...
Missing 'member' from CN=pg_RO_users,OU=Groups,OU=testAcounts,DC=win,DC=initmax,DC=cz. Considering
it as an empty list.
Nothing to do.
Comparison complete.

V případě, že test proběhl úspěšně, pak ldap2pg spustíme s parametrem --real, který už námi otestovanou konfiguraci přímo projeví konkrétními změnami v PostgreSQL.

Pro tento příkaz pak stačí už jen vytvořit pravidelně spouštěnou úlohu, například pomocí cron.

ldap2pg --real

V tuto chvíli tak máme funkční ověřování uživatelů do PostgreSQL pomocí Kerberos, včetně automatizace jejich správy z údajů v Active Directory, a to pomocí nástroje ldap2pg.