Tout d'abord quelques informations.
Le projet LedgerSMB est un projet de logiciel de comptabilité financière open source qui fonctionne sur PostgreSQL. Nous implémentons une très grande quantité de logique métier dans les fonctions définies par l'utilisateur, qui agissent comme le principal outil de mappage entre les méthodes d'objet programme et le comportement de la base de données. Actuellement, nous utilisons les utilisateurs de base de données comme utilisateurs d'authentification, en partie par choix (cela permet une logique de sécurité centralisée, de sorte que d'autres outils puissent être écrits et réutiliser les autorisations accordées aux utilisateurs), et en partie par nécessité (après avoir bifurqué depuis SQL-Ledger, il il n'y avait pas beaucoup d'options pour moderniser la sécurité sur cette base de code).
Cela nous permet d'accéder à un nombre raisonnable d'options de connexion unique auxquelles PostgreSQL a accès, de LDAP à Kerberos 5. Nous pouvons même utiliser PAM pour les mots de passe. Il nous permet également de réutiliser les autorisations lors de l'intégration avec d'autres applications, ou d'autoriser d'autres interfaces client. Pour une application de comptabilité financière, cela semble être une victoire nette.
Il y a des coûts évidents impliqués. Pour l'application Web, nous sommes très limités aux types d'authentification http qui peuvent être pris en charge. DIGEST par exemple est entièrement sorti. BASIC fonctionne, et nous pourrions implémenter KRB5 assez facilement (je prévois de le prendre en charge et de le sortir de la boîte pour 1.4). Des mesures d'authentification très fortes ne peuvent pas être correctement gérées directement sur ce point, bien que nous pourrions probablement les shimer si nécessaire (par exemple, BASIC + certificat SSL côté client avec un cn correspondant au nom d'utilisateur et une racine spécifique ca).
En même temps, nous avons rencontré pas mal de critiques, principalement de la part des développeurs et plus occasionnellement des dba qui me disent que l'application devrait être la barrière de sécurité, pas la base de données. À mon avis, un périmètre de sécurité plus petit est généralement meilleur, la réutilisation de la logique métier et de la logique de sécurité va de pair et il me semble dangereux de réutiliser la logique métier sans réutiliser la logique de sécurité au même niveau. du programme.
Suis-je en train de manquer des compromis majeurs ici? Y a-t-il des problèmes que je ne considère pas?
la source
Réponses:
Je pense que vous confondez authentification et autorisation .
Je suis tout à fait d'accord qu'il est sage de conserver le modèle de sécurité dans la base de données, d'autant plus que LedgerSMB est conçu avec un accès à partir de plusieurs clients à l'esprit. À moins que vous ne prévoyiez de passer à 3 niveaux avec une couche middleware, il est parfaitement logique d'avoir des utilisateurs comme rôles de base de données, en particulier pour quelque chose comme une application de comptabilité.
Cela ne signifie pas que vous devez authentifier les utilisateurs par rapport à la base de données à l'aide d'une méthode d'authentification prise en charge par PostgreSQL. Les utilisateurs, rôles et autorisations de votre base de données ne peuvent être utilisés pour l' autorisation que si vous le souhaitez.
Voici comment cela fonctionne pour une interface utilisateur Web par exemple:
jane
se connecte au serveur Web UI et s'authentifie à l'aide de la méthode souhaitée, par exemple la négociation du certificat client HTTPS X.509 et l'authentification DIGEST. Le serveur a maintenant une connexion d'un utilisateur qu'il accepte vraimentjane
.Le serveur se connecte à PostgreSQL en utilisant un nom d'utilisateur / mot de passe fixe (ou Kerberos ou tout ce que vous voulez), s'authentifiant lui-même sur le serveur db en tant qu'utilisateur
webui
. Le serveur db fait confiancewebui
pour authentifier ses utilisateurs etwebui
a donc reçu lesGRANT
s appropriés (voir ci-dessous).Sur cette connexion, le serveur utilise
SET ROLE jane;
pour assumer le niveau d'autorisation de l'utilisateurjane
. Jusqu'à ceRESET ROLE;
qu'un ou un autreSET ROLE
soit exécuté, la connexion fonctionne avec les mêmes droits d'accès quejane
etSELECT current_user()
etc signalerajane
.Le serveur maintient l'association entre la connexion à la base de données sur laquelle il doit
SET ROLE
se connecterjane
et la session Web pour l'utilisateurjane
, ne permettant pas à cette connexion PostgreSQL d'être utilisée par d'autres connexions avec d'autres utilisateurs sans nouvelSET ROLE
intermédiaire.Vous vous authentifiez maintenant en dehors du serveur, mais vous conservez l' autorisation sur le serveur. Pg doit savoir quels utilisateurs existent, mais n'a pas besoin de mots de passe ou de méthodes d'authentification pour eux.
Voir:
SET SESSION AUTHORIZATION
SET ROLE
GRANT
Détails
Le serveur webui contrôle l'exécution des requêtes, et il ne laissera pas
jane
s'exécuter le SQL brut (j'espère!) Doncjane
ne peut pasRESET ROLE; SET ROLE special_admin_user;
via l'interface utilisateur web. Pour plus de sécurité, j'ajouterais un filtre de déclaration au serveur qui a rejetéSET ROLE
et àRESET ROLE
moins que la connexion ne soit établie ou n'entre dans un pool de connexions non attribuées.Vous êtes toujours libre d'utiliser l'authentification directe auprès de Pg dans d'autres clients; vous pouvez mélanger et assortir librement. Vous avez juste à
GRANT
l'webui
utilisateur les droits surSET ROLE
les utilisateurs qui peuvent se connecter via le Web, puis donnez à ces utilisateurs lesCONNECT
droits, mots de passe, etc. que vous souhaitez. Si vous souhaitez les rendre uniquement Web,REVOKE
leursCONNECT
droits sur la base de données (et à partir depublic
).Pour faciliter une telle séparation authentification / autorisation, j'ai un rôle spécial
assume_any_user
auquelGRANT
chaque utilisateur nouvellement créé doit jouer . J'ai ensuiteGRANT assume_any_user
le vrai nom d'utilisateur utilisé par des choses comme un frontal Web de confiance, leur donnant les droits de devenir n'importe quel utilisateur qu'ils aiment.Il est important de créer
assume_any_user
unNOINHERIT
rôle, afin que l'webui
utilisateur ou quoi que ce soit n'a aucun privilège par lui-même et ne peut agir sur la base de données qu'une fois qu'il estSET ROLE
destiné à un utilisateur réel. Vous newebui
devez en aucun cas être un superutilisateur ou un propriétaire de base de données .Si vous regroupez des connexions, vous pouvez utiliser
SET LOCAL ROLE
pour définir le rôle uniquement dans une transaction, afin de pouvoir renvoyer des connexions au pool aprèsCOMMIT
ouROLLBACK
. Attention, celaRESET ROLE
fonctionne toujours, il n'est donc pas sûr de laisser le client exécuter le SQL qu'il veut.SET SESSION AUTHORIZATION
est la version associée mais plus puissante de cette commande. Il ne nécessite pas d'appartenance à un rôle, mais c'est une commande uniquement superutilisateur. Vous ne voulez pas que votre interface utilisateur Web se connecte en tant que superutilisateur. Il peut être inversé avecRESET SESSION AUTHORIZATION
,SET SESSION AUTHORIZATION DEFAULT
ouSET SESSION AUTHORIZATION theusername
pour reprendre les droits de super - utilisateur il est donc pas un privilège laissant tomber la barrière de sécurité soit.Une commande qui fonctionnait comme
SET SESSION AUTHORIZATION
mais qui était irréversible et qui fonctionnerait si vous étiez un membre du rôle mais pas un superutilisateur serait géniale. À ce stade, il n'y en a pas, mais vous pouvez toujours bien séparer l'authentification et l'autorisation si vous faites attention.Exemple et explication
Connectez-vous maintenant en tant que
webui
. Notez que vous ne pouvez rien faire,test_table
mais vous pouvez leSET ROLE
fairejane
, puis vous pouvez accéder àtest_table
:Notez que
webui
peut leSET ROLE
fairejim
, même lorsqu'il est déjàSET ROLE
djane
et même s'iljane
n'a pas étéGRANT
autorisé à assumer le rôlejim
.SET ROLE
définit votre ID utilisateur effectif, mais il ne supprime pas votre capacité àSET ROLE
d'autres rôles, c'est une propriété du rôle que vous avez connecté en tant que, et non votre rôle effectif actuel. Par conséquent, vous devez contrôler soigneusement l'accès aux commandesSET ROLE
etRESET ROLE
. Il n'y a, AFAIK, aucun moyen d'SET ROLE
établir une connexion de manière permanente , en devenant vraiment l'utilisateur cible, même si ce serait certainement bien d'avoir.Comparer:
à:
Cela signifie que ce
SET ROLE
n'est pas exactement la même chose que de se connecter en tant que rôle donné, quelque chose que vous devez garder à l'esprit.webui
ne peut pasSET ROLE
àdbowner
puisqu'il n'a pas étéGRANT
ed ce droit:donc en soi, il est assez impuissant, il ne peut assumer les droits des autres utilisateurs et que lorsque ces utilisateurs ont activé l'accès Web.
la source
pgbouncer
fonctionne certains détails.DISCARD ALL
c'est une autre façon de ramener les droits par défaut. J'aimerais vraiment que Pg en ait unSET ROLE NORESET
ou similaire ...