mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 21:17:23 +00:00
Fix client-ca dynamic reload in apiserver
This commit is contained in:
parent
47daccb272
commit
b22a170d46
@ -13,7 +13,6 @@ go_library(
|
|||||||
"//cmd/kube-apiserver/app/options:go_default_library",
|
"//cmd/kube-apiserver/app/options:go_default_library",
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/capabilities:go_default_library",
|
"//pkg/capabilities:go_default_library",
|
||||||
"//pkg/controller/serviceaccount:go_default_library",
|
|
||||||
"//pkg/features:go_default_library",
|
"//pkg/features:go_default_library",
|
||||||
"//pkg/generated/openapi:go_default_library",
|
"//pkg/generated/openapi:go_default_library",
|
||||||
"//pkg/kubeapiserver:go_default_library",
|
"//pkg/kubeapiserver:go_default_library",
|
||||||
@ -29,7 +28,6 @@ go_library(
|
|||||||
"//pkg/registry/cachesize:go_default_library",
|
"//pkg/registry/cachesize:go_default_library",
|
||||||
"//pkg/registry/rbac/rest:go_default_library",
|
"//pkg/registry/rbac/rest:go_default_library",
|
||||||
"//pkg/serviceaccount:go_default_library",
|
"//pkg/serviceaccount:go_default_library",
|
||||||
"//plugin/pkg/auth/authenticator/token/bootstrap:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1:go_default_library",
|
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
|
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver:go_default_library",
|
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver:go_default_library",
|
||||||
@ -43,7 +41,6 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/features:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/features:go_default_library",
|
||||||
@ -76,12 +73,17 @@ go_library(
|
|||||||
"//staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1:go_default_library",
|
"//staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1:go_default_library",
|
"//staging/src/k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/kube-aggregator/pkg/controllers/autoregister:go_default_library",
|
"//staging/src/k8s.io/kube-aggregator/pkg/controllers/autoregister:go_default_library",
|
||||||
"//vendor/github.com/go-openapi/spec:go_default_library",
|
|
||||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "go_default_test",
|
||||||
|
srcs = ["server_test.go"],
|
||||||
|
embed = [":go_default_library"],
|
||||||
|
)
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "package-srcs",
|
name = "package-srcs",
|
||||||
srcs = glob(["**"]),
|
srcs = glob(["**"]),
|
||||||
@ -99,9 +101,3 @@ filegroup(
|
|||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
go_test(
|
|
||||||
name = "go_default_test",
|
|
||||||
srcs = ["server_test.go"],
|
|
||||||
embed = [":go_default_library"],
|
|
||||||
)
|
|
||||||
|
@ -30,17 +30,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-openapi/spec"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
extensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver"
|
extensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver"
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
utilwait "k8s.io/apimachinery/pkg/util/wait"
|
utilwait "k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
||||||
genericfeatures "k8s.io/apiserver/pkg/features"
|
genericfeatures "k8s.io/apiserver/pkg/features"
|
||||||
@ -70,7 +67,6 @@ import (
|
|||||||
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
"k8s.io/kubernetes/pkg/capabilities"
|
"k8s.io/kubernetes/pkg/capabilities"
|
||||||
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
|
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi"
|
generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi"
|
||||||
"k8s.io/kubernetes/pkg/kubeapiserver"
|
"k8s.io/kubernetes/pkg/kubeapiserver"
|
||||||
@ -85,7 +81,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/registry/cachesize"
|
"k8s.io/kubernetes/pkg/registry/cachesize"
|
||||||
rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest"
|
rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest"
|
||||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||||
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -440,9 +435,6 @@ func buildGenericConfig(
|
|||||||
if lastErr = s.SecureServing.ApplyTo(&genericConfig.SecureServing, &genericConfig.LoopbackClientConfig); lastErr != nil {
|
if lastErr = s.SecureServing.ApplyTo(&genericConfig.SecureServing, &genericConfig.LoopbackClientConfig); lastErr != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if lastErr = s.Authentication.ApplyTo(genericConfig); lastErr != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if lastErr = s.Features.ApplyTo(genericConfig); lastErr != nil {
|
if lastErr = s.Features.ApplyTo(genericConfig); lastErr != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -498,9 +490,8 @@ func buildGenericConfig(
|
|||||||
}
|
}
|
||||||
versionedInformers = clientgoinformers.NewSharedInformerFactory(clientgoExternalClient, 10*time.Minute)
|
versionedInformers = clientgoinformers.NewSharedInformerFactory(clientgoExternalClient, 10*time.Minute)
|
||||||
|
|
||||||
genericConfig.Authentication.Authenticator, genericConfig.OpenAPIConfig.SecurityDefinitions, err = BuildAuthenticator(s, genericConfig.EgressSelector, clientgoExternalClient, versionedInformers)
|
// Authentication.ApplyTo requires already applied OpenAPIConfig and EgressSelector if present
|
||||||
if err != nil {
|
if lastErr = s.Authentication.ApplyTo(&genericConfig.Authentication, genericConfig.SecureServing, genericConfig.EgressSelector, genericConfig.OpenAPIConfig, clientgoExternalClient, versionedInformers); lastErr != nil {
|
||||||
lastErr = fmt.Errorf("invalid authentication config: %v", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,35 +550,6 @@ func buildGenericConfig(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildAuthenticator constructs the authenticator
|
|
||||||
func BuildAuthenticator(s *options.ServerRunOptions, EgressSelector *egressselector.EgressSelector, extclient clientgoclientset.Interface, versionedInformer clientgoinformers.SharedInformerFactory) (authenticator.Request, *spec.SecurityDefinitions, error) {
|
|
||||||
authenticatorConfig, err := s.Authentication.ToAuthenticationConfig()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
if s.Authentication.ServiceAccounts.Lookup || utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) {
|
|
||||||
authenticatorConfig.ServiceAccountTokenGetter = serviceaccountcontroller.NewGetterFromClient(
|
|
||||||
extclient,
|
|
||||||
versionedInformer.Core().V1().Secrets().Lister(),
|
|
||||||
versionedInformer.Core().V1().ServiceAccounts().Lister(),
|
|
||||||
versionedInformer.Core().V1().Pods().Lister(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
authenticatorConfig.BootstrapTokenAuthenticator = bootstrap.NewTokenAuthenticator(
|
|
||||||
versionedInformer.Core().V1().Secrets().Lister().Secrets(v1.NamespaceSystem),
|
|
||||||
)
|
|
||||||
|
|
||||||
if EgressSelector != nil {
|
|
||||||
egressDialer, err := EgressSelector.Lookup(egressselector.Master.AsNetworkContext())
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
authenticatorConfig.CustomDial = egressDialer
|
|
||||||
}
|
|
||||||
|
|
||||||
return authenticatorConfig.New()
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildAuthorizer constructs the authorizer
|
// BuildAuthorizer constructs the authorizer
|
||||||
func BuildAuthorizer(s *options.ServerRunOptions, EgressSelector *egressselector.EgressSelector, versionedInformers clientgoinformers.SharedInformerFactory) (authorizer.Authorizer, authorizer.RuleResolver, error) {
|
func BuildAuthorizer(s *options.ServerRunOptions, EgressSelector *egressselector.EgressSelector, versionedInformers clientgoinformers.SharedInformerFactory) (authorizer.Authorizer, authorizer.RuleResolver, error) {
|
||||||
authorizationConfig := s.Authorization.ToAuthorizationConfig(versionedInformers)
|
authorizationConfig := s.Authorization.ToAuthorizationConfig(versionedInformers)
|
||||||
|
@ -36,7 +36,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// BuildAuth creates an authenticator, an authorizer, and a matching authorizer attributes getter compatible with the kubelet's needs
|
// BuildAuth creates an authenticator, an authorizer, and a matching authorizer attributes getter compatible with the kubelet's needs
|
||||||
func BuildAuth(nodeName types.NodeName, client clientset.Interface, config kubeletconfig.KubeletConfiguration) (server.AuthInterface, error) {
|
// It returns AuthInterface, a run method to start internal controllers (like cert reloading) and error.
|
||||||
|
func BuildAuth(nodeName types.NodeName, client clientset.Interface, config kubeletconfig.KubeletConfiguration) (server.AuthInterface, func(<-chan struct{}), error) {
|
||||||
// Get clients, if provided
|
// Get clients, if provided
|
||||||
var (
|
var (
|
||||||
tokenClient authenticationclient.TokenReviewInterface
|
tokenClient authenticationclient.TokenReviewInterface
|
||||||
@ -47,47 +48,55 @@ func BuildAuth(nodeName types.NodeName, client clientset.Interface, config kubel
|
|||||||
sarClient = client.AuthorizationV1().SubjectAccessReviews()
|
sarClient = client.AuthorizationV1().SubjectAccessReviews()
|
||||||
}
|
}
|
||||||
|
|
||||||
authenticator, err := BuildAuthn(tokenClient, config.Authentication)
|
authenticator, runAuthenticatorCAReload, err := BuildAuthn(tokenClient, config.Authentication)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes := server.NewNodeAuthorizerAttributesGetter(nodeName)
|
attributes := server.NewNodeAuthorizerAttributesGetter(nodeName)
|
||||||
|
|
||||||
authorizer, err := BuildAuthz(sarClient, config.Authorization)
|
authorizer, err := BuildAuthz(sarClient, config.Authorization)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return server.NewKubeletAuth(authenticator, attributes, authorizer), nil
|
return server.NewKubeletAuth(authenticator, attributes, authorizer), runAuthenticatorCAReload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildAuthn creates an authenticator compatible with the kubelet's needs
|
// BuildAuthn creates an authenticator compatible with the kubelet's needs
|
||||||
func BuildAuthn(client authenticationclient.TokenReviewInterface, authn kubeletconfig.KubeletAuthentication) (authenticator.Request, error) {
|
func BuildAuthn(client authenticationclient.TokenReviewInterface, authn kubeletconfig.KubeletAuthentication) (authenticator.Request, func(<-chan struct{}), error) {
|
||||||
var clientCertificateCAContentProvider authenticatorfactory.CAContentProvider
|
var dynamicCAContentFromFile *dynamiccertificates.DynamicFileCAContent
|
||||||
var err error
|
var err error
|
||||||
if len(authn.X509.ClientCAFile) > 0 {
|
if len(authn.X509.ClientCAFile) > 0 {
|
||||||
clientCertificateCAContentProvider, err = dynamiccertificates.NewDynamicCAContentFromFile("client-ca-bundle", authn.X509.ClientCAFile)
|
dynamicCAContentFromFile, err = dynamiccertificates.NewDynamicCAContentFromFile("client-ca-bundle", authn.X509.ClientCAFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
authenticatorConfig := authenticatorfactory.DelegatingAuthenticatorConfig{
|
authenticatorConfig := authenticatorfactory.DelegatingAuthenticatorConfig{
|
||||||
Anonymous: authn.Anonymous.Enabled,
|
Anonymous: authn.Anonymous.Enabled,
|
||||||
CacheTTL: authn.Webhook.CacheTTL.Duration,
|
CacheTTL: authn.Webhook.CacheTTL.Duration,
|
||||||
ClientCertificateCAContentProvider: clientCertificateCAContentProvider,
|
ClientCertificateCAContentProvider: dynamicCAContentFromFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
if authn.Webhook.Enabled {
|
if authn.Webhook.Enabled {
|
||||||
if client == nil {
|
if client == nil {
|
||||||
return nil, errors.New("no client provided, cannot use webhook authentication")
|
return nil, nil, errors.New("no client provided, cannot use webhook authentication")
|
||||||
}
|
}
|
||||||
authenticatorConfig.TokenAccessReviewClient = client
|
authenticatorConfig.TokenAccessReviewClient = client
|
||||||
}
|
}
|
||||||
|
|
||||||
authenticator, _, err := authenticatorConfig.New()
|
authenticator, _, err := authenticatorConfig.New()
|
||||||
return authenticator, err
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return authenticator, func(stopCh <-chan struct{}) {
|
||||||
|
if dynamicCAContentFromFile != nil {
|
||||||
|
go dynamicCAContentFromFile.Run(1, stopCh)
|
||||||
|
}
|
||||||
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildAuthz creates an authorizer compatible with the kubelet's needs
|
// BuildAuthz creates an authorizer compatible with the kubelet's needs
|
||||||
|
@ -599,11 +599,12 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, featureGate f
|
|||||||
}
|
}
|
||||||
|
|
||||||
if kubeDeps.Auth == nil {
|
if kubeDeps.Auth == nil {
|
||||||
auth, err := BuildAuth(nodeName, kubeDeps.KubeClient, s.KubeletConfiguration)
|
auth, runAuthenticatorCAReload, err := BuildAuth(nodeName, kubeDeps.KubeClient, s.KubeletConfiguration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
kubeDeps.Auth = auth
|
kubeDeps.Auth = auth
|
||||||
|
runAuthenticatorCAReload(stopCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cgroupRoots []string
|
var cgroupRoots []string
|
||||||
|
@ -14,6 +14,7 @@ go_library(
|
|||||||
importpath = "k8s.io/kubernetes/pkg/kubeapiserver/options",
|
importpath = "k8s.io/kubernetes/pkg/kubeapiserver/options",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//pkg/controller/serviceaccount:go_default_library",
|
||||||
"//pkg/features:go_default_library",
|
"//pkg/features:go_default_library",
|
||||||
"//pkg/kubeapiserver/authenticator:go_default_library",
|
"//pkg/kubeapiserver/authenticator:go_default_library",
|
||||||
"//pkg/kubeapiserver/authorizer:go_default_library",
|
"//pkg/kubeapiserver/authorizer:go_default_library",
|
||||||
@ -50,6 +51,8 @@ go_library(
|
|||||||
"//plugin/pkg/admission/storage/persistentvolume/resize:go_default_library",
|
"//plugin/pkg/admission/storage/persistentvolume/resize:go_default_library",
|
||||||
"//plugin/pkg/admission/storage/storageclass/setdefault:go_default_library",
|
"//plugin/pkg/admission/storage/storageclass/setdefault:go_default_library",
|
||||||
"//plugin/pkg/admission/storage/storageobjectinuseprotection:go_default_library",
|
"//plugin/pkg/admission/storage/storageobjectinuseprotection:go_default_library",
|
||||||
|
"//plugin/pkg/auth/authenticator/token/bootstrap:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||||
@ -58,14 +61,17 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/server:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/server:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apiserver/pkg/server/egressselector:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/server/options:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/server/options:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||||
|
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/cli/flag:go_default_library",
|
"//staging/src/k8s.io/component-base/cli/flag:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/featuregate:go_default_library",
|
"//staging/src/k8s.io/component-base/featuregate:go_default_library",
|
||||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/kube-openapi/pkg/common:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,17 +24,24 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"k8s.io/klog"
|
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"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"
|
||||||
|
"k8s.io/apiserver/pkg/server/egressselector"
|
||||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
"k8s.io/client-go/informers"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
|
"k8s.io/klog"
|
||||||
|
openapicommon "k8s.io/kube-openapi/pkg/common"
|
||||||
|
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
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"
|
||||||
|
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BuiltInAuthenticationOptions struct {
|
type BuiltInAuthenticationOptions struct {
|
||||||
@ -406,35 +413,60 @@ func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() (kubeauthenticat
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *BuiltInAuthenticationOptions) ApplyTo(c *genericapiserver.Config) error {
|
// ApplyTo requires already applied OpenAPIConfig and EgressSelector if present.
|
||||||
|
func (o *BuiltInAuthenticationOptions) ApplyTo(authInfo *genericapiserver.AuthenticationInfo, secureServing *genericapiserver.SecureServingInfo, egressSelector *egressselector.EgressSelector, openAPIConfig *openapicommon.Config, extclient kubernetes.Interface, versionedInformer informers.SharedInformerFactory) error {
|
||||||
if o == nil {
|
if o == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.ClientCert != nil {
|
if openAPIConfig == nil {
|
||||||
clientCertificateCAContentProvider, err := o.ClientCert.GetClientCAContentProvider()
|
return errors.New("uninitialized OpenAPIConfig")
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticatorConfig, err := o.ToAuthenticationConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to load client CA file: %v", err)
|
return err
|
||||||
}
|
}
|
||||||
if err = c.Authentication.ApplyClientCert(clientCertificateCAContentProvider, c.SecureServing); err != nil {
|
|
||||||
|
if authenticatorConfig.ClientCAContentProvider != nil {
|
||||||
|
if err = authInfo.ApplyClientCert(authenticatorConfig.ClientCAContentProvider, secureServing); err != nil {
|
||||||
return fmt.Errorf("unable to load client CA file: %v", err)
|
return fmt.Errorf("unable to load client CA file: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if o.RequestHeader != nil {
|
if authenticatorConfig.RequestHeaderConfig != nil && authenticatorConfig.RequestHeaderConfig.CAContentProvider != nil {
|
||||||
requestHeaderConfig, err := o.RequestHeader.ToAuthenticationRequestHeaderConfig()
|
if err = authInfo.ApplyClientCert(authenticatorConfig.RequestHeaderConfig.CAContentProvider, secureServing); err != nil {
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to create request header authentication config: %v", err)
|
|
||||||
}
|
|
||||||
if requestHeaderConfig != nil {
|
|
||||||
if err = c.Authentication.ApplyClientCert(requestHeaderConfig.CAContentProvider, c.SecureServing); err != nil {
|
|
||||||
return fmt.Errorf("unable to load client CA file: %v", err)
|
return fmt.Errorf("unable to load client CA file: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
c.Authentication.APIAudiences = o.APIAudiences
|
authInfo.APIAudiences = o.APIAudiences
|
||||||
if o.ServiceAccounts != nil && o.ServiceAccounts.Issuer != "" && len(o.APIAudiences) == 0 {
|
if o.ServiceAccounts != nil && o.ServiceAccounts.Issuer != "" && len(o.APIAudiences) == 0 {
|
||||||
c.Authentication.APIAudiences = authenticator.Audiences{o.ServiceAccounts.Issuer}
|
authInfo.APIAudiences = authenticator.Audiences{o.ServiceAccounts.Issuer}
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.ServiceAccounts.Lookup || utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) {
|
||||||
|
authenticatorConfig.ServiceAccountTokenGetter = serviceaccountcontroller.NewGetterFromClient(
|
||||||
|
extclient,
|
||||||
|
versionedInformer.Core().V1().Secrets().Lister(),
|
||||||
|
versionedInformer.Core().V1().ServiceAccounts().Lister(),
|
||||||
|
versionedInformer.Core().V1().Pods().Lister(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
authenticatorConfig.BootstrapTokenAuthenticator = bootstrap.NewTokenAuthenticator(
|
||||||
|
versionedInformer.Core().V1().Secrets().Lister().Secrets(metav1.NamespaceSystem),
|
||||||
|
)
|
||||||
|
|
||||||
|
if egressSelector != nil {
|
||||||
|
egressDialer, err := egressSelector.Lookup(egressselector.Master.AsNetworkContext())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
authenticatorConfig.CustomDial = egressDialer
|
||||||
|
}
|
||||||
|
|
||||||
|
authInfo.Authenticator, openAPIConfig.SecurityDefinitions, err = authenticatorConfig.New()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -9,11 +9,14 @@ go_test(
|
|||||||
tags = ["integration"],
|
tags = ["integration"],
|
||||||
deps = [
|
deps = [
|
||||||
"//cmd/kube-apiserver/app/options:go_default_library",
|
"//cmd/kube-apiserver/app/options:go_default_library",
|
||||||
|
"//staging/src/k8s.io/api/authorization/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/server/dynamiccertificates:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/server/dynamiccertificates:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
|
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
||||||
|
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/util/cert:go_default_library",
|
"//staging/src/k8s.io/client-go/util/cert:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/cli/flag:go_default_library",
|
"//staging/src/k8s.io/component-base/cli/flag:go_default_library",
|
||||||
"//test/integration/framework:go_default_library",
|
"//test/integration/framework:go_default_library",
|
||||||
|
@ -19,63 +19,150 @@ package podlogs
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math/big"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
authorizationv1 "k8s.io/api/authorization/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apiserver/pkg/server/dynamiccertificates"
|
"k8s.io/apiserver/pkg/server/dynamiccertificates"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/util/cert"
|
"k8s.io/client-go/util/cert"
|
||||||
"k8s.io/component-base/cli/flag"
|
"k8s.io/component-base/cli/flag"
|
||||||
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
||||||
"k8s.io/kubernetes/test/integration/framework"
|
"k8s.io/kubernetes/test/integration/framework"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type caWithClient struct {
|
||||||
|
CACert []byte
|
||||||
|
ClientCert []byte
|
||||||
|
ClientKey []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTestCAWithClient(caSubject pkix.Name, caSerial *big.Int, clientSubject pkix.Name, subjectSerial *big.Int) (*caWithClient, error) {
|
||||||
|
ca := &x509.Certificate{
|
||||||
|
SerialNumber: caSerial,
|
||||||
|
Subject: caSubject,
|
||||||
|
NotBefore: time.Now(),
|
||||||
|
NotAfter: time.Now().Add(24 * time.Hour),
|
||||||
|
IsCA: true,
|
||||||
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||||
|
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
caPrivateKey, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivateKey.PublicKey, caPrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
caPEM := new(bytes.Buffer)
|
||||||
|
err = pem.Encode(caPEM, &pem.Block{
|
||||||
|
Type: "CERTIFICATE",
|
||||||
|
Bytes: caBytes,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
clientCert := &x509.Certificate{
|
||||||
|
SerialNumber: subjectSerial,
|
||||||
|
Subject: clientSubject,
|
||||||
|
NotBefore: time.Now(),
|
||||||
|
NotAfter: time.Now().Add(24 * time.Hour),
|
||||||
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||||
|
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||||
|
}
|
||||||
|
|
||||||
|
clientCertPrivateKey, err := rsa.GenerateKey(rand.Reader, 4096)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
clientCertPrivateKeyPEM := new(bytes.Buffer)
|
||||||
|
err = pem.Encode(clientCertPrivateKeyPEM, &pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: x509.MarshalPKCS1PrivateKey(clientCertPrivateKey),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
clientCertBytes, err := x509.CreateCertificate(rand.Reader, clientCert, ca, &clientCertPrivateKey.PublicKey, caPrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
clientCertPEM := new(bytes.Buffer)
|
||||||
|
err = pem.Encode(clientCertPEM, &pem.Block{
|
||||||
|
Type: "CERTIFICATE",
|
||||||
|
Bytes: clientCertBytes,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &caWithClient{
|
||||||
|
CACert: caPEM.Bytes(),
|
||||||
|
ClientCert: clientCertPEM.Bytes(),
|
||||||
|
ClientKey: clientCertPrivateKeyPEM.Bytes(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestClientCA(t *testing.T) {
|
func TestClientCA(t *testing.T) {
|
||||||
stopCh := make(chan struct{})
|
stopCh := make(chan struct{})
|
||||||
defer close(stopCh)
|
defer close(stopCh)
|
||||||
|
|
||||||
// I have no idea what this cert is, but it doesn't matter, we just want something that always fails validation
|
frontProxyCA, err := newTestCAWithClient(
|
||||||
differentClientCA := []byte(`-----BEGIN CERTIFICATE-----
|
pkix.Name{
|
||||||
MIIDQDCCAiigAwIBAgIJANWw74P5KJk2MA0GCSqGSIb3DQEBCwUAMDQxMjAwBgNV
|
CommonName: "test-front-proxy-ca",
|
||||||
BAMMKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX
|
},
|
||||||
DTE3MTExNjAwMDUzOVoYDzIyOTEwOTAxMDAwNTM5WjAjMSEwHwYDVQQDExh3ZWJo
|
big.NewInt(43),
|
||||||
b29rLXRlc3QuZGVmYXVsdC5zdmMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
pkix.Name{
|
||||||
AoIBAQDXd/nQ89a5H8ifEsigmMd01Ib6NVR3bkJjtkvYnTbdfYEBj7UzqOQtHoLa
|
CommonName: "test-aggregated-apiserver",
|
||||||
dIVmefny5uIHvj93WD8WDVPB3jX2JHrXkDTXd/6o6jIXHcsUfFTVLp6/bZ+Anqe0
|
Organization: []string{"system:masters"},
|
||||||
r/7hAPkzA2A7APyTWM3ZbEeo1afXogXhOJ1u/wz0DflgcB21gNho4kKTONXO3NHD
|
},
|
||||||
XLpspFqSkxfEfKVDJaYAoMnYZJtFNsa2OvsmLnhYF8bjeT3i07lfwrhUZvP+7Gsp
|
big.NewInt(86),
|
||||||
7UgUwc06WuNHjfx1s5e6ySzH0QioMD1rjYneqOvk0pKrMIhuAEWXqq7jlXcDtx1E
|
)
|
||||||
j+wnYbVqqVYheHZ8BCJoVAAQGs9/AgMBAAGjZDBiMAkGA1UdEwQCMAAwCwYDVR0P
|
if err != nil {
|
||||||
BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATApBgNVHREEIjAg
|
t.Error(err)
|
||||||
hwR/AAABghh3ZWJob29rLXRlc3QuZGVmYXVsdC5zdmMwDQYJKoZIhvcNAQELBQAD
|
return
|
||||||
ggEBAD/GKSPNyQuAOw/jsYZesb+RMedbkzs18sSwlxAJQMUrrXwlVdHrA8q5WhE6
|
}
|
||||||
ABLqU1b8lQ8AWun07R8k5tqTmNvCARrAPRUqls/ryER+3Y9YEcxEaTc3jKNZFLbc
|
|
||||||
T6YtcnkdhxsiO136wtiuatpYL91RgCmuSpR8+7jEHhuFU01iaASu7ypFrUzrKHTF
|
clientCA, err := newTestCAWithClient(
|
||||||
bKwiLRQi1cMzVcLErq5CDEKiKhUkoDucyARFszrGt9vNIl/YCcBOkcNvM3c05Hn3
|
pkix.Name{
|
||||||
M++C29JwS3Hwbubg6WO3wjFjoEhpCwU6qRYUz3MRp4tHO4kxKXx+oQnUiFnR7vW0
|
CommonName: "test-client-ca",
|
||||||
YkNtGc1RUDHwecCTFpJtPb7Yu/E=
|
},
|
||||||
-----END CERTIFICATE-----
|
big.NewInt(42),
|
||||||
`)
|
pkix.Name{
|
||||||
differentFrontProxyCA := []byte(`-----BEGIN CERTIFICATE-----
|
CommonName: "system:admin",
|
||||||
MIIBqDCCAU2gAwIBAgIUfbqeieihh/oERbfvRm38XvS/xHAwCgYIKoZIzj0EAwIw
|
Organization: []string{"system:masters"},
|
||||||
GjEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlLUNBMCAXDTE2MTAxMTA1MDYwMFoYDzIx
|
},
|
||||||
MTYwOTE3MDUwNjAwWjAUMRIwEAYDVQQDEwlNeSBDbGllbnQwWTATBgcqhkjOPQIB
|
big.NewInt(84),
|
||||||
BggqhkjOPQMBBwNCAARv6N4R/sjMR65iMFGNLN1GC/vd7WhDW6J4X/iAjkRLLnNb
|
)
|
||||||
KbRG/AtOUZ+7upJ3BWIRKYbOabbQGQe2BbKFiap4o3UwczAOBgNVHQ8BAf8EBAMC
|
if err != nil {
|
||||||
BaAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU
|
t.Error(err)
|
||||||
K/pZOWpNcYai6eHFpmJEeFpeQlEwHwYDVR0jBBgwFoAUX6nQlxjfWnP6aM1meO/Q
|
return
|
||||||
a6b3a9kwCgYIKoZIzj0EAwIDSQAwRgIhAIWTKw/sjJITqeuNzJDAKU4xo1zL+xJ5
|
}
|
||||||
MnVCuBwfwDXCAiEAw/1TA+CjPq9JC5ek1ifR0FybTURjeQqYkKpve1dveps=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
|
|
||||||
`)
|
|
||||||
clientCAFilename := ""
|
clientCAFilename := ""
|
||||||
frontProxyCAFilename := ""
|
frontProxyCAFilename := ""
|
||||||
|
|
||||||
@ -84,12 +171,13 @@ MnVCuBwfwDXCAiEAw/1TA+CjPq9JC5ek1ifR0FybTURjeQqYkKpve1dveps=
|
|||||||
opts.GenericServerRunOptions.MaxRequestBodyBytes = 1024 * 1024
|
opts.GenericServerRunOptions.MaxRequestBodyBytes = 1024 * 1024
|
||||||
clientCAFilename = opts.Authentication.ClientCert.ClientCA
|
clientCAFilename = opts.Authentication.ClientCert.ClientCA
|
||||||
frontProxyCAFilename = opts.Authentication.RequestHeader.ClientCAFile
|
frontProxyCAFilename = opts.Authentication.RequestHeader.ClientCAFile
|
||||||
|
opts.Authentication.RequestHeader.AllowedNames = append(opts.Authentication.RequestHeader.AllowedNames, "test-aggregated-apiserver")
|
||||||
dynamiccertificates.FileRefreshDuration = 1 * time.Second
|
dynamiccertificates.FileRefreshDuration = 1 * time.Second
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// wait for request header info
|
// wait for request header info
|
||||||
err := wait.PollImmediate(100*time.Millisecond, 30*time.Second, waitForConfigMapCAContent(t, kubeClient, "requestheader-client-ca-file", "-----BEGIN CERTIFICATE-----", 1))
|
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, waitForConfigMapCAContent(t, kubeClient, "requestheader-client-ca-file", "-----BEGIN CERTIFICATE-----", 1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -100,10 +188,10 @@ MnVCuBwfwDXCAiEAw/1TA+CjPq9JC5ek1ifR0FybTURjeQqYkKpve1dveps=
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when we run this the second time, we know which one we are expecting
|
// when we run this the second time, we know which one we are expecting
|
||||||
if err := ioutil.WriteFile(clientCAFilename, differentClientCA, 0644); err != nil {
|
if err := ioutil.WriteFile(clientCAFilename, clientCA.CACert, 0644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(frontProxyCAFilename, differentFrontProxyCA, 0644); err != nil {
|
if err := ioutil.WriteFile(frontProxyCAFilename, frontProxyCA.CACert, 0644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +202,7 @@ MnVCuBwfwDXCAiEAw/1TA+CjPq9JC5ek1ifR0FybTURjeQqYkKpve1dveps=
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedCAs := []string{"webhook-test.default.svc", "My Client"}
|
expectedCAs := []string{"test-client-ca", "test-front-proxy-ca"}
|
||||||
if len(expectedCAs) != len(acceptableCAs) {
|
if len(expectedCAs) != len(acceptableCAs) {
|
||||||
t.Fatal(strings.Join(acceptableCAs, ":"))
|
t.Fatal(strings.Join(acceptableCAs, ":"))
|
||||||
}
|
}
|
||||||
@ -129,7 +217,7 @@ MnVCuBwfwDXCAiEAw/1TA+CjPq9JC5ek1ifR0FybTURjeQqYkKpve1dveps=
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, waitForConfigMapCAContent(t, kubeClient, "requestheader-client-ca-file", "MnVCuBwfwDXCAiEAw/1TA+CjPq9JC5ek1ifR0FybTURjeQqYkKpve1dveps=", 1))
|
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, waitForConfigMapCAContent(t, kubeClient, "requestheader-client-ca-file", string(frontProxyCA.CACert), 1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -138,7 +226,68 @@ MnVCuBwfwDXCAiEAw/1TA+CjPq9JC5ek1ifR0FybTURjeQqYkKpve1dveps=
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, waitForConfigMapCAContent(t, kubeClient, "client-ca-file", "M++C29JwS3Hwbubg6WO3wjFjoEhpCwU6qRYUz3MRp4tHO4kxKXx+oQnUiFnR7vW0", 1))
|
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, waitForConfigMapCAContent(t, kubeClient, "client-ca-file", string(clientCA.CACert), 1))
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test an aggregated apiserver client (signed by the new front proxy CA) is authorized
|
||||||
|
extensionApiserverClient, err := kubernetes.NewForConfig(&rest.Config{
|
||||||
|
Host: kubeconfig.Host,
|
||||||
|
TLSClientConfig: rest.TLSClientConfig{
|
||||||
|
CAData: kubeconfig.TLSClientConfig.CAData,
|
||||||
|
CAFile: kubeconfig.TLSClientConfig.CAFile,
|
||||||
|
ServerName: kubeconfig.TLSClientConfig.ServerName,
|
||||||
|
KeyData: frontProxyCA.ClientKey,
|
||||||
|
CertData: frontProxyCA.ClientCert,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call an endpoint to make sure we are authenticated
|
||||||
|
err = extensionApiserverClient.AuthorizationV1().RESTClient().
|
||||||
|
Post().
|
||||||
|
Resource("subjectaccessreviews").
|
||||||
|
VersionedParams(&metav1.CreateOptions{}, scheme.ParameterCodec).
|
||||||
|
Body(&authorizationv1.SubjectAccessReview{
|
||||||
|
Spec: authorizationv1.SubjectAccessReviewSpec{
|
||||||
|
ResourceAttributes: &authorizationv1.ResourceAttributes{
|
||||||
|
Verb: "create",
|
||||||
|
Resource: "pods",
|
||||||
|
Namespace: "default",
|
||||||
|
},
|
||||||
|
User: "deads2k",
|
||||||
|
},
|
||||||
|
}).
|
||||||
|
SetHeader("X-Remote-User", "test-aggregated-apiserver").
|
||||||
|
SetHeader("X-Remote-Group", "system:masters").
|
||||||
|
Do(context.Background()).
|
||||||
|
Into(&authorizationv1.SubjectAccessReview{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test a client signed by the new ClientCA is authorized
|
||||||
|
testClient, err := kubernetes.NewForConfig(&rest.Config{
|
||||||
|
Host: kubeconfig.Host,
|
||||||
|
TLSClientConfig: rest.TLSClientConfig{
|
||||||
|
CAData: kubeconfig.TLSClientConfig.CAData,
|
||||||
|
CAFile: kubeconfig.TLSClientConfig.CAFile,
|
||||||
|
ServerName: kubeconfig.TLSClientConfig.ServerName,
|
||||||
|
KeyData: clientCA.ClientKey,
|
||||||
|
CertData: clientCA.ClientCert,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call an endpoint to make sure we are authenticated
|
||||||
|
_, err = testClient.CoreV1().Nodes().List(context.Background(), metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user