日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Kubernetes: kube-apiserver 之认证

發布時間:2023/11/16 windows 46 coder
生活随笔 收集整理的這篇文章主要介紹了 Kubernetes: kube-apiserver 之认证 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

kubernetes:kube-apiserver 系列文章:

  • Kubernetes:kube-apiserver 之 scheme(一)
  • Kubernetes:kube-apiserver 之 scheme(二)
  • Kubernetes:kube-apiserver 之啟動流程(一)
  • Kubernetes:kube-apiserver 之啟動流程(二)
  • Kubernetes:kube-apiserver 和 etcd 的交互

0. 前言

kube-apiserver 不僅負責 RESTful API 路由的建立,也負責請求的認證,授權和準入。如下圖所示:

本篇文章將介紹 kube-apiserver 的認證機制。

1. 認證 Authentication

認證是對請求的認證,確認請求是否具有訪問 Kubernetes 集群的權限。在 kube-apiserver 中,通過 handler 處理請求的認證,所有請求都將通過認證 handler 進行認證。可以把它理解成 Gin 框架的中間件。

1.1 認證 handler

首先,從認證 handler 的創建過程入手。

# kubernetes/vendor/k8s.io/apiserver/pkg/server/config.go
// 進入 GenericAPIServer 的創建函數 New
func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*GenericAPIServer, error) {
	handlerChainBuilder := func(handler http.Handler) http.Handler {
		return c.BuildHandlerChainFunc(handler, c.Config)
	}


	apiServerHandler := NewAPIServerHandler(name, c.Serializer, handlerChainBuilder, delegationTarget.UnprotectedHandler())
    ...
}

# kubernetes/vendor/k8s.io/apiserver/pkg/server/config.go
func NewAPIServerHandler(name string, s runtime.NegotiatedSerializer, handlerChainBuilder HandlerChainBuilderFn, notFoundHandler http.Handler) *APIServerHandler {
	...

	director := director{
		name:               name,
		goRestfulContainer: gorestfulContainer,
		nonGoRestfulMux:    nonGoRestfulMux,
	}

	return &APIServerHandler{
        // 創建 FullHandlerChain
		FullHandlerChain:   handlerChainBuilder(director),
		GoRestfulContainer: gorestfulContainer,
		NonGoRestfulMux:    nonGoRestfulMux,
		Director:           director,
	}
}

這里 FullHandlerChain 內裝有認證 handler。繼續看哪里定義 handlerChainBuilder 函數的。

# kubernetes/vendor/k8s.io/apiserver/pkg/server/config.go
func NewConfig(codecs serializer.CodecFactory) *Config {
	return &Config{
        ...
		BuildHandlerChainFunc:          DefaultBuildHandlerChain,
    }
}

# kubernetes/vendor/k8s.io/apiserver/pkg/server/config.go
func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
    handler = genericapifilters.WithAuthentication(handler, c.Authentication.Authenticator, failedHandler, c.Authentication.APIAudiences, c.Authentication.RequestHeaderConfig)
    return handler
}

# kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/filters/authentication.go
func WithAuthentication(handler http.Handler, auth authenticator.Request, failed http.Handler, apiAuds authenticator.Audiences, requestHeaderConfig *authenticatorfactory.RequestHeaderConfig) http.Handler {
	return withAuthentication(handler, auth, failed, apiAuds, requestHeaderConfig, recordAuthenticationMetrics)
}

在創建配置 Config 時,將 DefaultBuildHandlerChain 賦值給 BuildHandlerChainFuncDefaultBuildHandlerChain 內的 genericapifilters.WithAuthentication 創建了認證 handler

接著往下走,進入 genericapifilters.WithAuthentication

func withAuthentication(handler http.Handler, auth authenticator.Request, failed http.Handler, apiAuds authenticator.Audiences, requestHeaderConfig *authenticatorfactory.RequestHeaderConfig, metrics authenticationRecordMetricsFunc) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		resp, ok, err := auth.AuthenticateRequest(req)

		// authorization header is not required anymore in case of a successful authentication.
		req.Header.Del("Authorization")

		req = req.WithContext(genericapirequest.WithUser(req.Context(), resp.User))
		handler.ServeHTTP(w, req)
	})
}

type Request interface {
	AuthenticateRequest(req *http.Request) (*Response, bool, error)
}

可以看到,認證 handler 中通過 auth.AuthenticateRequest(req)RESTful API 請求進行認證。這里 auth 是一個實現 Request 接口的實例。

那么,auth 實例是在哪里創建的呢,調用的 AuthenticateRequest 方法具體做的是什么呢?帶著這個問題我們看下一節認證實例。

1.2 認證實例

通過層層回溯找到調用點。

handler = genericapifilters.WithAuthentication(handler, c.Authentication.Authenticator, failedHandler, c.Authentication.APIAudiences, c.Authentication.RequestHeaderConfig)

這里 c.Authentication.Authenticator 即為 auth 的實例。我們看 c.Authentication.Authenticator 是在哪里創建的。

