Utiliser la sécurité dans Wikitty

Wikitty fournit un système de gestion des droits en lecture et en écriture pour les entitées. Vous pouvez aller jusqu'à limiter l'accès à certains objet d'un type à certains utilisateurs. Vous pouvez également accorder des droits différents à certains champs des objets.

Ajouter la couche de sécurité

Pour mettre en place la sécurité dans Wikitty, il suffit de rajouter org.nuiton.wikitty.services.WikittyServiceSecurity dans la liste des composants à utiliser de votre configuration:

wikitty.WikittyService.components=org.nuiton.wikitty.services.WikittyServiceStorage,org.nuiton.wikitty.services.WikittyServiceCached,org.nuiton.wikitty.services.WikittyServiceSecurity

Cela rajoute la couche de sécurité à Wikitty. Vous pouvez maintenant rajouter des droits à certaines entitées pour en limiter l'accès.

Si vous souhaitez utiliser le module de cache en même temps que le module de sécurité, cela implique une bonne utilisation et de faire attention à certaine chose. Il faut faire attention qu'un utilisateur qui a récupéré un objet ne le rende pas disponible à un autre utilisateur au travers du cache. Il faut donc que la couche de sécurité soit toujours au dessus de la couche de cache.

De la même façon, si l'on a mis du cache côté client dans certain cas, il faudra aussi remettre la couche de sécurité. Cela arrive si le côté client est multi-utilisateur. Si ce n'est pas le cas, il n'est pas nécessaire de le faire.

 +--------------+ +--------------+
WClient ----->| sécurité |<----+ | sécurité |<------ WClient
+--------------+ | +--------------+
| cache | | | cache |
+--------------+ | +--------------+
| notification | | | notification |
+--------------+ | +--------------+
| WS Impl | +----| WS Hessian |
+--------------+ +--------------+
serveur client

Utiliser un moyen externe d'authentification

Il est possible d'utiliser un moyen externe d'authentification, par exemple LDAP. Pour cela il faut implanter la classe WikittyServiceSecurityExternalAuthentication en implantant le mécanisme que l'on souhaite. Ensuite il faut l'ajouter a la configuration pour que le service de security l'utilise:

wikitty.WikittyService.components= org.nuiton.wikitty.WikittyServiceStorage, // ...autres.services..., org.nuiton.wikitty.services.WikittyServiceSecurity
wikitty.WikittyServiceSecurity.components=packages.MyExternalAuthentication
wikitty.security.externalAuthenticationOnly=true

Il faut bien vérifier que org.nuiton.wikitty.services.WikittyServiceSecurity est déclaré dans la configuration sinon l'option seule wikitty.WikittyServiceSecurity.components n'aura aucun effet.

La dernier option wikitty.security.externalAuthenticationOnly indique ici que si l'authentification sur MyExternalAuthentication échoue il ne faut pas essayer sur le local (par défaut on essaie en local)

Exemple d'utilisation de WikittyServiceSecurityExternalAuthenticationLDAP

Dans wikitty une implantation par défaut a été faite pour l'authentification LDAP Voici un exemple de configuration:

wikitty.WikittyService.components= org.nuiton.wikitty.WikittyServiceStorage, // ...autres.services..., org.nuiton.wikitty.services.WikittyServiceSecurity
wikitty.WikittyServiceSecurity.components= org.nuiton.wikitty.services.WikittyServiceSecurityExternalAuthenticationLDAP
wikitty.security.externalAuthentication.ldap.server=ldap://intranet.codelutin.home:389
wikitty.security.externalAuthentication.ldap.loginPattern=uid=%s,ou=People,dc=codelutin,dc=home

Les deux options obligatoires sont l'url du serveur et le format des logins (DN) le '%s' est remplacé par le login.

Il est possible d'ajouter toutes les options acceptées par JNDI en les préfixant par 'wikitty.security.externalAuthentication.ldap.jndi.' Par exemple on peut modifier la factory par défaut avec:

wikitty.security.externalAuthentication.ldap.jndi.java.naming.factory.initial

Voir la documentation JNDI pour toutes les options possibles

Utilisateurs et groupes

Dans Wikitty, deux notions sont utilisées pour gérer la sécurité : les utilisateurs (WikittyUser) et groupes (WikittyGroup).

Les utilisateurs ont un identifiant et un mot de passe, les groupes contiennent des utilisateurs et d'autres groupes.

Par défaut il existe un WikittyGroup portant le nom WikittyAppAdmin. Si ce groupe n'existe pas ou qu'il est vide, cela indique que tous les utilisateurs sont AppAdmin. Cela est nécessaire pour deux choses:

  • pour permettre d'avoir une authentification, mais que l'on ne souhaite pas de gestion d'autorisation.

  • pour servir de bootstrap au lancement de l'application seul les AppAdmin peuvent modifier le WikittyGroup portant le nom WikittyAppAdmin, or s'il est vide il faut pouvoir le remplir.

