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 vraiment jane
.
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 confiance webui
pour authentifier ses utilisateurs et webui
a donc reçu les GRANT
s appropriés (voir ci-dessous).
Sur cette connexion, le serveur utilise SET ROLE jane;
pour assumer le niveau d'autorisation de l'utilisateur jane
. Jusqu'à ce RESET ROLE;
qu'un ou un autre SET ROLE
soit exécuté, la connexion fonctionne avec les mêmes droits d'accès que jane
et SELECT current_user()
etc signalera jane
.
Le serveur maintient l'association entre la connexion à la base de données sur laquelle il doit SET ROLE
se connecter jane
et la session Web pour l'utilisateur jane
, ne permettant pas à cette connexion PostgreSQL d'être utilisée par d'autres connexions avec d'autres utilisateurs sans nouvel SET 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:
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!) Donc jane
ne peut pas RESET 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 sur SET ROLE
les utilisateurs qui peuvent se connecter via le Web, puis donnez à ces utilisateurs les CONNECT
droits, mots de passe, etc. que vous souhaitez. Si vous souhaitez les rendre uniquement Web, REVOKE
leurs CONNECT
droits sur la base de données (et à partir de public
).
Pour faciliter une telle séparation authentification / autorisation, j'ai un rôle spécial assume_any_user
auquel GRANT
chaque utilisateur nouvellement créé doit jouer . J'ai ensuite GRANT 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
un NOINHERIT
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 est SET ROLE
destiné à un utilisateur réel. Vous ne webui
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ès COMMIT
ou ROLLBACK
. Attention, cela RESET 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é avec RESET SESSION AUTHORIZATION
, SET SESSION AUTHORIZATION DEFAULT
ou SET 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
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;
Connectez-vous maintenant en tant que webui
. Notez que vous ne pouvez rien faire, test_table
mais vous pouvez le SET ROLE
faire jane
, puis vous pouvez accéder à 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)
Notez que webui
peut le SET ROLE
faire jim
, même lorsqu'il est déjà SET ROLE
d jane
et même s'il jane
n'a pas été GRANT
autorisé à assumer le rôle jim
. 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 commandes SET ROLE
et RESET 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:
$ 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)
à:
$ 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"
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 pas SET ROLE
à dbowner
puisqu'il n'a pas été GRANT
ed ce droit:
regress=> SET ROLE dbowner;
ERROR: permission denied to set role "dbowner"
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.