Penso che stai unendo autenticazione e autorizzazione .
Sono pienamente d'accordo sul fatto che mantenere il modello di sicurezza nel DB sia saggio, soprattutto perché LedgerSMB è progettato pensando all'accesso da più client. A meno che tu non abbia intenzione di passare a 3 livelli con un livello middleware, ha perfettamente senso avere utenti come ruoli di database, specialmente per qualcosa come un'app di contabilità.
Ciò non significa che devi autenticare gli utenti sul database usando un metodo di autenticazione supportato da PostgreSQL. Gli utenti, i ruoli e le sovvenzioni del database possono essere utilizzati per l' autorizzazione solo se lo si desidera.
Ecco come funziona per un'interfaccia utente Web, ad esempio:
jane
si collega al server dell'interfaccia utente Web e si autentica utilizzando il metodo desiderato, ad esempio handshake del certificato client HTTPS X.509 e autenticazione DIGEST. Il server ora ha una connessione da un utente che accetta davvero jane
.
Il server si connette a PostgreSQL usando un nome utente / password fissi (o Kerberos o qualunque cosa tu voglia), autenticandosi sul server db come utente webui
. Il server db si fida webui
dell'autenticazione dei suoi utenti, quindi webui
sono stati dati i messaggi appropriati GRANT
(vedi sotto).
Su quella connessione il server utilizza SET ROLE jane;
per assumere il livello di autorizzazione dell'utente jane
. Fino a quando RESET ROLE;
o in un altro SET ROLE
viene eseguito, il collegamento è in funzione con gli stessi diritti di accesso come jane
e SELECT current_user()
ecc riporterà jane
.
Il server mantiene l'associazione tra la connessione al database su cui si ha SET ROLE
a jane
e la sessione web per l'utente jane
, non permettere che la connessione PostgreSQL per essere utilizzati da altre connessioni con altri utenti senza un nuovo SET ROLE
mezzo.
Ora stai eseguendo l' autenticazione all'esterno del server, ma mantenendo l' autorizzazione nel server. Pg ha bisogno di sapere quali utenti esistono, ma non ha bisogno di password o metodi di autenticazione per loro.
Vedere:
Dettagli
Il server webui controlla l'esecuzione delle query e non consentirà l' jane
esecuzione di SQL raw (spero!), Quindi jane
non è possibile RESET ROLE; SET ROLE special_admin_user;
tramite l'interfaccia utente Web. Per maggiore sicurezza, aggiungerei un filtro di istruzioni al server che ha rifiutato SET ROLE
e, a RESET ROLE
meno che la connessione non fosse o entrasse in un pool di connessioni non assegnate.
Sei ancora libero di utilizzare l'autenticazione diretta su Pg in altri client; puoi mescolare e abbinare liberamente. Non vi resta che GRANT
l' webui
utente i diritti per SET ROLE
gli utenti che possono accedere via web e poi dare quegli utenti eventuali normali CONNECT
diritti, password, ecc che si desidera. Se vuoi renderli solo web, i REVOKE
loro CONNECT
diritti sul database (e da public
).
Per semplificare una tale suddivisione dell'autenticazione / autorizzazione, ho un ruolo speciale a assume_any_user
cui GRANT
ogni utente appena creato. Passo quindi GRANT assume_any_user
al vero nome utente utilizzato da cose come un front-end web di fiducia, dando loro il diritto di diventare qualsiasi utente a loro piace.
È importante ricoprire assume_any_user
un NOINHERIT
ruolo, quindi l' webui
utente o qualsiasi altra cosa non ha alcun privilegio da solo e può agire sul database solo una volta che è SET ROLE
un utente reale. In nessun caso dovrebbe webui
essere un superutente o un proprietario di DB .
Se si utilizza il pool di connessioni, è possibile utilizzare SET LOCAL ROLE
per impostare il ruolo solo all'interno di una transazione, in modo da poter restituire le connessioni al pool dopo COMMIT
o ROLLBACK
. Attenzione che RESET ROLE
funziona ancora, quindi non è ancora sicuro lasciare che il client esegua qualunque SQL voglia.
SET SESSION AUTHORIZATION
è la versione correlata ma più forte di questo comando. Non richiede l'appartenenza al ruolo, ma è solo un comando per superutente. Non vuoi che la tua interfaccia web si connetta come superutente. Si può essere invertito con RESET SESSION AUTHORIZATION
, SET SESSION AUTHORIZATION DEFAULT
o SET SESSION AUTHORIZATION theusername
per recuperare i diritti di superutente quindi non è una barriera di sicurezza privilegio far cadere neanche.
Un comando che funzionava come SET SESSION AUTHORIZATION
se fosse irreversibile e funzionerebbe se fossi un membro del ruolo ma non un superutente sarebbe fantastico. A questo punto non ce n'è uno, ma puoi comunque separare abbastanza bene l'autenticazione e l'autorizzazione se stai attento.
Esempio e spiegazione
CREATE ROLE dbowner NOLOGIN;
CREATE TABLE test_table(x text);
INSERT INTO test_table(x) VALUES ('bork');
ALTER TABLE test_table OWNER TO dbowner;
CREATE ROLE assume_any_user NOINHERIT NOLOGIN;
CREATE ROLE webui LOGIN PASSWORD 'somepw' IN ROLE assume_any_user;
CREATE ROLE jane LOGIN PASSWORD 'somepw';
GRANT jane TO assume_any_user;
GRANT ALL ON TABLE test_table TO jane;
CREATE ROLE jim LOGIN PASSWORD 'somepw';
GRANT jim TO assume_any_user;
Ora connettiti come webui
. Nota che non puoi fare nulla, test_table
ma puoi SET ROLE
farlo jane
e quindi puoi accedere a test_table
:
$ psql -h 127.0.0.1 -U webui regress
Password for user webui:
regress=> SELECT session_user, current_user;
session_user | current_user
--------------+--------------
webui | webui
(1 row)
regress=> SELECT * FROM test_table;
ERROR: permission denied for relation test_table
regress=> SET ROLE jane;
SET
regress=> SELECT session_user, current_user;
session_user | current_user
--------------+--------------
webui | jane
(1 row)
regress=> SELECT * FROM test_table;
x
------
bork
(1 row)
Si noti che webui
può SET ROLE
a jim
, anche quando già SET ROLE
Ð jane
e anche se jane
non è stato GRANT
cato il diritto di assumere il ruolo jim
. SET ROLE
imposta il tuo ID utente effettivo, ma non rimuove la tua capacità di SET ROLE
ricoprire altri ruoli, questa è una proprietà del ruolo in cui ti sei connesso, non del tuo attuale ruolo effettivo. Di conseguenza è necessario controllare attentamente l'accesso ai comandi SET ROLE
e RESET ROLE
. AFAIK non esiste un modo per stabilire SET ROLE
una connessione in modo permanente , diventando veramente l'utente di destinazione, anche se sarebbe sicuramente bello averlo.
Confrontare:
$ psql -h 127.0.0.1 -U webui regress
Password for user webui:
regress=> SET ROLE jane;
SET
regress=> SET ROLE jim;
SET
regress=> SELECT session_user, current_user;
session_user | current_user
--------------+--------------
webui | jim
(1 row)
per:
$ psql -h 127.0.0.1 -U jane regress
Password for user jane:
regress=> SET ROLE webui;
ERROR: permission denied to set role "webui"
regress=> SET ROLE jim;
ERROR: permission denied to set role "jim"
Ciò significa che SET ROLE
non è esattamente uguale all'accesso come ruolo dato, qualcosa che devi tenere a mente.
webui
non può SET ROLE
per dbowner
quanto non è stato GRANT
cato tale diritto:
regress=> SET ROLE dbowner;
ERROR: permission denied to set role "dbowner"
quindi da solo è piuttosto impotente, può assumere solo i diritti di altri utenti e solo quando tali utenti hanno l'accesso al web abilitato.