docker registry v2认证过程
https://docs.docker.com/registry/spec/images/v2-registry-auth.png
1、尝试从docker regisry中push/pull镜像
2、如果docker registry需要授权,将会返回401 Unauthorized的http响应,并在返回的头信息中提供到哪认证的信息
3、客户端向授权服务请求获取token。
4、认证服务到数据库或ldap中验证用户信息,跟据验证结果生成token
5、docker client携带token令牌再次尝试访问docker registry.
6、docker registry验证用户提交的token,判断是否有有权限进行操作,如果有则进行相应的pull或push。
docker registry 配置文件中的auth
auth:
silly:
realm: silly-realm
service: silly-service
token:
realm: token-realm
service: token-service
issuer: registry-token-issuer
rootcertbundle: /root/certs/bundle
htpasswd:
realm: basic-realm
path: /path/to/htpasswd
过程
例如当用户尝试向registry push镜像samalba/my-app时,为了完成当前操作,
用户需要对repository samalba/my-app具有push的权限,registry将会返回401 Unuthorized信息
例如我们执行命令curl -i https://docker.test/v2/_catalog
1、
HTTP/1.1 401 Unauthorized
Server: nginx
Date: Fri, 11 Aug 2017 02:43:09 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 134
Connection: keep-alive
Docker-Distribution-Api-Version: registry/2.0
Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="container_registry",scope="registry:catalog:*"
X-Content-Type-Options: nosniff
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]}
2、
Docker Client提供用户输入用户名和密码后向auth server发送请求:
https://auth.docker.io/token?service=registry.docker.io&scope=repository:samalba/my-app:pull,push
同时在http head中包含用户相关的登录信息
authorized: Basic YWtaW46cGzc3dvmcQ=
3、
auth server只需要从http head中通过base64获取登录的用户名和密码,并且验证登录信息的合法性,
同时根据业务数据返回用户的实际权限(pull, push)即可.
4、
当docker client获取到token之后,client会将得到的token作为http请求头信息再次尝试访问registry,registry使用公钥解密并验证token内容,并根据token包含的权限信息完成实际的操作
加密
通过公钥私钥加密
auth:
token:
realm: https://auth.docker.io/token
service: Docker registry
issuer: Auth Service
rootcertbundle: /certs/auth.crt
token的生成
JWT(Json web token)的构成
第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).
1、生成jwt的Header信息
{
"typ": "JWT",
"alg": "ES256",
"kid": "PYYO:TEWU:V7JH:26JV:AQTZ:LJC3:SXVJ:XGHA:34F2:2LAQ:ZRMK:Z7Q6"
}
typ: 当使用JWT时,typ固定为“JWT”
alg: 对应私钥文件的加密方式,本示例中即对应auth.key文件的加密方式,可以通过代码读取私钥文件获取
kid: 根据docker提供的规则生成公钥文件的kid,registry会根据同样的算法获取公钥的kid,如果匹配失败则认证失败
2、设置jwt的payload信息
{
"iss": "Auth Service", //需要注意必须与auth.token.issuer配置保持一致
"sub": "some id", //根据业务系统的规则自定义生成即可
"aud": "Docker registry",// 从请求的service参数获取
"exp": 1415387315, //过期时间
"nbf": 1415387015, // not before 可选参数
"iat": 1415387015, // 正式发行时间
"jti": "tYJCO1c6cnyy7kAn0c7rKPgbV1H1bFws", //随机生成即可
// access根据请求的scope获取,当然业务系统要判断用户的实际权限并在actions中放回
"access": [
{
"type": "repository",
"name": "samalba/my-app",
"actions": [
"pull",
"push"
]
}
]
}
3、使用私钥进行签名
参考资料
https://docs.docker.com/registry/spec/auth/token/#how-to-authenticate
https://yunlzheng.github.io/2016/11/29/docker-registry-details/