注册中心身份验证

本文档概述了 registry 认证方案

v2 registry auth
  1. 尝试开始对 registry 的推/拉操作。
  2. 如果 registry 需要授权,它将返回 `401 Unauthorized` HTTP 响应,其中包含有关如何认证的信息。
  3. registry 客户端向授权服务请求不记名令牌。
  4. 授权服务返回一个不透明的不记名令牌,表示客户端的授权访问。
  5. 客户端使用嵌入在请求的 Authorization 头中的不记名令牌重试原始请求。
  6. Registry 通过验证不记名令牌及其嵌入的声明集来授权客户端,并照常开始推/拉会话。

要求

  • 能够理解并响应资源服务器返回的令牌认证挑战的 Registry 客户端。
  • 一个授权服务器,能够管理由任何给定服务(例如 Docker Registry 中的仓库)托管的资源的访问控制。
  • 一个 Docker Registry,能够信任授权服务器签署客户端可用于授权的令牌,并能够验证这些令牌用于一次性使用或在足够短的时间内使用。

授权服务器端点描述

所描述的服务器旨在作为独立访问控制管理器,用于托管在需要使用独立访问控制管理器进行认证和授权管理的其他服务上的资源。

官方 Docker Registry 使用此服务来认证客户端并验证其对 Docker 镜像仓库的授权。

自 Docker 1.6 起,Docker Engine 中的 registry 客户端已更新以处理此类授权工作流。

如何认证

Registry V1 客户端首先联系索引以启动推送或拉取。在 Registry V2 工作流中,客户端应首先联系 registry。如果 registry 服务器需要认证,它将返回 `401 Unauthorized` 响应,并在 `WWW-Authenticate` 头中详细说明如何对该 registry 进行认证。

例如,假设我(用户名 `jlhawn`)正在尝试将镜像推送到仓库 `samalba/my-app`。为了让 registry 授权此操作,我需要对 `samalba/my-app` 仓库具有 `push` 访问权限。registry 将首先返回此响应

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"}]}]}

请注意指示认证挑战的 HTTP 响应头

Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push"

此格式记录在 RFC 6750 第 3 节:OAuth 2.0 授权框架:不记名令牌使用

此挑战表明 registry 需要由指定令牌服务器颁发的令牌,并且客户端尝试的请求需要包含其声明集中的足够访问条目。为了响应此挑战,客户端需要使用 `WWW-Authenticate` 头中的 `service` 和 `scope` 值向 URL `https://auth.docker.io/token` 发出 `GET` 请求。

请求令牌

定义使用令牌端点获取不记名令牌和刷新令牌。

查询参数

服务

托管资源的服务的名称。

离线令牌

是否随不记名令牌一起返回刷新令牌。刷新令牌能够为同一主题和不同范围获取额外的 bearer 令牌。刷新令牌没有过期时间,应被客户端视为完全不透明。

客户端 ID

标识客户端的字符串。此 `client_id` 无需在授权服务器注册,但应设置为有意义的值,以便允许审计由未注册客户端创建的密钥。接受的语法在 RFC6749 附录 A.1 中定义。

范围

所讨论的资源,格式为先前所示 `WWW-Authenticate` 头中 `scope` 参数的空格分隔条目之一。如果 `WWW-Authenticate` 头中有多个 `scope` 条目,则应多次指定此查询参数。上一个示例将指定为:`scope=repository:samalba/my-app:push`。范围字段可以为空,以请求刷新令牌而不向返回的不记名令牌提供任何资源权限。

令牌响应字段

令牌

一个不透明的 `Bearer` 令牌,客户端应在后续请求的 `Authorization` 头中提供。

访问令牌

为了与 OAuth 2.0 兼容,也接受名为 `access_token` 的 `token`。这些字段中至少必须指定一个,但两者也可以同时出现(为了与旧客户端兼容)。当两者都指定时,它们应该等效;如果它们不同,客户端的选择是未定义的。

过期时间

(可选)自令牌颁发以来它将保持有效的秒数。省略时,默认为 60 秒。为了与旧客户端兼容,令牌永远不应在剩余不到 60 秒时返回。

签发时间

(可选)给定令牌的颁发时间,采用 RFC3339 序列化的 UTC 标准时间格式。如果省略 `issued_at`,则过期时间从令牌交换完成时算起。

刷新令牌

(可选)可用于为同一主体和不同范围获取额外访问令牌的令牌。客户端应妥善保管此令牌,并且只能发送给颁发不记名令牌的授权服务器。仅当请求中提供了 `offline_token=true` 时,才会设置此字段。

示例

在本例中,客户端向以下 URL 发出 HTTP GET 请求

https://auth.docker.io/token?service=registry.docker.io&scope=repository:samalba/my-app:pull,push

