mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #129816 from sambdavidson/master
Improve SA max token expiry with external signer logic, and plumb extended expiry duration.
This commit is contained in:
		@@ -44,6 +44,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/controlplane/reconcilers"
 | 
						"k8s.io/kubernetes/pkg/controlplane/reconcilers"
 | 
				
			||||||
	kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
 | 
						kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
 | 
				
			||||||
	kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
 | 
						kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/serviceaccount"
 | 
				
			||||||
	netutils "k8s.io/utils/net"
 | 
						netutils "k8s.io/utils/net"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -272,8 +273,9 @@ func TestAddFlags(t *testing.T) {
 | 
				
			|||||||
				OIDC:           s.Authentication.OIDC,
 | 
									OIDC:           s.Authentication.OIDC,
 | 
				
			||||||
				RequestHeader:  &apiserveroptions.RequestHeaderAuthenticationOptions{},
 | 
									RequestHeader:  &apiserveroptions.RequestHeaderAuthenticationOptions{},
 | 
				
			||||||
				ServiceAccounts: &kubeoptions.ServiceAccountAuthenticationOptions{
 | 
									ServiceAccounts: &kubeoptions.ServiceAccountAuthenticationOptions{
 | 
				
			||||||
					Lookup:           true,
 | 
										Lookup:                true,
 | 
				
			||||||
					ExtendExpiration: true,
 | 
										ExtendExpiration:      true,
 | 
				
			||||||
 | 
										MaxExtendedExpiration: serviceaccount.ExpirationExtensionSeconds * time.Second,
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				TokenFile:            &kubeoptions.TokenFileAuthenticationOptions{},
 | 
									TokenFile:            &kubeoptions.TokenFileAuthenticationOptions{},
 | 
				
			||||||
				TokenSuccessCacheTTL: 10 * time.Second,
 | 
									TokenSuccessCacheTTL: 10 * time.Second,
 | 
				
			||||||
@@ -348,7 +350,7 @@ func TestAddFlags(t *testing.T) {
 | 
				
			|||||||
	s.Authorization.AreLegacyFlagsSet = nil
 | 
						s.Authorization.AreLegacyFlagsSet = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !reflect.DeepEqual(expected, s) {
 | 
						if !reflect.DeepEqual(expected, s) {
 | 
				
			||||||
		t.Errorf("Got different run options than expected.\nDifference detected on:\n%s", cmp.Diff(expected, s, cmpopts.IgnoreUnexported(admission.Plugins{}, kubeoptions.OIDCAuthenticationOptions{}, kubeoptions.AnonymousAuthenticationOptions{})))
 | 
							t.Errorf("Got different run options than expected.\nDifference detected on:\n%s", cmp.Diff(expected, s, cmpopts.IgnoreFields(apiserveroptions.ServerRunOptions{}, "ComponentGlobalsRegistry"), cmpopts.IgnoreUnexported(admission.Plugins{}, kubeoptions.OIDCAuthenticationOptions{}, kubeoptions.AnonymousAuthenticationOptions{})))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testEffectiveVersion := s.GenericServerRunOptions.ComponentGlobalsRegistry.EffectiveVersionFor("test")
 | 
						testEffectiveVersion := s.GenericServerRunOptions.ComponentGlobalsRegistry.EffectiveVersionFor("test")
 | 
				
			||||||
	if testEffectiveVersion.EmulationVersion().String() != "1.31" {
 | 
						if testEffectiveVersion.EmulationVersion().String() != "1.31" {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,8 +52,8 @@ func (c *CompletedConfig) NewCoreGenericConfig() *corerest.GenericConfig {
 | 
				
			|||||||
		LoopbackClientConfig:        c.Generic.LoopbackClientConfig,
 | 
							LoopbackClientConfig:        c.Generic.LoopbackClientConfig,
 | 
				
			||||||
		ServiceAccountIssuer:        c.Extra.ServiceAccountIssuer,
 | 
							ServiceAccountIssuer:        c.Extra.ServiceAccountIssuer,
 | 
				
			||||||
		ExtendExpiration:            c.Extra.ExtendExpiration,
 | 
							ExtendExpiration:            c.Extra.ExtendExpiration,
 | 
				
			||||||
		IsTokenSignerExternal:       c.Extra.IsTokenSignerExternal,
 | 
					 | 
				
			||||||
		ServiceAccountMaxExpiration: c.Extra.ServiceAccountMaxExpiration,
 | 
							ServiceAccountMaxExpiration: c.Extra.ServiceAccountMaxExpiration,
 | 
				
			||||||
 | 
							MaxExtendedExpiration:       c.Extra.ServiceAccountExtendedMaxExpiration,
 | 
				
			||||||
		APIAudiences:                c.Generic.Authentication.APIAudiences,
 | 
							APIAudiences:                c.Generic.Authentication.APIAudiences,
 | 
				
			||||||
		Informers:                   c.Extra.VersionedInformers,
 | 
							Informers:                   c.Extra.VersionedInformers,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,10 +89,10 @@ type Extra struct {
 | 
				
			|||||||
	// version skew. If unset, AdvertiseAddress/BindAddress will be used.
 | 
						// version skew. If unset, AdvertiseAddress/BindAddress will be used.
 | 
				
			||||||
	PeerAdvertiseAddress peerreconcilers.PeerAdvertiseAddress
 | 
						PeerAdvertiseAddress peerreconcilers.PeerAdvertiseAddress
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ServiceAccountIssuer        serviceaccount.TokenGenerator
 | 
						ServiceAccountIssuer                serviceaccount.TokenGenerator
 | 
				
			||||||
	ServiceAccountMaxExpiration time.Duration
 | 
						ServiceAccountMaxExpiration         time.Duration
 | 
				
			||||||
	ExtendExpiration            bool
 | 
						ServiceAccountExtendedMaxExpiration time.Duration
 | 
				
			||||||
	IsTokenSignerExternal       bool
 | 
						ExtendExpiration                    bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ServiceAccountIssuerDiscovery
 | 
						// ServiceAccountIssuerDiscovery
 | 
				
			||||||
	ServiceAccountIssuerURL        string
 | 
						ServiceAccountIssuerURL        string
 | 
				
			||||||
@@ -299,10 +299,10 @@ func CreateConfig(
 | 
				
			|||||||
			ProxyTransport:          proxyTransport,
 | 
								ProxyTransport:          proxyTransport,
 | 
				
			||||||
			SystemNamespaces:        opts.SystemNamespaces,
 | 
								SystemNamespaces:        opts.SystemNamespaces,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ServiceAccountIssuer:        opts.ServiceAccountIssuer,
 | 
								ServiceAccountIssuer:                opts.ServiceAccountIssuer,
 | 
				
			||||||
			ServiceAccountMaxExpiration: opts.ServiceAccountTokenMaxExpiration,
 | 
								ServiceAccountMaxExpiration:         opts.ServiceAccountTokenMaxExpiration,
 | 
				
			||||||
			ExtendExpiration:            opts.Authentication.ServiceAccounts.ExtendExpiration,
 | 
								ServiceAccountExtendedMaxExpiration: opts.Authentication.ServiceAccounts.MaxExtendedExpiration,
 | 
				
			||||||
			IsTokenSignerExternal:       opts.Authentication.ServiceAccounts.IsTokenSignerExternal,
 | 
								ExtendExpiration:                    opts.Authentication.ServiceAccounts.ExtendExpiration,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			VersionedInformers: versionedInformers,
 | 
								VersionedInformers: versionedInformers,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -316,15 +316,19 @@ func (o *Options) completeServiceAccountOptions(ctx context.Context, completed *
 | 
				
			|||||||
			if metadata.MaxTokenExpirationSeconds < validation.MinTokenAgeSec {
 | 
								if metadata.MaxTokenExpirationSeconds < validation.MinTokenAgeSec {
 | 
				
			||||||
				return fmt.Errorf("max token life supported by external-jwt-signer (%ds) is less than acceptable (min %ds)", metadata.MaxTokenExpirationSeconds, validation.MinTokenAgeSec)
 | 
									return fmt.Errorf("max token life supported by external-jwt-signer (%ds) is less than acceptable (min %ds)", metadata.MaxTokenExpirationSeconds, validation.MinTokenAgeSec)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if completed.Authentication.ServiceAccounts.MaxExpiration != 0 {
 | 
								maxExternalExpiration := time.Duration(metadata.MaxTokenExpirationSeconds) * time.Second
 | 
				
			||||||
				return fmt.Errorf("service-account-max-token-expiration and service-account-signing-endpoint are mutually exclusive and cannot be set at the same time")
 | 
								switch {
 | 
				
			||||||
 | 
								case completed.Authentication.ServiceAccounts.MaxExpiration == 0:
 | 
				
			||||||
 | 
									completed.Authentication.ServiceAccounts.MaxExpiration = maxExternalExpiration
 | 
				
			||||||
 | 
								case completed.Authentication.ServiceAccounts.MaxExpiration > maxExternalExpiration:
 | 
				
			||||||
 | 
									return fmt.Errorf("service-account-max-token-expiration cannot be set longer than the token expiration supported by service-account-signing-endpoint: %s > %s", completed.Authentication.ServiceAccounts.MaxExpiration, maxExternalExpiration)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			transitionWarningFmt = "service-account-extend-token-expiration is true, in order to correctly trigger safe transition logic, token lifetime supported by external-jwt-signer must be longer than %d seconds (currently %s)"
 | 
								transitionWarningFmt = "service-account-extend-token-expiration is true, in order to correctly trigger safe transition logic, token lifetime supported by external-jwt-signer must be longer than %d seconds (currently %s)"
 | 
				
			||||||
			expExtensionWarningFmt = "service-account-extend-token-expiration is true, tokens validity will be caped at the smaller of %d seconds and maximum token lifetime supported by external-jwt-signer (%s)"
 | 
								expExtensionWarningFmt = "service-account-extend-token-expiration is true, tokens validity will be caped at the smaller of %d seconds and maximum token lifetime supported by external-jwt-signer (%s)"
 | 
				
			||||||
			completed.ServiceAccountIssuer = plugin
 | 
								completed.ServiceAccountIssuer = plugin
 | 
				
			||||||
			completed.Authentication.ServiceAccounts.ExternalPublicKeysGetter = cache
 | 
								completed.Authentication.ServiceAccounts.ExternalPublicKeysGetter = cache
 | 
				
			||||||
			completed.Authentication.ServiceAccounts.MaxExpiration = time.Duration(metadata.MaxTokenExpirationSeconds) * time.Second
 | 
								// shorten ExtendedExpiration, if needed, to fit within the external signer's max expiration
 | 
				
			||||||
			completed.Authentication.ServiceAccounts.IsTokenSignerExternal = true
 | 
								completed.Authentication.ServiceAccounts.MaxExtendedExpiration = min(maxExternalExpiration, completed.Authentication.ServiceAccounts.MaxExtendedExpiration)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,6 @@ import (
 | 
				
			|||||||
	"github.com/google/go-cmp/cmp/cmpopts"
 | 
						"github.com/google/go-cmp/cmp/cmpopts"
 | 
				
			||||||
	"github.com/spf13/pflag"
 | 
						"github.com/spf13/pflag"
 | 
				
			||||||
	noopoteltrace "go.opentelemetry.io/otel/trace/noop"
 | 
						noopoteltrace "go.opentelemetry.io/otel/trace/noop"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 | 
						utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/admission"
 | 
						"k8s.io/apiserver/pkg/admission"
 | 
				
			||||||
	apiserveroptions "k8s.io/apiserver/pkg/server/options"
 | 
						apiserveroptions "k8s.io/apiserver/pkg/server/options"
 | 
				
			||||||
@@ -46,6 +45,7 @@ import (
 | 
				
			|||||||
	"k8s.io/component-base/metrics"
 | 
						"k8s.io/component-base/metrics"
 | 
				
			||||||
	utilversion "k8s.io/component-base/version"
 | 
						utilversion "k8s.io/component-base/version"
 | 
				
			||||||
	kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
 | 
						kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/serviceaccount"
 | 
				
			||||||
	v1alpha1testing "k8s.io/kubernetes/pkg/serviceaccount/externaljwt/plugin/testing/v1alpha1"
 | 
						v1alpha1testing "k8s.io/kubernetes/pkg/serviceaccount/externaljwt/plugin/testing/v1alpha1"
 | 
				
			||||||
	netutils "k8s.io/utils/net"
 | 
						netutils "k8s.io/utils/net"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -264,8 +264,9 @@ func TestAddFlags(t *testing.T) {
 | 
				
			|||||||
			OIDC:           s.Authentication.OIDC,
 | 
								OIDC:           s.Authentication.OIDC,
 | 
				
			||||||
			RequestHeader:  &apiserveroptions.RequestHeaderAuthenticationOptions{},
 | 
								RequestHeader:  &apiserveroptions.RequestHeaderAuthenticationOptions{},
 | 
				
			||||||
			ServiceAccounts: &kubeoptions.ServiceAccountAuthenticationOptions{
 | 
								ServiceAccounts: &kubeoptions.ServiceAccountAuthenticationOptions{
 | 
				
			||||||
				Lookup:           true,
 | 
									Lookup:                true,
 | 
				
			||||||
				ExtendExpiration: true,
 | 
									ExtendExpiration:      true,
 | 
				
			||||||
 | 
									MaxExtendedExpiration: serviceaccount.ExpirationExtensionSeconds * time.Second,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			TokenFile:            &kubeoptions.TokenFileAuthenticationOptions{},
 | 
								TokenFile:            &kubeoptions.TokenFileAuthenticationOptions{},
 | 
				
			||||||
			TokenSuccessCacheTTL: 10 * time.Second,
 | 
								TokenSuccessCacheTTL: 10 * time.Second,
 | 
				
			||||||
@@ -309,7 +310,7 @@ func TestAddFlags(t *testing.T) {
 | 
				
			|||||||
	s.Authorization.AreLegacyFlagsSet = nil
 | 
						s.Authorization.AreLegacyFlagsSet = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !reflect.DeepEqual(expected, s) {
 | 
						if !reflect.DeepEqual(expected, s) {
 | 
				
			||||||
		t.Errorf("Got different run options than expected.\nDifference detected on:\n%s", cmp.Diff(expected, s, cmpopts.IgnoreUnexported(admission.Plugins{}, kubeoptions.OIDCAuthenticationOptions{}, kubeoptions.AnonymousAuthenticationOptions{})))
 | 
							t.Errorf("Got different run options than expected.\nDifference detected on:\n%s", cmp.Diff(expected, s, cmpopts.IgnoreFields(apiserveroptions.ServerRunOptions{}, "ComponentGlobalsRegistry"), cmpopts.IgnoreUnexported(admission.Plugins{}, kubeoptions.OIDCAuthenticationOptions{}, kubeoptions.AnonymousAuthenticationOptions{})))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	testEffectiveVersion := s.GenericServerRunOptions.ComponentGlobalsRegistry.EffectiveVersionFor("test")
 | 
						testEffectiveVersion := s.GenericServerRunOptions.ComponentGlobalsRegistry.EffectiveVersionFor("test")
 | 
				
			||||||
@@ -352,13 +353,14 @@ func TestCompleteForServiceAccount(t *testing.T) {
 | 
				
			|||||||
		externalSigner           bool
 | 
							externalSigner           bool
 | 
				
			||||||
		signingKeyFiles          string
 | 
							signingKeyFiles          string
 | 
				
			||||||
		maxExpiration            time.Duration
 | 
							maxExpiration            time.Duration
 | 
				
			||||||
 | 
							maxExtendedExpiration    time.Duration
 | 
				
			||||||
		externalMaxExpirationSec int64
 | 
							externalMaxExpirationSec int64
 | 
				
			||||||
		fetchError               error
 | 
							fetchError               error
 | 
				
			||||||
		metadataError            error
 | 
							metadataError            error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		wantError                      error
 | 
							wantError                      error
 | 
				
			||||||
		expectedMaxtokenExp            time.Duration
 | 
							expectedMaxtokenExp            time.Duration
 | 
				
			||||||
		expectedIsExternalSigner       bool
 | 
							expectedExtendedMaxTokenExp    time.Duration
 | 
				
			||||||
		externalPublicKeyGetterPresent bool
 | 
							externalPublicKeyGetterPresent bool
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -373,7 +375,7 @@ func TestCompleteForServiceAccount(t *testing.T) {
 | 
				
			|||||||
			wantError: fmt.Errorf("service-account-signing-key-file and service-account-signing-endpoint are mutually exclusive and cannot be set at the same time"),
 | 
								wantError: fmt.Errorf("service-account-signing-key-file and service-account-signing-endpoint are mutually exclusive and cannot be set at the same time"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			desc: "max token expiration breaching accepteable values",
 | 
								desc: "max token expiration breaching acceptable values",
 | 
				
			||||||
			issuers: []string{
 | 
								issuers: []string{
 | 
				
			||||||
				"iss",
 | 
									"iss",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -392,35 +394,50 @@ func TestCompleteForServiceAccount(t *testing.T) {
 | 
				
			|||||||
			signingKeyFiles: "private_key.pem",
 | 
								signingKeyFiles: "private_key.pem",
 | 
				
			||||||
			maxExpiration:   time.Second * 3600,
 | 
								maxExpiration:   time.Second * 3600,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			expectedIsExternalSigner:       false,
 | 
					 | 
				
			||||||
			externalPublicKeyGetterPresent: false,
 | 
								externalPublicKeyGetterPresent: false,
 | 
				
			||||||
			expectedMaxtokenExp:            time.Second * 3600,
 | 
								expectedMaxtokenExp:            time.Second * 3600,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			desc: "signing endpoint provided",
 | 
								desc: "signing endpoint provided, use endpoint expiration",
 | 
				
			||||||
			issuers: []string{
 | 
								issuers: []string{
 | 
				
			||||||
				"iss",
 | 
									"iss",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			externalSigner:           true,
 | 
								externalSigner:           true,
 | 
				
			||||||
			signingKeyFiles:          "",
 | 
								signingKeyFiles:          "",
 | 
				
			||||||
			maxExpiration:            0,
 | 
								maxExpiration:            0,
 | 
				
			||||||
 | 
								maxExtendedExpiration:    365 * 24 * time.Hour,
 | 
				
			||||||
			externalMaxExpirationSec: 600, // 10m
 | 
								externalMaxExpirationSec: 600, // 10m
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			expectedIsExternalSigner:       true,
 | 
								expectedMaxtokenExp:            10 * time.Minute,
 | 
				
			||||||
 | 
								expectedExtendedMaxTokenExp:    10 * time.Minute,
 | 
				
			||||||
			externalPublicKeyGetterPresent: true,
 | 
								externalPublicKeyGetterPresent: true,
 | 
				
			||||||
			expectedMaxtokenExp:            time.Second * 600, // 10m
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			desc: "signing endpoint provided and max token expiration set",
 | 
								desc: "signing endpoint provided, use local smaller expirations",
 | 
				
			||||||
			issuers: []string{
 | 
								issuers: []string{
 | 
				
			||||||
				"iss",
 | 
									"iss",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			externalSigner:           true,
 | 
								externalSigner:           true,
 | 
				
			||||||
			signingKeyFiles:          "",
 | 
								signingKeyFiles:          "",
 | 
				
			||||||
			maxExpiration:            time.Second * 3600,
 | 
								maxExpiration:            1 * time.Hour,
 | 
				
			||||||
			externalMaxExpirationSec: 600, // 10m
 | 
								maxExtendedExpiration:    24 * time.Hour,
 | 
				
			||||||
 | 
								externalMaxExpirationSec: 31556952, // 1 year
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			wantError: fmt.Errorf("service-account-max-token-expiration and service-account-signing-endpoint are mutually exclusive and cannot be set at the same time"),
 | 
								expectedMaxtokenExp:            1 * time.Hour,
 | 
				
			||||||
 | 
								expectedExtendedMaxTokenExp:    24 * time.Hour,
 | 
				
			||||||
 | 
								externalPublicKeyGetterPresent: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								desc: "signing endpoint provided and want larger than signer can provide",
 | 
				
			||||||
 | 
								issuers: []string{
 | 
				
			||||||
 | 
									"iss",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								externalSigner:           true,
 | 
				
			||||||
 | 
								signingKeyFiles:          "",
 | 
				
			||||||
 | 
								maxExpiration:            1 * time.Hour, // want 1hr
 | 
				
			||||||
 | 
								externalMaxExpirationSec: 600,           // signer can only sign 10m
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								wantError: fmt.Errorf("service-account-max-token-expiration cannot be set longer than the token expiration supported by service-account-signing-endpoint: 1h0m0s > 10m0s"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			desc: "signing endpoint provided but return smaller than accaptable max token exp",
 | 
								desc: "signing endpoint provided but return smaller than accaptable max token exp",
 | 
				
			||||||
@@ -481,8 +498,9 @@ func TestCompleteForServiceAccount(t *testing.T) {
 | 
				
			|||||||
			options.ServiceAccountSigningKeyFile = tc.signingKeyFiles
 | 
								options.ServiceAccountSigningKeyFile = tc.signingKeyFiles
 | 
				
			||||||
			options.Authentication = &kubeoptions.BuiltInAuthenticationOptions{
 | 
								options.Authentication = &kubeoptions.BuiltInAuthenticationOptions{
 | 
				
			||||||
				ServiceAccounts: &kubeoptions.ServiceAccountAuthenticationOptions{
 | 
									ServiceAccounts: &kubeoptions.ServiceAccountAuthenticationOptions{
 | 
				
			||||||
					Issuers:       tc.issuers,
 | 
										Issuers:               tc.issuers,
 | 
				
			||||||
					MaxExpiration: tc.maxExpiration,
 | 
										MaxExpiration:         tc.maxExpiration,
 | 
				
			||||||
 | 
										MaxExtendedExpiration: tc.maxExtendedExpiration,
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -507,8 +525,8 @@ func TestCompleteForServiceAccount(t *testing.T) {
 | 
				
			|||||||
			if tc.externalPublicKeyGetterPresent != (co.Authentication.ServiceAccounts.ExternalPublicKeysGetter != nil) {
 | 
								if tc.externalPublicKeyGetterPresent != (co.Authentication.ServiceAccounts.ExternalPublicKeysGetter != nil) {
 | 
				
			||||||
				t.Errorf("Unexpected value of ExternalPublicKeysGetter: %v", co.Authentication.ServiceAccounts.ExternalPublicKeysGetter)
 | 
									t.Errorf("Unexpected value of ExternalPublicKeysGetter: %v", co.Authentication.ServiceAccounts.ExternalPublicKeysGetter)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if tc.expectedIsExternalSigner != co.Authentication.ServiceAccounts.IsTokenSignerExternal {
 | 
								if tc.expectedExtendedMaxTokenExp != co.Authentication.ServiceAccounts.MaxExtendedExpiration {
 | 
				
			||||||
				t.Errorf("Expected IsTokenSignerExternal %v, found %v", tc.expectedIsExternalSigner, co.Authentication.ServiceAccounts.IsTokenSignerExternal)
 | 
									t.Errorf("Expected MaxExtendedExpiration %v, found %v", tc.expectedExtendedMaxTokenExp, co.Authentication.ServiceAccounts.MaxExtendedExpiration)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if tc.expectedMaxtokenExp.Seconds() != co.Authentication.ServiceAccounts.MaxExpiration.Seconds() {
 | 
								if tc.expectedMaxtokenExp.Seconds() != co.Authentication.ServiceAccounts.MaxExpiration.Seconds() {
 | 
				
			||||||
				t.Errorf("Expected MaxExpiration to be %v, found %v", tc.expectedMaxtokenExp, co.Authentication.ServiceAccounts.MaxExpiration)
 | 
									t.Errorf("Expected MaxExpiration to be %v, found %v", tc.expectedMaxtokenExp, co.Authentication.ServiceAccounts.MaxExpiration)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -131,9 +131,9 @@ type ServiceAccountAuthenticationOptions struct {
 | 
				
			|||||||
	Lookup                bool
 | 
						Lookup                bool
 | 
				
			||||||
	Issuers               []string
 | 
						Issuers               []string
 | 
				
			||||||
	JWKSURI               string
 | 
						JWKSURI               string
 | 
				
			||||||
	MaxExpiration         time.Duration
 | 
					 | 
				
			||||||
	ExtendExpiration      bool
 | 
						ExtendExpiration      bool
 | 
				
			||||||
	IsTokenSignerExternal bool
 | 
						MaxExpiration         time.Duration
 | 
				
			||||||
 | 
						MaxExtendedExpiration time.Duration
 | 
				
			||||||
	// OptionalTokenGetter is a function that returns a service account token getter.
 | 
						// OptionalTokenGetter is a function that returns a service account token getter.
 | 
				
			||||||
	// If not set, the default token getter will be used.
 | 
						// If not set, the default token getter will be used.
 | 
				
			||||||
	OptionalTokenGetter func(factory informers.SharedInformerFactory) serviceaccount.ServiceAccountTokenGetter
 | 
						OptionalTokenGetter func(factory informers.SharedInformerFactory) serviceaccount.ServiceAccountTokenGetter
 | 
				
			||||||
@@ -224,6 +224,7 @@ func (o *BuiltInAuthenticationOptions) WithServiceAccounts() *BuiltInAuthenticat
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	o.ServiceAccounts.Lookup = true
 | 
						o.ServiceAccounts.Lookup = true
 | 
				
			||||||
	o.ServiceAccounts.ExtendExpiration = true
 | 
						o.ServiceAccounts.ExtendExpiration = true
 | 
				
			||||||
 | 
						o.ServiceAccounts.MaxExtendedExpiration = serviceaccount.ExpirationExtensionSeconds * time.Second
 | 
				
			||||||
	return o
 | 
						return o
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -437,11 +437,12 @@ func TestBuiltInAuthenticationOptionsAddFlags(t *testing.T) {
 | 
				
			|||||||
			AllowedNames:    []string{"kube-aggregator"},
 | 
								AllowedNames:    []string{"kube-aggregator"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		ServiceAccounts: &ServiceAccountAuthenticationOptions{
 | 
							ServiceAccounts: &ServiceAccountAuthenticationOptions{
 | 
				
			||||||
			KeyFiles:         []string{"cert", "key"},
 | 
								KeyFiles:              []string{"cert", "key"},
 | 
				
			||||||
			Lookup:           true,
 | 
								Lookup:                true,
 | 
				
			||||||
			Issuers:          []string{"http://foo.bar.com"},
 | 
								Issuers:               []string{"http://foo.bar.com"},
 | 
				
			||||||
			JWKSURI:          "https://qux.com",
 | 
								JWKSURI:               "https://qux.com",
 | 
				
			||||||
			ExtendExpiration: true,
 | 
								ExtendExpiration:      true,
 | 
				
			||||||
 | 
								MaxExtendedExpiration: serviceaccount.ExpirationExtensionSeconds * time.Second,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		TokenFile: &TokenFileAuthenticationOptions{
 | 
							TokenFile: &TokenFileAuthenticationOptions{
 | 
				
			||||||
			TokenFile: "tokenfile",
 | 
								TokenFile: "tokenfile",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -223,7 +223,7 @@ func (p *legacyProvider) NewRESTStorage(apiResourceConfigSource serverstorage.AP
 | 
				
			|||||||
			utilfeature.DefaultFeatureGate.Enabled(features.ServiceAccountTokenPodNodeInfo) {
 | 
								utilfeature.DefaultFeatureGate.Enabled(features.ServiceAccountTokenPodNodeInfo) {
 | 
				
			||||||
			nodeGetter = nodeStorage.Node.Store
 | 
								nodeGetter = nodeStorage.Node.Store
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		serviceAccountStorage, err = serviceaccountstore.NewREST(restOptionsGetter, p.ServiceAccountIssuer, p.APIAudiences, p.ServiceAccountMaxExpiration, podStorage.Pod.Store, storage["secrets"].(rest.Getter), nodeGetter, p.ExtendExpiration, p.IsTokenSignerExternal)
 | 
							serviceAccountStorage, err = serviceaccountstore.NewREST(restOptionsGetter, p.ServiceAccountIssuer, p.APIAudiences, p.ServiceAccountMaxExpiration, podStorage.Pod.Store, storage["secrets"].(rest.Getter), nodeGetter, p.ExtendExpiration, p.MaxExtendedExpiration)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return genericapiserver.APIGroupInfo{}, err
 | 
								return genericapiserver.APIGroupInfo{}, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,7 +57,7 @@ type GenericConfig struct {
 | 
				
			|||||||
	ServiceAccountIssuer        serviceaccount.TokenGenerator
 | 
						ServiceAccountIssuer        serviceaccount.TokenGenerator
 | 
				
			||||||
	ServiceAccountMaxExpiration time.Duration
 | 
						ServiceAccountMaxExpiration time.Duration
 | 
				
			||||||
	ExtendExpiration            bool
 | 
						ExtendExpiration            bool
 | 
				
			||||||
	IsTokenSignerExternal       bool
 | 
						MaxExtendedExpiration       time.Duration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	APIAudiences authenticator.Audiences
 | 
						APIAudiences authenticator.Audiences
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -103,9 +103,9 @@ func (c *GenericConfig) NewRESTStorage(apiResourceConfigSource serverstorage.API
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var serviceAccountStorage *serviceaccountstore.REST
 | 
						var serviceAccountStorage *serviceaccountstore.REST
 | 
				
			||||||
	if c.ServiceAccountIssuer != nil {
 | 
						if c.ServiceAccountIssuer != nil {
 | 
				
			||||||
		serviceAccountStorage, err = serviceaccountstore.NewREST(restOptionsGetter, c.ServiceAccountIssuer, c.APIAudiences, c.ServiceAccountMaxExpiration, newNotFoundGetter(schema.GroupResource{Resource: "pods"}), secretStorage.Store, newNotFoundGetter(schema.GroupResource{Resource: "nodes"}), c.ExtendExpiration, c.IsTokenSignerExternal)
 | 
							serviceAccountStorage, err = serviceaccountstore.NewREST(restOptionsGetter, c.ServiceAccountIssuer, c.APIAudiences, c.ServiceAccountMaxExpiration, newNotFoundGetter(schema.GroupResource{Resource: "pods"}), secretStorage.Store, newNotFoundGetter(schema.GroupResource{Resource: "nodes"}), c.ExtendExpiration, c.MaxExtendedExpiration)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		serviceAccountStorage, err = serviceaccountstore.NewREST(restOptionsGetter, nil, nil, 0, newNotFoundGetter(schema.GroupResource{Resource: "pods"}), newNotFoundGetter(schema.GroupResource{Resource: "secrets"}), newNotFoundGetter(schema.GroupResource{Resource: "nodes"}), false, c.IsTokenSignerExternal)
 | 
							serviceAccountStorage, err = serviceaccountstore.NewREST(restOptionsGetter, nil, nil, 0, newNotFoundGetter(schema.GroupResource{Resource: "pods"}), newNotFoundGetter(schema.GroupResource{Resource: "secrets"}), newNotFoundGetter(schema.GroupResource{Resource: "nodes"}), false, c.MaxExtendedExpiration)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return genericapiserver.APIGroupInfo{}, err
 | 
							return genericapiserver.APIGroupInfo{}, err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,7 +39,7 @@ type REST struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewREST returns a RESTStorage object that will work against service accounts.
 | 
					// NewREST returns a RESTStorage object that will work against service accounts.
 | 
				
			||||||
func NewREST(optsGetter generic.RESTOptionsGetter, issuer token.TokenGenerator, auds authenticator.Audiences, max time.Duration, podStorage, secretStorage, nodeStorage rest.Getter, extendExpiration bool, isTokenSignerExternal bool) (*REST, error) {
 | 
					func NewREST(optsGetter generic.RESTOptionsGetter, issuer token.TokenGenerator, auds authenticator.Audiences, max time.Duration, podStorage, secretStorage, nodeStorage rest.Getter, extendExpiration bool, maxExtendedExpiration time.Duration) (*REST, error) {
 | 
				
			||||||
	store := &genericregistry.Store{
 | 
						store := &genericregistry.Store{
 | 
				
			||||||
		NewFunc:                   func() runtime.Object { return &api.ServiceAccount{} },
 | 
							NewFunc:                   func() runtime.Object { return &api.ServiceAccount{} },
 | 
				
			||||||
		NewListFunc:               func() runtime.Object { return &api.ServiceAccountList{} },
 | 
							NewListFunc:               func() runtime.Object { return &api.ServiceAccountList{} },
 | 
				
			||||||
@@ -61,16 +61,16 @@ func NewREST(optsGetter generic.RESTOptionsGetter, issuer token.TokenGenerator,
 | 
				
			|||||||
	var trest *TokenREST
 | 
						var trest *TokenREST
 | 
				
			||||||
	if issuer != nil && podStorage != nil && secretStorage != nil {
 | 
						if issuer != nil && podStorage != nil && secretStorage != nil {
 | 
				
			||||||
		trest = &TokenREST{
 | 
							trest = &TokenREST{
 | 
				
			||||||
			svcaccts:              store,
 | 
								svcaccts:                     store,
 | 
				
			||||||
			pods:                  podStorage,
 | 
								pods:                         podStorage,
 | 
				
			||||||
			secrets:               secretStorage,
 | 
								secrets:                      secretStorage,
 | 
				
			||||||
			nodes:                 nodeStorage,
 | 
								nodes:                        nodeStorage,
 | 
				
			||||||
			issuer:                issuer,
 | 
								issuer:                       issuer,
 | 
				
			||||||
			auds:                  auds,
 | 
								auds:                         auds,
 | 
				
			||||||
			audsSet:               sets.NewString(auds...),
 | 
								audsSet:                      sets.NewString(auds...),
 | 
				
			||||||
			maxExpirationSeconds:  int64(max.Seconds()),
 | 
								maxExpirationSeconds:         int64(max.Seconds()),
 | 
				
			||||||
			extendExpiration:      extendExpiration,
 | 
								maxExtendedExpirationSeconds: int64(maxExtendedExpiration.Seconds()),
 | 
				
			||||||
			isTokenSignerExternal: isTokenSignerExternal,
 | 
								extendExpiration:             extendExpiration,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,7 @@ package storage
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
						"gopkg.in/go-jose/go-jose.v2/jwt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -55,7 +56,7 @@ func newTokenStorage(t *testing.T, issuer token.TokenGenerator, auds authenticat
 | 
				
			|||||||
		ResourcePrefix:          "serviceaccounts",
 | 
							ResourcePrefix:          "serviceaccounts",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// set issuer, podStore and secretStore to allow the token endpoint to be initialised
 | 
						// set issuer, podStore and secretStore to allow the token endpoint to be initialised
 | 
				
			||||||
	rest, err := NewREST(restOptions, issuer, auds, 0, podStorage, secretStorage, nodeStorage, false, false)
 | 
						rest, err := NewREST(restOptions, issuer, auds, 0, podStorage, secretStorage, nodeStorage, false, time.Hour*9999)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("unexpected error from REST storage: %v", err)
 | 
							t.Fatalf("unexpected error from REST storage: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,16 +56,16 @@ func (r *TokenREST) Destroy() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TokenREST struct {
 | 
					type TokenREST struct {
 | 
				
			||||||
	svcaccts              rest.Getter
 | 
						svcaccts                     rest.Getter
 | 
				
			||||||
	pods                  rest.Getter
 | 
						pods                         rest.Getter
 | 
				
			||||||
	secrets               rest.Getter
 | 
						secrets                      rest.Getter
 | 
				
			||||||
	nodes                 rest.Getter
 | 
						nodes                        rest.Getter
 | 
				
			||||||
	issuer                token.TokenGenerator
 | 
						issuer                       token.TokenGenerator
 | 
				
			||||||
	auds                  authenticator.Audiences
 | 
						auds                         authenticator.Audiences
 | 
				
			||||||
	audsSet               sets.String
 | 
						audsSet                      sets.String
 | 
				
			||||||
	maxExpirationSeconds  int64
 | 
						maxExpirationSeconds         int64
 | 
				
			||||||
	extendExpiration      bool
 | 
						extendExpiration             bool
 | 
				
			||||||
	isTokenSignerExternal bool
 | 
						maxExtendedExpirationSeconds int64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _ = rest.NamedCreater(&TokenREST{})
 | 
					var _ = rest.NamedCreater(&TokenREST{})
 | 
				
			||||||
@@ -218,13 +218,7 @@ func (r *TokenREST) Create(ctx context.Context, name string, obj runtime.Object,
 | 
				
			|||||||
	exp := req.Spec.ExpirationSeconds
 | 
						exp := req.Spec.ExpirationSeconds
 | 
				
			||||||
	if r.extendExpiration && pod != nil && req.Spec.ExpirationSeconds == token.WarnOnlyBoundTokenExpirationSeconds && r.isKubeAudiences(req.Spec.Audiences) {
 | 
						if r.extendExpiration && pod != nil && req.Spec.ExpirationSeconds == token.WarnOnlyBoundTokenExpirationSeconds && r.isKubeAudiences(req.Spec.Audiences) {
 | 
				
			||||||
		warnAfter = exp
 | 
							warnAfter = exp
 | 
				
			||||||
		// If token issuer is external-jwt-signer, then choose the smaller of
 | 
							exp = r.maxExtendedExpirationSeconds
 | 
				
			||||||
		// ExpirationExtensionSeconds and max token lifetime supported by external signer.
 | 
					 | 
				
			||||||
		if r.isTokenSignerExternal {
 | 
					 | 
				
			||||||
			exp = min(r.maxExpirationSeconds, token.ExpirationExtensionSeconds)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			exp = token.ExpirationExtensionSeconds
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sc, pc, err := token.Claims(*svcacct, pod, secret, node, exp, warnAfter, req.Spec.Audiences)
 | 
						sc, pc, err := token.Claims(*svcacct, pod, secret, node, exp, warnAfter, req.Spec.Audiences)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,46 +42,53 @@ import (
 | 
				
			|||||||
func TestCreate_Token_WithExpiryCap(t *testing.T) {
 | 
					func TestCreate_Token_WithExpiryCap(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	testcases := []struct {
 | 
						testcases := []struct {
 | 
				
			||||||
		desc                 string
 | 
							desc                         string
 | 
				
			||||||
		extendExpiration     bool
 | 
							extendExpiration             bool
 | 
				
			||||||
		maxExpirationSeconds int
 | 
							maxExpirationSeconds         int
 | 
				
			||||||
		expectedTokenAgeSec  int
 | 
							maxExtendedExpirationSeconds int
 | 
				
			||||||
		isExternal           bool
 | 
							expectedTokenAgeSec          int
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			desc:                 "maxExpirationSeconds honoured",
 | 
								desc:                         "passed expiration respected if less than max",
 | 
				
			||||||
			extendExpiration:     true,
 | 
								extendExpiration:             false,
 | 
				
			||||||
			maxExpirationSeconds: 5 * 60 * 60, // 5h
 | 
								maxExpirationSeconds:         5 * 60 * 60,                               // 5h
 | 
				
			||||||
			expectedTokenAgeSec:  5 * 60 * 60, // 5h
 | 
								maxExtendedExpirationSeconds: token.ExpirationExtensionSeconds,          // 1y
 | 
				
			||||||
			isExternal:           true,
 | 
								expectedTokenAgeSec:          token.WarnOnlyBoundTokenExpirationSeconds, // 1h 7s
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			desc:                 "ExpirationExtensionSeconds used for exp",
 | 
								desc:                         "maxExtendedExpirationSeconds honoured",
 | 
				
			||||||
			extendExpiration:     true,
 | 
								extendExpiration:             true,
 | 
				
			||||||
			maxExpirationSeconds: 2 * 365 * 24 * 60 * 60,           // 2 years
 | 
								maxExpirationSeconds:         2 * 60 * 60, // 2h
 | 
				
			||||||
			expectedTokenAgeSec:  token.ExpirationExtensionSeconds, // 1y
 | 
								maxExtendedExpirationSeconds: 5 * 60 * 60, // 5h
 | 
				
			||||||
			isExternal:           true,
 | 
								expectedTokenAgeSec:          5 * 60 * 60, // 5h
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			desc:                 "ExpirationExtensionSeconds used for exp",
 | 
								desc:                         "ExpirationExtensionSeconds used for exp",
 | 
				
			||||||
			extendExpiration:     true,
 | 
								extendExpiration:             true,
 | 
				
			||||||
			maxExpirationSeconds: 5 * 60 * 60,                      // 5h
 | 
								maxExpirationSeconds:         2 * 365 * 24 * 60 * 60,           // 2y
 | 
				
			||||||
			expectedTokenAgeSec:  token.ExpirationExtensionSeconds, // 1y
 | 
								maxExtendedExpirationSeconds: token.ExpirationExtensionSeconds, // 1y
 | 
				
			||||||
			isExternal:           false,
 | 
								expectedTokenAgeSec:          token.ExpirationExtensionSeconds, // 1y
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			desc:                 "requested time use with extension disabled",
 | 
								desc:                         "ExpirationSeconds used for exp",
 | 
				
			||||||
			extendExpiration:     false,
 | 
								extendExpiration:             true,
 | 
				
			||||||
			maxExpirationSeconds: 5 * 60 * 60, // 5h
 | 
								maxExpirationSeconds:         5 * 60 * 60,                      // 5h
 | 
				
			||||||
			expectedTokenAgeSec:  3607,        // 1h
 | 
								maxExtendedExpirationSeconds: token.ExpirationExtensionSeconds, // 1y
 | 
				
			||||||
			isExternal:           true,
 | 
								expectedTokenAgeSec:          token.ExpirationExtensionSeconds, // 1y
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			desc:                 "maxExpirationSeconds honoured with extension disabled",
 | 
								desc:                         "requested time use with extension disabled",
 | 
				
			||||||
			extendExpiration:     false,
 | 
								extendExpiration:             false,
 | 
				
			||||||
			maxExpirationSeconds: 30 * 60, // 30m
 | 
								maxExpirationSeconds:         5 * 60 * 60, // 5h
 | 
				
			||||||
			expectedTokenAgeSec:  30 * 60, // 30m
 | 
								expectedTokenAgeSec:          3607,        // 1h
 | 
				
			||||||
			isExternal:           true,
 | 
								maxExtendedExpirationSeconds: token.ExpirationExtensionSeconds,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								desc:                         "maxExpirationSeconds honoured with extension disabled",
 | 
				
			||||||
 | 
								extendExpiration:             false,
 | 
				
			||||||
 | 
								maxExpirationSeconds:         30 * 60, // 30m
 | 
				
			||||||
 | 
								expectedTokenAgeSec:          30 * 60, // 30m
 | 
				
			||||||
 | 
								maxExtendedExpirationSeconds: token.ExpirationExtensionSeconds,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -127,7 +134,7 @@ func TestCreate_Token_WithExpiryCap(t *testing.T) {
 | 
				
			|||||||
			ctx = request.WithNamespace(ctx, serviceAccount.Namespace)
 | 
								ctx = request.WithNamespace(ctx, serviceAccount.Namespace)
 | 
				
			||||||
			storage.Token.extendExpiration = tc.extendExpiration
 | 
								storage.Token.extendExpiration = tc.extendExpiration
 | 
				
			||||||
			storage.Token.maxExpirationSeconds = int64(tc.maxExpirationSeconds)
 | 
								storage.Token.maxExpirationSeconds = int64(tc.maxExpirationSeconds)
 | 
				
			||||||
			storage.Token.isTokenSignerExternal = tc.isExternal
 | 
								storage.Token.maxExtendedExpirationSeconds = int64(tc.maxExtendedExpirationSeconds)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			tokenReqTimeStamp := time.Now()
 | 
								tokenReqTimeStamp := time.Now()
 | 
				
			||||||
			out, err := storage.Token.Create(ctx, serviceAccount.Name, &authenticationapi.TokenRequest{
 | 
								out, err := storage.Token.Create(ctx, serviceAccount.Name, &authenticationapi.TokenRequest{
 | 
				
			||||||
@@ -161,13 +168,15 @@ func TestCreate_Token_WithExpiryCap(t *testing.T) {
 | 
				
			|||||||
				t.Fatalf("Error unmarshalling Claims: %v", err)
 | 
									t.Fatalf("Error unmarshalling Claims: %v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			structuredClaim.Expiry.Time()
 | 
								structuredClaim.Expiry.Time()
 | 
				
			||||||
			upperBound := tokenReqTimeStamp.Add(time.Duration(tc.expectedTokenAgeSec+10) * time.Second)
 | 
								confidenceInterval := 10 // seconds
 | 
				
			||||||
			lowerBound := tokenReqTimeStamp.Add(time.Duration(tc.expectedTokenAgeSec-10) * time.Second)
 | 
								upperBound := tokenReqTimeStamp.Add(time.Duration(tc.expectedTokenAgeSec+confidenceInterval) * time.Second)
 | 
				
			||||||
 | 
								lowerBound := tokenReqTimeStamp.Add(time.Duration(tc.expectedTokenAgeSec-confidenceInterval) * time.Second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// check for token expiration with a toleration of +/-10s after tokenReqTimeStamp to make for latencies.
 | 
								// check for token expiration with a toleration of +/-10s after tokenReqTimeStamp to make for latencies.
 | 
				
			||||||
			if structuredClaim.Expiry.Time().After(upperBound) ||
 | 
								if structuredClaim.Expiry.Time().After(upperBound) ||
 | 
				
			||||||
				structuredClaim.Expiry.Time().Before(lowerBound) {
 | 
									structuredClaim.Expiry.Time().Before(lowerBound) {
 | 
				
			||||||
				t.Fatalf("expected token expiration to be between %v to %v\n was %v", upperBound, lowerBound, structuredClaim.Expiry.Time())
 | 
									expiryDiff := structuredClaim.Expiry.Time().Sub(tokenReqTimeStamp)
 | 
				
			||||||
 | 
									t.Fatalf("expected token expiration to be %v (±%ds) in the future, was %v", time.Duration(tc.expectedTokenAgeSec)*time.Second, confidenceInterval, expiryDiff)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user