Acho que você está confundindo autenticação e autorização .
Concordo plenamente que é prudente manter o modelo de segurança no banco de dados, especialmente porque o LedgerSMB foi projetado com o acesso de vários clientes em mente. A menos que você planeje usar três camadas com uma camada de middleware, faz todo sentido ter usuários como funções de banco de dados, especialmente para algo como um aplicativo de contabilidade.
Isso não significa que você precise autenticar usuários no banco de dados usando um método de autenticação suportado pelo PostgreSQL. Os usuários, funções e concessões do banco de dados podem ser usados para autorização somente se você desejar.
Veja como funciona para uma interface de usuário da web, por exemplo:
janeconecta-se ao servidor da interface do usuário da web e se autentica usando qualquer método desejado, como handshake de certificado de cliente HTTPS X.509 e autenticação DIGEST. O servidor agora tem uma conexão de um usuário que aceita realmente jane.
O servidor se conecta ao PostgreSQL usando um nome de usuário / senha fixo (ou Kerberos ou o que você quiser), autenticando-se no servidor db como usuário webui. O servidor db confia webuipara autenticar seus usuários e, portanto webui, recebe GRANTs apropriados (veja abaixo).
Nessa conexão, o servidor usa SET ROLE jane;para assumir o nível de autorização do usuário jane. Até que RESET ROLE;outro SET ROLEseja executado, a conexão está operando com os mesmos direitos de acesso que janee SELECT current_user()etc serão relatados jane.
O servidor mantém a associação entre a conexão do banco de dados em que se tem SET ROLEa janeea sessão web para o usuário jane, não permitindo que a conexão PostgreSQL para ser usado por outras conexões com outros usuários sem um novo SET ROLEinbetween.
Agora você está autenticando fora do servidor, mas mantendo a autorização no servidor. A Pg precisa saber quais usuários existem, mas não precisa de senhas ou métodos de autenticação para eles.
Vejo:
Detalhes
O servidor webui controla a execução das consultas e não permitirá a janeexecução de SQL bruto (espero!), Por isso janenão é possível RESET ROLE; SET ROLE special_admin_user;através da interface do usuário da web. Para maior segurança, eu adicionaria um filtro de declaração ao servidor que rejeitou SET ROLEe a RESET ROLEmenos que a conexão estivesse dentro ou entrando em um conjunto de conexões não atribuídas.
Você ainda pode usar a autenticação direta à página em outros clientes; você pode misturar e combinar livremente. Você apenas tem que GRANTo webuiusuário os direitos para SET ROLEa usuários que podem fazer login através da web e, em seguida, dar esses usuários quaisquer normais CONNECTdireitos, senhas, etc que você deseja. Se você deseja torná-los somente para a Web, REVOKEseus CONNECTdireitos no banco de dados (e de public).
Para facilitar essa divisão de autenticação / autorização, tenho uma função especial para a assume_any_userqual GRANTtodos os usuários recém-criados. Depois, passo GRANT assume_any_userpara o nome de usuário real usado por coisas como um front-end da web confiável, dando a eles o direito de se tornarem qualquer usuário que eles gostem.
É importante fazer assume_any_useruma NOINHERITfunção, para que o webuiusuário ou qualquer outra coisa não tenha privilégios e só possa atuar no banco de dados quando for SET ROLEpara um usuário real. Sob nenhuma circunstância deve webuiser um superusuário ou proprietário do banco de dados .
Se você for um pool de conexões, poderá SET LOCAL ROLEdefinir apenas a função dentro de uma transação, para poder retornar as conexões ao pool após COMMITou ROLLBACK. Cuidado com o que RESET ROLEainda funciona, por isso ainda não é seguro deixar o cliente executar o SQL que quiser.
SET SESSION AUTHORIZATIONé a versão relacionada, mas mais forte, deste comando. Não requer associação de função, mas é um comando apenas de superusuário. Você não deseja que a interface do usuário da web se conecte como superusuário. Ele pode ser revertida com RESET SESSION AUTHORIZATION, SET SESSION AUTHORIZATION DEFAULTou SET SESSION AUTHORIZATION theusernamepara recuperar direitos de superusuário por isso não é uma barreira de segurança de cair o privilégio quer.
Um comando que funcionasse como SET SESSION AUTHORIZATIONfosse irreversível e funcionaria se você fosse um membro da função, mas não um superusuário, seria ótimo. Neste ponto, não há um, mas você ainda pode separar a autenticação e a autorização muito bem se tomar cuidado.
Exemplo e explicação
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;
Agora conecte como webui. Note que você não pode fazer nada para test_tablemas você pode SET ROLE para janee , em seguida, você pode acessar 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)
Note-se que webui lata SET ROLE para jim, mesmo quando já SET ROLEd para janee mesmo que janenão tenha sido GRANTed o direito de assumir o papel jim. SET ROLEdefine seu ID de usuário efetivo, mas não remove sua capacidade para SET ROLEoutras funções, isso é propriedade da função que você conectou e não da sua função efetiva atual. Conseqüentemente, você deve controlar cuidadosamente o acesso aos comandos SET ROLEe RESET ROLE. No AFAIK, não há como permanecer permanentemente SET ROLEem uma conexão, realmente se tornando o usuário alvo, embora certamente seja bom ter isso.
Comparar:
$ 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)
para:
$ 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"
Isso significa que SET ROLEnão é exatamente o mesmo que fazer login como uma determinada função, algo que você deve ter em mente.
webuinão pode SET ROLEde dbowneruma vez que não foi GRANTed certo:
regress=> SET ROLE dbowner;
ERROR: permission denied to set role "dbowner"
portanto, por si só, é bastante impotente, só pode assumir os direitos de outros usuários e somente quando esses usuários têm acesso à Web ativado.