Le Role Based Access Control

Publié le 17 décembre 2014 par Guillaume Goureau | architecture

Cet article est publié sous licence CC BY-NC-SA

Nous utilisons pour la plupart de nos applications web des systèmes d’autorisations d’accès. Ce que je vous propose c’est de revenir sur la conception de ces systèmes et de prendre un exemple en utilisant les gems cancancan pour la gestion des autorisations et rolify pour la gestion des rôles.

Tout d’abord parlons du Role-Based Access Control (RBAC). Pour certains cette notion peut sembler floue mais pourtant c’est une notion que nous utilisons très régulièrement.

Le Role-Based Access Control

Le RBAC c’est quoi ? Un peu d’histoire : C’est un modèle de contrôle d’accès proposé en 1992 par Ferraiolo et Kuhn qui est basé sur le fait d’attacher des rôles aux utilisateurs afin de leur donner certains accès.  Il a été mis en place afin de donner une alternative à deux modèles :

  • Mandatory Access contrôle (MAC), modèle utilisé majoritairement pour des systèmes de sécurité militaire, qui permet de restreindre l’accès à des informations en fonction du niveau de sensibilité de celle-ci et de l’autorisation des utilisateurs à pouvoir accéder à un tel niveau d’information.

  • Discretionary Access contrôle (DAC), modèle utilisé pour les entreprises ou encore pour des systèmes de sécurité militaire de bas niveau, qui permet à un utilisateur d’accorder ou révoquer l’accès à l’un des objets sous son contrôle sans l’intervention d’un administrateur.

Prenons pour exemple le modèle DAC qui est orienté entreprise : je suis un docteur et j’ai la permission de prescrire des médicaments. Si on se base sur la logique du modèle, étant donné que la prescription de médicament est sous le contrôle du docteur, il peut la donner à qui il veut, par exemple à une infirmière. Or cela est aberrant car une infirmière n’a pas le droit de prescrire de médicaments.

Les utilisateurs peuvent dans le cas du modèle DAC passer leurs permissions à d’autres utilisateurs. C’est la différence fondamentale avec le modèle RBAC qui pour ce dernier permet de protéger les données ainsi que leurs intégralités et leurs confidentialités.

Ce modèle est basé sur 3 notions :

  • 1ère notion : Un utilisateur va pouvoir exécuter une tâche si il a été affecté à un rôle.
  • 2nd notion : Un utilisateur à besoin d’une autorisation pour détenir un rôle.
  • 3ème notion : Un utilisateur va pouvoir exécuter certaines opérations sur un objet si celles-ci sont permises par le rôle qu’il possède.

Les rôles dans leurs formes les plus simples sont basés sur les niveaux d’utilisation : Admin, Modérateur, Utilisateur, etc. Mais pour des formes plus complexes, les rôles vont représenter les corps de métier, les projets ou encore les activités.

Ce modèle RBAC est devenu le modèle de gestion le plus employé car il s’applique aisément aux différentes structures. Chaque rôle est une simple collection de permissions et les utilisateurs reçoivent des autorisations uniquement à travers les rôles auxquels ils sont affectés.

rbac_notions

Mise en application

Passons à une utilisation pratique afin de comprendre le fonctionnement de ce modèle RBAC.

Nous allons utiliser 2 gems : Cancancan et Rolify. Ajoutons à notre Gemfile les 2 gems :

gem 'cancancan'
gem 'rolify'

Installons les gems avec un bundle install puis passons à la configuration. Dans un premier temps nous allons créer un rôle User. Pour cette démonstration les attributs nous importent peu : 

rails generate model User

Dans un second temps nous allons créer la classe Ability qui va nous permettre de définir les permissions de nos utilisateurs avec Cancancan.

rails generate cancan:ability

Enfin nous allons nous simplifier la gestion des rôles avec Rolify

rails generate rolify Role User

Lancez la migration avec un rake db:migrate

Que venons nous de faire ? Nous venons de créer un modèle User qui dispose grâce à Cancancan et Rolify d’un gestionnaire d’autorisations et de rôles. Configurons maintenant l’ensemble. Dans le fichier Ability, ajoutons dans la méthode initialize les autorisations suivantes :

# app/models/ability.rb

if user.has_role? :employee
	can :go, :cloakroom
elsif user.has_role? :doctor
	can [:heal, :give_medications], :patient
elsif user.has_role? :nurse
	can :heal, :patient
else
	can :wait, :waiting_room
end

