Authentification Registry
Ce document décrit le schéma d'authentification du registry :


- Tentative de commencer une opération push/pull avec le registry.
- Si le registry nécessite une autorisation, il retournera une réponse
HTTP
401 Unauthorized
avec des informations sur la façon de s'authentifier. - Le client registry fait une demande au service d'autorisation pour un jeton Bearer.
- Le service d'autorisation retourne un jeton Bearer opaque représentant l'accès autorisé du client.
- Le client réessaie la demande originale avec le jeton Bearer intégré dans l'en-tête Authorization de la demande.
- Le Registry autorise le client en validant le jeton Bearer et l'ensemble de revendications intégré à l'intérieur et commence la session push/pull comme d'habitude.
Exigences
- Clients registry qui peuvent comprendre et répondre aux défis d'authentification par jeton retournés par le serveur de ressources.
- Un serveur d'autorisation capable de gérer les contrôles d'accès à leurs ressources hébergées par tout service donné (comme les dépôts dans un Docker Registry).
- Un Docker Registry capable de faire confiance au serveur d'autorisation pour signer des jetons que les clients peuvent utiliser pour l'autorisation et la capacité de vérifier ces jetons pour un usage unique ou pour un usage pendant une période suffisamment courte.
Descriptions des points de terminaison du serveur d'autorisation
Le serveur décrit est destiné à servir comme gestionnaire de contrôle d'accès autonome pour les ressources hébergées par d'autres services qui veulent authentifier et gérer les autorisations en utilisant un gestionnaire de contrôle d'accès séparé.
Un service comme celui-ci est utilisé par le Docker Registry officiel pour authentifier les clients et vérifier leur autorisation aux dépôts d'images Docker.
À partir de Docker 1.6, le client registry dans le Docker Engine a été mis à jour pour gérer un tel flux de travail d'autorisation.
Comment s'authentifier
Les clients Registry V1 contactent d'abord l'index pour initier un push ou pull. Sous
le flux de travail Registry V2, les clients doivent contacter le registry en premier. Si le
serveur registry nécessite une authentification, il retournera une réponse 401 Unauthorized
avec un en-tête WWW-Authenticate
détaillant comment s'authentifier à ce
registry.
Par exemple, disons que moi (nom d'utilisateur jlhawn
) j'essaie de pousser une image vers le
dépôt samalba/my-app
. Pour que le registry autorise cela, j'aurai besoin
d'un accès push
au dépôt samalba/my-app
. Le registry retournera d'abord
cette réponse :
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push"
Date: Thu, 10 Sep 2015 19:32:31 GMT
Content-Length: 235
Strict-Transport-Security: max-age=31536000
{"errors":[{"code":"UNAUTHORIZED","message":"access to the requested resource is not authorized","detail":[{"Type":"repository","Name":"samalba/my-app","Action":"pull"},{"Type":"repository","Name":"samalba/my-app","Action":"push"}]}]}
Notez l'en-tête de réponse HTTP indiquant le défi d'authentification :
Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push"
Ce format est documenté dans Section 3 de RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage
Ce défi indique que le registry nécessite un jeton émis par le
serveur de jetons spécifié et que la demande que le client tente devra
inclure des entrées d'accès suffisantes dans son ensemble de revendications. Pour répondre à ce
défi, le client devra faire une demande GET
à l'URL
https://auth.docker.io/token
en utilisant les valeurs service
et scope
de l'en-tête
WWW-Authenticate
.
Demander un jeton
Définit l'obtention d'un jeton bearer et refresh en utilisant le point de terminaison de jeton.
Paramètres de requête
service
Le nom du service qui héberge la ressource.
offline_token
Indique s'il faut retourner un jeton de rafraîchissement avec le jeton bearer. Un jeton de rafraîchissement est capable d'obtenir des jetons bearer supplémentaires pour le même sujet avec des portées différentes. Le jeton de rafraîchissement n'a pas d'expiration et doit être considéré comme complètement opaque pour le client.
client_id
Chaîne identifiant le client. Ce client_id
n'a pas besoin d'être enregistré
avec le serveur d'autorisation mais doit être défini à une valeur significative afin
de permettre l'audit des clés créées par des clients non enregistrés. La syntaxe acceptée est
définie dans RFC6749 Appendix
A.1.
scope
La ressource en question, formatée comme l'une des entrées délimitées par des espaces de
les paramètres scope
de l'en-tête WWW-Authenticate
montré précédemment. Ce
paramètre de requête doit être spécifié plusieurs fois s'il y a plus d'une
entrée scope
de l'en-tête WWW-Authenticate
. L'exemple précédent serait
spécifié comme : scope=repository:samalba/my-app:push
. Le champ scope peut être
vide pour demander un jeton de rafraîchissement sans fournir de permissions de ressource au
jeton bearer retourné.
Champs de réponse de jeton
token
Un jeton Bearer
opaque que les clients doivent fournir aux demandes
ultérieures dans l'en-tête Authorization
.
access_token
Pour la compatibilité avec OAuth 2.0, le token
sous le nom access_token
est
également accepté. Au moins un de ces champs doit être spécifié, mais les deux peuvent
aussi apparaître (pour la compatibilité avec les clients plus anciens). Quand les deux sont spécifiés,
ils doivent être équivalents ; s'ils diffèrent, le choix du client est indéfini.
expires_in
(Optionnel) La durée en secondes depuis que le jeton a été émis qu'il restera valide. Quand omis, cela par défaut à 60 secondes. Pour la compatibilité avec les clients plus anciens, un jeton ne devrait jamais être retourné avec moins de 60 secondes de vie.
issued_at
(Optionnel) Le temps standard UTC sérialisé RFC3339
auquel un jeton donné a été émis. Si issued_at
est omis, l'expiration
est à partir du moment où l'échange de jeton s'est terminé.
refresh_token
(Optionnel) Jeton qui peut être utilisé pour obtenir des jetons d'accès supplémentaires pour
le même sujet avec des portées différentes. Ce jeton doit être gardé en sécurité
par le client et seulement envoyé au serveur d'autorisation qui émet
les jetons bearer. Ce champ sera seulement défini quand offline_token=true
est
fourni dans la demande.
Exemple
Pour cet exemple, le client fait une demande HTTP GET à l'URL suivante :
https://auth.docker.io/token?service=registry.docker.io&scope=repository:samalba/my-app:pull,push
Le serveur de jetons devrait d'abord tenter d'authentifier le client en utilisant toutes
les informations d'authentification fournies avec la demande. À partir de Docker 1.11, le
Docker Engine prend en charge à la fois l'Authentification Basique et OAuth2 pour
obtenir des jetons. Docker 1.10 et avant, le client registry dans le Docker Engine
ne prend en charge que l'Authentification Basique. Si une tentative d'authentification au serveur
de jetons échoue, le serveur de jetons devrait retourner une réponse 401 Unauthorized
indiquant que les informations d'identification fournies sont invalides.
Que le serveur de jetons nécessite une authentification dépend de la politique de ce fournisseur de contrôle d'accès. Certaines demandes peuvent nécessiter une authentification pour déterminer l'accès (comme pousser ou tirer un dépôt privé) tandis que d'autres peuvent ne pas (comme tirer d'un dépôt public).
Après avoir authentifié le client (qui peut simplement être un client anonyme si
aucune tentative n'a été faite pour s'authentifier), le serveur de jetons doit ensuite interroger sa
liste de contrôle d'accès pour déterminer si le client a la portée demandée. Dans
cette demande d'exemple, si je me suis authentifié comme utilisateur jlhawn
, le serveur
de jetons déterminera quel accès j'ai au dépôt samalba/my-app
hébergé par l'entité registry.docker.io
.
Une fois que le serveur de jetons a déterminé quel accès le client a aux
ressources demandées dans le paramètre scope
, il prendra l'intersection de
l'ensemble des actions demandées sur chaque ressource et l'ensemble des actions que le
client a effectivement été accordé. Si le client n'a qu'un sous-ensemble de
l'accès demandé cela ne doit pas être considéré comme une erreur car ce n'est pas la
responsabilité du serveur de jetons d'indiquer les erreurs d'autorisation dans le cadre de
ce flux de travail.
En continuant avec la demande d'exemple, le serveur de jetons trouvera que l'ensemble
d'accès accordé du client au dépôt est [pull, push]
qui quand
intersecté avec l'accès demandé [pull, push]
donne un ensemble égal. Si
l'ensemble d'accès accordé n'était trouvé que comme [pull]
alors l'ensemble intersecté
ne serait que [pull]
. Si le client n'a aucun accès au dépôt alors l'ensemble
intersecté serait vide, []
.
C'est cet ensemble intersecté d'accès qui est placé dans le jeton retourné.
Using the Bearer token
Once the client has a token, it will try the registry request again with the
token placed in the HTTP Authorization
header like so:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IkJWM0Q6MkFWWjpVQjVaOktJQVA6SU5QTDo1RU42Ok40SjQ6Nk1XTzpEUktFOkJWUUs6M0ZKTDpQT1RMIn0.eyJpc3MiOiJhdXRoLmRvY2tlci5jb20iLCJzdWIiOiJCQ0NZOk9VNlo6UUVKNTpXTjJDOjJBVkM6WTdZRDpBM0xZOjQ1VVc6NE9HRDpLQUxMOkNOSjU6NUlVTCIsImF1ZCI6InJlZ2lzdHJ5LmRvY2tlci5jb20iLCJleHAiOjE0MTUzODczMTUsIm5iZiI6MTQxNTM4NzAxNSwiaWF0IjoxNDE1Mzg3MDE1LCJqdGkiOiJ0WUpDTzFjNmNueXk3a0FuMGM3cktQZ2JWMUgxYkZ3cyIsInNjb3BlIjoiamxoYXduOnJlcG9zaXRvcnk6c2FtYWxiYS9teS1hcHA6cHVzaCxwdWxsIGpsaGF3bjpuYW1lc3BhY2U6c2FtYWxiYTpwdWxsIn0.Y3zZSwaZPqy4y9oRBVRImZyv3m_S9XDHF1tWwN7mL52C_IiA73SJkWVNsvNqpJIn5h7A2F8biv_S2ppQ1lgkbw
This is also described in Section 2.1 of RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage