⚠️ Traduction non officielle - Cette documentation est une traduction communautaire non officielle de Docker.

Authentification Registry

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

v2 registry auth
  1. Tentative de commencer une opération push/pull avec le registry.
  2. 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.
  3. Le client registry fait une demande au service d'autorisation pour un jeton Bearer.
  4. Le service d'autorisation retourne un jeton Bearer opaque représentant l'accès autorisé du client.
  5. Le client réessaie la demande originale avec le jeton Bearer intégré dans l'en-tête Authorization de la demande.
  6. 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