# kubernetes/pkg/controlplane/apiserver/config.go
func BuildGenericConfig(
	s controlplaneapiserver.CompletedOptions,
	schemes []*runtime.Scheme,
	getOpenAPIDefinitions func(ref openapicommon.ReferenceCallback) map[string]openapicommon.OpenAPIDefinition,
) (
	genericConfig *genericapiserver.Config,
	versionedInformers clientgoinformers.SharedInformerFactory,
	storageFactory *serverstorage.DefaultStorageFactory,

	lastErr error,
) {
    // Authentication.ApplyTo requires already applied OpenAPIConfig and EgressSelector if present
	if lastErr = s.Authentication.ApplyTo(&genericConfig.Authentication, genericConfig.SecureServing, genericConfig.EgressSelector, genericConfig.OpenAPIConfig, genericConfig.OpenAPIV3Config, clientgoExternalClient, versionedInformers); lastErr != nil {
		return
	}
}

# kubernetes/pkg/kubeapiserver/options/authentication.go
func (o *BuiltInAuthenticationOptions) ApplyTo(authInfo *genericapiserver.AuthenticationInfo, secureServing *genericapiserver.SecureServingInfo, egressSelector *egressselector.EgressSelector, openAPIConfig *openapicommon.Config, openAPIV3Config *openapicommon.Config, extclient kubernetes.Interface, versionedInformer informers.SharedInformerFactory) error {
	authenticatorConfig, err := o.ToAuthenticationConfig()
	if err != nil {
		return err
	}

    ...

	authInfo.Authenticator, openAPIConfig.SecurityDefinitions, err = authenticatorConfig.New()
}

c.Authentication.Authenticator 實際是 authenticatorConfig.New() 創建的 authInfo.Authenticator 認證器。進入 authenticatorConfig.New() 看創建認證器過程。

# kubernetes/pkg/controlplane/apiserver/config.go
func (config Config) New() (authenticator.Request, *spec.SecurityDefinitions, error) {
	var authenticators []authenticator.Request
	var tokenAuthenticators []authenticator.Token
	securityDefinitions := spec.SecurityDefinitions{}

	// front-proxy, BasicAuth methods, local first, then remote
	// Add the front proxy authenticator if requested
	if config.RequestHeaderConfig != nil {
		requestHeaderAuthenticator := headerrequest.NewDynamicVerifyOptionsSecure(
			config.RequestHeaderConfig.CAContentProvider.VerifyOptions,
			config.RequestHeaderConfig.AllowedClientNames,
			config.RequestHeaderConfig.UsernameHeaders,
			config.RequestHeaderConfig.GroupHeaders,
			config.RequestHeaderConfig.ExtraHeaderPrefixes,
		)
		authenticators = append(authenticators, authenticator.WrapAudienceAgnosticRequest(config.APIAudiences, requestHeaderAuthenticator))
	}

	// X509 methods
	if config.ClientCAContentProvider != nil {
		certAuth := x509.NewDynamic(config.ClientCAContentProvider.VerifyOptions, x509.CommonNameUserConversion)
		authenticators = append(authenticators, certAuth)
	}

    ...

    authenticator := union.New(authenticators...)
	authenticator = group.NewAuthenticatedGroupAdder(authenticator)
    return authenticator, &securityDefinitions, nil
}

# kubernetes/vendor/k8s.io/apiserver/pkg/authentication/request/union/union.go
func New(authRequestHandlers ...authenticator.Request) authenticator.Request {
	if len(authRequestHandlers) == 1 {
		return authRequestHandlers[0]
	}
	return &unionAuthRequestHandler{Handlers: authRequestHandlers, FailOnError: false}
}

# kubernetes/vendor/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go
func NewAuthenticatedGroupAdder(auth authenticator.Request) authenticator.Request {
	return &AuthenticatedGroupAdder{auth}
}

可以看到,認證器是一系列認證器的組合。每個認證器包括組合的認證器都實現了 authenticator.Request 接口的 AuthenticateRequest 方法。

回頭看在 handler 中定義的 auth.AuthenticateRequest(req) 方法,實際執行的是 authenticator.AuthenticateRequest(req)

# kubernetes/vendor/k8s.io/apiserver/pkg/authentication/group/authenticated_group_adder.go
func (g *AuthenticatedGroupAdder) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
	r, ok, err := g.Authenticator.AuthenticateRequest(req)
	if err != nil || !ok {
		return nil, ok, err
	}
}

# kubernetes/vendor/k8s.io/apiserver/pkg/authentication/request/union/union.go
func (authHandler *unionAuthRequestHandler) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
	var errlist []error
	for _, currAuthRequestHandler := range authHandler.Handlers {
		resp, ok, err := currAuthRequestHandler.AuthenticateRequest(req)
		if err != nil {
			if authHandler.FailOnError {
				return resp, ok, err
			}
			errlist = append(errlist, err)
			continue
		}

		if ok {
			return resp, ok, err
		}
	}

	return nil, false, utilerrors.NewAggregate(errlist)
}

通過層層調用,最終執行到 unionAuthRequestHandler.AuthenticateRequest。該方法中循環執行各個認證器的 AuthenticateRequest 方法,直到認證成功。

各認證器的認證方式不同,這里就不過多介紹了,具體涉及到各種認證方式的時候可詳細看相應認證器的 AuthenticateRequest 方法。

2. 總結

通過本篇文章介紹了 kube-apiserver 中的 Authentication 認證流程,下一篇將繼續介紹 kube-apiserverAuthorization 授權流程。


總結

以上是生活随笔為你收集整理的Kubernetes: kube-apiserver 之认证的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。