blog.notmyidea.org/service-de-nuages-la-gestion-des-permissions-fr.html

666 lines
No EOL
31 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="fr">
<head>
<title>
Service de nuages : La gestion des&nbsp;permissions - Alexis Métaireau </title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
href="https://blog.notmyidea.org/theme/css/main.css?v2"
type="text/css" />
<link href="https://blog.notmyidea.org/feeds/all.atom.xml"
type="application/atom+xml"
rel="alternate"
title="Alexis Métaireau ATOM Feed" />
</head>
<body>
<div id="content">
<section id="links">
<ul>
<li>
<a class="main" href="/">Alexis Métaireau</a>
</li>
<li>
<a class=""
href="https://blog.notmyidea.org/journal/index.html">Journal</a>
</li>
<li>
<a class="selected"
href="https://blog.notmyidea.org/code/">Code, etc.</a>
</li>
<li>
<a class=""
href="https://blog.notmyidea.org/weeknotes/">Notes hebdo</a>
</li>
<li>
<a class=""
href="https://blog.notmyidea.org/lectures/">Lectures</a>
</li>
<li>
<a class=""
href="https://blog.notmyidea.org/projets.html">Projets</a>
</li>
</ul>
</section>
<header>
<h1 class="post-title">Service de nuages : La gestion des&nbsp;permissions</h1>
<time datetime="2015-05-01T00:00:00+02:00">01 mai 2015</time>
</header>
<article>
<p><em>Cet article est repris depuis le blog « Service de Nuages » de mon équipe à&nbsp;Mozilla</em></p>
<p>Dans le cadre de la création d&#8217;un service de stockage de données personnelles
(Kinto), la gestion des permissions est un des gros challenges : qui doit avoir
accès à quoi, et comment le définir&nbsp;?</p>
<p><strong>tl;dr: Quelques retours sur le vocabulaire des systèmes de permission et sur nos idées pour l&#8217;implementation des permissions dans un stockage&nbsp;générique.</strong></p>
<div class="section" id="la-problematique">
<h2>La&nbsp;problématique</h2>
<p>La problématique est simple : des données sont stockées en ligne, et il
faut un moyen de pouvoir les partager avec d&#8217;autres&nbsp;personnes.</p>
<p>En regardant les cas d&#8217;utilisations, on se rend compte qu&#8217;on a plusieurs types
d&#8217;utilisateurs&nbsp;:</p>
<ul class="simple">
<li>les utilisateurs &#8220;finaux&#8221; (vous)&nbsp;;</li>
<li>les applications qui interagissent en leurs&nbsp;noms.</li>
</ul>
<p>Tous les intervenants n&#8217;ont donc pas les mêmes droits : certains doivent
pouvoir lire, d&#8217;autres écrire, d&#8217;autres encore créer de nouveaux
enregistrements, et le contrôle doit pouvoir s&#8217;effectuer de manière fine : il
doit être possible de lire un enregistrement mais pas un autre, par&nbsp;exemple.</p>
<p>Nous sommes partis du constat que les solutions disponibles n&#8217;apportaient pas
une réponse satisfaisante à ces&nbsp;besoins.</p>
</div>
<div class="section" id="un-probleme-de-vocabulaire">
<h2>Un problème de&nbsp;vocabulaire</h2>
<p>Le principal problème rencontré lors des réflexions fût le&nbsp;vocabulaire.</p>
<p>Voici ci-dessous une explication des différents&nbsp;termes.</p>
<div class="section" id="le-concept-de-principal">
<h3>Le concept de « principal&nbsp;»</h3>
<p>Un <em>principal</em>, en sécurité informatique, est une entité qui peut être
authentifiée par un système informatique. <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a> En Français il s&#8217;agit
du « commettant », l&#8217;acteur qui commet l&#8217;action (oui, le terme est conceptuel&nbsp;!)</p>
<p>Il peut s&#8217;agir aussi bien d&#8217;un individu, d&#8217;un ordinateur, d&#8217;un
service ou d&#8217;un groupe regroupant l&#8217;une de ces entités, ce qui
est plus large que le classique « <em>user id</em>&nbsp;».</p>
<p>Les permissions sont alors associées à ces <em>principals</em>.</p>
<p>Par exemple, un utilisateur est identifié de manière unique lors de la
connexion par le système d&#8217;authentification dont le rôle est de
définir une liste de <em>principals</em> pour l&#8217;utilisateur se&nbsp;connectant.</p>
<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>Pour en savoir plus sur les <em>principals</em> :
<a class="reference external" href="https://en.wikipedia.org/wiki/Principal_%28computer_security%29">https://en.wikipedia.org/wiki/Principal_%28computer_security%29</a></td></tr>
</tbody>
</table>
</div>
<div class="section" id="la-difference-entre-role-et-groupe">
<h3>La différence entre rôle et&nbsp;groupe</h3>
<p>De but en blanc, il n&#8217;est pas évident de définir précisément la
différence entre ces deux concepts qui permettent d&#8217;associer
des permissions à un groupe de <em>principals</em>. <a class="footnote-reference" href="#footnote-2" id="footnote-reference-2">[2]</a></p>
<p>La différence est principalement sémantique. Mais on peut y voir une
différence dans la « direction » de la relation entre les deux&nbsp;concepts.</p>
<ul class="simple">
<li>Un rôle est une liste de permissions que l&#8217;on associe à un <em>principal</em>.</li>
<li>Un groupe est une liste de <em>principals</em> que l&#8217;on peut associer à une&nbsp;permission.</li>
</ul>
<table class="docutils footnote" frame="void" id="footnote-2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[2]</a></td><td>Plus d&#8217;informations :
<a class="reference external" href="http://stackoverflow.com/questions/7770728/group-vs-role-any-real-difference">http://stackoverflow.com/questions/7770728/group-vs-role-any-real-difference</a></td></tr>
</tbody>
</table>
</div>
<div class="section" id="la-difference-entre-permission-acl-ace">
<h3>La différence entre permission, <span class="caps">ACL</span>, <span class="caps">ACE</span></h3>
<blockquote class="epigraph">
<p>Une <span class="caps">ACL</span> est une liste dAccess Control Entry (<span class="caps">ACE</span>) ou entrée de contrôle d&#8217;accès
donnant ou supprimant des droits d&#8217;accès à une personne ou un&nbsp;groupe.</p>
<p class="attribution">&mdash;<a class="reference external" href="https://fr.wikipedia.org/wiki/Access_Control_List">https://fr.wikipedia.org/wiki/Access_Control_List</a></p>
</blockquote>
<p>Je dirais même plus, dans notre cas, « à un <em>principal</em> ». Par&nbsp;exemple:</p>
<div class="highlight"><pre><span></span>create_record: alexis,remy,tarek
</pre></div>
<p>Cet <span class="caps">ACE</span> donne la permission <tt class="docutils literal">create</tt> sur l&#8217;objet <tt class="docutils literal">record</tt> aux
utilisateurs Tarek, Rémy et&nbsp;Alexis.</p>
</div>
</div>
<div class="section" id="la-delegation-de-permissions">
<h2>La délégation de&nbsp;permissions</h2>
<p>Imaginez l&#8217;exemple suivant, où un utilisateur stocke deux types de données en
ligne&nbsp;:</p>
<ul class="simple">
<li>des contacts&nbsp;;</li>
<li>une liste de tâches à faire qu&#8217;il peut associer à ses&nbsp;contacts.</li>
</ul>
<p>L&#8217;utilisateur a tous les droits sur ses&nbsp;données.</p>
<p>Cependant il utilise deux applications qui doivent elles avoir un accès restreint&nbsp;:</p>
<ul class="simple">
<li>une application de gestion des contacts à qui il souhaite déléguer
la gestion intégrale de ses contacts : <tt class="docutils literal">contacts:write</tt> ;</li>
<li>une application de gestion des tâches à qui il souhaite déléguer la
gestion des tâches : <tt class="docutils literal">contacts:read tasks:write</tt></li>
</ul>
<p>Il souhaite que son application de contacts ne puisse pas accéder à
ses tâches et que son application de tâches ne puisse pas modifier ses
contacts existants, juste éventuellement en créer de&nbsp;nouveaux.</p>
<p>Il lui faut donc un moyen de déléguer certains de ses droits à un tiers&nbsp;(l&#8217;application).</p>
<p>C&#8217;est précisément le rôle des <a class="reference external" href="http://tools.ietf.org/html/rfc6749#page-23">scopes OAuth2</a>.</p>
<p>Lors de la connexion d&#8217;un utilisateur, une fenêtre lui demande quels
accès il veut donner à l&#8217;application qui va agir en son&nbsp;nom.</p>
<p>Le service aura ensuite accès à ces <em>scopes</em> en regardant le jeton
d&#8217;authentification utilisé. Cette information doit être
considérée comme une entrée utilisateur (c&#8217;est à dire qu&#8217;on ne peut
pas lui faire confiance). Il s&#8217;agit de ce que l&#8217;utilisateur&nbsp;souhaite.</p>
<p>Or, il est également possible que l&#8217;utilisateur n&#8217;ait pas accès aux données
qu&#8217;il demande. Le service doit donc utiliser deux niveaux de permissions :
celles de l&#8217;utilisateur, et celles qui ont été déléguées à&nbsp;l&#8217;application.</p>
</div>
<div class="section" id="espace-de-noms">
<h2>Espace de&nbsp;noms</h2>
<p>Dans notre implémentation initiale de <em>Kinto</em> (notre service de stockage en
construction), l&#8217;espace de nom était implicite : les données stockées étaient
nécessairement celles de l&#8217;utilisateur&nbsp;connecté.</p>
<p>Les données d&#8217;un utilisateur étaient donc cloisonnées et impossible à&nbsp;partager.</p>
<p>L&#8217;utilisation d&#8217;espaces de noms est une manière simple de gérer le partage des&nbsp;données.</p>
<p>Nous avons choisi de reprendre le modèle de GitHub et de Bitbucket, qui
utilisent les « organisations » comme espaces de&nbsp;noms.</p>
<p>Dans notre cas, il est possible de créer des &#8220;buckets&#8221;, qui correspondent à ces
espaces de noms. Un bucket est un conteneur de collections et de groupes&nbsp;utilisateurs.</p>
<p>Les ACLs sur ces collections peuvent être attribuées à certains groupes du
<em>bucket</em> ainsi qu&#8217;à d&#8217;autres <em>principals</em>&nbsp;directement.</p>
</div>
<div class="section" id="notre-proposition-d-api">
<h2>Notre proposition d&#8217;<span class="caps">API</span></h2>
<div class="section" id="les-objets-manipules">
<h3>Les objets&nbsp;manipulés</h3>
<p>Pour mettre en place la gestion des permissions, nous avons identifié les
objets suivants&nbsp;:</p>
<table border="1" class="docutils">
<colgroup>
<col width="23%" />
<col width="77%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Objet</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td><strong>bucket</strong></td>
<td>On peut les voir comme des espaces de noms. Ils
permettent d&#8217;avoir différentes collections portant
le même nom mais stockées dans différents <em>buckets</em> de
manière à ce que les données soient distinctes.</td>
</tr>
<tr><td><strong>collection</strong></td>
<td>Une liste d&#8217;enregistrements.</td>
</tr>
<tr><td><strong>record</strong></td>
<td>Un enregistrement d&#8217;une collection.</td>
</tr>
<tr><td><strong>group</strong></td>
<td>Un groupe de commetants (« <em>principals</em> »).</td>
</tr>
</tbody>
</table>
<p>Pour la définition des ACLs, il y a une hiérarchie et les objets « héritent » des
ACLs de leur parents&nbsp;:</p>
<div class="highlight"><pre><span></span> +---------------+
| Bucket |
+---------------+
+-----&gt;+ - id +&lt;---+
| | - permissions | |
| +---------------+ |
| |
| |
| |
| |
| |
+---+-----------+ +------+---------+
| Collection | | Group |
+---------------+ +----------------+
| - id | | - id |
| - permissions | | - members |
+------+--------+ | - permissions |
^ +----------------+
|
|
+------+---------+
| Record |
+----------------+
| - id |
| - data |
| - permissions |
+----------------+
</pre></div>
</div>
<div class="section" id="les-permissions">
<h3>Les&nbsp;permissions</h3>
<p>Pour chacun de ces objets nous avons identifié les permissions suivantes&nbsp;:</p>
<table border="1" class="docutils">
<colgroup>
<col width="23%" />
<col width="77%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Permission</th>
<th class="head">Description</th>
</tr>
</thead>
<tbody valign="top">
<tr><td><strong>read</strong></td>
<td>La permission de lire le contenu de
l&#8217;objet et de ses sous-objets.</td>
</tr>
<tr><td><strong>write</strong></td>
<td>La permission de modifier et
d&#8217;administrer un objet et ses sous-
objets. La permission <em>write</em> permet la
lecture, modification et suppression
d&#8217;un objet ainsi que la gestion de ses
permissions.</td>
</tr>
<tr><td><strong>create</strong></td>
<td>La permission de créer le sous-objet
spécifié. Par exemple:
<tt class="docutils literal">collections:create</tt></td>
</tr>
</tbody>
</table>
<p>À chaque permission spécifiée sur un objet est associée une liste de
<em>principals</em>.</p>
<p>Dans le cas de la permission <tt class="docutils literal">create</tt> on est obligé de spécifier
l&#8217;objet enfant en question car un objet peut avoir plusieurs types
d&#8217;enfants. Par exemple : <tt class="docutils literal">collections:create</tt>, <tt class="docutils literal">groups:create</tt>.</p>
<p>Nous n&#8217;avons pour l&#8217;instant pas de permission pour <cite>delete</cite> et <cite>update</cite>,
puisque nous n&#8217;avons pas trouvé de cas d&#8217;utilisation qui les nécessitent.
Quiconque avec le droit d&#8217;écriture peut donc supprimer un&nbsp;enregistrement.</p>
<p>Les permissions d&#8217;un objet sont héritées de son parent. Par exemple,
un enregistrement créé dans une collection accessible à tout le monde
en lecture sera lui aussi accessible à tout le&nbsp;monde.</p>
<p>Par conséquent, les permissions sont cumulées. Autrement dit, il n&#8217;est pas
possible qu&#8217;un objet ait des permissions plus restrictives que son&nbsp;parent.</p>
<p>Voici la liste exhaustive des permissions&nbsp;:</p>
<table border="1" class="docutils">
<colgroup>
<col width="21%" />
<col width="32%" />
<col width="47%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Objet</th>
<th class="head">Permissions associées</th>
<th class="head">Commentaire</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>Configuration
(.ini)</td>
<td><cite>buckets:create</cite></td>
<td>Les <em>principals</em> ayant le droit
de créer un bucket sont définis
dans la configuration du serveur.
(<em>ex. utilisateurs authentifiés</em>)</td>
</tr>
<tr><td rowspan="4"><tt class="docutils literal">bucket</tt></td>
<td><cite>write</cite></td>
<td>C&#8217;est en quelque sorte le droit
d&#8217;administration du <em>bucket</em>.</td>
</tr>
<tr><td><cite>read</cite></td>
<td>C&#8217;est le droit de lire le contenu
de tous les objets du <em>bucket</em>.</td>
</tr>
<tr><td><cite>collections:create</cite></td>
<td>Permission de créer des
collections dans le <em>bucket</em>.</td>
</tr>
<tr><td><cite>groups:create</cite></td>
<td>Permission de créer des groupes
dans le <em>bucket</em>.</td>
</tr>
<tr><td rowspan="3"><tt class="docutils literal">collection</tt></td>
<td><cite>write</cite></td>
<td>Permission d&#8217;administrer tous les
objets de la collection.</td>
</tr>
<tr><td><cite>read</cite></td>
<td>Permission de consulter tous les
objets de la collection.</td>
</tr>
<tr><td><cite>records:create</cite></td>
<td>Permission de créer des nouveaux
enregistrement dans la collection.</td>
</tr>
<tr><td rowspan="2"><tt class="docutils literal">record</tt></td>
<td><cite>write</cite></td>
<td>Permission de modifier ou de
partager l&#8217;enregistrement.</td>
</tr>
<tr><td><cite>read</cite></td>
<td>Permission de consulter
l&#8217;enregistrement.</td>
</tr>
<tr><td rowspan="2"><tt class="docutils literal">group</tt></td>
<td><cite>write</cite></td>
<td>Permission d&#8217;administrer le
groupe</td>
</tr>
<tr><td><cite>read</cite></td>
<td>Permission de consulter les
membres du groupe.</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="les-principals">
<h3>Les « <em>principals</em>&nbsp;»</h3>
<p>Les acteurs se connectant au service de stockage peuvent&nbsp;s&#8217;authentifier.</p>
<p>Ils reçoivent alors une liste de <em>principals</em>&nbsp;:</p>
<ul class="simple">
<li><tt class="docutils literal">Everyone</tt>: le <em>principal</em> donné à tous les acteurs (authentifiés ou pas)&nbsp;;</li>
<li><tt class="docutils literal">Authenticated</tt>: le <em>principal</em> donné à tous les acteurs authentifiés&nbsp;;</li>
<li>un <em>principal</em> identifiant l&#8217;acteur, par exemple <tt class="docutils literal">fxa:32aa95a474c984d41d395e2d0b614aa2</tt></li>
</ul>
<p>Afin d&#8217;éviter les collisions d&#8217;identifiants, le <em>principal</em> de l&#8217;acteur dépend
de son type d&#8217;authentification (<tt class="docutils literal">system</tt>, <tt class="docutils literal">basic</tt>, <tt class="docutils literal">ipaddr</tt>, <tt class="docutils literal">hawk</tt>,
<tt class="docutils literal">fxa</tt>) et de son identifiant (unique par&nbsp;acteur).</p>
<p>En fonction du <em>bucket</em> sur lequel se passe l&#8217;action, les groupes dont
fait partie l&#8217;utilisateur sont également ajoutés à sa liste de
<tt class="docutils literal">principals</tt>. <tt class="docutils literal">group:moderators</tt> par&nbsp;exemple.</p>
<p>Ainsi, si Bob se connecte avec <em>Firefox Accounts</em> sur le <em>bucket</em>
<tt class="docutils literal">servicedenuages_blog</tt> dans lequel il fait partie du groupe
<tt class="docutils literal">moderators</tt>, il aura la liste de <em>principals</em> suivante :
<tt class="docutils literal">Everyone, Authenticated, fxa:32aa95a474c984d41d395e2d0b614aa2, group:moderators</tt></p>
<p>Il est donc possible d&#8217;assigner une permission à Bob en utilisant l&#8217;un de
ces quatre <em>principals</em>.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Le <em>principal</em> <tt class="docutils literal">&lt;userid&gt;</tt> dépend du <em>back-end</em> d&#8217;authentification (e.g.
<tt class="docutils literal">github:leplatrem</tt>).</p>
</div>
</div>
<div class="section" id="quelques-exemples">
<h3>Quelques&nbsp;exemples</h3>
<p><strong>Blog</strong></p>
<table border="1" class="docutils">
<colgroup>
<col width="35%" />
<col width="18%" />
<col width="46%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Objet</th>
<th class="head">Permissions</th>
<th class="head">Principals</th>
</tr>
</thead>
<tbody valign="top">
<tr><td><tt class="docutils literal">bucket:blog</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal"><span class="pre">fxa:&lt;blog</span> owner id&gt;</tt></td>
</tr>
<tr><td rowspan="2"><tt class="docutils literal">collection:articles</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal">group:moderators</tt></td>
</tr>
<tr><td><tt class="docutils literal">read</tt></td>
<td><tt class="docutils literal">Everyone</tt></td>
</tr>
<tr><td><tt class="docutils literal">record:569e28r98889</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal"><span class="pre">fxa:&lt;co-author</span> id&gt;</tt></td>
</tr>
</tbody>
</table>
<p><strong>Wiki</strong></p>
<table border="1" class="docutils">
<colgroup>
<col width="35%" />
<col width="18%" />
<col width="46%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Object</th>
<th class="head">Permissions</th>
<th class="head">Principals</th>
</tr>
</thead>
<tbody valign="top">
<tr><td><tt class="docutils literal">bucket:wiki</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal"><span class="pre">fxa:&lt;wiki</span> administrator id&gt;</tt></td>
</tr>
<tr><td rowspan="2"><tt class="docutils literal">collection:articles</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal">Authenticated</tt></td>
</tr>
<tr><td><tt class="docutils literal">read</tt></td>
<td><tt class="docutils literal">Everyone</tt></td>
</tr>
</tbody>
</table>
<p><strong>Sondages</strong></p>
<table border="1" class="docutils">
<colgroup>
<col width="34%" />
<col width="31%" />
<col width="35%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Objet</th>
<th class="head">Permissions</th>
<th class="head">Principals</th>
</tr>
</thead>
<tbody valign="top">
<tr><td rowspan="2"><tt class="docutils literal">bucket:poll</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal"><span class="pre">fxa:&lt;admin</span> id&gt;</tt></td>
</tr>
<tr><td><tt class="docutils literal">collection:create</tt></td>
<td><tt class="docutils literal">Authenticated</tt></td>
</tr>
<tr><td rowspan="2"><tt class="docutils literal"><span class="pre">collection:&lt;poll</span> id&gt;</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal"><span class="pre">fxa:&lt;poll</span> author id&gt;</tt></td>
</tr>
<tr><td><tt class="docutils literal">record:create</tt></td>
<td><tt class="docutils literal">Everyone</tt></td>
</tr>
</tbody>
</table>
<p><strong>Cartes&nbsp;colaboratives</strong></p>
<table border="1" class="docutils">
<colgroup>
<col width="34%" />
<col width="31%" />
<col width="35%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Objet</th>
<th class="head">Permissions</th>
<th class="head">Principals</th>
</tr>
</thead>
<tbody valign="top">
<tr><td rowspan="2"><tt class="docutils literal">bucket:maps</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal"><span class="pre">fxa:&lt;admin</span> id&gt;</tt></td>
</tr>
<tr><td><tt class="docutils literal">collection:create</tt></td>
<td><tt class="docutils literal">Authenticated</tt></td>
</tr>
<tr><td rowspan="2"><tt class="docutils literal"><span class="pre">collection:&lt;map</span> id&gt;</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal"><span class="pre">fxa:&lt;map</span> author id&gt;</tt></td>
</tr>
<tr><td><tt class="docutils literal">read</tt></td>
<td><tt class="docutils literal">Everyone</tt></td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">record:&lt;record</span> id&gt;</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal"><span class="pre">fxa:&lt;maintainer</span> id&gt;</tt>
(<em>ex. event staff member
maintaining venues</em>)</td>
</tr>
</tbody>
</table>
<p><strong>Plateformes</strong></p>
<p>Bien sûr, il y a plusieurs façons de modéliser les cas d&#8217;utilisation typiques.
Par exemple, on peut imaginer une plateforme de wikis (à la wikia.com), où les
wikis sont privés par défaut et certaines pages peuvent être rendues publiques&nbsp;:</p>
<table border="1" class="docutils">
<colgroup>
<col width="32%" />
<col width="30%" />
<col width="38%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head">Objet</th>
<th class="head">Permissions</th>
<th class="head">Principals</th>
</tr>
</thead>
<tbody valign="top">
<tr><td rowspan="3"><tt class="docutils literal">bucket:freewiki</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal"><span class="pre">fxa:&lt;administrator</span> id&gt;</tt></td>
</tr>
<tr><td><tt class="docutils literal">collection:create</tt></td>
<td><tt class="docutils literal">Authenticated</tt></td>
</tr>
<tr><td><tt class="docutils literal">group:create</tt></td>
<td><tt class="docutils literal">Authenticated</tt></td>
</tr>
<tr><td rowspan="2"><tt class="docutils literal"><span class="pre">collection:&lt;wiki</span> id&gt;</tt></td>
<td><tt class="docutils literal">write</tt></td>
<td><tt class="docutils literal"><span class="pre">fxa:&lt;wiki</span> owner id&gt;</tt>,
<tt class="docutils literal"><span class="pre">group:&lt;editors</span> id&gt;</tt></td>
</tr>
<tr><td><tt class="docutils literal">read</tt></td>
<td><tt class="docutils literal"><span class="pre">group:&lt;readers</span> id&gt;</tt></td>
</tr>
<tr><td><tt class="docutils literal"><span class="pre">record:&lt;page</span> id&gt;</tt></td>
<td><tt class="docutils literal">read</tt></td>
<td><tt class="docutils literal">Everyone</tt></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="l-api-http">
<h3>L&#8217;<span class="caps">API</span> <span class="caps">HTTP</span></h3>
<p>Lors de la création d&#8217;un objet, l&#8217;utilisateur se voit
attribué la permission <tt class="docutils literal">write</tt> sur l&#8217;objet&nbsp;:</p>
<div class="highlight"><pre><span></span><span class="nf">PUT</span> <span class="nn">/v1/buckets/servicedenuages_blog</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
<span class="na">Authorization</span><span class="o">:</span> <span class="l">Bearer 0b9c2625dc21ef05f6ad4ddf47c5f203837aa32ca42fced54c2625dc21efac32</span>
<span class="na">Accept</span><span class="o">:</span> <span class="l">application/json</span>
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
{
&quot;id&quot;: &quot;servicedenuages_blog&quot;,
&quot;permissions&quot;: {
&quot;write&quot;: [&quot;fxa:49d02d55ad10973b7b9d0dc9eba7fdf0&quot;]
}
}
</pre></div>
<p>Il est possible d&#8217;ajouter des permissions à l&#8217;aide de <tt class="docutils literal"><span class="caps">PATCH</span></tt> :</p>
<div class="highlight"><pre><span></span><span class="nf">PATCH</span> <span class="nn">/v1/buckets/servicedenuages_blog/collections/articles</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
<span class="na">Authorization</span><span class="o">:</span> <span class="l">Bearer 0b9c2625dc21ef05f6ad4ddf47c5f203837aa32ca42fced54c2625dc21efac32</span>
<span class="na">Accept</span><span class="o">:</span> <span class="l">application/json</span>
{
&quot;permissions&quot;: {
&quot;read&quot;: [&quot;+system.Everyone&quot;]
}
}
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
{
&quot;id&quot;: &quot;servicedenuages_blog&quot;,
&quot;permissions&quot;: {
&quot;write&quot;: [&quot;fxa:49d02d55ad10973b7b9d0dc9eba7fdf0&quot;],
&quot;read&quot;: [&quot;system.Everyone&quot;]
}
}
</pre></div>
<p>Pour le <tt class="docutils literal"><span class="caps">PATCH</span></tt> nous utilisons la syntaxe préfixée par un <tt class="docutils literal">+</tt> ou
par un <tt class="docutils literal">-</tt> pour ajouter ou enlever des <em>principals</em> sur un <span class="caps">ACL</span>.</p>
<p>Il est également possible de faire un <tt class="docutils literal"><span class="caps">PUT</span></tt> pour réinitialiser les ACLs,
sachant que le <tt class="docutils literal"><span class="caps">PUT</span></tt> va ajouter l&#8217;utilisateur courant à la
liste automatiquement mais qu&#8217;il pourra se retirer avec un <tt class="docutils literal"><span class="caps">PATCH</span></tt>.
Ajouter l&#8217;utilisateur courant permet d&#8217;éviter les situations où plus
personne n&#8217;a accès aux&nbsp;données.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">La permission <tt class="docutils literal">create</tt> est valable pour <tt class="docutils literal"><span class="caps">POST</span></tt> mais aussi pour <tt class="docutils literal"><span class="caps">PUT</span></tt>
lorsque l&#8217;enregistrement n&#8217;existe&nbsp;pas.</p>
</div>
</div>
<div class="section" id="le-cas-specifique-des-donnees-utilisateurs">
<h3>Le cas spécifique des données&nbsp;utilisateurs</h3>
<p>Une des fonctionnalités actuelles de <em>Kinto</em> est de pouvoir gérer des
collections d&#8217;enregistrements par&nbsp;utilisateur.</p>
<p>Sous <em>*nix</em> il est possible, pour une
application, de sauvegarder la configuration de l&#8217;utilisateur courant
dans son dossier personnel sans se soucier de l&#8217;emplacement sur
le disque en utilisant <tt class="docutils literal">~/</tt>.</p>
<p>Dans notre cas si une application souhaite sauvegarder les contacts d&#8217;un
utilisateur, elle peut utiliser le raccourci <tt class="docutils literal">~</tt> pour faire référence au
<em>bucket</em> <strong>personnel</strong> de l&#8217;utilisateur : <tt class="docutils literal"><span class="pre">/buckets/~/collections/contacts</span></tt></p>
<p>Cette <span class="caps">URL</span> retournera le code <tt class="docutils literal"><span class="caps">HTTP</span> 307</tt> vers le <em>bucket</em> de l&#8217;utilisateur courant&nbsp;:</p>
<div class="highlight"><pre><span></span><span class="nf">POST</span> <span class="nn">/v1/buckets/~/collections/contacts/records</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
{
&quot;name&quot;: &quot;Rémy&quot;,
&quot;emails&quot;: [&quot;remy@example.com&quot;],
&quot;phones&quot;: [&quot;+330820800800&quot;]
}
HTTP/1.1 307 Temporary Redirect
Location: /v1/buckets/fxa:49d02d55ad10973b7b9d0dc9eba7fdf0/collections/contacts/records
</pre></div>
<p>Ainsi il est tout à fait possible à Alice de partager ses contacts
avec Bob. Il lui suffit pour cela de donner la permission <tt class="docutils literal">read</tt> à
Bob sur sa collection et de donner l&#8217;<span class="caps">URL</span> complète
<tt class="docutils literal">/v1/buckets/fxa:49d02d55ad10973b7b9d0dc9eba7fdf0/collections/contacts/records</tt>
à&nbsp;Bob.</p>
</div>
<div class="section" id="la-delegation-des-permissions">
<h3>La délégation des&nbsp;permissions</h3>
<p>Dans le cas de <em>Kinto</em>, nous avons défini un format pour restreindre les
permissions via les scopes OAuth2:
<tt class="docutils literal"><span class="pre">storage:&lt;bucket_id&gt;:&lt;collection_id&gt;:&lt;permissions_list&gt;</span></tt>.</p>
<p>Ainsi, si on reprend l&#8217;exemple précédent de la liste de tâches, il est possible pour
Bob de créer un token OAuth spécifique avec les <em>scopes</em> suivants :
<tt class="docutils literal">profile storage:todolist:tasks:write <span class="pre">storage:~:contacts:read+records:create</span></tt></p>
<p>Donc, bien que Bob a la permission <tt class="docutils literal">write</tt> sur ses contacts,
l&#8217;application utilisant ce token pourra uniquement lire les contacts
existants et en ajouter de&nbsp;nouveaux.</p>
<p>Une partie de la complexité est donc de réussir à présenter ces <em>scopes</em> de
manière lisible à l&#8217;utilisateur, afin qu&#8217;il choisisse quelles permissions
donner aux applications qui agissent en son&nbsp;nom.</p>
<p>Voilà où nous en sommes de notre réflexion&nbsp;!</p>
<p>Si vous avez des choses à ajouter, des points de désaccord ou autres
réflexions, n&#8217;hésitez pas à nous interrompre pendant qu&#8217;il est encore temps&nbsp;!</p>
</div>
</div>
</article>
<footer>
<a id="feed" href="/feeds/all.atom.xml">
<img alt="RSS Logo" src="/theme/rss.svg" />
</a>
</footer>
</div>
</body>
</html>