k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cmd/kubelet/app/auth.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package app 18 19 import ( 20 "context" 21 "errors" 22 "fmt" 23 "reflect" 24 25 "k8s.io/apimachinery/pkg/types" 26 "k8s.io/apiserver/pkg/authentication/authenticator" 27 "k8s.io/apiserver/pkg/authentication/authenticatorfactory" 28 "k8s.io/apiserver/pkg/authorization/authorizer" 29 "k8s.io/apiserver/pkg/authorization/authorizerfactory" 30 "k8s.io/apiserver/pkg/server/dynamiccertificates" 31 genericoptions "k8s.io/apiserver/pkg/server/options" 32 clientset "k8s.io/client-go/kubernetes" 33 authenticationclient "k8s.io/client-go/kubernetes/typed/authentication/v1" 34 authorizationclient "k8s.io/client-go/kubernetes/typed/authorization/v1" 35 36 kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" 37 "k8s.io/kubernetes/pkg/kubelet/server" 38 ) 39 40 // BuildAuth creates an authenticator, an authorizer, and a matching authorizer attributes getter compatible with the kubelet's needs 41 // It returns AuthInterface, a run method to start internal controllers (like cert reloading) and error. 42 func BuildAuth(nodeName types.NodeName, client clientset.Interface, config kubeletconfig.KubeletConfiguration) (server.AuthInterface, func(<-chan struct{}), error) { 43 // Get clients, if provided 44 var ( 45 tokenClient authenticationclient.AuthenticationV1Interface 46 sarClient authorizationclient.AuthorizationV1Interface 47 ) 48 if client != nil && !reflect.ValueOf(client).IsNil() { 49 tokenClient = client.AuthenticationV1() 50 sarClient = client.AuthorizationV1() 51 } 52 53 authenticator, runAuthenticatorCAReload, err := BuildAuthn(tokenClient, config.Authentication) 54 if err != nil { 55 return nil, nil, err 56 } 57 58 attributes := server.NewNodeAuthorizerAttributesGetter(nodeName) 59 60 authorizer, err := BuildAuthz(sarClient, config.Authorization) 61 if err != nil { 62 return nil, nil, err 63 } 64 65 return server.NewKubeletAuth(authenticator, attributes, authorizer), runAuthenticatorCAReload, nil 66 } 67 68 // BuildAuthn creates an authenticator compatible with the kubelet's needs 69 func BuildAuthn(client authenticationclient.AuthenticationV1Interface, authn kubeletconfig.KubeletAuthentication) (authenticator.Request, func(<-chan struct{}), error) { 70 var dynamicCAContentFromFile *dynamiccertificates.DynamicFileCAContent 71 var err error 72 if len(authn.X509.ClientCAFile) > 0 { 73 dynamicCAContentFromFile, err = dynamiccertificates.NewDynamicCAContentFromFile("client-ca-bundle", authn.X509.ClientCAFile) 74 if err != nil { 75 return nil, nil, err 76 } 77 } 78 79 authenticatorConfig := authenticatorfactory.DelegatingAuthenticatorConfig{ 80 Anonymous: authn.Anonymous.Enabled, 81 CacheTTL: authn.Webhook.CacheTTL.Duration, 82 ClientCertificateCAContentProvider: dynamicCAContentFromFile, 83 } 84 85 if authn.Webhook.Enabled { 86 if client == nil { 87 return nil, nil, errors.New("no client provided, cannot use webhook authentication") 88 } 89 authenticatorConfig.WebhookRetryBackoff = genericoptions.DefaultAuthWebhookRetryBackoff() 90 authenticatorConfig.TokenAccessReviewClient = client 91 } 92 93 authenticator, _, err := authenticatorConfig.New() 94 if err != nil { 95 return nil, nil, err 96 } 97 98 return authenticator, func(stopCh <-chan struct{}) { 99 // generate a context from stopCh. This is to avoid modifying files which are relying on this method 100 // TODO: See if we can pass ctx to the current method 101 ctx, cancel := context.WithCancel(context.Background()) 102 go func() { 103 select { 104 case <-stopCh: 105 cancel() // stopCh closed, so cancel our context 106 case <-ctx.Done(): 107 } 108 }() 109 if dynamicCAContentFromFile != nil { 110 go dynamicCAContentFromFile.Run(ctx, 1) 111 } 112 }, err 113 } 114 115 // BuildAuthz creates an authorizer compatible with the kubelet's needs 116 func BuildAuthz(client authorizationclient.AuthorizationV1Interface, authz kubeletconfig.KubeletAuthorization) (authorizer.Authorizer, error) { 117 switch authz.Mode { 118 case kubeletconfig.KubeletAuthorizationModeAlwaysAllow: 119 return authorizerfactory.NewAlwaysAllowAuthorizer(), nil 120 121 case kubeletconfig.KubeletAuthorizationModeWebhook: 122 if client == nil { 123 return nil, errors.New("no client provided, cannot use webhook authorization") 124 } 125 authorizerConfig := authorizerfactory.DelegatingAuthorizerConfig{ 126 SubjectAccessReviewClient: client, 127 AllowCacheTTL: authz.Webhook.CacheAuthorizedTTL.Duration, 128 DenyCacheTTL: authz.Webhook.CacheUnauthorizedTTL.Duration, 129 WebhookRetryBackoff: genericoptions.DefaultAuthWebhookRetryBackoff(), 130 } 131 return authorizerConfig.New() 132 133 case "": 134 return nil, fmt.Errorf("no authorization mode specified") 135 136 default: 137 return nil, fmt.Errorf("unknown authorization mode %s", authz.Mode) 138 139 } 140 }