Si on traduit nos droits littéralement, cela nous donne : 1. Un employé va pouvoir aller dans les vestiaires 2. Un docteur va pouvoir soigner et prescrire des médicaments aux patients 3. Une infirmière va pouvoir soigner les patients 4. Les personnes qui ne sont ni employés, ni docteurs et ni infirmières sont conviées à attendre bien gentiment dans la salle d’attente

1ère notion : L’attribution

Passons en console rails console Nous allons ici créer des utilisateurs et tester leurs droits en fonction de leurs rôles et faire une comparaison avec les 3 notions d’un modèle RBAC.

patient = User.new
patient.save
patient.roles
=> []

patient.roles nous permet de lister les rôles associés aux patients. Comme nous n’avons pas attribué de rôles à celui-ci, cette commande nous retourne une liste vide. Nous allons maintenant récupérer les droits du patient et comprendre leurs fonctionnements.

ability = Ability.new(patient)
ability.can? :wait, :waiting_room
=> true
ability.can? :go, :cloakroom
=> false

ability.can? :wait, :waiting_room nous permet de vérifier si les autorisations du patient lui permettent d’attendre dans la salle d’attente. La réponse retournée est oui.

Même principe avec la commande ability.can? :go, :cloakroom qui permet de vérifier si le patient peut aller dans le vestiaire, la réponse retournée est non.

En regardant notre méthode initialize cela semble évident mais pourquoi ? Reprenons les 3 notions sur lequel un modèle RBAC est fondé :

  • 1ère notion : Un utilisateur va pouvoir exécuter une tâche si il a été affecté à un rôle.
  • 2nd notion : Un utilisateur a besoin d’une autorisation pour détenir un rôle.
  • 3ème notion : Un utilisateur va pouvoir exécuter certaines opérations si celles-ci sont autorisées par le rôle qu’il possède.

C’est la première notion ici qui fait défaut dans notre exemple. Le patient n’aillant aucun rôle, il ne peut donc effectuer aucune tache et est contraint à rester dans la salle d’attente.

2nd notion : La permission

Passons à une nurse. Une nurse (en anglais) est comme son nom l’indique une infirmière mais elle est aussi une employée. Nous allons donc lui appliquer les 2 rôles.

nurse = User.new
nurse.save
nurse.add_role [:employee, :nurse]
nurse.roles
=> [:employee, :nurse]

Dans cet exemple, nous avons attribué des rôles à notre nurse. De ce fait nous avons remplis la première notion du modèle RBAC. Mais ce n’est pas tout. Si nous avons pu attribuer un rôle à notre nurse, c’est que celle-ci avait l’autorisation pour détenir ce rôle.

Il est important de vérifier deux choses pour valider notre 2nd notion du modèle RBAC et de la dissocier de la 1ère :

  • qu’elle est l’entité qui donne l’autorisation ?
  • qu’elle est l’entité qui demande l’autorisation ?

Ai-je les permissions (le rôle) pour pouvoir attribuer ce rôle ? Si oui, l’entité qui demande le rôle est-elle autorisée à l’avoir ? Sans cette vérification, notre 2nd notion n’existe plus et le modèle RBAC perd de son utilité.

3ème notion : l’autorisation

Pour finir avec cette application du modèle RBAC, nous allons vérifier les autorisations de notre nurse.

ability = Ability.new(nurse)
ability.can? :go, :cloakroom
=> true
ability.can? :heal, :patient
=> true
ability.can? :give_medications, :patient
=> false

Une nurse peut aller soigner un patient ou encore aller dans le vestiaire car ses rôles l’y autorisent. Mais bien qu’elle ait accès au patient, ce n’est pas pour autant qu’elle peut lui prescrire des médicaments.

C’est la qu’intervient la 3ème notion du modèle RBAC. Dans cet exemple nous avons autorisé dans notre méthode initialize la nurse à accéder au modèle patient mais nous lui avons autorisé uniquement les soins sur celui-ci.

L’accès au modèle patient est bien autorisé à notre nurse mais les autorisations qu’elle reçoit à travers les rôles ne lui permettent pas de réaliser l’ensemble des opérations.

rbac_roles

Conclusion

J’espère que ce petit retour sous forme d’application du modèle RBAC vous a permis de mieux comprendre son fonctionnement et de l’importance à respecter les différentes notions qui le compose afin d’optimiser la sécurité de vos applications.

Une bonne configuration et une bonne gestion des rôles vous permettra d’éviter bien des problèmes et de gagner pas mal de temps.

L’équipe Synbioz.

Libres d’être ensemble.