令牌服务器应首先尝试使用请求中提供的任何认证凭据来认证客户端。从 Docker 1.11 开始,Docker Engine 同时支持基本认证和 OAuth2 获取令牌。Docker 1.10 及以前版本,Docker Engine 中的 registry 客户端仅支持基本认证。如果尝试认证到令牌服务器失败,令牌服务器应返回 `401 Unauthorized` 响应,表明提供的凭据无效。

令牌服务器是否需要认证取决于该访问控制提供商的策略。某些请求可能需要认证才能确定访问权限(例如推送或拉取私有仓库),而另一些请求则可能不需要(例如从公共仓库拉取)。

在认证客户端之后(如果未尝试认证,则可能只是匿名客户端),令牌服务器接下来必须查询其访问控制列表以确定客户端是否具有所请求的范围。在此示例请求中,如果我已认证为用户 `jlhawn`,令牌服务器将确定我对实体 `registry.docker.io` 托管的仓库 `samalba/my-app` 具有哪些访问权限。

一旦令牌服务器确定了客户端对 `scope` 参数中请求的资源的访问权限,它将取每个资源上请求的操作集与客户端实际被授予的操作集的交集。如果客户端只拥有所请求访问权限的子集,则 **不应将其视为错误**,因为令牌服务器在此工作流中指示授权错误不是其职责。

继续前面的示例请求,令牌服务器将发现客户端对仓库被授予的访问集是 `[pull, push]`,与请求的访问集 `[pull, push]` 求交集后得到一个相等的集合。如果被授予的访问集只包含 `[pull]`,则求交集后的集合将只包含 `[pull]`。如果客户端对仓库没有访问权限,则求交集后的集合将为空,即 `[]`。

放入返回令牌中的正是这个求交集后的访问集。

然后,服务器使用这个求交集后的访问集构建一个特定于实现的令牌,并将其返回给 Docker 客户端,以便在指定的时间窗口内用于向受众服务进行认证。

HTTP/1.1 200 OK
Content-Type: application/json

{"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IlBZWU86VEVXVTpWN0pIOjI2SlY6QVFUWjpMSkMzOlNYVko6WEdIQTozNEYyOjJMQVE6WlJNSzpaN1E2In0.eyJpc3MiOiJhdXRoLmRvY2tlci5jb20iLCJzdWIiOiJqbGhhd24iLCJhdWQiOiJyZWdpc3RyeS5kb2NrZXIuY29tIiwiZXhwIjoxNDE1Mzg3MzE1LCJuYmYiOjE0MTUzODcwMTUsImlhdCI6MTQxNTM4NzAxNSwianRpIjoidFlKQ08xYzZjbnl5N2tBbjBjN3JLUGdiVjFIMWJGd3MiLCJhY2Nlc3MiOlt7InR5cGUiOiJyZXBvc2l0b3J5IiwibmFtZSI6InNhbWFsYmEvbXktYXBwIiwiYWN0aW9ucyI6WyJwdXNoIl19XX0.QhflHPfbd6eVF4lM9bwYpFZIV0PfikbyXuLx959ykRTBpe3CYnzs6YBK8FToVb5R47920PVLrh8zuLzdCr9t3w", "expires_in": 3600,"issued_at": "2009-11-10T23:00:00Z"}

使用不记名令牌

一旦客户端获得令牌,它将再次尝试 registry 请求,并将令牌放在 HTTP `Authorization` 头中,如下所示

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IkJWM0Q6MkFWWjpVQjVaOktJQVA6SU5QTDo1RU42Ok40SjQ6Nk1XTzpEUktFOkJWUUs6M0ZKTDpQT1RMIn0.eyJpc3MiOiJhdXRoLmRvY2tlci5jb20iLCJzdWIiOiJCQ0NZOk9VNlo6UUVKNTpXTjJDOjJBVkM6WTdZRDpBM0xZOjQ1VVc6NE9HRDpLQUxMOkNOSjU6NUlVTCIsImF1ZCI6InJlZ2lzdHJ5LmRvY2tlci5jb20iLCJleHAiOjE0MTUzODczMTUsIm5iZiI6MTQxNTM4NzAxNSwiaWF0IjoxNDE1Mzg3MDE1LCJqdGkiOiJ0WUpDTzFjNmNueXk3a0FuMGM3cktQZ2JWMUgxYkZ3cyIsInNjb3BlIjoiamxoYXduOnJlcG9zaXRvcnk6c2FtYWxiYS9teS1hcHA6cHVzaCxwdWxsIGpsaGF3bjpuYW1lc3BhY2U6c2FtYWxiYTpwdWxsIn0.Y3zZSwaZPqy4y9oRBVRImZyv3m_S9XDHF1tWwN7mL52C_IiA73SJkWVNsvNqpJIn5h7A2F8biv_S2ppQ1lgkbw

这也记录在 RFC 6750 第 2.1 节:OAuth 2.0 授权框架:不记名令牌使用

© . This site is unofficial and not affiliated with Kubernetes or Docker Inc.