mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	svcacct: move claim generation out of TokenGenerator
This commit is contained in:
		@@ -58,6 +58,7 @@ go_test(
 | 
				
			|||||||
        "//pkg/controller:go_default_library",
 | 
					        "//pkg/controller:go_default_library",
 | 
				
			||||||
        "//vendor/github.com/davecgh/go-spew/spew:go_default_library",
 | 
					        "//vendor/github.com/davecgh/go-spew/spew:go_default_library",
 | 
				
			||||||
        "//vendor/github.com/golang/glog:go_default_library",
 | 
					        "//vendor/github.com/golang/glog:go_default_library",
 | 
				
			||||||
 | 
					        "//vendor/gopkg.in/square/go-jose.v2/jwt:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/api/core/v1:go_default_library",
 | 
					        "//vendor/k8s.io/api/core/v1:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
 | 
					        "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
					        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -395,7 +395,7 @@ func (e *TokensController) ensureReferencedToken(serviceAccount *v1.ServiceAccou
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Generate the token
 | 
						// Generate the token
 | 
				
			||||||
	token, err := e.token.GenerateToken(*serviceAccount, *secret)
 | 
						token, err := e.token.GenerateToken(serviceaccount.LegacyClaims(*serviceAccount, *secret))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// retriable error
 | 
							// retriable error
 | 
				
			||||||
		return true, err
 | 
							return true, err
 | 
				
			||||||
@@ -551,7 +551,7 @@ func (e *TokensController) generateTokenIfNeeded(serviceAccount *v1.ServiceAccou
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Generate the token
 | 
						// Generate the token
 | 
				
			||||||
	if needsToken {
 | 
						if needsToken {
 | 
				
			||||||
		token, err := e.token.GenerateToken(*serviceAccount, *liveSecret)
 | 
							token, err := e.token.GenerateToken(serviceaccount.LegacyClaims(*serviceAccount, *liveSecret))
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return false, err
 | 
								return false, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/davecgh/go-spew/spew"
 | 
						"github.com/davecgh/go-spew/spew"
 | 
				
			||||||
	"github.com/golang/glog"
 | 
						"github.com/golang/glog"
 | 
				
			||||||
 | 
						"gopkg.in/square/go-jose.v2/jwt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/api/core/v1"
 | 
						"k8s.io/api/core/v1"
 | 
				
			||||||
	apierrors "k8s.io/apimachinery/pkg/api/errors"
 | 
						apierrors "k8s.io/apimachinery/pkg/api/errors"
 | 
				
			||||||
@@ -39,15 +40,11 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type testGenerator struct {
 | 
					type testGenerator struct {
 | 
				
			||||||
	GeneratedServiceAccounts []v1.ServiceAccount
 | 
						Token string
 | 
				
			||||||
	GeneratedSecrets         []v1.Secret
 | 
						Err   error
 | 
				
			||||||
	Token                    string
 | 
					 | 
				
			||||||
	Err                      error
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (t *testGenerator) GenerateToken(serviceAccount v1.ServiceAccount, secret v1.Secret) (string, error) {
 | 
					func (t *testGenerator) GenerateToken(sc *jwt.Claims, pc interface{}) (string, error) {
 | 
				
			||||||
	t.GeneratedSecrets = append(t.GeneratedSecrets, secret)
 | 
					 | 
				
			||||||
	t.GeneratedServiceAccounts = append(t.GeneratedServiceAccounts, serviceAccount)
 | 
					 | 
				
			||||||
	return t.Token, t.Err
 | 
						return t.Token, t.Err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,7 @@ go_library(
 | 
				
			|||||||
    name = "go_default_library",
 | 
					    name = "go_default_library",
 | 
				
			||||||
    srcs = [
 | 
					    srcs = [
 | 
				
			||||||
        "jwt.go",
 | 
					        "jwt.go",
 | 
				
			||||||
 | 
					        "legacy.go",
 | 
				
			||||||
        "util.go",
 | 
					        "util.go",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    importpath = "k8s.io/kubernetes/pkg/serviceaccount",
 | 
					    importpath = "k8s.io/kubernetes/pkg/serviceaccount",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,15 +38,6 @@ import (
 | 
				
			|||||||
	"gopkg.in/square/go-jose.v2/jwt"
 | 
						"gopkg.in/square/go-jose.v2/jwt"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const LegacyIssuer = "kubernetes/serviceaccount"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type privateClaims struct {
 | 
					 | 
				
			||||||
	ServiceAccountName string `json:"kubernetes.io/serviceaccount/service-account.name"`
 | 
					 | 
				
			||||||
	ServiceAccountUID  string `json:"kubernetes.io/serviceaccount/service-account.uid"`
 | 
					 | 
				
			||||||
	SecretName         string `json:"kubernetes.io/serviceaccount/secret.name"`
 | 
					 | 
				
			||||||
	Namespace          string `json:"kubernetes.io/serviceaccount/namespace"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ServiceAccountTokenGetter defines functions to retrieve a named service account and secret
 | 
					// ServiceAccountTokenGetter defines functions to retrieve a named service account and secret
 | 
				
			||||||
type ServiceAccountTokenGetter interface {
 | 
					type ServiceAccountTokenGetter interface {
 | 
				
			||||||
	GetServiceAccount(namespace, name string) (*v1.ServiceAccount, error)
 | 
						GetServiceAccount(namespace, name string) (*v1.ServiceAccount, error)
 | 
				
			||||||
@@ -54,9 +45,13 @@ type ServiceAccountTokenGetter interface {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TokenGenerator interface {
 | 
					type TokenGenerator interface {
 | 
				
			||||||
	// GenerateToken generates a token which will identify the given ServiceAccount.
 | 
						// GenerateToken generates a token which will identify the given
 | 
				
			||||||
	// The returned token will be stored in the given (and yet-unpersisted) Secret.
 | 
						// ServiceAccount. privateClaims is an interface that will be
 | 
				
			||||||
	GenerateToken(serviceAccount v1.ServiceAccount, secret v1.Secret) (string, error)
 | 
						// serialized into the JWT payload JSON encoding at the root level of
 | 
				
			||||||
 | 
						// the payload object. Public claims take precedent over private
 | 
				
			||||||
 | 
						// claims i.e. if both claims and privateClaims have an "exp" field,
 | 
				
			||||||
 | 
						// the value in claims will be used.
 | 
				
			||||||
 | 
						GenerateToken(claims *jwt.Claims, privateClaims interface{}) (string, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// JWTTokenGenerator returns a TokenGenerator that generates signed JWT tokens, using the given privateKey.
 | 
					// JWTTokenGenerator returns a TokenGenerator that generates signed JWT tokens, using the given privateKey.
 | 
				
			||||||
@@ -74,7 +69,7 @@ type jwtTokenGenerator struct {
 | 
				
			|||||||
	privateKey interface{}
 | 
						privateKey interface{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (j *jwtTokenGenerator) GenerateToken(serviceAccount v1.ServiceAccount, secret v1.Secret) (string, error) {
 | 
					func (j *jwtTokenGenerator) GenerateToken(claims *jwt.Claims, privateClaims interface{}) (string, error) {
 | 
				
			||||||
	var alg jose.SignatureAlgorithm
 | 
						var alg jose.SignatureAlgorithm
 | 
				
			||||||
	switch privateKey := j.privateKey.(type) {
 | 
						switch privateKey := j.privateKey.(type) {
 | 
				
			||||||
	case *rsa.PrivateKey:
 | 
						case *rsa.PrivateKey:
 | 
				
			||||||
@@ -105,17 +100,14 @@ func (j *jwtTokenGenerator) GenerateToken(serviceAccount v1.ServiceAccount, secr
 | 
				
			|||||||
		return "", err
 | 
							return "", err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// claims are applied in reverse precedence
 | 
				
			||||||
	return jwt.Signed(signer).
 | 
						return jwt.Signed(signer).
 | 
				
			||||||
 | 
							Claims(privateClaims).
 | 
				
			||||||
 | 
							Claims(claims).
 | 
				
			||||||
		Claims(&jwt.Claims{
 | 
							Claims(&jwt.Claims{
 | 
				
			||||||
			Issuer:  j.iss,
 | 
								Issuer: j.iss,
 | 
				
			||||||
			Subject: apiserverserviceaccount.MakeUsername(serviceAccount.Namespace, serviceAccount.Name),
 | 
					 | 
				
			||||||
		}).
 | 
							}).
 | 
				
			||||||
		Claims(&privateClaims{
 | 
							CompactSerialize()
 | 
				
			||||||
			Namespace:          serviceAccount.Namespace,
 | 
					 | 
				
			||||||
			ServiceAccountName: serviceAccount.Name,
 | 
					 | 
				
			||||||
			ServiceAccountUID:  string(serviceAccount.UID),
 | 
					 | 
				
			||||||
			SecretName:         secret.Name,
 | 
					 | 
				
			||||||
		}).CompactSerialize()
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// JWTTokenAuthenticator authenticates tokens as JWT tokens produced by JWTTokenGenerator
 | 
					// JWTTokenAuthenticator authenticates tokens as JWT tokens produced by JWTTokenGenerator
 | 
				
			||||||
@@ -139,7 +131,7 @@ type jwtTokenAuthenticator struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Validator interface {
 | 
					type Validator interface {
 | 
				
			||||||
	Validate(tokenData string, public *jwt.Claims, private *privateClaims) error
 | 
						Validate(tokenData string, public *jwt.Claims, private *legacyPrivateClaims) error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var errMismatchedSigningMethod = errors.New("invalid signing method")
 | 
					var errMismatchedSigningMethod = errors.New("invalid signing method")
 | 
				
			||||||
@@ -155,7 +147,7 @@ func (j *jwtTokenAuthenticator) AuthenticateToken(tokenData string) (user.Info,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public := &jwt.Claims{}
 | 
						public := &jwt.Claims{}
 | 
				
			||||||
	private := &privateClaims{}
 | 
						private := &legacyPrivateClaims{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		found   bool
 | 
							found   bool
 | 
				
			||||||
@@ -218,7 +210,7 @@ type legacyValidator struct {
 | 
				
			|||||||
	getter ServiceAccountTokenGetter
 | 
						getter ServiceAccountTokenGetter
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (v *legacyValidator) Validate(tokenData string, public *jwt.Claims, private *privateClaims) error {
 | 
					func (v *legacyValidator) Validate(tokenData string, public *jwt.Claims, private *legacyPrivateClaims) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Make sure the claims we need exist
 | 
						// Make sure the claims we need exist
 | 
				
			||||||
	if len(public.Subject) == 0 {
 | 
						if len(public.Subject) == 0 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -129,7 +129,7 @@ func TestTokenGenerateAndValidate(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Generate the RSA token
 | 
						// Generate the RSA token
 | 
				
			||||||
	rsaGenerator := serviceaccount.JWTTokenGenerator(serviceaccount.LegacyIssuer, getPrivateKey(rsaPrivateKey))
 | 
						rsaGenerator := serviceaccount.JWTTokenGenerator(serviceaccount.LegacyIssuer, getPrivateKey(rsaPrivateKey))
 | 
				
			||||||
	rsaToken, err := rsaGenerator.GenerateToken(*serviceAccount, *rsaSecret)
 | 
						rsaToken, err := rsaGenerator.GenerateToken(serviceaccount.LegacyClaims(*serviceAccount, *rsaSecret))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("error generating token: %v", err)
 | 
							t.Fatalf("error generating token: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -142,7 +142,7 @@ func TestTokenGenerateAndValidate(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Generate the ECDSA token
 | 
						// Generate the ECDSA token
 | 
				
			||||||
	ecdsaGenerator := serviceaccount.JWTTokenGenerator(serviceaccount.LegacyIssuer, getPrivateKey(ecdsaPrivateKey))
 | 
						ecdsaGenerator := serviceaccount.JWTTokenGenerator(serviceaccount.LegacyIssuer, getPrivateKey(ecdsaPrivateKey))
 | 
				
			||||||
	ecdsaToken, err := ecdsaGenerator.GenerateToken(*serviceAccount, *ecdsaSecret)
 | 
						ecdsaToken, err := ecdsaGenerator.GenerateToken(serviceaccount.LegacyClaims(*serviceAccount, *ecdsaSecret))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("error generating token: %v", err)
 | 
							t.Fatalf("error generating token: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -155,7 +155,7 @@ func TestTokenGenerateAndValidate(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Generate signer with same keys as RSA signer but different issuer
 | 
						// Generate signer with same keys as RSA signer but different issuer
 | 
				
			||||||
	badIssuerGenerator := serviceaccount.JWTTokenGenerator("foo", getPrivateKey(rsaPrivateKey))
 | 
						badIssuerGenerator := serviceaccount.JWTTokenGenerator("foo", getPrivateKey(rsaPrivateKey))
 | 
				
			||||||
	badIssuerToken, err := badIssuerGenerator.GenerateToken(*serviceAccount, *rsaSecret)
 | 
						badIssuerToken, err := badIssuerGenerator.GenerateToken(serviceaccount.LegacyClaims(*serviceAccount, *rsaSecret))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("error generating token: %v", err)
 | 
							t.Fatalf("error generating token: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										44
									
								
								pkg/serviceaccount/legacy.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								pkg/serviceaccount/legacy.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2018 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package serviceaccount
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"k8s.io/api/core/v1"
 | 
				
			||||||
 | 
						apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"gopkg.in/square/go-jose.v2/jwt"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func LegacyClaims(serviceAccount v1.ServiceAccount, secret v1.Secret) (*jwt.Claims, interface{}) {
 | 
				
			||||||
 | 
						return &jwt.Claims{
 | 
				
			||||||
 | 
								Subject: apiserverserviceaccount.MakeUsername(serviceAccount.Namespace, serviceAccount.Name),
 | 
				
			||||||
 | 
							}, &legacyPrivateClaims{
 | 
				
			||||||
 | 
								Namespace:          serviceAccount.Namespace,
 | 
				
			||||||
 | 
								ServiceAccountName: serviceAccount.Name,
 | 
				
			||||||
 | 
								ServiceAccountUID:  string(serviceAccount.UID),
 | 
				
			||||||
 | 
								SecretName:         secret.Name,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const LegacyIssuer = "kubernetes/serviceaccount"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type legacyPrivateClaims struct {
 | 
				
			||||||
 | 
						ServiceAccountName string `json:"kubernetes.io/serviceaccount/service-account.name"`
 | 
				
			||||||
 | 
						ServiceAccountUID  string `json:"kubernetes.io/serviceaccount/service-account.uid"`
 | 
				
			||||||
 | 
						SecretName         string `json:"kubernetes.io/serviceaccount/secret.name"`
 | 
				
			||||||
 | 
						Namespace          string `json:"kubernetes.io/serviceaccount/namespace"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user