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:
jane
conecta-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 webui
para autenticar seus usuários e, portanto webui
, recebe GRANT
s 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 ROLE
seja executado, a conexão está operando com os mesmos direitos de acesso que jane
e 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 ROLE
a jane
ea 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 ROLE
inbetween.
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 jane
execução de SQL bruto (espero!), Por isso jane
nã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 ROLE
e a RESET ROLE
menos 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 GRANT
o webui
usuário os direitos para SET ROLE
a usuários que podem fazer login através da web e, em seguida, dar esses usuários quaisquer normais CONNECT
direitos, senhas, etc que você deseja. Se você deseja torná-los somente para a Web, REVOKE
seus CONNECT
direitos 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_user
qual GRANT
todos os usuários recém-criados. Depois, passo GRANT assume_any_user
para 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_user
uma NOINHERIT
função, para que o webui
usuário ou qualquer outra coisa não tenha privilégios e só possa atuar no banco de dados quando for SET ROLE
para um usuário real. Sob nenhuma circunstância deve webui
ser um superusuário ou proprietário do banco de dados .
Se você for um pool de conexões, poderá SET LOCAL ROLE
definir apenas a função dentro de uma transação, para poder retornar as conexões ao pool após COMMIT
ou ROLLBACK
. Cuidado com o que RESET ROLE
ainda 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 DEFAULT
ou SET SESSION AUTHORIZATION theusername
para 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 AUTHORIZATION
fosse 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_table
mas você pode SET ROLE
para jane
e , 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 ROLE
d para jane
e mesmo que jane
não tenha sido GRANT
ed o direito de assumir o papel jim
. SET ROLE
define seu ID de usuário efetivo, mas não remove sua capacidade para SET ROLE
outras 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 ROLE
e RESET ROLE
. No AFAIK, não há como permanecer permanentemente SET ROLE
em 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 ROLE
não é exatamente o mesmo que fazer login como uma determinada função, algo que você deve ter em mente.
webui
não pode SET ROLE
de dbowner
uma vez que não foi GRANT
ed 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.