註冊中心身份驗證
本文件概述了 registry 認證方案


- 嘗試開始對 registry 的推/拉操作。
- 如果 registry 需要授權,它將返回 `401 Unauthorized` HTTP 響應,其中包含有關如何認證的資訊。
- registry 客戶端向授權服務請求不記名令牌。
- 授權服務返回一個不透明的不記名令牌,表示客戶端的授權訪問。
- 客戶端使用嵌入在請求的 Authorization 頭中的不記名令牌重試原始請求。
- 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