Harbor 认证过程
Harbor以 Docker Registry v2认证为基础,添加上一层权限保护。
	1.v2 集成了一个安全认证的功能,将安全认证暴露给外部服务,让外部服务去实现
	2.强制用户每次Docker pull/push请求都要带一个合法的Token,Registry会通过公钥对Token进行解密验证
	3.如果不包含Token,会被重定向到Token服务获取Token后重新请求
Registry v2 authentication官方文档
 Registry v2 生成令牌代码
 
1.尝试使用registry开始推/拉操作
2.如果registry需要进行授权时,registry将会返回401 Unauthorized响应,同时在响应中包含了docker client如何进行认证的信息
3.registry client根据返回的信息,向auth server发送请求获取认证token
4.auth server将会根据查询的用户信息,生成token令牌,以及当前用户所具有的相关权限信息
5.client携带这附有token的请求,重试原始请求
6.registry接受了认证的token并且使得client继续操作
上述就是完整的授权过程.当用户完成上述过程以后便可以执行相关的pull/push操作。认证信息会每次都带在请求头中。
例:输入docker login,以下为整个登录过程流程图
 
1.registry 服务怎么知道服务认证地址?
registry 服务本身就提供了一个配置文件,可以在启动 registry 服务的配置文件中指定上认证服务地址即可
...
auth:
  token:
    realm: token-realm
    service: token-service
    issuer: registry-token-issuer
    rootcertbundle: /root/certs/bundle
...
其中 realm 就可以用来指定一个认证服务的地址
Harbor 后台认证
- authserver
路径:src/core/service/token/token.go
func (h *Handler) Get() {
	...
	token, err := tokenCreator.Create(request)
	...
}
路径:src/core/service/token/creator.go
func (g generalCreator) Create(r *http.Request) (*models.Token, error) {
	...
	access := GetResourceActions(scopes)
	...
	return MakeToken(r.Context(), ctx.GetUsername(), g.service, access)
}
路径:src/core/service/token/authutils.go
// MakeToken makes a valid jwt token based on parms.
func MakeToken(ctx context.Context, username, service string, access []*token.ResourceActions) (*models.Token, error) {
	options, err := tokenpkg.NewOptions(signingMethod, v2.Issuer, privateKey)
	if err != nil {
		return nil, err
	}
	expiration, err := config.TokenExpiration(ctx)
	if err != nil {
		return nil, err
	}
	now := time.Now().UTC()
	claims := &v2.Claims{
		RegisteredClaims: jwt.RegisteredClaims{
			Issuer:    options.Issuer,
			Subject:   username,
			Audience:  jwt.ClaimStrings([]string{service}),
			ExpiresAt: jwt.NewNumericDate(now.Add(time.Duration(expiration) * time.Minute)),
			NotBefore: jwt.NewNumericDate(now),
			IssuedAt:  jwt.NewNumericDate(now),
			ID:        utils.GenerateRandomStringWithLen(16),
		},
		Access: access,
	}
	tok, err := tokenpkg.New(options, claims)
	if err != nil {
		return nil, err
	}
	// Add kid to token header for compatibility with docker distribution's code
	// see https://github.com/docker/distribution/blob/release/2.7/registry/auth/token/token.go#L197
	k, err := libtrust.UnmarshalPrivateKeyPEM(options.PrivateKey)
	if err != nil {
		return nil, err
	}
	tok.Header["kid"] = k.KeyID()
	rawToken, err := tok.Raw()
	if err != nil {
		return nil, err
	}
	return &models.Token{
		Token:     rawToken,
		ExpiresIn: expiration * 60,
		IssuedAt:  now.Format(time.RFC3339),
	}, nil
}


















