Merge pull request #34381 from liggitt/kubelet-auth

Automatic merge from submit-queue

kubelet authn/authz

Implements https://github.com/kubernetes/kubernetes/blob/master/docs/proposals/kubelet-auth.md

Part of [Authenticated/Authorized access to kubelet API](https://github.com/kubernetes/features/issues/89) feature
This commit is contained in:
Kubernetes Submit Queue 2016-10-25 17:40:27 -07:00 committed by GitHub
commit a898f3d996
19 changed files with 6087 additions and 3643 deletions

View File

@ -13,6 +13,7 @@ load(
go_library(
name = "go_default_library",
srcs = [
"auth.go",
"bootstrap.go",
"plugins.go",
"server.go",
@ -24,9 +25,15 @@ go_library(
"//pkg/api:go_default_library",
"//pkg/apis/componentconfig:go_default_library",
"//pkg/apis/componentconfig/v1alpha1:go_default_library",
"//pkg/auth/authenticator:go_default_library",
"//pkg/auth/authenticator/bearertoken:go_default_library",
"//pkg/auth/authorizer:go_default_library",
"//pkg/auth/group:go_default_library",
"//pkg/capabilities:go_default_library",
"//pkg/client/chaosclient:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/authentication/unversioned:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/authorization/unversioned:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/certificates/unversioned:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/unversioned:go_default_library",
"//pkg/client/record:go_default_library",
@ -39,6 +46,7 @@ go_library(
"//pkg/credentialprovider:go_default_library",
"//pkg/credentialprovider/aws:go_default_library",
"//pkg/credentialprovider/gcp:go_default_library",
"//pkg/genericapiserver/authorizer:go_default_library",
"//pkg/healthz:go_default_library",
"//pkg/kubelet:go_default_library",
"//pkg/kubelet/cadvisor:go_default_library",
@ -89,6 +97,11 @@ go_library(
"//pkg/volume/rbd:go_default_library",
"//pkg/volume/secret:go_default_library",
"//pkg/volume/vsphere_volume:go_default_library",
"//plugin/pkg/auth/authenticator/request/anonymous:go_default_library",
"//plugin/pkg/auth/authenticator/request/union:go_default_library",
"//plugin/pkg/auth/authenticator/request/x509:go_default_library",
"//plugin/pkg/auth/authenticator/token/webhook:go_default_library",
"//plugin/pkg/auth/authorizer/webhook:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:github.com/spf13/cobra",
"//vendor:github.com/spf13/pflag",

131
cmd/kubelet/app/auth.go Normal file
View File

@ -0,0 +1,131 @@
/*
Copyright 2016 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 app
import (
"errors"
"fmt"
"reflect"
"k8s.io/kubernetes/pkg/apis/componentconfig"
"k8s.io/kubernetes/pkg/auth/authenticator"
"k8s.io/kubernetes/pkg/auth/authenticator/bearertoken"
"k8s.io/kubernetes/pkg/auth/authorizer"
"k8s.io/kubernetes/pkg/auth/group"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
authenticationclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authentication/unversioned"
authorizationclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/unversioned"
alwaysallowauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer"
"k8s.io/kubernetes/pkg/kubelet/server"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util/cert"
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/anonymous"
unionauth "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union"
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/x509"
webhooktoken "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/webhook"
webhooksar "k8s.io/kubernetes/plugin/pkg/auth/authorizer/webhook"
)
func buildAuth(nodeName types.NodeName, client internalclientset.Interface, config componentconfig.KubeletConfiguration) (server.AuthInterface, error) {
// Get clients, if provided
var (
tokenClient authenticationclient.TokenReviewInterface
sarClient authorizationclient.SubjectAccessReviewInterface
)
if client != nil && !reflect.ValueOf(client).IsNil() {
tokenClient = client.Authentication().TokenReviews()
sarClient = client.Authorization().SubjectAccessReviews()
}
authenticator, err := buildAuthn(tokenClient, config.Authentication)
if err != nil {
return nil, err
}
attributes := server.NewNodeAuthorizerAttributesGetter(nodeName)
authorizer, err := buildAuthz(sarClient, config.Authorization)
if err != nil {
return nil, err
}
return server.NewKubeletAuth(authenticator, attributes, authorizer), nil
}
func buildAuthn(client authenticationclient.TokenReviewInterface, authn componentconfig.KubeletAuthentication) (authenticator.Request, error) {
authenticators := []authenticator.Request{}
// x509 client cert auth
if len(authn.X509.ClientCAFile) > 0 {
clientCAs, err := cert.NewPool(authn.X509.ClientCAFile)
if err != nil {
return nil, fmt.Errorf("unable to load client CA file %s: %v", authn.X509.ClientCAFile, err)
}
verifyOpts := x509.DefaultVerifyOptions()
verifyOpts.Roots = clientCAs
authenticators = append(authenticators, x509.New(verifyOpts, x509.CommonNameUserConversion))
}
// bearer token auth that uses authentication.k8s.io TokenReview to determine userinfo
if authn.Webhook.Enabled {
if client == nil {
return nil, errors.New("no client provided, cannot use webhook authentication")
}
tokenAuth, err := webhooktoken.NewFromInterface(client, authn.Webhook.CacheTTL.Duration)
if err != nil {
return nil, err
}
authenticators = append(authenticators, bearertoken.New(tokenAuth))
}
if len(authenticators) == 0 {
if authn.Anonymous.Enabled {
return anonymous.NewAuthenticator(), nil
}
return nil, errors.New("No authentication method configured")
}
authenticator := group.NewGroupAdder(unionauth.New(authenticators...), []string{"system:authenticated"})
if authn.Anonymous.Enabled {
authenticator = unionauth.NewFailOnError(authenticator, anonymous.NewAuthenticator())
}
return authenticator, nil
}
func buildAuthz(client authorizationclient.SubjectAccessReviewInterface, authz componentconfig.KubeletAuthorization) (authorizer.Authorizer, error) {
switch authz.Mode {
case componentconfig.KubeletAuthorizationModeAlwaysAllow:
return alwaysallowauthorizer.NewAlwaysAllowAuthorizer(), nil
case componentconfig.KubeletAuthorizationModeWebhook:
if client == nil {
return nil, errors.New("no client provided, cannot use webhook authorization")
}
return webhooksar.NewFromInterface(
client,
authz.Webhook.CacheAuthorizedTTL.Duration,
authz.Webhook.CacheUnauthorizedTTL.Duration,
)
case "":
return nil, fmt.Errorf("No authorization mode specified")
default:
return nil, fmt.Errorf("Unknown authorization mode %s", authz.Mode)
}
}

View File

@ -98,6 +98,29 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) {
fs.Var(componentconfig.IPVar{Val: &s.Address}, "address", "The IP address for the Kubelet to serve on (set to 0.0.0.0 for all interfaces)")
fs.Int32Var(&s.Port, "port", s.Port, "The port for the Kubelet to serve on.")
fs.Int32Var(&s.ReadOnlyPort, "read-only-port", s.ReadOnlyPort, "The read-only port for the Kubelet to serve on with no authentication/authorization (set to 0 to disable)")
// Authentication
fs.BoolVar(&s.Authentication.Anonymous.Enabled, "anonymous-auth", s.Authentication.Anonymous.Enabled, ""+
"Enables anonymous requests to the Kubelet server. Requests that are not rejected by another "+
"authentication method are treated as anonymous requests. Anonymous requests have a username "+
"of system:anonymous, and a group name of system:unauthenticated.")
fs.BoolVar(&s.Authentication.Webhook.Enabled, "authentication-token-webhook", s.Authentication.Webhook.Enabled, ""+
"Use the TokenReview API to determine authentication for bearer tokens.")
fs.DurationVar(&s.Authentication.Webhook.CacheTTL.Duration, "authentication-token-webhook-cache-ttl", s.Authentication.Webhook.CacheTTL.Duration, ""+
"The duration to cache responses from the webhook token authenticator.")
fs.StringVar(&s.Authentication.X509.ClientCAFile, "client-ca-file", s.Authentication.X509.ClientCAFile, ""+
"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.")
// Authorization
fs.StringVar((*string)(&s.Authorization.Mode), "authorization-mode", string(s.Authorization.Mode), ""+
"Authorization mode for Kubelet server. Valid options are AlwaysAllow or Webhook. "+
"Webhook mode uses the SubjectAccessReview API to determine authorization.")
fs.DurationVar(&s.Authorization.Webhook.CacheAuthorizedTTL.Duration, "authorization-webhook-cache-authorized-ttl", s.Authorization.Webhook.CacheAuthorizedTTL.Duration, ""+
"The duration to cache 'authorized' responses from the webhook authorizer.")
fs.DurationVar(&s.Authorization.Webhook.CacheUnauthorizedTTL.Duration, "authorization-webhook-cache-unauthorized-ttl", s.Authorization.Webhook.CacheUnauthorizedTTL.Duration, ""+
"The duration to cache 'unauthorized' responses from the webhook authorizer.")
fs.StringVar(&s.TLSCertFile, "tls-cert-file", s.TLSCertFile, ""+
"File containing x509 Certificate for HTTPS. (CA cert, if any, concatenated after server cert). "+
"If --tls-cert-file and --tls-private-key-file are not provided, a self-signed certificate and key "+

View File

@ -62,6 +62,7 @@ import (
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util/cert"
certutil "k8s.io/kubernetes/pkg/util/cert"
utilconfig "k8s.io/kubernetes/pkg/util/config"
"k8s.io/kubernetes/pkg/util/configz"
@ -399,6 +400,18 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.KubeletDeps) (err error) {
kubeDeps.EventClient = eventClient
}
if kubeDeps.Auth == nil {
nodeName, err := getNodeName(kubeDeps.Cloud, nodeutil.GetHostname(s.HostnameOverride))
if err != nil {
return err
}
auth, err := buildAuth(nodeName, kubeDeps.KubeClient, s.KubeletConfiguration)
if err != nil {
return err
}
kubeDeps.Auth = auth
}
if kubeDeps.CAdvisorInterface == nil {
kubeDeps.CAdvisorInterface, err = cadvisor.New(uint(s.CAdvisorPort), s.ContainerRuntime)
if err != nil {
@ -501,12 +514,22 @@ func InitializeTLS(kc *componentconfig.KubeletConfiguration) (*server.TLSOptions
// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
// Can't use TLSv1.1 because of RC4 cipher usage
MinVersion: tls.VersionTLS12,
// Populate PeerCertificates in requests, but don't yet reject connections without certificates.
ClientAuth: tls.RequestClientCert,
},
CertFile: kc.TLSCertFile,
KeyFile: kc.TLSPrivateKeyFile,
}
if len(kc.Authentication.X509.ClientCAFile) > 0 {
clientCAs, err := cert.NewPool(kc.Authentication.X509.ClientCAFile)
if err != nil {
return nil, fmt.Errorf("unable to load client CA file %s: %v", kc.Authentication.X509.ClientCAFile, err)
}
// Specify allowed CAs for client certificates
tlsOptions.Config.ClientCAs = clientCAs
// Populate PeerCertificates in requests, but don't reject connections without verified certificates
tlsOptions.Config.ClientAuth = tls.RequestClientCert
}
return tlsOptions, nil
}

View File

@ -32,6 +32,7 @@ auth-provider
auth-provider
auth-provider-arg
auth-provider-arg
authentication-token-webhook
authentication-token-webhook-cache-ttl
authentication-token-webhook-config-file
authorization-mode

File diff suppressed because it is too large Load Diff

View File

@ -153,6 +153,10 @@ type KubeletConfiguration struct {
// default /var/run/kubernetes). If tlsCertFile and tlsPrivateKeyFile
// are provided, this flag will be ignored.
CertDirectory string `json:"certDirectory"`
// authentication specifies how requests to the Kubelet's server are authenticated
Authentication KubeletAuthentication `json:"authentication"`
// authorization specifies how requests to the Kubelet's server are authorized
Authorization KubeletAuthorization `json:"authorization"`
// hostnameOverride is the hostname used to identify the kubelet instead
// of the actual hostname.
HostnameOverride string `json:"hostnameOverride"`
@ -452,6 +456,62 @@ type KubeletConfiguration struct {
ExperimentalRuntimeIntegrationType string `json:"experimentalRuntimeIntegrationType,omitempty"`
}
type KubeletAuthorizationMode string
const (
// KubeletAuthorizationModeAlwaysAllow authorizes all authenticated requests
KubeletAuthorizationModeAlwaysAllow KubeletAuthorizationMode = "AlwaysAllow"
// KubeletAuthorizationModeWebhook uses the SubjectAccessReview API to determine authorization
KubeletAuthorizationModeWebhook KubeletAuthorizationMode = "Webhook"
)
type KubeletAuthorization struct {
// mode is the authorization mode to apply to requests to the kubelet server.
// Valid values are AlwaysAllow and Webhook.
// Webhook mode uses the SubjectAccessReview API to determine authorization.
Mode KubeletAuthorizationMode `json:"mode"`
// webhook contains settings related to Webhook authorization.
Webhook KubeletWebhookAuthorization `json:"webhook"`
}
type KubeletWebhookAuthorization struct {
// cacheAuthorizedTTL is the duration to cache 'authorized' responses from the webhook authorizer.
CacheAuthorizedTTL unversioned.Duration `json:"cacheAuthorizedTTL"`
// cacheUnauthorizedTTL is the duration to cache 'unauthorized' responses from the webhook authorizer.
CacheUnauthorizedTTL unversioned.Duration `json:"cacheUnauthorizedTTL"`
}
type KubeletAuthentication struct {
// x509 contains settings related to x509 client certificate authentication
X509 KubeletX509Authentication `json:"x509"`
// webhook contains settings related to webhook bearer token authentication
Webhook KubeletWebhookAuthentication `json:"webhook"`
// anonymous contains settings related to anonymous authentication
Anonymous KubeletAnonymousAuthentication `json:"anonymous"`
}
type KubeletX509Authentication struct {
// clientCAFile is the path to a PEM-encoded certificate bundle. If set, any request presenting a client certificate
// signed by one of the authorities in the bundle is authenticated with a username corresponding to the CommonName,
// and groups corresponding to the Organization in the client certificate.
ClientCAFile string `json:"clientCAFile"`
}
type KubeletWebhookAuthentication struct {
// enabled allows bearer token authentication backed by the tokenreviews.authentication.k8s.io API
Enabled bool `json:"enabled"`
// cacheTTL enables caching of authentication results
CacheTTL unversioned.Duration `json:"cacheTTL"`
}
type KubeletAnonymousAuthentication struct {
// enabled allows anonymous requests to the kubelet server.
// Requests that are not rejected by another authentication method are treated as anonymous requests.
// Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.
Enabled bool `json:"enabled"`
}
type KubeSchedulerConfiguration struct {
unversioned.TypeMeta

View File

@ -147,6 +147,25 @@ func SetDefaults_LeaderElectionConfiguration(obj *LeaderElectionConfiguration) {
}
func SetDefaults_KubeletConfiguration(obj *KubeletConfiguration) {
if obj.Authentication.Anonymous.Enabled == nil {
obj.Authentication.Anonymous.Enabled = boolVar(true)
}
if obj.Authentication.Webhook.Enabled == nil {
obj.Authentication.Webhook.Enabled = boolVar(false)
}
if obj.Authentication.Webhook.CacheTTL == zeroDuration {
obj.Authentication.Webhook.CacheTTL = unversioned.Duration{Duration: 2 * time.Minute}
}
if obj.Authorization.Mode == "" {
obj.Authorization.Mode = KubeletAuthorizationModeAlwaysAllow
}
if obj.Authorization.Webhook.CacheAuthorizedTTL == zeroDuration {
obj.Authorization.Webhook.CacheAuthorizedTTL = unversioned.Duration{Duration: 5 * time.Minute}
}
if obj.Authorization.Webhook.CacheUnauthorizedTTL == zeroDuration {
obj.Authorization.Webhook.CacheUnauthorizedTTL = unversioned.Duration{Duration: 30 * time.Second}
}
if obj.Address == "" {
obj.Address = "0.0.0.0"
}

View File

@ -207,6 +207,10 @@ type KubeletConfiguration struct {
// default /var/run/kubernetes). If tlsCertFile and tlsPrivateKeyFile
// are provided, this flag will be ignored.
CertDirectory string `json:"certDirectory"`
// authentication specifies how requests to the Kubelet's server are authenticated
Authentication KubeletAuthentication `json:"authentication"`
// authorization specifies how requests to the Kubelet's server are authorized
Authorization KubeletAuthorization `json:"authorization"`
// hostnameOverride is the hostname used to identify the kubelet instead
// of the actual hostname.
HostnameOverride string `json:"hostnameOverride"`
@ -490,3 +494,59 @@ type KubeletConfiguration struct {
// +optional
ExperimentalRuntimeIntegrationType string `json:"experimentalRuntimeIntegrationType,omitempty"`
}
type KubeletAuthorizationMode string
const (
// KubeletAuthorizationModeAlwaysAllow authorizes all authenticated requests
KubeletAuthorizationModeAlwaysAllow KubeletAuthorizationMode = "AlwaysAllow"
// KubeletAuthorizationModeWebhook uses the SubjectAccessReview API to determine authorization
KubeletAuthorizationModeWebhook KubeletAuthorizationMode = "Webhook"
)
type KubeletAuthorization struct {
// mode is the authorization mode to apply to requests to the kubelet server.
// Valid values are AlwaysAllow and Webhook.
// Webhook mode uses the SubjectAccessReview API to determine authorization.
Mode KubeletAuthorizationMode `json:"mode"`
// webhook contains settings related to Webhook authorization.
Webhook KubeletWebhookAuthorization `json:"webhook"`
}
type KubeletWebhookAuthorization struct {
// cacheAuthorizedTTL is the duration to cache 'authorized' responses from the webhook authorizer.
CacheAuthorizedTTL unversioned.Duration `json:"cacheAuthorizedTTL"`
// cacheUnauthorizedTTL is the duration to cache 'unauthorized' responses from the webhook authorizer.
CacheUnauthorizedTTL unversioned.Duration `json:"cacheUnauthorizedTTL"`
}
type KubeletAuthentication struct {
// x509 contains settings related to x509 client certificate authentication
X509 KubeletX509Authentication `json:"x509"`
// webhook contains settings related to webhook bearer token authentication
Webhook KubeletWebhookAuthentication `json:"webhook"`
// anonymous contains settings related to anonymous authentication
Anonymous KubeletAnonymousAuthentication `json:"anonymous"`
}
type KubeletX509Authentication struct {
// clientCAFile is the path to a PEM-encoded certificate bundle. If set, any request presenting a client certificate
// signed by one of the authorities in the bundle is authenticated with a username corresponding to the CommonName,
// and groups corresponding to the Organization in the client certificate.
ClientCAFile string `json:"clientCAFile"`
}
type KubeletWebhookAuthentication struct {
// enabled allows bearer token authentication backed by the tokenreviews.authentication.k8s.io API
Enabled *bool `json:"enabled"`
// cacheTTL enables caching of authentication results
CacheTTL unversioned.Duration `json:"cacheTTL"`
}
type KubeletAnonymousAuthentication struct {
// enabled allows anonymous requests to the kubelet server.
// Requests that are not rejected by another authentication method are treated as anonymous requests.
// Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.
Enabled *bool `json:"enabled"`
}

View File

@ -40,8 +40,20 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_componentconfig_KubeProxyConfiguration_To_v1alpha1_KubeProxyConfiguration,
Convert_v1alpha1_KubeSchedulerConfiguration_To_componentconfig_KubeSchedulerConfiguration,
Convert_componentconfig_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration,
Convert_v1alpha1_KubeletAnonymousAuthentication_To_componentconfig_KubeletAnonymousAuthentication,
Convert_componentconfig_KubeletAnonymousAuthentication_To_v1alpha1_KubeletAnonymousAuthentication,
Convert_v1alpha1_KubeletAuthentication_To_componentconfig_KubeletAuthentication,
Convert_componentconfig_KubeletAuthentication_To_v1alpha1_KubeletAuthentication,
Convert_v1alpha1_KubeletAuthorization_To_componentconfig_KubeletAuthorization,
Convert_componentconfig_KubeletAuthorization_To_v1alpha1_KubeletAuthorization,
Convert_v1alpha1_KubeletConfiguration_To_componentconfig_KubeletConfiguration,
Convert_componentconfig_KubeletConfiguration_To_v1alpha1_KubeletConfiguration,
Convert_v1alpha1_KubeletWebhookAuthentication_To_componentconfig_KubeletWebhookAuthentication,
Convert_componentconfig_KubeletWebhookAuthentication_To_v1alpha1_KubeletWebhookAuthentication,
Convert_v1alpha1_KubeletWebhookAuthorization_To_componentconfig_KubeletWebhookAuthorization,
Convert_componentconfig_KubeletWebhookAuthorization_To_v1alpha1_KubeletWebhookAuthorization,
Convert_v1alpha1_KubeletX509Authentication_To_componentconfig_KubeletX509Authentication,
Convert_componentconfig_KubeletX509Authentication_To_v1alpha1_KubeletX509Authentication,
Convert_v1alpha1_LeaderElectionConfiguration_To_componentconfig_LeaderElectionConfiguration,
Convert_componentconfig_LeaderElectionConfiguration_To_v1alpha1_LeaderElectionConfiguration,
)
@ -161,6 +173,86 @@ func Convert_componentconfig_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedule
return autoConvert_componentconfig_KubeSchedulerConfiguration_To_v1alpha1_KubeSchedulerConfiguration(in, out, s)
}
func autoConvert_v1alpha1_KubeletAnonymousAuthentication_To_componentconfig_KubeletAnonymousAuthentication(in *KubeletAnonymousAuthentication, out *componentconfig.KubeletAnonymousAuthentication, s conversion.Scope) error {
if err := api.Convert_Pointer_bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil {
return err
}
return nil
}
func Convert_v1alpha1_KubeletAnonymousAuthentication_To_componentconfig_KubeletAnonymousAuthentication(in *KubeletAnonymousAuthentication, out *componentconfig.KubeletAnonymousAuthentication, s conversion.Scope) error {
return autoConvert_v1alpha1_KubeletAnonymousAuthentication_To_componentconfig_KubeletAnonymousAuthentication(in, out, s)
}
func autoConvert_componentconfig_KubeletAnonymousAuthentication_To_v1alpha1_KubeletAnonymousAuthentication(in *componentconfig.KubeletAnonymousAuthentication, out *KubeletAnonymousAuthentication, s conversion.Scope) error {
if err := api.Convert_bool_To_Pointer_bool(&in.Enabled, &out.Enabled, s); err != nil {
return err
}
return nil
}
func Convert_componentconfig_KubeletAnonymousAuthentication_To_v1alpha1_KubeletAnonymousAuthentication(in *componentconfig.KubeletAnonymousAuthentication, out *KubeletAnonymousAuthentication, s conversion.Scope) error {
return autoConvert_componentconfig_KubeletAnonymousAuthentication_To_v1alpha1_KubeletAnonymousAuthentication(in, out, s)
}
func autoConvert_v1alpha1_KubeletAuthentication_To_componentconfig_KubeletAuthentication(in *KubeletAuthentication, out *componentconfig.KubeletAuthentication, s conversion.Scope) error {
if err := Convert_v1alpha1_KubeletX509Authentication_To_componentconfig_KubeletX509Authentication(&in.X509, &out.X509, s); err != nil {
return err
}
if err := Convert_v1alpha1_KubeletWebhookAuthentication_To_componentconfig_KubeletWebhookAuthentication(&in.Webhook, &out.Webhook, s); err != nil {
return err
}
if err := Convert_v1alpha1_KubeletAnonymousAuthentication_To_componentconfig_KubeletAnonymousAuthentication(&in.Anonymous, &out.Anonymous, s); err != nil {
return err
}
return nil
}
func Convert_v1alpha1_KubeletAuthentication_To_componentconfig_KubeletAuthentication(in *KubeletAuthentication, out *componentconfig.KubeletAuthentication, s conversion.Scope) error {
return autoConvert_v1alpha1_KubeletAuthentication_To_componentconfig_KubeletAuthentication(in, out, s)
}
func autoConvert_componentconfig_KubeletAuthentication_To_v1alpha1_KubeletAuthentication(in *componentconfig.KubeletAuthentication, out *KubeletAuthentication, s conversion.Scope) error {
if err := Convert_componentconfig_KubeletX509Authentication_To_v1alpha1_KubeletX509Authentication(&in.X509, &out.X509, s); err != nil {
return err
}
if err := Convert_componentconfig_KubeletWebhookAuthentication_To_v1alpha1_KubeletWebhookAuthentication(&in.Webhook, &out.Webhook, s); err != nil {
return err
}
if err := Convert_componentconfig_KubeletAnonymousAuthentication_To_v1alpha1_KubeletAnonymousAuthentication(&in.Anonymous, &out.Anonymous, s); err != nil {
return err
}
return nil
}
func Convert_componentconfig_KubeletAuthentication_To_v1alpha1_KubeletAuthentication(in *componentconfig.KubeletAuthentication, out *KubeletAuthentication, s conversion.Scope) error {
return autoConvert_componentconfig_KubeletAuthentication_To_v1alpha1_KubeletAuthentication(in, out, s)
}
func autoConvert_v1alpha1_KubeletAuthorization_To_componentconfig_KubeletAuthorization(in *KubeletAuthorization, out *componentconfig.KubeletAuthorization, s conversion.Scope) error {
out.Mode = componentconfig.KubeletAuthorizationMode(in.Mode)
if err := Convert_v1alpha1_KubeletWebhookAuthorization_To_componentconfig_KubeletWebhookAuthorization(&in.Webhook, &out.Webhook, s); err != nil {
return err
}
return nil
}
func Convert_v1alpha1_KubeletAuthorization_To_componentconfig_KubeletAuthorization(in *KubeletAuthorization, out *componentconfig.KubeletAuthorization, s conversion.Scope) error {
return autoConvert_v1alpha1_KubeletAuthorization_To_componentconfig_KubeletAuthorization(in, out, s)
}
func autoConvert_componentconfig_KubeletAuthorization_To_v1alpha1_KubeletAuthorization(in *componentconfig.KubeletAuthorization, out *KubeletAuthorization, s conversion.Scope) error {
out.Mode = KubeletAuthorizationMode(in.Mode)
if err := Convert_componentconfig_KubeletWebhookAuthorization_To_v1alpha1_KubeletWebhookAuthorization(&in.Webhook, &out.Webhook, s); err != nil {
return err
}
return nil
}
func Convert_componentconfig_KubeletAuthorization_To_v1alpha1_KubeletAuthorization(in *componentconfig.KubeletAuthorization, out *KubeletAuthorization, s conversion.Scope) error {
return autoConvert_componentconfig_KubeletAuthorization_To_v1alpha1_KubeletAuthorization(in, out, s)
}
func autoConvert_v1alpha1_KubeletConfiguration_To_componentconfig_KubeletConfiguration(in *KubeletConfiguration, out *componentconfig.KubeletConfiguration, s conversion.Scope) error {
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
@ -180,6 +272,12 @@ func autoConvert_v1alpha1_KubeletConfiguration_To_componentconfig_KubeletConfigu
out.TLSCertFile = in.TLSCertFile
out.TLSPrivateKeyFile = in.TLSPrivateKeyFile
out.CertDirectory = in.CertDirectory
if err := Convert_v1alpha1_KubeletAuthentication_To_componentconfig_KubeletAuthentication(&in.Authentication, &out.Authentication, s); err != nil {
return err
}
if err := Convert_v1alpha1_KubeletAuthorization_To_componentconfig_KubeletAuthorization(&in.Authorization, &out.Authorization, s); err != nil {
return err
}
out.HostnameOverride = in.HostnameOverride
out.PodInfraContainerImage = in.PodInfraContainerImage
out.DockerEndpoint = in.DockerEndpoint
@ -359,6 +457,12 @@ func autoConvert_componentconfig_KubeletConfiguration_To_v1alpha1_KubeletConfigu
out.TLSCertFile = in.TLSCertFile
out.TLSPrivateKeyFile = in.TLSPrivateKeyFile
out.CertDirectory = in.CertDirectory
if err := Convert_componentconfig_KubeletAuthentication_To_v1alpha1_KubeletAuthentication(&in.Authentication, &out.Authentication, s); err != nil {
return err
}
if err := Convert_componentconfig_KubeletAuthorization_To_v1alpha1_KubeletAuthorization(&in.Authorization, &out.Authorization, s); err != nil {
return err
}
out.HostnameOverride = in.HostnameOverride
out.PodInfraContainerImage = in.PodInfraContainerImage
out.DockerEndpoint = in.DockerEndpoint
@ -519,6 +623,68 @@ func Convert_componentconfig_KubeletConfiguration_To_v1alpha1_KubeletConfigurati
return autoConvert_componentconfig_KubeletConfiguration_To_v1alpha1_KubeletConfiguration(in, out, s)
}
func autoConvert_v1alpha1_KubeletWebhookAuthentication_To_componentconfig_KubeletWebhookAuthentication(in *KubeletWebhookAuthentication, out *componentconfig.KubeletWebhookAuthentication, s conversion.Scope) error {
if err := api.Convert_Pointer_bool_To_bool(&in.Enabled, &out.Enabled, s); err != nil {
return err
}
out.CacheTTL = in.CacheTTL
return nil
}
func Convert_v1alpha1_KubeletWebhookAuthentication_To_componentconfig_KubeletWebhookAuthentication(in *KubeletWebhookAuthentication, out *componentconfig.KubeletWebhookAuthentication, s conversion.Scope) error {
return autoConvert_v1alpha1_KubeletWebhookAuthentication_To_componentconfig_KubeletWebhookAuthentication(in, out, s)
}
func autoConvert_componentconfig_KubeletWebhookAuthentication_To_v1alpha1_KubeletWebhookAuthentication(in *componentconfig.KubeletWebhookAuthentication, out *KubeletWebhookAuthentication, s conversion.Scope) error {
if err := api.Convert_bool_To_Pointer_bool(&in.Enabled, &out.Enabled, s); err != nil {
return err
}
out.CacheTTL = in.CacheTTL
return nil
}
func Convert_componentconfig_KubeletWebhookAuthentication_To_v1alpha1_KubeletWebhookAuthentication(in *componentconfig.KubeletWebhookAuthentication, out *KubeletWebhookAuthentication, s conversion.Scope) error {
return autoConvert_componentconfig_KubeletWebhookAuthentication_To_v1alpha1_KubeletWebhookAuthentication(in, out, s)
}
func autoConvert_v1alpha1_KubeletWebhookAuthorization_To_componentconfig_KubeletWebhookAuthorization(in *KubeletWebhookAuthorization, out *componentconfig.KubeletWebhookAuthorization, s conversion.Scope) error {
out.CacheAuthorizedTTL = in.CacheAuthorizedTTL
out.CacheUnauthorizedTTL = in.CacheUnauthorizedTTL
return nil
}
func Convert_v1alpha1_KubeletWebhookAuthorization_To_componentconfig_KubeletWebhookAuthorization(in *KubeletWebhookAuthorization, out *componentconfig.KubeletWebhookAuthorization, s conversion.Scope) error {
return autoConvert_v1alpha1_KubeletWebhookAuthorization_To_componentconfig_KubeletWebhookAuthorization(in, out, s)
}
func autoConvert_componentconfig_KubeletWebhookAuthorization_To_v1alpha1_KubeletWebhookAuthorization(in *componentconfig.KubeletWebhookAuthorization, out *KubeletWebhookAuthorization, s conversion.Scope) error {
out.CacheAuthorizedTTL = in.CacheAuthorizedTTL
out.CacheUnauthorizedTTL = in.CacheUnauthorizedTTL
return nil
}
func Convert_componentconfig_KubeletWebhookAuthorization_To_v1alpha1_KubeletWebhookAuthorization(in *componentconfig.KubeletWebhookAuthorization, out *KubeletWebhookAuthorization, s conversion.Scope) error {
return autoConvert_componentconfig_KubeletWebhookAuthorization_To_v1alpha1_KubeletWebhookAuthorization(in, out, s)
}
func autoConvert_v1alpha1_KubeletX509Authentication_To_componentconfig_KubeletX509Authentication(in *KubeletX509Authentication, out *componentconfig.KubeletX509Authentication, s conversion.Scope) error {
out.ClientCAFile = in.ClientCAFile
return nil
}
func Convert_v1alpha1_KubeletX509Authentication_To_componentconfig_KubeletX509Authentication(in *KubeletX509Authentication, out *componentconfig.KubeletX509Authentication, s conversion.Scope) error {
return autoConvert_v1alpha1_KubeletX509Authentication_To_componentconfig_KubeletX509Authentication(in, out, s)
}
func autoConvert_componentconfig_KubeletX509Authentication_To_v1alpha1_KubeletX509Authentication(in *componentconfig.KubeletX509Authentication, out *KubeletX509Authentication, s conversion.Scope) error {
out.ClientCAFile = in.ClientCAFile
return nil
}
func Convert_componentconfig_KubeletX509Authentication_To_v1alpha1_KubeletX509Authentication(in *componentconfig.KubeletX509Authentication, out *KubeletX509Authentication, s conversion.Scope) error {
return autoConvert_componentconfig_KubeletX509Authentication_To_v1alpha1_KubeletX509Authentication(in, out, s)
}
func autoConvert_v1alpha1_LeaderElectionConfiguration_To_componentconfig_LeaderElectionConfiguration(in *LeaderElectionConfiguration, out *componentconfig.LeaderElectionConfiguration, s conversion.Scope) error {
if err := api.Convert_Pointer_bool_To_bool(&in.LeaderElect, &out.LeaderElect, s); err != nil {
return err

View File

@ -36,7 +36,13 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeProxyConfiguration, InType: reflect.TypeOf(&KubeProxyConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeSchedulerConfiguration, InType: reflect.TypeOf(&KubeSchedulerConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeletAnonymousAuthentication, InType: reflect.TypeOf(&KubeletAnonymousAuthentication{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeletAuthentication, InType: reflect.TypeOf(&KubeletAuthentication{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeletAuthorization, InType: reflect.TypeOf(&KubeletAuthorization{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeletConfiguration, InType: reflect.TypeOf(&KubeletConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeletWebhookAuthentication, InType: reflect.TypeOf(&KubeletWebhookAuthentication{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeletWebhookAuthorization, InType: reflect.TypeOf(&KubeletWebhookAuthorization{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_KubeletX509Authentication, InType: reflect.TypeOf(&KubeletX509Authentication{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_LeaderElectionConfiguration, InType: reflect.TypeOf(&LeaderElectionConfiguration{})},
)
}
@ -110,6 +116,46 @@ func DeepCopy_v1alpha1_KubeSchedulerConfiguration(in interface{}, out interface{
}
}
func DeepCopy_v1alpha1_KubeletAnonymousAuthentication(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletAnonymousAuthentication)
out := out.(*KubeletAnonymousAuthentication)
if in.Enabled != nil {
in, out := &in.Enabled, &out.Enabled
*out = new(bool)
**out = **in
} else {
out.Enabled = nil
}
return nil
}
}
func DeepCopy_v1alpha1_KubeletAuthentication(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletAuthentication)
out := out.(*KubeletAuthentication)
out.X509 = in.X509
if err := DeepCopy_v1alpha1_KubeletWebhookAuthentication(&in.Webhook, &out.Webhook, c); err != nil {
return err
}
if err := DeepCopy_v1alpha1_KubeletAnonymousAuthentication(&in.Anonymous, &out.Anonymous, c); err != nil {
return err
}
return nil
}
}
func DeepCopy_v1alpha1_KubeletAuthorization(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletAuthorization)
out := out.(*KubeletAuthorization)
out.Mode = in.Mode
out.Webhook = in.Webhook
return nil
}
}
func DeepCopy_v1alpha1_KubeletConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletConfiguration)
@ -134,6 +180,10 @@ func DeepCopy_v1alpha1_KubeletConfiguration(in interface{}, out interface{}, c *
out.TLSCertFile = in.TLSCertFile
out.TLSPrivateKeyFile = in.TLSPrivateKeyFile
out.CertDirectory = in.CertDirectory
if err := DeepCopy_v1alpha1_KubeletAuthentication(&in.Authentication, &out.Authentication, c); err != nil {
return err
}
out.Authorization = in.Authorization
out.HostnameOverride = in.HostnameOverride
out.PodInfraContainerImage = in.PodInfraContainerImage
out.DockerEndpoint = in.DockerEndpoint
@ -411,6 +461,41 @@ func DeepCopy_v1alpha1_KubeletConfiguration(in interface{}, out interface{}, c *
}
}
func DeepCopy_v1alpha1_KubeletWebhookAuthentication(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletWebhookAuthentication)
out := out.(*KubeletWebhookAuthentication)
if in.Enabled != nil {
in, out := &in.Enabled, &out.Enabled
*out = new(bool)
**out = **in
} else {
out.Enabled = nil
}
out.CacheTTL = in.CacheTTL
return nil
}
}
func DeepCopy_v1alpha1_KubeletWebhookAuthorization(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletWebhookAuthorization)
out := out.(*KubeletWebhookAuthorization)
out.CacheAuthorizedTTL = in.CacheAuthorizedTTL
out.CacheUnauthorizedTTL = in.CacheUnauthorizedTTL
return nil
}
}
func DeepCopy_v1alpha1_KubeletX509Authentication(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletX509Authentication)
out := out.(*KubeletX509Authentication)
out.ClientCAFile = in.ClientCAFile
return nil
}
}
func DeepCopy_v1alpha1_LeaderElectionConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*LeaderElectionConfiguration)

View File

@ -39,7 +39,13 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeControllerManagerConfiguration, InType: reflect.TypeOf(&KubeControllerManagerConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeProxyConfiguration, InType: reflect.TypeOf(&KubeProxyConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeSchedulerConfiguration, InType: reflect.TypeOf(&KubeSchedulerConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeletAnonymousAuthentication, InType: reflect.TypeOf(&KubeletAnonymousAuthentication{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeletAuthentication, InType: reflect.TypeOf(&KubeletAuthentication{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeletAuthorization, InType: reflect.TypeOf(&KubeletAuthorization{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeletConfiguration, InType: reflect.TypeOf(&KubeletConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeletWebhookAuthentication, InType: reflect.TypeOf(&KubeletWebhookAuthentication{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeletWebhookAuthorization, InType: reflect.TypeOf(&KubeletWebhookAuthorization{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_KubeletX509Authentication, InType: reflect.TypeOf(&KubeletX509Authentication{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_LeaderElectionConfiguration, InType: reflect.TypeOf(&LeaderElectionConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_PersistentVolumeRecyclerConfiguration, InType: reflect.TypeOf(&PersistentVolumeRecyclerConfiguration{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_componentconfig_PortRangeVar, InType: reflect.TypeOf(&PortRangeVar{})},
@ -190,6 +196,36 @@ func DeepCopy_componentconfig_KubeSchedulerConfiguration(in interface{}, out int
}
}
func DeepCopy_componentconfig_KubeletAnonymousAuthentication(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletAnonymousAuthentication)
out := out.(*KubeletAnonymousAuthentication)
out.Enabled = in.Enabled
return nil
}
}
func DeepCopy_componentconfig_KubeletAuthentication(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletAuthentication)
out := out.(*KubeletAuthentication)
out.X509 = in.X509
out.Webhook = in.Webhook
out.Anonymous = in.Anonymous
return nil
}
}
func DeepCopy_componentconfig_KubeletAuthorization(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletAuthorization)
out := out.(*KubeletAuthorization)
out.Mode = in.Mode
out.Webhook = in.Webhook
return nil
}
}
func DeepCopy_componentconfig_KubeletConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletConfiguration)
@ -208,6 +244,8 @@ func DeepCopy_componentconfig_KubeletConfiguration(in interface{}, out interface
out.TLSCertFile = in.TLSCertFile
out.TLSPrivateKeyFile = in.TLSPrivateKeyFile
out.CertDirectory = in.CertDirectory
out.Authentication = in.Authentication
out.Authorization = in.Authorization
out.HostnameOverride = in.HostnameOverride
out.PodInfraContainerImage = in.PodInfraContainerImage
out.DockerEndpoint = in.DockerEndpoint
@ -353,6 +391,35 @@ func DeepCopy_componentconfig_KubeletConfiguration(in interface{}, out interface
}
}
func DeepCopy_componentconfig_KubeletWebhookAuthentication(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletWebhookAuthentication)
out := out.(*KubeletWebhookAuthentication)
out.Enabled = in.Enabled
out.CacheTTL = in.CacheTTL
return nil
}
}
func DeepCopy_componentconfig_KubeletWebhookAuthorization(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletWebhookAuthorization)
out := out.(*KubeletWebhookAuthorization)
out.CacheAuthorizedTTL = in.CacheAuthorizedTTL
out.CacheUnauthorizedTTL = in.CacheUnauthorizedTTL
return nil
}
}
func DeepCopy_componentconfig_KubeletX509Authentication(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*KubeletX509Authentication)
out := out.(*KubeletX509Authentication)
out.ClientCAFile = in.ClientCAFile
return nil
}
}
func DeepCopy_componentconfig_LeaderElectionConfiguration(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*LeaderElectionConfiguration)

View File

@ -2099,6 +2099,76 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
Dependencies: []string{
"componentconfig.LeaderElectionConfiguration", "unversioned.TypeMeta"},
},
"componentconfig.KubeletAnonymousAuthentication": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"enabled": {
SchemaProps: spec.SchemaProps{
Description: "enabled allows anonymous requests to the kubelet server. Requests that are not rejected by another authentication method are treated as anonymous requests. Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.",
Type: []string{"boolean"},
Format: "",
},
},
},
Required: []string{"enabled"},
},
},
Dependencies: []string{},
},
"componentconfig.KubeletAuthentication": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"x509": {
SchemaProps: spec.SchemaProps{
Description: "x509 contains settings related to x509 client certificate authentication",
Ref: spec.MustCreateRef("#/definitions/componentconfig.KubeletX509Authentication"),
},
},
"webhook": {
SchemaProps: spec.SchemaProps{
Description: "webhook contains settings related to webhook bearer token authentication",
Ref: spec.MustCreateRef("#/definitions/componentconfig.KubeletWebhookAuthentication"),
},
},
"anonymous": {
SchemaProps: spec.SchemaProps{
Description: "anonymous contains settings related to anonymous authentication",
Ref: spec.MustCreateRef("#/definitions/componentconfig.KubeletAnonymousAuthentication"),
},
},
},
Required: []string{"x509", "webhook", "anonymous"},
},
},
Dependencies: []string{
"componentconfig.KubeletAnonymousAuthentication", "componentconfig.KubeletWebhookAuthentication", "componentconfig.KubeletX509Authentication"},
},
"componentconfig.KubeletAuthorization": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"mode": {
SchemaProps: spec.SchemaProps{
Description: "mode is the authorization mode to apply to requests to the kubelet server. Valid values are AlwaysAllow and Webhook. Webhook mode uses the SubjectAccessReview API to determine authorization.",
Type: []string{"string"},
Format: "",
},
},
"webhook": {
SchemaProps: spec.SchemaProps{
Description: "webhook contains settings related to Webhook authorization.",
Ref: spec.MustCreateRef("#/definitions/componentconfig.KubeletWebhookAuthorization"),
},
},
},
Required: []string{"mode", "webhook"},
},
},
Dependencies: []string{
"componentconfig.KubeletWebhookAuthorization"},
},
"componentconfig.KubeletConfiguration": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@ -2196,6 +2266,18 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
Format: "",
},
},
"authentication": {
SchemaProps: spec.SchemaProps{
Description: "authentication specifies how requests to the Kubelet's server are authenticated",
Ref: spec.MustCreateRef("#/definitions/componentconfig.KubeletAuthentication"),
},
},
"authorization": {
SchemaProps: spec.SchemaProps{
Description: "authorization specifies how requests to the Kubelet's server are authorized",
Ref: spec.MustCreateRef("#/definitions/componentconfig.KubeletAuthorization"),
},
},
"hostnameOverride": {
SchemaProps: spec.SchemaProps{
Description: "hostnameOverride is the hostname used to identify the kubelet instead of the actual hostname.",
@ -2889,11 +2971,75 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
},
},
},
Required: []string{"TypeMeta", "podManifestPath", "syncFrequency", "fileCheckFrequency", "httpCheckFrequency", "manifestURL", "manifestURLHeader", "enableServer", "address", "port", "readOnlyPort", "tlsCertFile", "tlsPrivateKeyFile", "certDirectory", "hostnameOverride", "podInfraContainerImage", "dockerEndpoint", "rootDirectory", "seccompProfileRoot", "allowPrivileged", "hostNetworkSources", "hostPIDSources", "hostIPCSources", "registryPullQPS", "registryBurst", "eventRecordQPS", "eventBurst", "enableDebuggingHandlers", "minimumGCAge", "maxPerPodContainerCount", "maxContainerCount", "cAdvisorPort", "healthzPort", "healthzBindAddress", "oomScoreAdj", "registerNode", "clusterDomain", "masterServiceNamespace", "clusterDNS", "streamingConnectionIdleTimeout", "nodeStatusUpdateFrequency", "imageMinimumGCAge", "imageGCHighThresholdPercent", "imageGCLowThresholdPercent", "lowDiskSpaceThresholdMB", "volumeStatsAggPeriod", "networkPluginName", "networkPluginMTU", "networkPluginDir", "cniConfDir", "cniBinDir", "volumePluginDir", "containerRuntime", "remoteRuntimeEndpoint", "remoteImageEndpoint", "mounterPath", "lockFilePath", "exitOnLockContention", "hairpinMode", "babysitDaemons", "maxPods", "nvidiaGPUs", "dockerExecHandlerName", "podCIDR", "resolvConf", "cpuCFSQuota", "containerized", "maxOpenFiles", "reconcileCIDR", "registerSchedulable", "contentType", "kubeAPIQPS", "kubeAPIBurst", "serializeImagePulls", "nodeLabels", "nonMasqueradeCIDR", "enableCustomMetrics", "podsPerCore", "enableControllerAttachDetach", "systemReserved", "kubeReserved", "protectKernelDefaults", "makeIPTablesUtilChains", "iptablesMasqueradeBit", "iptablesDropBit"},
Required: []string{"TypeMeta", "podManifestPath", "syncFrequency", "fileCheckFrequency", "httpCheckFrequency", "manifestURL", "manifestURLHeader", "enableServer", "address", "port", "readOnlyPort", "tlsCertFile", "tlsPrivateKeyFile", "certDirectory", "authentication", "authorization", "hostnameOverride", "podInfraContainerImage", "dockerEndpoint", "rootDirectory", "seccompProfileRoot", "allowPrivileged", "hostNetworkSources", "hostPIDSources", "hostIPCSources", "registryPullQPS", "registryBurst", "eventRecordQPS", "eventBurst", "enableDebuggingHandlers", "minimumGCAge", "maxPerPodContainerCount", "maxContainerCount", "cAdvisorPort", "healthzPort", "healthzBindAddress", "oomScoreAdj", "registerNode", "clusterDomain", "masterServiceNamespace", "clusterDNS", "streamingConnectionIdleTimeout", "nodeStatusUpdateFrequency", "imageMinimumGCAge", "imageGCHighThresholdPercent", "imageGCLowThresholdPercent", "lowDiskSpaceThresholdMB", "volumeStatsAggPeriod", "networkPluginName", "networkPluginMTU", "networkPluginDir", "cniConfDir", "cniBinDir", "volumePluginDir", "containerRuntime", "remoteRuntimeEndpoint", "remoteImageEndpoint", "mounterPath", "lockFilePath", "exitOnLockContention", "hairpinMode", "babysitDaemons", "maxPods", "nvidiaGPUs", "dockerExecHandlerName", "podCIDR", "resolvConf", "cpuCFSQuota", "containerized", "maxOpenFiles", "reconcileCIDR", "registerSchedulable", "contentType", "kubeAPIQPS", "kubeAPIBurst", "serializeImagePulls", "nodeLabels", "nonMasqueradeCIDR", "enableCustomMetrics", "podsPerCore", "enableControllerAttachDetach", "systemReserved", "kubeReserved", "protectKernelDefaults", "makeIPTablesUtilChains", "iptablesMasqueradeBit", "iptablesDropBit"},
},
},
Dependencies: []string{
"unversioned.Duration", "unversioned.TypeMeta"},
"componentconfig.KubeletAuthentication", "componentconfig.KubeletAuthorization", "unversioned.Duration", "unversioned.TypeMeta"},
},
"componentconfig.KubeletWebhookAuthentication": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"enabled": {
SchemaProps: spec.SchemaProps{
Description: "enabled allows bearer token authentication backed by the tokenreviews.authentication.k8s.io API",
Type: []string{"boolean"},
Format: "",
},
},
"cacheTTL": {
SchemaProps: spec.SchemaProps{
Description: "cacheTTL enables caching of authentication results",
Ref: spec.MustCreateRef("#/definitions/unversioned.Duration"),
},
},
},
Required: []string{"enabled", "cacheTTL"},
},
},
Dependencies: []string{
"unversioned.Duration"},
},
"componentconfig.KubeletWebhookAuthorization": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"cacheAuthorizedTTL": {
SchemaProps: spec.SchemaProps{
Description: "cacheAuthorizedTTL is the duration to cache 'authorized' responses from the webhook authorizer.",
Ref: spec.MustCreateRef("#/definitions/unversioned.Duration"),
},
},
"cacheUnauthorizedTTL": {
SchemaProps: spec.SchemaProps{
Description: "cacheUnauthorizedTTL is the duration to cache 'unauthorized' responses from the webhook authorizer.",
Ref: spec.MustCreateRef("#/definitions/unversioned.Duration"),
},
},
},
Required: []string{"cacheAuthorizedTTL", "cacheUnauthorizedTTL"},
},
},
Dependencies: []string{
"unversioned.Duration"},
},
"componentconfig.KubeletX509Authentication": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"clientCAFile": {
SchemaProps: spec.SchemaProps{
Description: "clientCAFile is the path to a PEM-encoded certificate bundle. If set, any request presenting a client certificate signed by one of the authorities in the bundle is authenticated with a username corresponding to the CommonName, and groups corresponding to the Organization in the client certificate.",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"clientCAFile"},
},
},
Dependencies: []string{},
},
"componentconfig.LeaderElectionConfiguration": {
Schema: spec.Schema{
@ -13693,6 +13839,76 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
Dependencies: []string{
"unversioned.TypeMeta", "v1alpha1.LeaderElectionConfiguration"},
},
"v1alpha1.KubeletAnonymousAuthentication": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"enabled": {
SchemaProps: spec.SchemaProps{
Description: "enabled allows anonymous requests to the kubelet server. Requests that are not rejected by another authentication method are treated as anonymous requests. Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.",
Type: []string{"boolean"},
Format: "",
},
},
},
Required: []string{"enabled"},
},
},
Dependencies: []string{},
},
"v1alpha1.KubeletAuthentication": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"x509": {
SchemaProps: spec.SchemaProps{
Description: "x509 contains settings related to x509 client certificate authentication",
Ref: spec.MustCreateRef("#/definitions/v1alpha1.KubeletX509Authentication"),
},
},
"webhook": {
SchemaProps: spec.SchemaProps{
Description: "webhook contains settings related to webhook bearer token authentication",
Ref: spec.MustCreateRef("#/definitions/v1alpha1.KubeletWebhookAuthentication"),
},
},
"anonymous": {
SchemaProps: spec.SchemaProps{
Description: "anonymous contains settings related to anonymous authentication",
Ref: spec.MustCreateRef("#/definitions/v1alpha1.KubeletAnonymousAuthentication"),
},
},
},
Required: []string{"x509", "webhook", "anonymous"},
},
},
Dependencies: []string{
"v1alpha1.KubeletAnonymousAuthentication", "v1alpha1.KubeletWebhookAuthentication", "v1alpha1.KubeletX509Authentication"},
},
"v1alpha1.KubeletAuthorization": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"mode": {
SchemaProps: spec.SchemaProps{
Description: "mode is the authorization mode to apply to requests to the kubelet server. Valid values are AlwaysAllow and Webhook. Webhook mode uses the SubjectAccessReview API to determine authorization.",
Type: []string{"string"},
Format: "",
},
},
"webhook": {
SchemaProps: spec.SchemaProps{
Description: "webhook contains settings related to Webhook authorization.",
Ref: spec.MustCreateRef("#/definitions/v1alpha1.KubeletWebhookAuthorization"),
},
},
},
Required: []string{"mode", "webhook"},
},
},
Dependencies: []string{
"v1alpha1.KubeletWebhookAuthorization"},
},
"v1alpha1.KubeletConfiguration": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
@ -13790,6 +14006,18 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
Format: "",
},
},
"authentication": {
SchemaProps: spec.SchemaProps{
Description: "authentication specifies how requests to the Kubelet's server are authenticated",
Ref: spec.MustCreateRef("#/definitions/v1alpha1.KubeletAuthentication"),
},
},
"authorization": {
SchemaProps: spec.SchemaProps{
Description: "authorization specifies how requests to the Kubelet's server are authorized",
Ref: spec.MustCreateRef("#/definitions/v1alpha1.KubeletAuthorization"),
},
},
"hostnameOverride": {
SchemaProps: spec.SchemaProps{
Description: "hostnameOverride is the hostname used to identify the kubelet instead of the actual hostname.",
@ -14483,11 +14711,75 @@ var OpenAPIDefinitions *common.OpenAPIDefinitions = &common.OpenAPIDefinitions{
},
},
},
Required: []string{"TypeMeta", "podManifestPath", "syncFrequency", "fileCheckFrequency", "httpCheckFrequency", "manifestURL", "manifestURLHeader", "enableServer", "address", "port", "readOnlyPort", "tlsCertFile", "tlsPrivateKeyFile", "certDirectory", "hostnameOverride", "podInfraContainerImage", "dockerEndpoint", "rootDirectory", "seccompProfileRoot", "allowPrivileged", "hostNetworkSources", "hostPIDSources", "hostIPCSources", "registryPullQPS", "registryBurst", "eventRecordQPS", "eventBurst", "enableDebuggingHandlers", "minimumGCAge", "maxPerPodContainerCount", "maxContainerCount", "cAdvisorPort", "healthzPort", "healthzBindAddress", "oomScoreAdj", "registerNode", "clusterDomain", "masterServiceNamespace", "clusterDNS", "streamingConnectionIdleTimeout", "nodeStatusUpdateFrequency", "imageMinimumGCAge", "imageGCHighThresholdPercent", "imageGCLowThresholdPercent", "lowDiskSpaceThresholdMB", "volumeStatsAggPeriod", "networkPluginName", "networkPluginDir", "cniConfDir", "cniBinDir", "networkPluginMTU", "volumePluginDir", "cloudProvider", "cloudConfigFile", "kubeletCgroups", "runtimeCgroups", "systemCgroups", "cgroupRoot", "containerRuntime", "remoteRuntimeEndpoint", "remoteImageEndpoint", "runtimeRequestTimeout", "rktPath", "mounterPath", "rktAPIEndpoint", "rktStage1Image", "lockFilePath", "exitOnLockContention", "hairpinMode", "babysitDaemons", "maxPods", "nvidiaGPUs", "dockerExecHandlerName", "podCIDR", "resolvConf", "cpuCFSQuota", "containerized", "maxOpenFiles", "reconcileCIDR", "registerSchedulable", "contentType", "kubeAPIQPS", "kubeAPIBurst", "serializeImagePulls", "outOfDiskTransitionFrequency", "nodeIP", "nodeLabels", "nonMasqueradeCIDR", "enableCustomMetrics", "evictionHard", "evictionSoft", "evictionSoftGracePeriod", "evictionPressureTransitionPeriod", "evictionMaxPodGracePeriod", "evictionMinimumReclaim", "podsPerCore", "enableControllerAttachDetach", "systemReserved", "kubeReserved", "protectKernelDefaults", "makeIPTablesUtilChains", "iptablesMasqueradeBit", "iptablesDropBit"},
Required: []string{"TypeMeta", "podManifestPath", "syncFrequency", "fileCheckFrequency", "httpCheckFrequency", "manifestURL", "manifestURLHeader", "enableServer", "address", "port", "readOnlyPort", "tlsCertFile", "tlsPrivateKeyFile", "certDirectory", "authentication", "authorization", "hostnameOverride", "podInfraContainerImage", "dockerEndpoint", "rootDirectory", "seccompProfileRoot", "allowPrivileged", "hostNetworkSources", "hostPIDSources", "hostIPCSources", "registryPullQPS", "registryBurst", "eventRecordQPS", "eventBurst", "enableDebuggingHandlers", "minimumGCAge", "maxPerPodContainerCount", "maxContainerCount", "cAdvisorPort", "healthzPort", "healthzBindAddress", "oomScoreAdj", "registerNode", "clusterDomain", "masterServiceNamespace", "clusterDNS", "streamingConnectionIdleTimeout", "nodeStatusUpdateFrequency", "imageMinimumGCAge", "imageGCHighThresholdPercent", "imageGCLowThresholdPercent", "lowDiskSpaceThresholdMB", "volumeStatsAggPeriod", "networkPluginName", "networkPluginDir", "cniConfDir", "cniBinDir", "networkPluginMTU", "volumePluginDir", "cloudProvider", "cloudConfigFile", "kubeletCgroups", "runtimeCgroups", "systemCgroups", "cgroupRoot", "containerRuntime", "remoteRuntimeEndpoint", "remoteImageEndpoint", "runtimeRequestTimeout", "rktPath", "mounterPath", "rktAPIEndpoint", "rktStage1Image", "lockFilePath", "exitOnLockContention", "hairpinMode", "babysitDaemons", "maxPods", "nvidiaGPUs", "dockerExecHandlerName", "podCIDR", "resolvConf", "cpuCFSQuota", "containerized", "maxOpenFiles", "reconcileCIDR", "registerSchedulable", "contentType", "kubeAPIQPS", "kubeAPIBurst", "serializeImagePulls", "outOfDiskTransitionFrequency", "nodeIP", "nodeLabels", "nonMasqueradeCIDR", "enableCustomMetrics", "evictionHard", "evictionSoft", "evictionSoftGracePeriod", "evictionPressureTransitionPeriod", "evictionMaxPodGracePeriod", "evictionMinimumReclaim", "podsPerCore", "enableControllerAttachDetach", "systemReserved", "kubeReserved", "protectKernelDefaults", "makeIPTablesUtilChains", "iptablesMasqueradeBit", "iptablesDropBit"},
},
},
Dependencies: []string{
"unversioned.Duration", "unversioned.TypeMeta"},
"unversioned.Duration", "unversioned.TypeMeta", "v1alpha1.KubeletAuthentication", "v1alpha1.KubeletAuthorization"},
},
"v1alpha1.KubeletWebhookAuthentication": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"enabled": {
SchemaProps: spec.SchemaProps{
Description: "enabled allows bearer token authentication backed by the tokenreviews.authentication.k8s.io API",
Type: []string{"boolean"},
Format: "",
},
},
"cacheTTL": {
SchemaProps: spec.SchemaProps{
Description: "cacheTTL enables caching of authentication results",
Ref: spec.MustCreateRef("#/definitions/unversioned.Duration"),
},
},
},
Required: []string{"enabled", "cacheTTL"},
},
},
Dependencies: []string{
"unversioned.Duration"},
},
"v1alpha1.KubeletWebhookAuthorization": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"cacheAuthorizedTTL": {
SchemaProps: spec.SchemaProps{
Description: "cacheAuthorizedTTL is the duration to cache 'authorized' responses from the webhook authorizer.",
Ref: spec.MustCreateRef("#/definitions/unversioned.Duration"),
},
},
"cacheUnauthorizedTTL": {
SchemaProps: spec.SchemaProps{
Description: "cacheUnauthorizedTTL is the duration to cache 'unauthorized' responses from the webhook authorizer.",
Ref: spec.MustCreateRef("#/definitions/unversioned.Duration"),
},
},
},
Required: []string{"cacheAuthorizedTTL", "cacheUnauthorizedTTL"},
},
},
Dependencies: []string{
"unversioned.Duration"},
},
"v1alpha1.KubeletX509Authentication": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Properties: map[string]spec.Schema{
"clientCAFile": {
SchemaProps: spec.SchemaProps{
Description: "clientCAFile is the path to a PEM-encoded certificate bundle. If set, any request presenting a client certificate signed by one of the authorities in the bundle is authenticated with a username corresponding to the CommonName, and groups corresponding to the Organization in the client certificate.",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"clientCAFile"},
},
},
Dependencies: []string{},
},
"v1alpha1.LeaderElectionConfiguration": {
Schema: spec.Schema{

View File

@ -26,6 +26,7 @@ go_library(
"//pkg/api/validation:go_default_library",
"//pkg/auth/authenticator:go_default_library",
"//pkg/auth/authorizer:go_default_library",
"//pkg/auth/user:go_default_library",
"//pkg/healthz:go_default_library",
"//pkg/httplog:go_default_library",
"//pkg/kubelet/cm:go_default_library",
@ -50,7 +51,10 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["server_test.go"],
srcs = [
"auth_test.go",
"server_test.go",
],
library = "go_default_library",
tags = ["automanaged"],
deps = [

View File

@ -17,8 +17,14 @@ limitations under the License.
package server
import (
"net/http"
"strings"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/auth/authenticator"
"k8s.io/kubernetes/pkg/auth/authorizer"
"k8s.io/kubernetes/pkg/auth/user"
"k8s.io/kubernetes/pkg/types"
)
// KubeletAuth implements AuthInterface
@ -35,3 +41,74 @@ type KubeletAuth struct {
func NewKubeletAuth(authenticator authenticator.Request, authorizerAttributeGetter authorizer.RequestAttributesGetter, authorizer authorizer.Authorizer) AuthInterface {
return &KubeletAuth{authenticator, authorizerAttributeGetter, authorizer}
}
func NewNodeAuthorizerAttributesGetter(nodeName types.NodeName) authorizer.RequestAttributesGetter {
return nodeAuthorizerAttributesGetter{nodeName: nodeName}
}
type nodeAuthorizerAttributesGetter struct {
nodeName types.NodeName
}
func isSubpath(subpath, path string) bool {
path = strings.TrimSuffix(path, "/")
return subpath == path || (strings.HasPrefix(subpath, path) && subpath[len(path)] == '/')
}
// GetRequestAttributes populates authorizer attributes for the requests to the kubelet API.
// Default attributes are: {apiVersion=v1,verb=<http verb from request>,resource=nodes,name=<node name>,subresource=proxy}
// More specific verb/resource is set for the following request patterns:
// /stats/* => verb=<api verb from request>, resource=nodes, name=<node name>, subresource=stats
// /metrics/* => verb=<api verb from request>, resource=nodes, name=<node name>, subresource=metrics
// /logs/* => verb=<api verb from request>, resource=nodes, name=<node name>, subresource=log
// /spec/* => verb=<api verb from request>, resource=nodes, name=<node name>, subresource=spec
func (n nodeAuthorizerAttributesGetter) GetRequestAttributes(u user.Info, r *http.Request) authorizer.Attributes {
apiVerb := ""
switch r.Method {
case "POST":
apiVerb = "create"
case "GET":
apiVerb = "get"
case "PUT":
apiVerb = "update"
case "PATCH":
apiVerb = "patch"
case "DELETE":
apiVerb = "delete"
}
requestPath := r.URL.Path
// Default attributes mirror the API attributes that would allow this access to the kubelet API
attrs := authorizer.AttributesRecord{
User: u,
Verb: apiVerb,
Namespace: "",
APIGroup: "",
APIVersion: "v1",
Resource: "nodes",
Subresource: "proxy",
Name: string(n.nodeName),
ResourceRequest: true,
Path: requestPath,
}
// Override subresource for specific paths
// This allows subdividing access to the kubelet API
switch {
case isSubpath(requestPath, statsPath):
attrs.Subresource = "stats"
case isSubpath(requestPath, metricsPath):
attrs.Subresource = "metrics"
case isSubpath(requestPath, logsPath):
// "log" to match other log subresources (pods/log, etc)
attrs.Subresource = "log"
case isSubpath(requestPath, specPath):
attrs.Subresource = "spec"
}
glog.V(5).Infof("Node request attributes: attrs=%#v", attrs)
return attrs
}

View File

@ -0,0 +1,53 @@
/*
Copyright 2016 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 server
import "testing"
func TestIsSubPath(t *testing.T) {
testcases := map[string]struct {
subpath string
path string
expected bool
}{
"empty": {subpath: "", path: "", expected: true},
"match 1": {subpath: "foo", path: "foo", expected: true},
"match 2": {subpath: "/foo", path: "/foo", expected: true},
"match 3": {subpath: "/foo/", path: "/foo/", expected: true},
"match 4": {subpath: "/foo/bar", path: "/foo/bar", expected: true},
"subpath of root 1": {subpath: "/foo", path: "/", expected: true},
"subpath of root 2": {subpath: "/foo/", path: "/", expected: true},
"subpath of root 3": {subpath: "/foo/bar", path: "/", expected: true},
"subpath of path 1": {subpath: "/foo", path: "/foo", expected: true},
"subpath of path 2": {subpath: "/foo/", path: "/foo", expected: true},
"subpath of path 3": {subpath: "/foo/bar", path: "/foo", expected: true},
"mismatch 1": {subpath: "/foo", path: "/bar", expected: false},
"mismatch 2": {subpath: "/foo", path: "/foobar", expected: false},
"mismatch 3": {subpath: "/foobar", path: "/foo", expected: false},
}
for k, tc := range testcases {
result := isSubpath(tc.subpath, tc.path)
if result != tc.expected {
t.Errorf("%s: expected %v, got %v", k, tc.expected, result)
}
}
}

View File

@ -57,6 +57,13 @@ import (
"k8s.io/kubernetes/pkg/volume"
)
const (
metricsPath = "/metrics"
specPath = "/spec/"
statsPath = "/stats/"
logsPath = "/logs/"
)
// Server is a http.Handler which exposes kubelet functionality over HTTP.
type Server struct {
auth AuthInterface
@ -253,12 +260,12 @@ func (s *Server) InstallDefaultHandlers() {
Operation("getPods"))
s.restfulCont.Add(ws)
s.restfulCont.Add(stats.CreateHandlers(s.host, s.resourceAnalyzer))
s.restfulCont.Handle("/metrics", prometheus.Handler())
s.restfulCont.Add(stats.CreateHandlers(statsPath, s.host, s.resourceAnalyzer))
s.restfulCont.Handle(metricsPath, prometheus.Handler())
ws = new(restful.WebService)
ws.
Path("/spec/").
Path(specPath).
Produces(restful.MIME_JSON)
ws.Route(ws.GET("").
To(s.getSpec).
@ -331,7 +338,7 @@ func (s *Server) InstallDebuggingHandlers() {
ws = new(restful.WebService)
ws.
Path("/logs/")
Path(logsPath)
ws.Route(ws.GET("").
To(s.getLogs).
Operation("getLogs"))

View File

@ -605,10 +605,56 @@ func TestAuthFilters(t *testing.T) {
}
}
methodToAPIVerb := map[string]string{"GET": "get", "POST": "create", "PUT": "update"}
pathToSubresource := func(path string) string {
switch {
// Cases for subpaths we expect specific subresources for
case isSubpath(path, statsPath):
return "stats"
case isSubpath(path, specPath):
return "spec"
case isSubpath(path, logsPath):
return "log"
case isSubpath(path, metricsPath):
return "metrics"
// Cases for subpaths we expect to map to the "proxy" subresource
case isSubpath(path, "/attach"),
isSubpath(path, "/configz"),
isSubpath(path, "/containerLogs"),
isSubpath(path, "/debug"),
isSubpath(path, "/exec"),
isSubpath(path, "/healthz"),
isSubpath(path, "/pods"),
isSubpath(path, "/portForward"),
isSubpath(path, "/run"),
isSubpath(path, "/runningpods"):
return "proxy"
default:
panic(fmt.Errorf(`unexpected kubelet API path %s.
The kubelet API has likely registered a handler for a new path.
If the new path has a use case for partitioned authorization when requested from the kubelet API,
add a specific subresource for it in auth.go#GetRequestAttributes() and in TestAuthFilters().
Otherwise, add it to the expected list of paths that map to the "proxy" subresource in TestAuthFilters().`, path))
}
}
attributesGetter := NewNodeAuthorizerAttributesGetter(types.NodeName("test"))
for _, tc := range testcases {
var (
expectedUser = &user.DefaultInfo{Name: "test"}
expectedAttributes = &authorizer.AttributesRecord{User: expectedUser}
expectedAttributes = authorizer.AttributesRecord{
User: expectedUser,
APIGroup: "",
APIVersion: "v1",
Verb: methodToAPIVerb[tc.Method],
Resource: "nodes",
Name: "test",
Subresource: pathToSubresource(tc.Path),
ResourceRequest: true,
Path: tc.Path,
}
calledAuthenticate = false
calledAuthorize = false
@ -624,12 +670,12 @@ func TestAuthFilters(t *testing.T) {
if u != expectedUser {
t.Fatalf("%s: expected user %v, got %v", tc.Path, expectedUser, u)
}
return expectedAttributes
return attributesGetter.GetRequestAttributes(u, req)
}
fw.fakeAuth.authorizeFunc = func(a authorizer.Attributes) (authorized bool, reason string, err error) {
calledAuthorize = true
if a != expectedAttributes {
t.Fatalf("%s: expected attributes %v, got %v", tc.Path, expectedAttributes, a)
t.Fatalf("%s: expected attributes\n\t%#v\ngot\n\t%#v", tc.Path, expectedAttributes, a)
}
return false, "", nil
}

View File

@ -55,11 +55,11 @@ type handler struct {
summaryProvider SummaryProvider
}
func CreateHandlers(provider StatsProvider, summaryProvider SummaryProvider) *restful.WebService {
func CreateHandlers(rootPath string, provider StatsProvider, summaryProvider SummaryProvider) *restful.WebService {
h := &handler{provider, summaryProvider}
ws := &restful.WebService{}
ws.Path("/stats/").
ws.Path(rootPath).
Produces(restful.MIME_JSON)
endpoints := []struct {