Primeiro alguns antecedentes.
O projeto LedgerSMB é um projeto de software de contabilidade financeira de código aberto executado no PostgreSQL. Implementamos uma quantidade muito grande de lógica de negócios em funções definidas pelo usuário, que atuam como a principal ferramenta de mapeamento entre os métodos de objeto do programa e o comportamento do banco de dados. Atualmente, usamos usuários de banco de dados como usuários de autenticação, em parte por opção (isso permite lógica de segurança centralizada, para que outras ferramentas possam ser gravadas e reutilizadas permissões concedidas aos usuários), e em parte por necessidade (depois de sairmos do SQL-Ledger, lá não havia muitas opções para adaptar a segurança a essa base de código).
Isso nos permite acessar um número razoável de opções de conexão única às quais o PostgreSQL tem acesso, do LDAP ao Kerberos 5. Podemos até usar o PAM no que diz respeito às senhas. Também nos permite reutilizar permissões ao integrar com outros aplicativos ou permitir outras interfaces de cliente. Para um aplicativo de contabilidade financeira, isso parece uma vitória líquida.
Existem custos óbvios envolvidos. Para o aplicativo Web, estamos muito limitados aos tipos de autenticação http que podem ser suportados. DIGEST, por exemplo, está totalmente fora. O BASIC funciona, e poderíamos implementar o KRB5 com bastante facilidade (planejo ter esse suporte e trabalhar pronto para o 1.4). Medidas de autenticação muito fortes não podem ser gerenciadas adequadamente diretamente, embora possamos provavelmente colocá-las em prática, se necessário (por exemplo, certificado SSL BASIC + do lado do cliente com um cn correspondente ao nome do usuário e uma raiz específica ca).
Ao mesmo tempo, recebemos muitas críticas principalmente da multidão de desenvolvedores e, mais ocasionalmente, dos dbas que me dizem que o aplicativo deve ser a barreira de segurança, não o banco de dados. Minha opinião ainda é que um perímetro de segurança menor geralmente é melhor, que a reutilização da lógica de negócios e da lógica de segurança andam juntas e que me parece perigoso reutilizar a lógica de negócios sem reutilizar a lógica de segurança no mesmo nível do programa.
Estou perdendo algumas grandes compensações aqui? Existem truques que eu não estou considerando?
fonte
Respostas:
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 realmentejane
.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 confiawebui
para autenticar seus usuários e, portantowebui
, recebeGRANT
s apropriados (veja abaixo).Nessa conexão, o servidor usa
SET ROLE jane;
para assumir o nível de autorização do usuáriojane
. Até queRESET ROLE;
outroSET ROLE
seja executado, a conexão está operando com os mesmos direitos de acesso quejane
eSELECT current_user()
etc serão relatadosjane
.O servidor mantém a associação entre a conexão do banco de dados em que se tem
SET ROLE
ajane
ea sessão web para o usuáriojane
, não permitindo que a conexão PostgreSQL para ser usado por outras conexões com outros usuários sem um novoSET 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:
SET SESSION AUTHORIZATION
SET ROLE
GRANT
Detalhes
O servidor webui controla a execução das consultas e não permitirá a
jane
execução de SQL bruto (espero!), Por issojane
não é possívelRESET 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 rejeitouSET ROLE
e aRESET 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
owebui
usuário os direitos paraSET ROLE
a usuários que podem fazer login através da web e, em seguida, dar esses usuários quaisquer normaisCONNECT
direitos, senhas, etc que você deseja. Se você deseja torná-los somente para a Web,REVOKE
seusCONNECT
direitos no banco de dados (e depublic
).Para facilitar essa divisão de autenticação / autorização, tenho uma função especial para a
assume_any_user
qualGRANT
todos os usuários recém-criados. Depois, passoGRANT 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
umaNOINHERIT
função, para que owebui
usuário ou qualquer outra coisa não tenha privilégios e só possa atuar no banco de dados quando forSET ROLE
para um usuário real. Sob nenhuma circunstância devewebui
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ósCOMMIT
ouROLLBACK
. Cuidado com o queRESET 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 comRESET SESSION AUTHORIZATION
,SET SESSION AUTHORIZATION DEFAULT
ouSET 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
Agora conecte como
webui
. Note que você não pode fazer nada paratest_table
mas você podeSET ROLE
parajane
e , em seguida, você pode acessartest_table
:Note-se que
webui
lataSET ROLE
parajim
, mesmo quando jáSET ROLE
d parajane
e mesmo quejane
não tenha sidoGRANT
ed o direito de assumir o papeljim
.SET ROLE
define seu ID de usuário efetivo, mas não remove sua capacidade paraSET 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 comandosSET ROLE
eRESET ROLE
. No AFAIK, não há como permanecer permanentementeSET ROLE
em uma conexão, realmente se tornando o usuário alvo, embora certamente seja bom ter isso.Comparar:
para:
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 podeSET ROLE
dedbowner
uma vez que não foiGRANT
ed certo: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.
fonte
pgbouncer
funciona para alguns detalhes.DISCARD ALL
é outra maneira de os direitos voltarem ao padrão. Eu realmente gostaria que a Pg tivesse umSET ROLE NORESET
ou algo semelhante ...