split TokenRequest initialization out of run and into complete and validate

pull/58/head
Mike Danese 2018-11-12 16:27:37 -08:00
parent 766aab509a
commit 06935e1c90
6 changed files with 68 additions and 57 deletions

View File

@ -14,7 +14,6 @@ go_library(
"//pkg/api/legacyscheme:go_default_library",
"//pkg/capabilities:go_default_library",
"//pkg/controller/serviceaccount:go_default_library",
"//pkg/features:go_default_library",
"//pkg/generated/openapi:go_default_library",
"//pkg/kubeapiserver:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",

View File

@ -21,10 +21,12 @@ go_library(
"//pkg/kubelet/client:go_default_library",
"//pkg/master/ports:go_default_library",
"//pkg/master/reconcilers:go_default_library",
"//pkg/serviceaccount:go_default_library",
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/server/options:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/storagebackend:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/flag:go_default_library",
"//staging/src/k8s.io/kube-aggregator/pkg/apiserver/scheme:go_default_library",
],

View File

@ -27,13 +27,12 @@ import (
"k8s.io/apiserver/pkg/storage/storagebackend"
apiserverflag "k8s.io/apiserver/pkg/util/flag"
api "k8s.io/kubernetes/pkg/apis/core"
_ "k8s.io/kubernetes/pkg/features" // add the kubernetes feature gates
kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
"k8s.io/kubernetes/pkg/master/ports"
"k8s.io/kubernetes/pkg/master/reconcilers"
// add the kubernetes feature gates
_ "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/serviceaccount"
)
// ServerRunOptions runs a kubernetes api server.
@ -70,7 +69,9 @@ type ServerRunOptions struct {
MasterCount int
EndpointReconcilerType string
ServiceAccountSigningKeyFile string
ServiceAccountSigningKeyFile string
ServiceAccountIssuer serviceaccount.TokenGenerator
ServiceAccountTokenMaxExpiration time.Duration
}
// NewServerRunOptions creates a new ServerRunOptions object with default parameters

View File

@ -20,8 +20,10 @@ import (
"fmt"
apiextensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver"
utilfeature "k8s.io/apiserver/pkg/util/feature"
aggregatorscheme "k8s.io/kube-aggregator/pkg/apiserver/scheme"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/features"
)
// TODO: Longer term we should read this from some config store, rather than a flag.
@ -49,6 +51,34 @@ func validateServiceNodePort(options *ServerRunOptions) []error {
return errors
}
func validateTokenRequest(options *ServerRunOptions) []error {
errors := []error{}
enableAttempted := options.ServiceAccountSigningKeyFile != "" ||
options.Authentication.ServiceAccounts.Issuer != "" ||
len(options.Authentication.APIAudiences) != 0
enableSucceeded := options.ServiceAccountIssuer != nil
if enableAttempted && !utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) {
errors = append(errors, fmt.Errorf("the TokenRequest feature is not enabled but --service-account-signing-key-file, --service-account-issuer and/or --api-audiences flags were passed"))
}
if utilfeature.DefaultFeatureGate.Enabled(features.BoundServiceAccountTokenVolume) && !utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) {
errors = append(errors, fmt.Errorf("the BoundServiceAccountTokenVolume feature depends on the TokenRequest feature, but the TokenRequest features is not enabled"))
}
if !enableAttempted && utilfeature.DefaultFeatureGate.Enabled(features.BoundServiceAccountTokenVolume) {
errors = append(errors, fmt.Errorf("--service-account-signing-key-file and --service-account-issuer are required flags"))
}
if enableAttempted && !enableSucceeded {
errors = append(errors, fmt.Errorf("--service-account-signing-key-file, --service-account-issuer, and --api-audiences should be specified together"))
}
return errors
}
// Validate checks ServerRunOptions and return a slice of found errors.
func (s *ServerRunOptions) Validate() []error {
var errors []error
@ -85,6 +115,9 @@ func (s *ServerRunOptions) Validate() []error {
if errs := s.APIEnablement.Validate(legacyscheme.Scheme, apiextensionsapiserver.Scheme, aggregatorscheme.Scheme); len(errs) > 0 {
errors = append(errors, errs...)
}
if errs := validateTokenRequest(s); len(errs) > 0 {
errors = append(errors, errs...)
}
return errors
}

View File

@ -33,7 +33,6 @@ import (
"github.com/go-openapi/spec"
"github.com/spf13/cobra"
"k8s.io/klog"
extensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver"
"k8s.io/apimachinery/pkg/apis/meta/v1"
@ -50,13 +49,13 @@ import (
serveroptions "k8s.io/apiserver/pkg/server/options"
serverstorage "k8s.io/apiserver/pkg/server/storage"
"k8s.io/apiserver/pkg/storage/etcd3/preflight"
utilfeature "k8s.io/apiserver/pkg/util/feature"
apiserverflag "k8s.io/apiserver/pkg/util/flag"
"k8s.io/apiserver/pkg/util/webhook"
clientgoinformers "k8s.io/client-go/informers"
clientgoclientset "k8s.io/client-go/kubernetes"
certutil "k8s.io/client-go/util/cert"
cloudprovider "k8s.io/cloud-provider"
"k8s.io/klog"
aggregatorapiserver "k8s.io/kube-aggregator/pkg/apiserver"
aggregatorscheme "k8s.io/kube-aggregator/pkg/apiserver/scheme"
openapi "k8s.io/kube-openapi/pkg/common"
@ -64,7 +63,6 @@ import (
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/capabilities"
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
"k8s.io/kubernetes/pkg/features"
generatedopenapi "k8s.io/kubernetes/pkg/generated/openapi"
"k8s.io/kubernetes/pkg/kubeapiserver"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
@ -78,13 +76,12 @@ import (
"k8s.io/kubernetes/pkg/registry/cachesize"
rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest"
"k8s.io/kubernetes/pkg/serviceaccount"
"k8s.io/kubernetes/pkg/version"
"k8s.io/kubernetes/pkg/version/verflag"
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap"
utilflag "k8s.io/kubernetes/pkg/util/flag"
_ "k8s.io/kubernetes/pkg/util/reflector/prometheus" // for reflector metric registration
_ "k8s.io/kubernetes/pkg/util/workqueue/prometheus" // for workqueue metric registration
"k8s.io/kubernetes/pkg/version"
"k8s.io/kubernetes/pkg/version/verflag"
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap"
)
const etcdRetryLimit = 60
@ -318,48 +315,6 @@ func CreateKubeAPIServerConfig(
return
}
var (
issuer serviceaccount.TokenGenerator
maxExpiration time.Duration
)
if s.ServiceAccountSigningKeyFile != "" ||
s.Authentication.ServiceAccounts.Issuer != "" ||
len(s.Authentication.APIAudiences) > 0 {
if !utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) {
lastErr = fmt.Errorf("the TokenRequest feature is not enabled but --service-account-signing-key-file, --service-account-issuer and/or --service-account-api-audiences flags were passed")
return
}
if s.ServiceAccountSigningKeyFile == "" ||
s.Authentication.ServiceAccounts.Issuer == "" ||
len(s.Authentication.APIAudiences) == 0 ||
len(s.Authentication.ServiceAccounts.KeyFiles) == 0 {
lastErr = fmt.Errorf("service-account-signing-key-file, service-account-issuer, service-account-api-audiences and service-account-key-file should be specified together")
return
}
sk, err := certutil.PrivateKeyFromFile(s.ServiceAccountSigningKeyFile)
if err != nil {
lastErr = fmt.Errorf("failed to parse service-account-issuer-key-file: %v", err)
return
}
if s.Authentication.ServiceAccounts.MaxExpiration != 0 {
lowBound := time.Hour
upBound := time.Duration(1<<32) * time.Second
if s.Authentication.ServiceAccounts.MaxExpiration < lowBound ||
s.Authentication.ServiceAccounts.MaxExpiration > upBound {
lastErr = fmt.Errorf("the serviceaccount max expiration is out of range, must be between 1 hour to 2^32 seconds")
return
}
}
issuer, err = serviceaccount.JWTTokenGenerator(s.Authentication.ServiceAccounts.Issuer, sk)
if err != nil {
lastErr = fmt.Errorf("failed to build token generator: %v", err)
return
}
maxExpiration = s.Authentication.ServiceAccounts.MaxExpiration
}
config = &master.Config{
GenericConfig: genericConfig,
ExtraConfig: master.ExtraConfig{
@ -391,8 +346,8 @@ func CreateKubeAPIServerConfig(
EndpointReconcilerType: reconcilers.Type(s.EndpointReconcilerType),
MasterCount: s.MasterCount,
ServiceAccountIssuer: issuer,
ServiceAccountMaxExpiration: maxExpiration,
ServiceAccountIssuer: s.ServiceAccountIssuer,
ServiceAccountMaxExpiration: s.ServiceAccountTokenMaxExpiration,
VersionedInformers: versionedInformers,
},
@ -603,6 +558,27 @@ func Complete(s *options.ServerRunOptions) (completedServerRunOptions, error) {
}
}
if s.ServiceAccountSigningKeyFile != "" && s.Authentication.ServiceAccounts.Issuer != "" {
sk, err := certutil.PrivateKeyFromFile(s.ServiceAccountSigningKeyFile)
if err != nil {
return options, fmt.Errorf("failed to parse service-account-issuer-key-file: %v", err)
}
if s.Authentication.ServiceAccounts.MaxExpiration != 0 {
lowBound := time.Hour
upBound := time.Duration(1<<32) * time.Second
if s.Authentication.ServiceAccounts.MaxExpiration < lowBound ||
s.Authentication.ServiceAccounts.MaxExpiration > upBound {
return options, fmt.Errorf("the serviceaccount max expiration must be between 1 hour to 2^32 seconds")
}
}
s.ServiceAccountIssuer, err = serviceaccount.JWTTokenGenerator(s.Authentication.ServiceAccounts.Issuer, sk)
if err != nil {
return options, fmt.Errorf("failed to build token generator: %v", err)
}
s.ServiceAccountTokenMaxExpiration = s.Authentication.ServiceAccounts.MaxExpiration
}
if s.Etcd.EnableWatchCache {
klog.V(2).Infof("Initializing cache sizes based on %dMB limit", s.GenericServerRunOptions.TargetRAMMB)
sizes := cachesize.NewHeuristicWatchCacheSizes(s.GenericServerRunOptions.TargetRAMMB)

View File

@ -89,7 +89,7 @@ func TestServiceAccountTokenCreate(t *testing.T) {
}
masterConfig.ExtraConfig.ServiceAccountIssuer = tokenGenerator
masterConfig.ExtraConfig.ServiceAccountMaxExpiration = maxExpirationDuration
masterConfig.ExtraConfig.APIAudiences = aud
masterConfig.GenericConfig.Authentication.APIAudiences = aud
master, _, closeFn := framework.RunAMaster(masterConfig)
defer closeFn()