auth

Registry的Token认证

registry的认证方式有三种,本文介绍最常用的token认证机制。

认证流程

我们以docker pull操作描述一下token认证的流程

1、docker-daemon向registry发起pull操作 2、如果registry开启了认证,则会返回401 Unauthorized的响应,并且在响应头中携带如何去认证的信息 3、docker-daemon向授权服务(authorization service)发起请求,获取token 4、授权服务返回一个token,该token中携带了权限信息 5、docker-daemon重新向registry发起同样的请求,并且在头部中携带token 6、registry对token进行验证,然后开始正常的pull流程

registry开启token认证

registry要开启token认证,需要在配置文件中添加如下内容,以下四个参数都为必填。

  • realm:授权服务器的url

  • service:被认证的服务的名字

  • issuer:token签发者的名字,授权服务器签发的token中也有该字段;registry与授权服务的该字段要配置成一致,以便registry验证token是否由目标授权服务签发

  • rootcertbundle:根证书的绝对路径

以下为本地harbor的registry配置文件中关于token配置的样例:

如何认证

当docker-daemon没有携带任何认证信息向registry发起某个API请求时(对应上图中的步骤1),registry会返回401 Unauthorized,并且在响应头的参数WWW-Authenticate中给出如何去获取token的详细信息。

比如,pull镜像的第一步是获取manifest,那么我们没有携带任何认证信息去拉取本地harbor中的library/registry:2.5.0镜像的manifest文件,会得到如下的响应头(docker-daemon也是请求registry的API,这里我们使用curl模拟下载镜像的API请求):

注意头部中的Www-Authenticate字段的值,告诉我们应该如何去获取token:

其中realmservice字段的值就是registry的配置文件中的值;scope字段的值,是registry根据接收到的API请求生成的,关于scope字段的语法请参考官网

请求Token

QUERY参数

  • service:使用registry返回的值

  • scope:使用registry返回的值

  • client_id:(可选)发起请求的客户端的标识,比如docker-daemon发起的请求会将该字段设置为docker,harbor的复制策略中会将该字段设置为harbor-registry-client

响应BODY字段

  • token:授权服务器返回的带有授权信息的token

  • issued_at:(可选)token的签发时间,UTC标准时间格式

  • expires_in:(可选)token在多少秒以后过期,如果没有说明则默认为60秒

Example

接下来,我们去获取token

得到的token是一个很长的字符串。不过我们可以复制上面的token字段的内容到jwt.io,查看token的明文,得到payload的内容如下:,查看token的明文,得到payload的内容如下:

access字段可以看出,该token对library/registry这个repository具有pull权限。

携带用户信息

在上面获取token的请求中,没有携带任何的用户信息,所以payload的sub字段为空。但是harbor的授权服务器返回的token还是具有pull权限,这是因为harbor允许匿名用户pull library中的镜像。不过我们可以携带harbor的admin用户信息去获取token,如下:

其中YWRtaW46SGFyYm9yMTIzNDU=admin:Harbor12345使用base64加密后的字符串:

使用Token

在得到token后,我们就可以在API请求的Header中添加token信息,比如下载镜像的manifest,这次请求就会正常返回了:

扩展知识

说说docker-login

docker login命令的使用方法如下:

当docker login登录成功后,会在当前用户的 ~/.docker/config.json中出现如下的内容:

其中字符串YWRtaW46SGFyYm9yMTIzNDU=是通过base64算法加密得到的字符串。关于base64算法的加密与解密如下:

当docker login成功后,我们再执行docker pull或push操作的时候,docker client便会从当前用户下查找registry的登录信息,并携带给docker daemon,docker-daemon便会在向Authorization Service请求token的API请求头中携带这个字符串。

Last updated

Was this helpful?