Nou, nee.
Ik ga ook uit van een PHP webbased omgeving.
Wat je wilt is geen probleem. Voor de applicatie kan je prima een sleutelbestand maken waarin je per verbinding de hostnaam, het poortnummer, de databanknaam, het account en het wachtwoord opslaat.
Kijk je naar
PostgreSQL, die kan uit zichzelf gebruik maken van een verborgen bestand
.pgpass , opgeslagen in de 'home' map van de applicatie-account. Het bestand zou alleen te lezen moeten zijn door de applicatie-account (in te stellen via chmod) en voor extra veiligheid is het goed om de /home map te versleutelen, of de hele partitie of schrijf te versleutelen met bijvoorbeeld
LUKS.
Controleer dat PostgreSQL de wachtwoorden opslaat met
scram-sha-256, dit is de standaard in nieuwere versies, in oudere moest je dit zelf aanpassen.
Het .pgpass bestand heb je alleen nodig als je de applicatie-firewall van PostgreSQL via
pg_hba.conf zo hebt ingesteld dat er een wachtwoord nodig is. Je kunt er bijvoorbeeld ook voor kiezen dat de account waarmee de PHP-applicatie draait, juist géén wachtwoord nodig heeft om in te loggen, maar bijvoorbeeld standaard vertrouwd wordt. Het is dan wel zaak dat je applicatie niet draait op het standaard account van de webserver (bijvoorbeeld 'www-data')
Je wilt ook de verbinding tussen de PHP-applicatie en de database versleutelen, zodat er niet meegelezen kan worden. Dit regel je met een eigen CA-certificaat en private sleutel, en kan je aanmaken via openssl:
openssl genpkey -genparam -algorithm ec -pkeyopt ec_paramgen_curve:secp521r1 -out ecparam.pem
openssl req -new -newkey ec:ecparam.pem -x509 -noenc -days 365 -out ca-cert.pem -keyout ca-key.pem
Met het CA-certificaat kan je andere certificaten tekenen, zodat je later kunt controleren of een aangeboden certificaat is getekend door het CA-certificaat. Dus of je een met TLS beveleigde verbinding vertrouwt. Het CA-certificaat houd je zelf, het getekende certificaat stel je in op de database. De server.key en server.crt zijn voor de database, en kan je configureren via
postgresql.conf:
openssl req -newkey ec:ecparam.pem -noenc -keyout server.key -out server-req.pem
openssl x509 -req -days 3650 -set_serial 01 -in server-req.pem -out server.crt -CA ca-cert.pem -CAkey ca-key.pem
Als je alles eenmaal veilig hebt opgezet, heeft je PHP-applicatie een veilige verbinding met de database. Maar dan moet je ook nog wat als een gebruiker wil inloggen via jouw applicatie. Er van uitgaande dat je alleen PHP gebruikt zonder andere authenticatiemechanismen, kan je volstaan met een eigen "account" tabel waarmee je authenticatie regelt via PHP. Heb je een gebruiker geauthenticeerd, dan kan je in de database omschakelen naar de database account van de gebruiker met
SET SESSION AUTHORIZATION, zodat de database de autorisaties regelt. Hiermee kan je het fijnmazige autorisatiesysteem van de database gebruiken met onder meer RLS, wat praktisch ondoenlijk is in PHP.
Dit is de oplossing zoals ik hem zelf heb geimplementeerd in mijn PHP-applicatie.
Een alternatief idee is dat je helemaal geen applicatie-account nodig hebt. Dit idee heb ik nog niet volledig kunnen uitwerken, omdat ik aanliep tegen de beperking dat SET SESSION AUTHORIZATION niet werkt binnen een SECURITY DEFINER functie. Mijn idee was om per sessie een extra account in de database aan te maken met de rechten van de ingelogde gebruiker, waarbij de accountnaam de sessie ID zou zijn, met natuurlijk een korte prefix. Zodat je met een paar UDF's sessiebeheer in de database zou kunnen doen in plaats van met PHP. Maar die vlieger gaat niet op. (Het is overigens sowieso veiliger om sessies in de database op te slaan, met een eigen sessie-implementatie of via de
SessionHandlerInterface.)
Het beste wat ik nu kan bedenken is om de applicatie-account en de tabellen nodig voor authenticatie en sessies geheel te scheiden van de database van de gebruiker. Maar dan loop je tegen de beperking aan dat je geen uitzondering kunt maken voor noodgevallen met een
red envelope procedure. Dus blijf ik met de situatie dat er altijd een applicatie-account nodig is.
Ik hoop dat iemand die dit tot hier leest een betere oplossing heeft?
Last but not least: vergeet ook niet om de webserver te voorzien van een TLS-certificaat, en check of je domeinnaam veilig is via
internet.nl .
Wanneer je ondanks deze maatregelen toch wordt gehackt, dan heb je in ieder geval voldoende je best gedaan om hackers te weren, en kan je niet zomaar aansprakelijk gesteld worden wegens nalatigheid. Tenminste, als je ook de andere best practices, die in de IT-sector als bekend worden verondersteld, hebt geïmplementeerd. Hiervoor verwijs ik nogmaals naar de Cheat Sheets zoals gepubliceerd door OWASP.