Autenticación de Registry
Este documento describe el esquema de autenticación de registry:

- Intentar iniciar una operación push/pull con el registry.
- Si el registry requiere autorización, devolverá una respuesta HTTP
401 Unauthorizedcon información sobre cómo autenticarse. - El cliente de registry realiza una solicitud al servicio de autorización para obtener un token Bearer.
- El servicio de autorización devuelve un token Bearer opaco que representa el acceso autorizado del cliente.
- El cliente reintenta la solicitud original con el token Bearer incrustado en la cabecera
Authorizationde la solicitud. - El Registry autoriza al cliente validando el token Bearer y el conjunto de notificaciones (claim set) incrustado en él, e inicia la sesión push/pull como de costumbre.
Requisitos
- Clientes de registry que puedan comprender y responder a los desafíos (challenges) de autenticación de token devueltos por el servidor de recursos.
- Un servidor de autorización capaz de gestionar los controles de acceso a sus recursos alojados en cualquier servicio dado (como repositorios en un Docker Registry).
- Un Docker Registry capaz de confiar en el servidor de autorización para firmar los tokens que los clientes pueden utilizar para la autorización, y con la capacidad de verificar estos tokens para un solo uso o para su uso durante un período de tiempo suficientemente corto.
Descripciones de los endpoints del servidor de autorización
El servidor descrito está destinado a servir como un gestor de control de acceso independiente para recursos alojados por otros servicios que desean autenticar y gestionar autorizaciones utilizando un gestor de control de acceso independiente.
Un servicio como este es utilizado por el Docker Registry oficial para autenticar a los clientes y verificar su autorización en los repositorios de imágenes de Docker.
A partir de Docker 1.6, el cliente de registry dentro de Docker Engine se ha actualizado para manejar dicho flujo de trabajo de autorización.
Cómo autenticarse
Los clientes de Registry V1 contactan primero con el índice para iniciar un push o pull. Bajo el flujo de trabajo de Registry V2, los clientes deben contactar primero con el registry. Si el servidor de registry requiere autenticación, devolverá una respuesta 401 Unauthorized con una cabecera WWW-Authenticate que detalla cómo autenticarse en este registry.
Por ejemplo, supongamos que yo (usuario jlhawn) estoy intentando enviar (push) una imagen al repositorio samalba/my-app. Para que el registry autorice esto, necesitaré acceso de push al repositorio samalba/my-app. El registry devolverá primero esta respuesta:
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"}]}]}Ten en cuenta la cabecera de respuesta HTTP que indica el desafío de autenticación:
Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push"Este formato está documentado en la Sección 3 del RFC 6750: El marco de autorización OAuth 2.0: Uso del token Bearer.
Este desafío indica que el registry requiere un token emitido por el servidor de tokens especificado y que la solicitud que el cliente está intentando deberá incluir suficientes entradas de acceso en su conjunto de notificaciones (claim set). Para responder a este desafío, el cliente deberá realizar una solicitud GET a la URL https://auth.docker.io/token utilizando los valores de service y scope de la cabecera WWW-Authenticate.
Solicitar un token
Define la obtención de un token bearer y de actualización (refresh token) utilizando el endpoint de token.
Parámetros de consulta (Query parameters)
service
El nombre del servicio que aloja el recurso.
offline_token
Indica si se debe devolver un token de actualización junto con el token bearer. Un token de actualización es capaz de obtener tokens bearer adicionales para el mismo sujeto con diferentes alcances. El token de actualización no tiene fecha de caducidad y debe considerarse completamente opaco para el cliente.
client_id
Cadena que identifica al cliente. Este client_id no necesita estar registrado en el servidor de autorización, pero debe establecerse en un valor significativo para permitir la auditoría de claves creadas por clientes no registrados. La sintaxis aceptada se define en el Apéndice A.1 del RFC6749.
scope
El recurso en cuestión, formateado como una de las entradas delimitadas por espacios de los parámetros scope de la cabecera WWW-Authenticate mostrada anteriormente. Este parámetro de consulta debe especificarse varias veces si hay más de una entrada de scope en la cabecera WWW-Authenticate. El ejemplo anterior se especificaría como: scope=repository:samalba/my-app:push. El campo scope puede estar vacío para solicitar un token de actualización sin proporcionar ningún permiso de recurso al token bearer devuelto.
Campos de respuesta del token
token
Un token Bearer opaco que los clientes deben suministrar en las solicitudes subsiguientes en la cabecera Authorization.
access_token
Por compatibilidad con OAuth 2.0, también se acepta el token bajo el nombre access_token. Debe especificarse al menos uno de estos campos, pero también pueden aparecer ambos (para compatibilidad con clientes más antiguos). Cuando se especifican ambos, deben ser equivalentes; si difieren, la elección del cliente es indefinida.
expires_in
(Opcional) La duración en segundos desde que se emitió el token durante la cual seguirá siendo válido. Cuando se omite, el valor predeterminado es 60 segundos. Para compatibilidad con clientes más antiguos, nunca se debe devolver un token con menos de 60 segundos de vida.
issued_at
(Opcional) La hora estándar UTC serializada en RFC3339 en la que se emitió un token dado. Si se omite issued_at, la expiración se cuenta desde que se completó el intercambio del token.
refresh_token
(Opcional) Token que se puede utilizar para obtener tokens de acceso adicionales para el mismo sujeto con diferentes alcances. Este token debe mantenerse seguro por el cliente y solo debe enviarse al servidor de autorización que emite los tokens bearer. Este campo solo se establecerá cuando se proporcione offline_token=true en la solicitud.
Ejemplo
Para este ejemplo, el cliente realiza una solicitud HTTP GET a la siguiente URL:
https://auth.docker.io/token?service=registry.docker.io&scope=repository:samalba/my-app:pull,pushEl servidor de tokens debe intentar primero autenticar al cliente utilizando cualquier credencial de autenticación proporcionada con la solicitud. Desde Docker 1.11, Docker Engine admite tanto la autenticación básica (Basic Authentication) como OAuth2 para obtener tokens. En Docker 1.10 y anteriores, el cliente de registry en Docker Engine solo admite la autenticación básica. Si falla un intento de autenticación en el servidor de tokens, este debe devolver una respuesta 401 Unauthorized indicando que las credenciales proporcionadas no son válidas.
El hecho de que el servidor de tokens requiera autenticación depende de la política de ese proveedor de control de acceso. Algunas solicitudes pueden requerir autenticación para determinar el acceso (como hacer push o pull en un repositorio privado), mientras que otras no (como hacer pull desde un repositorio público).
Después de autenticar al cliente (que puede ser simplemente un cliente anónimo si no se intentó la autenticación), el servidor de tokens debe consultar a continuación su lista de control de acceso para determinar si el cliente tiene el alcance solicitado. En esta solicitud de ejemplo, si me he autenticado como el usuario jlhawn, el servidor de tokens determinará qué acceso tengo al repositorio samalba/my-app alojado por la entidad registry.docker.io.
Una vez que el servidor de tokens ha determinado qué acceso tiene el cliente a los recursos solicitados en el parámetro scope, tomará la intersección del conjunto de acciones solicitadas en cada recurso y el conjunto de acciones que de hecho se le han concedido al cliente. Si el cliente solo tiene un subconjunto del acceso solicitado, no debe considerarse un error, ya que no es responsabilidad del servidor de tokens indicar errores de autorización como parte de este flujo de trabajo.
Continuando con la solicitud de ejemplo, el servidor de tokens encontrará que el conjunto de accesos concedidos del cliente al repositorio es [pull, push], lo que al intersectarse con el acceso solicitado [pull, push] produce un conjunto igual. Si se descubriera que el conjunto de accesos concedidos fuera solo [pull], entonces el conjunto intersectado sería únicamente [pull]. Si el cliente no tiene acceso al repositorio, el conjunto intersectado estaría vacío, [].
Es este conjunto intersectado de accesos el que se coloca en el token devuelto.
A continuación, el servidor construye un token específico de la implementación con este conjunto intersectado de accesos, y lo devuelve al cliente de Docker para que lo use para autenticarse en el servicio de audiencia (dentro del período de tiempo indicado):
HTTP/1.1 200 OK
Content-Type: application/json
{"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IlBZWU86VEVXVTpWN0pIOjI2SlY6QVFUWjpMSkMzOlNYVko6WEdIQTozNEYyOjJMQVE6WlJNSzpaN1E2In0.eyJpc3MiOiJhdXRoLmRvY2tlci5jb20iLCJzdWIiOiJqbGhhd24iLCJhdWQiOiJyZWdpc3RyeS5kb2NrZXIuY29tIiwiZXhwIjoxNDE1Mzg3MzE1LCJuYmYiOjE0MTUzODcwMTUsImlhdCI6MTQxNTM4NzAxNSwianRpIjoidFlKQ08xYzZjbnl5N2tBbjBjN3JLUGdiVjFIMWJGd3MiLCJhY2Nlc3MiOlt7InR5cGUiOiJyZXBvc2l0b3J5IiwibmFtZSI6InNhbWFsYmEvbXktYXBwIiwiYWN0aW9ucyI6WyJwdXNoIl19XX0.QhflHPfbd6eVF4lM9bwYpFZIV0PfikbyXuLx959ykRTBpe3CYnzs6YBK8FToVb5R47920PVLrh8zuLzdCr9t3w", "expires_in": 3600,"issued_at": "2009-11-10T23:00:00Z"}Usar el token Bearer
Una vez que el cliente tiene un token, volverá a intentar la solicitud al registry con el token colocado en la cabecera HTTP Authorization de esta manera:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IkJWM0Q6MkFWWjpVQjVaOktJQVA6SU5QTDo1RU42Ok40SjQ6Nk1XTzpEUktFOkJWUUs6M0ZKTDpQT1RMIn0.eyJpc3MiOiJhdXRoLmRvY2tlci5jb20iLCJzdWIiOiJCQ0NZOk9VNlo6UUVKNTpXTjJDOjJBVkM6WTdZRDpBM0xZOjQ1VVc6NE9HRDpLQUxMOkNOSjU6NUlVTCIsImF1ZCI6InJlZ2lzdHJ5LmRvY2tlci5jb20iLCJleHAiOjE0MTUzODczMTUsIm5iZiI6MTQxNTM4NzAxNSwiaWF0IjoxNDE1Mzg3MDE1LCJqdGkiOiJ0WUpDTzFjNmNueXk3a0FuMGM3cktQZ2JWMUgxYkZ3cyIsInNjb3BlIjoiamxoYXduOnJlcG9zaXRvcnk6c2FtYWxiYS9teS1hcHA6cHVzaCxwdWxsIGpsaGF3bjpuYW1lc3BhY2U6c2FtYWxiYTpwdWxsIn0.Y3zZSwaZPqy4y9oRBVRImZyv3m_S9XDHF1tWwN7mL52C_IiA73SJkWVNsvNqpJIn5h7A2F8biv_S2ppQ1lgkbwEsto también se describe en la Sección 2.1 del RFC 6750: El marco de autorización OAuth 2.0: Uso del token Bearer.