Il ne doit donc exister un seul WikittyGroup portant le nom WikittyAppAdmin

L'authentification et les tokens de sécurité

À chaque login, un token de sécurité est fourni à l'utilisateur. L'utilisateur doit fournir ce token à chaque opération pour montrer qu'il a les droits. Pour un token donné, on peut savoir à quel utilisateur il appartient. Pour le développeur, cela n'implique pas de changement car le token de sécurité est conservé par le WikittyClient. Il faut juste faire attention à bien avoir un WikittyClient par utilisateur. Dans le cas d'applications web, il est conseillé de conserver le client dans la session de l'utilisateur.

Les tokens sont stockés en base et supprimés au logout de l'utilisateur.

Les SecurityToken ne sont supprimés de la base de données qu'au moment du logout Si les utilisateurs/applications quittent sans faire le logout le nombre de SecurityToken ne fera qu'augmenter. Pour éviter cela, il faut prévoir un petit job qui de temps en temps fait le ménage dans les SecurityToken trop vieux.

Création de l'administrateur de l'application (AppAdmin)

La première chose à faire maintenant, est donc de créer l'utilisateur administrateur de l'application et l'ajouter au groupe WikittyAppAdmin:

WikittyUser admin = new WikittyUserImpl();
admin.setLogin("admin");
admin.setPassword("admin");
admin = client.store(admin);

WikittyGroup adminGroup = WikittySecurityUtil.createAppAdminGroup(admin);

Note : il faut vérifier que le groupe existe avant de le créer).

Jouer avec les droits sur une entité (sécurité de niveau 1)

A partir de maintenant, l'utilisateur administrateur (et tous les autres utilisateurs faisant partie du groupe WikittyAppAdmin) peut ajouter/retirer des droits à des entités.

Par exemple, pour rajouter les droits de lecture à un utilisateur (l'utilisateur admin est déjà identifié) sur un wikitty:

//On commence par charger les wikitties concernés
WikittyAuthorisation skill = client.restore(WikittyAuthorisation.class, id);

//On ajoute en reader notre utilisateur
skill.addReader(user.getWikittyId());

//On enregistre
client.store(skill);

On peut de la même manière ajouter un groupe en tant que reader/writer/owner/admin d'une entité.

Les droits sont les suivants :

Type

Lecture

Ecriture

Suppression

Changement de droits

Reader

X

Writer

X

X

Admin

X

X

X

X

Owner

X

X

X

X

AppAdmin

X

X

X

X

Si on veut que tout le monde puisse lire un wikitty, il faut laisser vide la liste des readers (vide ou null).

Si l'on souhaite indiquer que personne ne peut lire l'objet il faut mettre le owner en tant que reader. Car de toute façon l'owner aura toujours le droit en lecture.

La granularité des droits se situe donc au niveau de chaque instance. On doit pouvoir définir le droit pour chaque extension, de chaque wikitty. Il n'y a pas de gestion des droits par champs. Avoir le droit reader sur une extension d'un wikitty donne le droit de lecture sur tous les champs de cette extension.

Différence entre Admin et AppAdmin

Un admin est administrateur d'une entité uniquement, alors qu'un AppAdmin est administrateur de toutes les entités de l'application.

Stockage des droits de niveau 1 en base de donnée

Du point de vue structure de données, les droits sont stockés sur le wikitty lui-même, dans des champs spécifiques. Par exemple, si le wikitty porte l'extension Ext, il portera également l'extension « Ext:WikittySecurity » et il y aura, sur le Wikitty, un champ nommé « owner » (dont le FQN est « Ext:WikittySecurity.owner »).

Autre exemple, si un Wikitty porte 3 extensions, ayant chacune 10 champs. Le wikitty aura, au total, 42 champs : 3 × 10 champs + 3 extensions × 4 champs (les 4 champs de l'extension WikittySecurity).

Jouer avec les droits sur les extensions (sécurité niveau 2)

Pour chaque extension, on a la même hiérachie de droit qui donnent des possibilités différentes :

Type

Lecture- Création d'instances

Ecriture

Suppression

Changement de droits

Reader

X

Writer

X

X

Admin

X

X

X

X

Owner

X

X

X

X

AppAdmin

X

X

X

X

Si le reader est vide, tout le monde peut créer des instances de l'extension. Pour que seuls les AppAdmin et le owner puissent créer des instances, il faut mettre le owner en reader.

Si une extension ne dispose pas de ces informations, seuls les AppAdmin peuvent créer les instances et modifier l'extension.

Stockage des droits de niveau 2 en base de donnée

Ces droits sont stockés sous le forme d'un Wikitty. Pour chaque extension connue, il y aura donc un Wikitty dont la seule extension sera WikittySecurity.

Chacun de ces wikitty aura pour identifiant « WikittySecurity:ExtensionName ». Cela permet de court-cuircuiter la recherche solR, et un passage par le réseau à chaque store/restore.