Commit d3dbbfad authored by Darren Shepherd's avatar Darren Shepherd

Remove RequestHeader and ClientCerts auth

parent 7b622843
...@@ -264,27 +264,9 @@ func CreateKubeAPIServerConfig( ...@@ -264,27 +264,9 @@ func CreateKubeAPIServerConfig(
return return
} }
clientCA, lastErr := readCAorNil(s.Authentication.ClientCert.ClientCA)
if lastErr != nil {
return
}
requestHeaderProxyCA, lastErr := readCAorNil(s.Authentication.RequestHeader.ClientCAFile)
if lastErr != nil {
return
}
config = &master.Config{ config = &master.Config{
GenericConfig: genericConfig, GenericConfig: genericConfig,
ExtraConfig: master.ExtraConfig{ ExtraConfig: master.ExtraConfig{
ClientCARegistrationHook: master.ClientCARegistrationHook{
ClientCA: clientCA,
RequestHeaderUsernameHeaders: s.Authentication.RequestHeader.UsernameHeaders,
RequestHeaderGroupHeaders: s.Authentication.RequestHeader.GroupHeaders,
RequestHeaderExtraHeaderPrefixes: s.Authentication.RequestHeader.ExtraHeaderPrefixes,
RequestHeaderCA: requestHeaderProxyCA,
RequestHeaderAllowedNames: s.Authentication.RequestHeader.AllowedNames,
},
APIResourceConfigSource: storageFactory.APIResourceConfigSource, APIResourceConfigSource: storageFactory.APIResourceConfigSource,
StorageFactory: storageFactory, StorageFactory: storageFactory,
EventTTL: s.EventTTL, EventTTL: s.EventTTL,
......
...@@ -20,11 +20,9 @@ import ( ...@@ -20,11 +20,9 @@ import (
"time" "time"
"k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/authenticatorfactory"
"k8s.io/apiserver/pkg/authentication/group" "k8s.io/apiserver/pkg/authentication/group"
"k8s.io/apiserver/pkg/authentication/request/anonymous" "k8s.io/apiserver/pkg/authentication/request/anonymous"
"k8s.io/apiserver/pkg/authentication/request/bearertoken" "k8s.io/apiserver/pkg/authentication/request/bearertoken"
"k8s.io/apiserver/pkg/authentication/request/headerrequest"
"k8s.io/apiserver/pkg/authentication/request/union" "k8s.io/apiserver/pkg/authentication/request/union"
"k8s.io/apiserver/pkg/authentication/request/websocket" "k8s.io/apiserver/pkg/authentication/request/websocket"
"k8s.io/apiserver/pkg/authentication/request/x509" "k8s.io/apiserver/pkg/authentication/request/x509"
...@@ -58,8 +56,6 @@ type Config struct { ...@@ -58,8 +56,6 @@ type Config struct {
TokenSuccessCacheTTL time.Duration TokenSuccessCacheTTL time.Duration
TokenFailureCacheTTL time.Duration TokenFailureCacheTTL time.Duration
RequestHeaderConfig *authenticatorfactory.RequestHeaderConfig
// TODO, this is the only non-serializable part of the entire config. Factor it out into a clientconfig // TODO, this is the only non-serializable part of the entire config. Factor it out into a clientconfig
ServiceAccountTokenGetter serviceaccount.ServiceAccountTokenGetter ServiceAccountTokenGetter serviceaccount.ServiceAccountTokenGetter
} }
...@@ -70,22 +66,6 @@ func (config Config) New() (authenticator.Request, error) { ...@@ -70,22 +66,6 @@ func (config Config) New() (authenticator.Request, error) {
var authenticators []authenticator.Request var authenticators []authenticator.Request
var tokenAuthenticators []authenticator.Token var tokenAuthenticators []authenticator.Token
// front-proxy, BasicAuth methods, local first, then remote
// Add the front proxy authenticator if requested
if config.RequestHeaderConfig != nil {
requestHeaderAuthenticator, err := headerrequest.NewSecure(
config.RequestHeaderConfig.ClientCA,
config.RequestHeaderConfig.AllowedClientNames,
config.RequestHeaderConfig.UsernameHeaders,
config.RequestHeaderConfig.GroupHeaders,
config.RequestHeaderConfig.ExtraHeaderPrefixes,
)
if err != nil {
return nil, err
}
authenticators = append(authenticators, authenticator.WrapAudienceAgnosticRequest(config.APIAudiences, requestHeaderAuthenticator))
}
// basic auth // basic auth
if len(config.BasicAuthFile) > 0 { if len(config.BasicAuthFile) > 0 {
basicAuth, err := newAuthenticatorFromBasicAuthFile(config.BasicAuthFile) basicAuth, err := newAuthenticatorFromBasicAuthFile(config.BasicAuthFile)
......
...@@ -28,7 +28,6 @@ import ( ...@@ -28,7 +28,6 @@ import (
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/authentication/authenticator" "k8s.io/apiserver/pkg/authentication/authenticator"
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
genericoptions "k8s.io/apiserver/pkg/server/options"
kubeauthenticator "k8s.io/kubernetes/pkg/kubeapiserver/authenticator" kubeauthenticator "k8s.io/kubernetes/pkg/kubeapiserver/authenticator"
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
) )
...@@ -36,9 +35,7 @@ import ( ...@@ -36,9 +35,7 @@ import (
type BuiltInAuthenticationOptions struct { type BuiltInAuthenticationOptions struct {
APIAudiences []string APIAudiences []string
Anonymous *AnonymousAuthenticationOptions Anonymous *AnonymousAuthenticationOptions
ClientCert *genericoptions.ClientCertAuthenticationOptions
PasswordFile *PasswordFileAuthenticationOptions PasswordFile *PasswordFileAuthenticationOptions
RequestHeader *genericoptions.RequestHeaderAuthenticationOptions
ServiceAccounts *ServiceAccountAuthenticationOptions ServiceAccounts *ServiceAccountAuthenticationOptions
TokenFile *TokenFileAuthenticationOptions TokenFile *TokenFileAuthenticationOptions
WebHook *WebHookAuthenticationOptions WebHook *WebHookAuthenticationOptions
...@@ -81,9 +78,7 @@ func NewBuiltInAuthenticationOptions() *BuiltInAuthenticationOptions { ...@@ -81,9 +78,7 @@ func NewBuiltInAuthenticationOptions() *BuiltInAuthenticationOptions {
func (s *BuiltInAuthenticationOptions) WithAll() *BuiltInAuthenticationOptions { func (s *BuiltInAuthenticationOptions) WithAll() *BuiltInAuthenticationOptions {
return s. return s.
WithAnonymous(). WithAnonymous().
WithClientCert().
WithPasswordFile(). WithPasswordFile().
WithRequestHeader().
WithServiceAccounts(). WithServiceAccounts().
WithTokenFile(). WithTokenFile().
WithWebHook() WithWebHook()
...@@ -94,21 +89,11 @@ func (s *BuiltInAuthenticationOptions) WithAnonymous() *BuiltInAuthenticationOpt ...@@ -94,21 +89,11 @@ func (s *BuiltInAuthenticationOptions) WithAnonymous() *BuiltInAuthenticationOpt
return s return s
} }
func (s *BuiltInAuthenticationOptions) WithClientCert() *BuiltInAuthenticationOptions {
s.ClientCert = &genericoptions.ClientCertAuthenticationOptions{}
return s
}
func (s *BuiltInAuthenticationOptions) WithPasswordFile() *BuiltInAuthenticationOptions { func (s *BuiltInAuthenticationOptions) WithPasswordFile() *BuiltInAuthenticationOptions {
s.PasswordFile = &PasswordFileAuthenticationOptions{} s.PasswordFile = &PasswordFileAuthenticationOptions{}
return s return s
} }
func (s *BuiltInAuthenticationOptions) WithRequestHeader() *BuiltInAuthenticationOptions {
s.RequestHeader = &genericoptions.RequestHeaderAuthenticationOptions{}
return s
}
func (s *BuiltInAuthenticationOptions) WithServiceAccounts() *BuiltInAuthenticationOptions { func (s *BuiltInAuthenticationOptions) WithServiceAccounts() *BuiltInAuthenticationOptions {
s.ServiceAccounts = &ServiceAccountAuthenticationOptions{Lookup: true} s.ServiceAccounts = &ServiceAccountAuthenticationOptions{Lookup: true}
return s return s
...@@ -153,20 +138,12 @@ func (s *BuiltInAuthenticationOptions) AddFlags(fs *pflag.FlagSet) { ...@@ -153,20 +138,12 @@ func (s *BuiltInAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
"Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.") "Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.")
} }
if s.ClientCert != nil {
s.ClientCert.AddFlags(fs)
}
if s.PasswordFile != nil { if s.PasswordFile != nil {
fs.StringVar(&s.PasswordFile.BasicAuthFile, "basic-auth-file", s.PasswordFile.BasicAuthFile, ""+ fs.StringVar(&s.PasswordFile.BasicAuthFile, "basic-auth-file", s.PasswordFile.BasicAuthFile, ""+
"If set, the file that will be used to admit requests to the secure port of the API server "+ "If set, the file that will be used to admit requests to the secure port of the API server "+
"via http basic authentication.") "via http basic authentication.")
} }
if s.RequestHeader != nil {
s.RequestHeader.AddFlags(fs)
}
if s.ServiceAccounts != nil { if s.ServiceAccounts != nil {
fs.StringArrayVar(&s.ServiceAccounts.KeyFiles, "service-account-key-file", s.ServiceAccounts.KeyFiles, ""+ fs.StringArrayVar(&s.ServiceAccounts.KeyFiles, "service-account-key-file", s.ServiceAccounts.KeyFiles, ""+
"File containing PEM-encoded x509 RSA or ECDSA private or public keys, used to verify "+ "File containing PEM-encoded x509 RSA or ECDSA private or public keys, used to verify "+
...@@ -219,19 +196,12 @@ func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() kubeauthenticato ...@@ -219,19 +196,12 @@ func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() kubeauthenticato
ret.Anonymous = s.Anonymous.Allow ret.Anonymous = s.Anonymous.Allow
} }
if s.ClientCert != nil {
ret.ClientCAFile = s.ClientCert.ClientCA
}
if s.PasswordFile != nil { if s.PasswordFile != nil {
ret.BasicAuthFile = s.PasswordFile.BasicAuthFile ret.BasicAuthFile = s.PasswordFile.BasicAuthFile
} }
if s.RequestHeader != nil {
ret.RequestHeaderConfig = s.RequestHeader.ToAuthenticationRequestHeaderConfig()
}
ret.APIAudiences = s.APIAudiences ret.APIAudiences = s.APIAudiences
if s.ServiceAccounts != nil { if s.ServiceAccounts != nil {
if s.ServiceAccounts.Issuer != "" && len(s.APIAudiences) == 0 { if s.ServiceAccounts.Issuer != "" && len(s.APIAudiences) == 0 {
ret.APIAudiences = authenticator.Audiences{s.ServiceAccounts.Issuer} ret.APIAudiences = authenticator.Audiences{s.ServiceAccounts.Issuer}
...@@ -267,18 +237,6 @@ func (o *BuiltInAuthenticationOptions) ApplyTo(c *genericapiserver.Config) error ...@@ -267,18 +237,6 @@ func (o *BuiltInAuthenticationOptions) ApplyTo(c *genericapiserver.Config) error
return nil return nil
} }
var err error
if o.ClientCert != nil {
if err = c.Authentication.ApplyClientCert(o.ClientCert.ClientCA, c.SecureServing); err != nil {
return fmt.Errorf("unable to load client CA file: %v", err)
}
}
if o.RequestHeader != nil {
if err = c.Authentication.ApplyClientCert(o.RequestHeader.ClientCAFile, c.SecureServing); err != nil {
return fmt.Errorf("unable to load client CA file: %v", err)
}
}
c.Authentication.SupportsBasicAuth = o.PasswordFile != nil && len(o.PasswordFile.BasicAuthFile) > 0 c.Authentication.SupportsBasicAuth = o.PasswordFile != nil && len(o.PasswordFile.BasicAuthFile) > 0
c.Authentication.APIAudiences = o.APIAudiences c.Authentication.APIAudiences = o.APIAudiences
......
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package master
import (
"encoding/json"
"fmt"
"reflect"
"time"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
genericapiserver "k8s.io/apiserver/pkg/server"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
)
type ClientCARegistrationHook struct {
ClientCA []byte
RequestHeaderUsernameHeaders []string
RequestHeaderGroupHeaders []string
RequestHeaderExtraHeaderPrefixes []string
RequestHeaderCA []byte
RequestHeaderAllowedNames []string
}
func (h ClientCARegistrationHook) PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
// initializing CAs is important so that aggregated API servers can come up with "normal" config.
// We've seen lagging etcd before, so we want to retry this a few times before we decide to crashloop
// the API server on it.
err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) {
// retry building the config since sometimes the server can be in an in-between state which caused
// some kind of auto detection failure as I recall from other post start hooks.
// TODO see if this is still true and fix the RBAC one too if it isn't.
client, err := corev1client.NewForConfig(hookContext.LoopbackClientConfig)
if err != nil {
utilruntime.HandleError(err)
return false, nil
}
return h.tryToWriteClientCAs(client)
})
// if we're never able to make it through initialization, kill the API server
if err != nil {
return fmt.Errorf("unable to initialize client CA configmap: %v", err)
}
return nil
}
// tryToWriteClientCAs is here for unit testing with a fake client. This is a wait.ConditionFunc so the bool
// indicates if the condition was met. True when its finished, false when it should retry.
func (h ClientCARegistrationHook) tryToWriteClientCAs(client corev1client.CoreV1Interface) (bool, error) {
if err := createNamespaceIfNeeded(client, metav1.NamespaceSystem); err != nil {
utilruntime.HandleError(err)
return false, nil
}
data := map[string]string{}
if len(h.ClientCA) > 0 {
data["client-ca-file"] = string(h.ClientCA)
}
if len(h.RequestHeaderCA) > 0 {
var err error
// encoding errors aren't going to get better, so just fail on them.
data["requestheader-username-headers"], err = jsonSerializeStringSlice(h.RequestHeaderUsernameHeaders)
if err != nil {
return false, err
}
data["requestheader-group-headers"], err = jsonSerializeStringSlice(h.RequestHeaderGroupHeaders)
if err != nil {
return false, err
}
data["requestheader-extra-headers-prefix"], err = jsonSerializeStringSlice(h.RequestHeaderExtraHeaderPrefixes)
if err != nil {
return false, err
}
data["requestheader-client-ca-file"] = string(h.RequestHeaderCA)
data["requestheader-allowed-names"], err = jsonSerializeStringSlice(h.RequestHeaderAllowedNames)
if err != nil {
return false, err
}
}
// write errors may work next time if we retry, so queue for retry
if err := writeConfigMap(client, "extension-apiserver-authentication", data); err != nil {
utilruntime.HandleError(err)
return false, nil
}
return true, nil
}
func jsonSerializeStringSlice(in []string) (string, error) {
out, err := json.Marshal(in)
if err != nil {
return "", err
}
return string(out), err
}
func writeConfigMap(client corev1client.ConfigMapsGetter, name string, data map[string]string) error {
existing, err := client.ConfigMaps(metav1.NamespaceSystem).Get(name, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
_, err := client.ConfigMaps(metav1.NamespaceSystem).Create(&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: name},
Data: data,
})
return err
}
if err != nil {
return err
}
if !reflect.DeepEqual(existing.Data, data) {
existing.Data = data
_, err = client.ConfigMaps(metav1.NamespaceSystem).Update(existing)
}
return err
}
...@@ -90,8 +90,6 @@ const ( ...@@ -90,8 +90,6 @@ const (
) )
type ExtraConfig struct { type ExtraConfig struct {
ClientCARegistrationHook ClientCARegistrationHook
APIResourceConfigSource serverstorage.APIResourceConfigSource APIResourceConfigSource serverstorage.APIResourceConfigSource
StorageFactory serverstorage.StorageFactory StorageFactory serverstorage.StorageFactory
EndpointReconcilerConfig EndpointReconcilerConfig EndpointReconcilerConfig EndpointReconcilerConfig
...@@ -176,8 +174,6 @@ type EndpointReconcilerConfig struct { ...@@ -176,8 +174,6 @@ type EndpointReconcilerConfig struct {
// Master contains state for a Kubernetes cluster master/api server. // Master contains state for a Kubernetes cluster master/api server.
type Master struct { type Master struct {
GenericAPIServer *genericapiserver.GenericAPIServer GenericAPIServer *genericapiserver.GenericAPIServer
ClientCARegistrationHook ClientCARegistrationHook
} }
func (c *Config) createMasterCountReconciler() reconcilers.EndpointReconciler { func (c *Config) createMasterCountReconciler() reconcilers.EndpointReconciler {
...@@ -332,8 +328,6 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) ...@@ -332,8 +328,6 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
} }
m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders...) m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders...)
m.GenericAPIServer.AddPostStartHookOrDie("ca-registration", c.ExtraConfig.ClientCARegistrationHook.PostStartHook)
return m, nil return m, nil
} }
......
...@@ -58,8 +58,6 @@ import ( ...@@ -58,8 +58,6 @@ import (
"k8s.io/apiserver/pkg/util/logs" "k8s.io/apiserver/pkg/util/logs"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
certutil "k8s.io/client-go/util/cert"
// install apis // install apis
_ "k8s.io/apiserver/pkg/apis/apiserver/install" _ "k8s.io/apiserver/pkg/apis/apiserver/install"
) )
...@@ -284,25 +282,6 @@ func NewRecommendedConfig(codecs serializer.CodecFactory) *RecommendedConfig { ...@@ -284,25 +282,6 @@ func NewRecommendedConfig(codecs serializer.CodecFactory) *RecommendedConfig {
} }
} }
func (c *AuthenticationInfo) ApplyClientCert(clientCAFile string, servingInfo *SecureServingInfo) error {
if servingInfo != nil {
if len(clientCAFile) > 0 {
clientCAs, err := certutil.CertsFromFile(clientCAFile)
if err != nil {
return fmt.Errorf("unable to load client CA file: %v", err)
}
if servingInfo.ClientCA == nil {
servingInfo.ClientCA = x509.NewCertPool()
}
for _, cert := range clientCAs {
servingInfo.ClientCA.AddCert(cert)
}
}
}
return nil
}
type completedConfig struct { type completedConfig struct {
*Config *Config
......
...@@ -17,15 +17,12 @@ limitations under the License. ...@@ -17,15 +17,12 @@ limitations under the License.
package options package options
import ( import (
"encoding/json"
"fmt" "fmt"
"io/ioutil"
"time" "time"
"github.com/spf13/pflag" "github.com/spf13/pflag"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/authentication/authenticatorfactory" "k8s.io/apiserver/pkg/authentication/authenticatorfactory"
...@@ -35,70 +32,6 @@ import ( ...@@ -35,70 +32,6 @@ import (
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
) )
type RequestHeaderAuthenticationOptions struct {
// ClientCAFile is the root certificate bundle to verify client certificates on incoming requests
// before trusting usernames in headers.
ClientCAFile string
UsernameHeaders []string
GroupHeaders []string
ExtraHeaderPrefixes []string
AllowedNames []string
}
func (s *RequestHeaderAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
if s == nil {
return
}
fs.StringSliceVar(&s.UsernameHeaders, "requestheader-username-headers", s.UsernameHeaders, ""+
"List of request headers to inspect for usernames. X-Remote-User is common.")
fs.StringSliceVar(&s.GroupHeaders, "requestheader-group-headers", s.GroupHeaders, ""+
"List of request headers to inspect for groups. X-Remote-Group is suggested.")
fs.StringSliceVar(&s.ExtraHeaderPrefixes, "requestheader-extra-headers-prefix", s.ExtraHeaderPrefixes, ""+
"List of request header prefixes to inspect. X-Remote-Extra- is suggested.")
fs.StringVar(&s.ClientCAFile, "requestheader-client-ca-file", s.ClientCAFile, ""+
"Root certificate bundle to use to verify client certificates on incoming requests "+
"before trusting usernames in headers specified by --requestheader-username-headers. "+
"WARNING: generally do not depend on authorization being already done for incoming requests.")
fs.StringSliceVar(&s.AllowedNames, "requestheader-allowed-names", s.AllowedNames, ""+
"List of client certificate common names to allow to provide usernames in headers "+
"specified by --requestheader-username-headers. If empty, any client certificate validated "+
"by the authorities in --requestheader-client-ca-file is allowed.")
}
// ToAuthenticationRequestHeaderConfig returns a RequestHeaderConfig config object for these options
// if necessary, nil otherwise.
func (s *RequestHeaderAuthenticationOptions) ToAuthenticationRequestHeaderConfig() *authenticatorfactory.RequestHeaderConfig {
if len(s.ClientCAFile) == 0 {
return nil
}
return &authenticatorfactory.RequestHeaderConfig{
UsernameHeaders: s.UsernameHeaders,
GroupHeaders: s.GroupHeaders,
ExtraHeaderPrefixes: s.ExtraHeaderPrefixes,
ClientCA: s.ClientCAFile,
AllowedClientNames: s.AllowedNames,
}
}
type ClientCertAuthenticationOptions struct {
// ClientCA is the certificate bundle for all the signers that you'll recognize for incoming client certificates
ClientCA string
}
func (s *ClientCertAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.ClientCA, "client-ca-file", s.ClientCA, ""+
"If set, any request presenting a client certificate signed by one of "+
"the authorities in the client-ca-file is authenticated with an identity "+
"corresponding to the CommonName of the client certificate.")
}
// DelegatingAuthenticationOptions provides an easy way for composing API servers to delegate their authentication to // DelegatingAuthenticationOptions provides an easy way for composing API servers to delegate their authentication to
// the root kube API server. The API federator will act as // the root kube API server. The API federator will act as
// a front proxy and direction connections will be able to delegate to the core kube API server // a front proxy and direction connections will be able to delegate to the core kube API server
...@@ -113,10 +46,6 @@ type DelegatingAuthenticationOptions struct { ...@@ -113,10 +46,6 @@ type DelegatingAuthenticationOptions struct {
// CacheTTL is the length of time that a token authentication answer will be cached. // CacheTTL is the length of time that a token authentication answer will be cached.
CacheTTL time.Duration CacheTTL time.Duration
ClientCert ClientCertAuthenticationOptions
RequestHeader RequestHeaderAuthenticationOptions
// SkipInClusterLookup indicates missing authentication configuration should not be retrieved from the cluster configmap
SkipInClusterLookup bool SkipInClusterLookup bool
// TolerateInClusterLookupFailure indicates failures to look up authentication configuration from the cluster configmap should not be fatal. // TolerateInClusterLookupFailure indicates failures to look up authentication configuration from the cluster configmap should not be fatal.
...@@ -128,12 +57,6 @@ func NewDelegatingAuthenticationOptions() *DelegatingAuthenticationOptions { ...@@ -128,12 +57,6 @@ func NewDelegatingAuthenticationOptions() *DelegatingAuthenticationOptions {
return &DelegatingAuthenticationOptions{ return &DelegatingAuthenticationOptions{
// very low for responsiveness, but high enough to handle storms // very low for responsiveness, but high enough to handle storms
CacheTTL: 10 * time.Second, CacheTTL: 10 * time.Second,
ClientCert: ClientCertAuthenticationOptions{},
RequestHeader: RequestHeaderAuthenticationOptions{
UsernameHeaders: []string{"x-remote-user"},
GroupHeaders: []string{"x-remote-group"},
ExtraHeaderPrefixes: []string{"x-remote-extra-"},
},
} }
} }
...@@ -158,9 +81,6 @@ func (s *DelegatingAuthenticationOptions) AddFlags(fs *pflag.FlagSet) { ...@@ -158,9 +81,6 @@ func (s *DelegatingAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
fs.DurationVar(&s.CacheTTL, "authentication-token-webhook-cache-ttl", s.CacheTTL, fs.DurationVar(&s.CacheTTL, "authentication-token-webhook-cache-ttl", s.CacheTTL,
"The duration to cache responses from the webhook token authenticator.") "The duration to cache responses from the webhook token authenticator.")
s.ClientCert.AddFlags(fs)
s.RequestHeader.AddFlags(fs)
fs.BoolVar(&s.SkipInClusterLookup, "authentication-skip-lookup", s.SkipInClusterLookup, ""+ fs.BoolVar(&s.SkipInClusterLookup, "authentication-skip-lookup", s.SkipInClusterLookup, ""+
"If false, the authentication-kubeconfig will be used to lookup missing authentication "+ "If false, the authentication-kubeconfig will be used to lookup missing authentication "+
"configuration from the cluster.") "configuration from the cluster.")
...@@ -199,17 +119,6 @@ func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.AuthenticationInfo, ...@@ -199,17 +119,6 @@ func (s *DelegatingAuthenticationOptions) ApplyTo(c *server.AuthenticationInfo,
} }
} }
// configure AuthenticationInfo config
cfg.ClientCAFile = s.ClientCert.ClientCA
if err = c.ApplyClientCert(s.ClientCert.ClientCA, servingInfo); err != nil {
return fmt.Errorf("unable to load client CA file: %v", err)
}
cfg.RequestHeaderConfig = s.RequestHeader.ToAuthenticationRequestHeaderConfig()
if err = c.ApplyClientCert(s.RequestHeader.ClientCAFile, servingInfo); err != nil {
return fmt.Errorf("unable to load client CA file: %v", err)
}
// create authenticator // create authenticator
authenticator, err := cfg.New() authenticator, err := cfg.New()
if err != nil { if err != nil {
...@@ -232,20 +141,11 @@ const ( ...@@ -232,20 +141,11 @@ const (
) )
func (s *DelegatingAuthenticationOptions) lookupMissingConfigInCluster(client kubernetes.Interface) error { func (s *DelegatingAuthenticationOptions) lookupMissingConfigInCluster(client kubernetes.Interface) error {
if len(s.ClientCert.ClientCA) > 0 && len(s.RequestHeader.ClientCAFile) > 0 {
return nil
}
if client == nil { if client == nil {
if len(s.ClientCert.ClientCA) == 0 {
klog.Warningf("No authentication-kubeconfig provided in order to lookup client-ca-file in configmap/%s in %s, so client certificate authentication won't work.", authenticationConfigMapName, authenticationConfigMapNamespace)
}
if len(s.RequestHeader.ClientCAFile) == 0 {
klog.Warningf("No authentication-kubeconfig provided in order to lookup requestheader-client-ca-file in configmap/%s in %s, so request-header client certificate authentication won't work.", authenticationConfigMapName, authenticationConfigMapNamespace)
}
return nil return nil
} }
authConfigMap, err := client.CoreV1().ConfigMaps(authenticationConfigMapNamespace).Get(authenticationConfigMapName, metav1.GetOptions{}) _, err := client.CoreV1().ConfigMaps(authenticationConfigMapNamespace).Get(authenticationConfigMapName, metav1.GetOptions{})
switch { switch {
case errors.IsNotFound(err): case errors.IsNotFound(err):
// ignore, authConfigMap is nil now // ignore, authConfigMap is nil now
...@@ -258,107 +158,9 @@ func (s *DelegatingAuthenticationOptions) lookupMissingConfigInCluster(client ku ...@@ -258,107 +158,9 @@ func (s *DelegatingAuthenticationOptions) lookupMissingConfigInCluster(client ku
return err return err
} }
if len(s.ClientCert.ClientCA) == 0 {
if authConfigMap != nil {
opt, err := inClusterClientCA(authConfigMap)
if err != nil {
return err
}
if opt != nil {
s.ClientCert = *opt
}
}
if len(s.ClientCert.ClientCA) == 0 {
klog.Warningf("Cluster doesn't provide client-ca-file in configmap/%s in %s, so client certificate authentication won't work.", authenticationConfigMapName, authenticationConfigMapNamespace)
}
}
if len(s.RequestHeader.ClientCAFile) == 0 {
if authConfigMap != nil {
opt, err := inClusterRequestHeader(authConfigMap)
if err != nil {
return err
}
if opt != nil {
s.RequestHeader = *opt
}
}
if len(s.RequestHeader.ClientCAFile) == 0 {
klog.Warningf("Cluster doesn't provide requestheader-client-ca-file in configmap/%s in %s, so request-header client certificate authentication won't work.", authenticationConfigMapName, authenticationConfigMapNamespace)
}
}
return nil return nil
} }
func inClusterClientCA(authConfigMap *v1.ConfigMap) (*ClientCertAuthenticationOptions, error) {
clientCA, ok := authConfigMap.Data["client-ca-file"]
if !ok {
// not having a client-ca is fine, return nil
return nil, nil
}
f, err := ioutil.TempFile("", "client-ca-file")
if err != nil {
return nil, err
}
if err := ioutil.WriteFile(f.Name(), []byte(clientCA), 0600); err != nil {
return nil, err
}
return &ClientCertAuthenticationOptions{ClientCA: f.Name()}, nil
}
func inClusterRequestHeader(authConfigMap *v1.ConfigMap) (*RequestHeaderAuthenticationOptions, error) {
requestHeaderCA, ok := authConfigMap.Data["requestheader-client-ca-file"]
if !ok {
// not having a requestheader-client-ca is fine, return nil
return nil, nil
}
f, err := ioutil.TempFile("", "requestheader-client-ca-file")
if err != nil {
return nil, err
}
if err := ioutil.WriteFile(f.Name(), []byte(requestHeaderCA), 0600); err != nil {
return nil, err
}
usernameHeaders, err := deserializeStrings(authConfigMap.Data["requestheader-username-headers"])
if err != nil {
return nil, err
}
groupHeaders, err := deserializeStrings(authConfigMap.Data["requestheader-group-headers"])
if err != nil {
return nil, err
}
extraHeaderPrefixes, err := deserializeStrings(authConfigMap.Data["requestheader-extra-headers-prefix"])
if err != nil {
return nil, err
}
allowedNames, err := deserializeStrings(authConfigMap.Data["requestheader-allowed-names"])
if err != nil {
return nil, err
}
return &RequestHeaderAuthenticationOptions{
UsernameHeaders: usernameHeaders,
GroupHeaders: groupHeaders,
ExtraHeaderPrefixes: extraHeaderPrefixes,
ClientCAFile: f.Name(),
AllowedNames: allowedNames,
}, nil
}
func deserializeStrings(in string) ([]string, error) {
if len(in) == 0 {
return nil, nil
}
var ret []string
if err := json.Unmarshal([]byte(in), &ret); err != nil {
return nil, err
}
return ret, nil
}
// getClient returns a Kubernetes clientset. If s.RemoteKubeConfigFileOptional is true, nil will be returned // getClient returns a Kubernetes clientset. If s.RemoteKubeConfigFileOptional is true, nil will be returned
// if no kubeconfig is specified by the user and the in-cluster config is not found. // if no kubeconfig is specified by the user and the in-cluster config is not found.
func (s *DelegatingAuthenticationOptions) getClient() (kubernetes.Interface, error) { func (s *DelegatingAuthenticationOptions) getClient() (kubernetes.Interface, error) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment