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