在istiod中对节点身份进行验证,分为两种
- KubeJWTAuthenticator
- jwt认证
authenticators := []authenticate.Authenticator{
&authenticate.ClientCertAuthenticator{},
authenticate.NewKubeJWTAuthenticator(s.kubeClient, s.clusterID, s.multicluster.GetRemoteKubeClient, spiffe.GetTrustDomain(), features.JwtPolicy.Get()),
}
func (a *KubeJWTAuthenticator) Authenticate(ctx context.Context) (*Caller, error) { targetJWT, err := extractBearerToken(ctx) if err != nil { return nil, fmt.Errorf("target JWT extraction error: %v", err) } clusterID := extractClusterID(ctx) var id []string
kubeClient := a.GetKubeClient(clusterID)
if kubeClient == nil {
return nil, fmt.Errorf("could not get cluster %s's kube client", clusterID)
}
var aud []string
if !util.IsK8SUnbound(targetJWT) || security.Require3PToken.Get() {
aud = security.TokenAudiences
// TODO: check the audience from token, no need to call
// apiserver if audience is not matching. This may also
// handle older apiservers that don't check audience.
} else {
// No audience will be passed to the check if the token
// is unbound and the setting to require bound tokens is off
aud = nil
}
// 通过tokenreview接口验证客户端token的有效性
id, err = tokenreview.ValidateK8sJwt(kubeClient, targetJWT, aud)
if err != nil {
return nil, fmt.Errorf("failed to validate the JWT from cluster %s: %v", clusterID, err)
}
if len(id) != 2 {
return nil, fmt.Errorf("failed to parse the JWT. Validation result length is not 2, but %d", len(id))
}
callerNamespace := id[0]
callerServiceAccount := id[1]
return &Caller{
AuthSource: AuthSourceIDToken,
Identities: []string{fmt.Sprintf(identityTemplate, a.trustDomain, callerNamespace, callerServiceAccount)},
}, nil
}
func (cca *ClientCertAuthenticator) Authenticate(ctx context.Context) (*Caller, error) { peer, ok := peer.FromContext(ctx) if !ok || peer.AuthInfo == nil { return nil, fmt.Errorf("no client certificate is presented") }
if authType := peer.AuthInfo.AuthType(); authType != "tls" {
return nil, fmt.Errorf("unsupported auth type: %q", authType)
}
tlsInfo := peer.AuthInfo.(credentials.TLSInfo)
chains := tlsInfo.State.VerifiedChains
if len(chains) == 0 || len(chains[0]) == 0 {
return nil, fmt.Errorf("no verified chain is found")
}
ids, err := util.ExtractIDs(chains[0][0].Extensions)
if err != nil {
return nil, err
}
return &Caller{
AuthSource: AuthSourceClientCertificate,
Identities: ids,
}, nil
}