k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/controller/serviceaccount/tokens_controller.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package serviceaccount
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"fmt"
    23  	"time"
    24  
    25  	v1 "k8s.io/api/core/v1"
    26  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/types"
    29  	utilerrors "k8s.io/apimachinery/pkg/util/errors"
    30  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    31  	"k8s.io/apimachinery/pkg/util/sets"
    32  	"k8s.io/apimachinery/pkg/util/wait"
    33  	apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount"
    34  	informers "k8s.io/client-go/informers/core/v1"
    35  	clientset "k8s.io/client-go/kubernetes"
    36  	listersv1 "k8s.io/client-go/listers/core/v1"
    37  	"k8s.io/client-go/tools/cache"
    38  	clientretry "k8s.io/client-go/util/retry"
    39  	"k8s.io/client-go/util/workqueue"
    40  	"k8s.io/klog/v2"
    41  	"k8s.io/kubernetes/pkg/serviceaccount"
    42  )
    43  
    44  // RemoveTokenBackoff is the recommended (empirical) retry interval for removing
    45  // a secret reference from a service account when the secret is deleted. It is
    46  // exported for use by custom secret controllers.
    47  var RemoveTokenBackoff = wait.Backoff{
    48  	Steps:    10,
    49  	Duration: 100 * time.Millisecond,
    50  	Jitter:   1.0,
    51  }
    52  
    53  // TokensControllerOptions contains options for the TokensController
    54  type TokensControllerOptions struct {
    55  	// TokenGenerator is the generator to use to create new tokens
    56  	TokenGenerator serviceaccount.TokenGenerator
    57  	// ServiceAccountResync is the time.Duration at which to fully re-list service accounts.
    58  	// If zero, re-list will be delayed as long as possible
    59  	ServiceAccountResync time.Duration
    60  	// SecretResync is the time.Duration at which to fully re-list secrets.
    61  	// If zero, re-list will be delayed as long as possible
    62  	SecretResync time.Duration
    63  	// This CA will be added in the secrets of service accounts
    64  	RootCA []byte
    65  
    66  	// MaxRetries controls the maximum number of times a particular key is retried before giving up
    67  	// If zero, a default max is used
    68  	MaxRetries int
    69  }
    70  
    71  // NewTokensController returns a new *TokensController.
    72  func NewTokensController(serviceAccounts informers.ServiceAccountInformer, secrets informers.SecretInformer, cl clientset.Interface, options TokensControllerOptions) (*TokensController, error) {
    73  	maxRetries := options.MaxRetries
    74  	if maxRetries == 0 {
    75  		maxRetries = 10
    76  	}
    77  
    78  	e := &TokensController{
    79  		client: cl,
    80  		token:  options.TokenGenerator,
    81  		rootCA: options.RootCA,
    82  
    83  		syncServiceAccountQueue: workqueue.NewTypedRateLimitingQueueWithConfig(
    84  			workqueue.DefaultTypedControllerRateLimiter[serviceAccountQueueKey](),
    85  			workqueue.TypedRateLimitingQueueConfig[serviceAccountQueueKey]{Name: "serviceaccount_tokens_service"},
    86  		),
    87  		syncSecretQueue: workqueue.NewTypedRateLimitingQueueWithConfig(
    88  			workqueue.DefaultTypedControllerRateLimiter[secretQueueKey](),
    89  			workqueue.TypedRateLimitingQueueConfig[secretQueueKey]{Name: "serviceaccount_tokens_service"},
    90  		),
    91  
    92  		maxRetries: maxRetries,
    93  	}
    94  
    95  	e.serviceAccounts = serviceAccounts.Lister()
    96  	e.serviceAccountSynced = serviceAccounts.Informer().HasSynced
    97  	serviceAccounts.Informer().AddEventHandlerWithResyncPeriod(
    98  		cache.ResourceEventHandlerFuncs{
    99  			AddFunc:    e.queueServiceAccountSync,
   100  			UpdateFunc: e.queueServiceAccountUpdateSync,
   101  			DeleteFunc: e.queueServiceAccountSync,
   102  		},
   103  		options.ServiceAccountResync,
   104  	)
   105  
   106  	secretCache := secrets.Informer().GetIndexer()
   107  	e.updatedSecrets = cache.NewIntegerResourceVersionMutationCache(secretCache, secretCache, 60*time.Second, true)
   108  	e.secretSynced = secrets.Informer().HasSynced
   109  	secrets.Informer().AddEventHandlerWithResyncPeriod(
   110  		cache.FilteringResourceEventHandler{
   111  			FilterFunc: func(obj interface{}) bool {
   112  				switch t := obj.(type) {
   113  				case *v1.Secret:
   114  					return t.Type == v1.SecretTypeServiceAccountToken
   115  				default:
   116  					utilruntime.HandleError(fmt.Errorf("object passed to %T that is not expected: %T", e, obj))
   117  					return false
   118  				}
   119  			},
   120  			Handler: cache.ResourceEventHandlerFuncs{
   121  				AddFunc:    e.queueSecretSync,
   122  				UpdateFunc: e.queueSecretUpdateSync,
   123  				DeleteFunc: e.queueSecretSync,
   124  			},
   125  		},
   126  		options.SecretResync,
   127  	)
   128  
   129  	return e, nil
   130  }
   131  
   132  // TokensController manages ServiceAccountToken secrets for ServiceAccount objects
   133  type TokensController struct {
   134  	client clientset.Interface
   135  	token  serviceaccount.TokenGenerator
   136  
   137  	rootCA []byte
   138  
   139  	serviceAccounts listersv1.ServiceAccountLister
   140  	// updatedSecrets is a wrapper around the shared cache which allows us to record
   141  	// and return our local mutations (since we're very likely to act on an updated
   142  	// secret before the watch reports it).
   143  	updatedSecrets cache.MutationCache
   144  
   145  	// Since we join two objects, we'll watch both of them with controllers.
   146  	serviceAccountSynced cache.InformerSynced
   147  	secretSynced         cache.InformerSynced
   148  
   149  	// syncServiceAccountQueue handles service account events:
   150  	//   * ensures tokens are removed for service accounts which no longer exist
   151  	// key is "<namespace>/<name>/<uid>"
   152  	syncServiceAccountQueue workqueue.TypedRateLimitingInterface[serviceAccountQueueKey]
   153  
   154  	// syncSecretQueue handles secret events:
   155  	//   * deletes tokens whose service account no longer exists
   156  	//   * updates tokens with missing token or namespace data, or mismatched ca data
   157  	//   * ensures service account secret references are removed for tokens which are deleted
   158  	// key is a secretQueueKey{}
   159  	syncSecretQueue workqueue.TypedRateLimitingInterface[secretQueueKey]
   160  
   161  	maxRetries int
   162  }
   163  
   164  // Run runs controller blocks until stopCh is closed
   165  func (e *TokensController) Run(ctx context.Context, workers int) {
   166  	// Shut down queues
   167  	defer utilruntime.HandleCrash()
   168  	defer e.syncServiceAccountQueue.ShutDown()
   169  	defer e.syncSecretQueue.ShutDown()
   170  
   171  	if !cache.WaitForNamedCacheSync("tokens", ctx.Done(), e.serviceAccountSynced, e.secretSynced) {
   172  		return
   173  	}
   174  
   175  	logger := klog.FromContext(ctx)
   176  	logger.V(5).Info("Starting workers")
   177  	for i := 0; i < workers; i++ {
   178  		go wait.UntilWithContext(ctx, e.syncServiceAccount, 0)
   179  		go wait.UntilWithContext(ctx, e.syncSecret, 0)
   180  	}
   181  	<-ctx.Done()
   182  	logger.V(1).Info("Shutting down")
   183  }
   184  
   185  func (e *TokensController) queueServiceAccountSync(obj interface{}) {
   186  	if serviceAccount, ok := obj.(*v1.ServiceAccount); ok {
   187  		e.syncServiceAccountQueue.Add(makeServiceAccountKey(serviceAccount))
   188  	}
   189  }
   190  
   191  func (e *TokensController) queueServiceAccountUpdateSync(oldObj interface{}, newObj interface{}) {
   192  	if serviceAccount, ok := newObj.(*v1.ServiceAccount); ok {
   193  		e.syncServiceAccountQueue.Add(makeServiceAccountKey(serviceAccount))
   194  	}
   195  }
   196  
   197  // complete optionally requeues key, then calls queue.Done(key)
   198  func retryOrForget[T comparable](logger klog.Logger, queue workqueue.TypedRateLimitingInterface[T], key T, requeue bool, maxRetries int) {
   199  	if !requeue {
   200  		queue.Forget(key)
   201  		return
   202  	}
   203  
   204  	requeueCount := queue.NumRequeues(key)
   205  	if requeueCount < maxRetries {
   206  		queue.AddRateLimited(key)
   207  		return
   208  	}
   209  
   210  	logger.V(4).Info("retried several times", "key", key, "count", requeueCount)
   211  	queue.Forget(key)
   212  }
   213  
   214  func (e *TokensController) queueSecretSync(obj interface{}) {
   215  	if secret, ok := obj.(*v1.Secret); ok {
   216  		e.syncSecretQueue.Add(makeSecretQueueKey(secret))
   217  	}
   218  }
   219  
   220  func (e *TokensController) queueSecretUpdateSync(oldObj interface{}, newObj interface{}) {
   221  	if secret, ok := newObj.(*v1.Secret); ok {
   222  		e.syncSecretQueue.Add(makeSecretQueueKey(secret))
   223  	}
   224  }
   225  
   226  func (e *TokensController) syncServiceAccount(ctx context.Context) {
   227  	logger := klog.FromContext(ctx)
   228  	key, quit := e.syncServiceAccountQueue.Get()
   229  	if quit {
   230  		return
   231  	}
   232  	defer e.syncServiceAccountQueue.Done(key)
   233  
   234  	retry := false
   235  	defer func() {
   236  		retryOrForget(logger, e.syncServiceAccountQueue, key, retry, e.maxRetries)
   237  	}()
   238  
   239  	saInfo, err := parseServiceAccountKey(key)
   240  	if err != nil {
   241  		logger.Error(err, "Parsing service account key")
   242  		return
   243  	}
   244  
   245  	sa, err := e.getServiceAccount(saInfo.namespace, saInfo.name, saInfo.uid, false)
   246  	switch {
   247  	case err != nil:
   248  		logger.Error(err, "Getting service account")
   249  		retry = true
   250  	case sa == nil:
   251  		// service account no longer exists, so delete related tokens
   252  		logger.V(4).Info("Service account deleted, removing tokens", "namespace", saInfo.namespace, "serviceaccount", saInfo.name)
   253  		sa = &v1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Namespace: saInfo.namespace, Name: saInfo.name, UID: saInfo.uid}}
   254  		retry, err = e.deleteTokens(sa)
   255  		if err != nil {
   256  			logger.Error(err, "Error deleting serviceaccount tokens", "namespace", saInfo.namespace, "serviceaccount", saInfo.name)
   257  		}
   258  	}
   259  }
   260  
   261  func (e *TokensController) syncSecret(ctx context.Context) {
   262  	key, quit := e.syncSecretQueue.Get()
   263  	if quit {
   264  		return
   265  	}
   266  	defer e.syncSecretQueue.Done(key)
   267  
   268  	logger := klog.FromContext(ctx)
   269  	// Track whether or not we should retry this sync
   270  	retry := false
   271  	defer func() {
   272  		retryOrForget(logger, e.syncSecretQueue, key, retry, e.maxRetries)
   273  	}()
   274  
   275  	secretInfo, err := parseSecretQueueKey(key)
   276  	if err != nil {
   277  		logger.Error(err, "Parsing secret queue key")
   278  		return
   279  	}
   280  
   281  	secret, err := e.getSecret(secretInfo.namespace, secretInfo.name, secretInfo.uid, false)
   282  	switch {
   283  	case err != nil:
   284  		logger.Error(err, "Getting secret")
   285  		retry = true
   286  	case secret == nil:
   287  		// If the service account exists
   288  		if sa, saErr := e.getServiceAccount(secretInfo.namespace, secretInfo.saName, secretInfo.saUID, false); saErr == nil && sa != nil {
   289  			// secret no longer exists, so delete references to this secret from the service account
   290  			if err := clientretry.RetryOnConflict(RemoveTokenBackoff, func() error {
   291  				return e.removeSecretReference(secretInfo.namespace, secretInfo.saName, secretInfo.saUID, secretInfo.name)
   292  			}); err != nil {
   293  				logger.Error(err, "Removing secret reference")
   294  			}
   295  		}
   296  	default:
   297  		// Ensure service account exists
   298  		sa, saErr := e.getServiceAccount(secretInfo.namespace, secretInfo.saName, secretInfo.saUID, true)
   299  		switch {
   300  		case saErr != nil:
   301  			logger.Error(saErr, "Getting service account")
   302  			retry = true
   303  		case sa == nil:
   304  			// Delete token
   305  			logger.V(4).Info("Service account does not exist, deleting token", "secret", klog.KRef(secretInfo.namespace, secretInfo.name))
   306  			if retriable, err := e.deleteToken(secretInfo.namespace, secretInfo.name, secretInfo.uid); err != nil {
   307  				logger.Error(err, "Deleting serviceaccount token", "secret", klog.KRef(secretInfo.namespace, secretInfo.name), "serviceAccount", klog.KRef(secretInfo.namespace, secretInfo.saName))
   308  				retry = retriable
   309  			}
   310  		default:
   311  			// Update token if needed
   312  			if retriable, err := e.generateTokenIfNeeded(logger, sa, secret); err != nil {
   313  				logger.Error(err, "Populating serviceaccount token", "secret", klog.KRef(secretInfo.namespace, secretInfo.name), "serviceAccount", klog.KRef(secretInfo.namespace, secretInfo.saName))
   314  				retry = retriable
   315  			}
   316  		}
   317  	}
   318  }
   319  
   320  func (e *TokensController) deleteTokens(serviceAccount *v1.ServiceAccount) ( /*retry*/ bool, error) {
   321  	tokens, err := e.listTokenSecrets(serviceAccount)
   322  	if err != nil {
   323  		// don't retry on cache lookup errors
   324  		return false, err
   325  	}
   326  	retry := false
   327  	errs := []error{}
   328  	for _, token := range tokens {
   329  		r, err := e.deleteToken(token.Namespace, token.Name, token.UID)
   330  		if err != nil {
   331  			errs = append(errs, err)
   332  		}
   333  		if r {
   334  			retry = true
   335  		}
   336  	}
   337  	return retry, utilerrors.NewAggregate(errs)
   338  }
   339  
   340  func (e *TokensController) deleteToken(ns, name string, uid types.UID) ( /*retry*/ bool, error) {
   341  	var opts metav1.DeleteOptions
   342  	if len(uid) > 0 {
   343  		opts.Preconditions = &metav1.Preconditions{UID: &uid}
   344  	}
   345  	err := e.client.CoreV1().Secrets(ns).Delete(context.TODO(), name, opts)
   346  	// NotFound doesn't need a retry (it's already been deleted)
   347  	// Conflict doesn't need a retry (the UID precondition failed)
   348  	if err == nil || apierrors.IsNotFound(err) || apierrors.IsConflict(err) {
   349  		return false, nil
   350  	}
   351  	// Retry for any other error
   352  	return true, err
   353  }
   354  
   355  func (e *TokensController) secretUpdateNeeded(secret *v1.Secret) (bool, bool, bool) {
   356  	caData := secret.Data[v1.ServiceAccountRootCAKey]
   357  	needsCA := len(e.rootCA) > 0 && !bytes.Equal(caData, e.rootCA)
   358  
   359  	needsNamespace := len(secret.Data[v1.ServiceAccountNamespaceKey]) == 0
   360  
   361  	tokenData := secret.Data[v1.ServiceAccountTokenKey]
   362  	needsToken := len(tokenData) == 0
   363  
   364  	return needsCA, needsNamespace, needsToken
   365  }
   366  
   367  // generateTokenIfNeeded populates the token data for the given Secret if not already set
   368  func (e *TokensController) generateTokenIfNeeded(logger klog.Logger, serviceAccount *v1.ServiceAccount, cachedSecret *v1.Secret) ( /* retry */ bool, error) {
   369  	// Check the cached secret to see if changes are needed
   370  	if needsCA, needsNamespace, needsToken := e.secretUpdateNeeded(cachedSecret); !needsCA && !needsToken && !needsNamespace {
   371  		return false, nil
   372  	}
   373  
   374  	// We don't want to update the cache's copy of the secret
   375  	// so add the token to a freshly retrieved copy of the secret
   376  	secrets := e.client.CoreV1().Secrets(cachedSecret.Namespace)
   377  	liveSecret, err := secrets.Get(context.TODO(), cachedSecret.Name, metav1.GetOptions{})
   378  	if err != nil {
   379  		// Retry for any error other than a NotFound
   380  		return !apierrors.IsNotFound(err), err
   381  	}
   382  	if liveSecret.ResourceVersion != cachedSecret.ResourceVersion {
   383  		// our view of the secret is not up to date
   384  		// we'll get notified of an update event later and get to try again
   385  		logger.V(2).Info("Secret is not up to date, skipping token population", "secret", klog.KRef(liveSecret.Namespace, liveSecret.Name))
   386  		return false, nil
   387  	}
   388  
   389  	needsCA, needsNamespace, needsToken := e.secretUpdateNeeded(liveSecret)
   390  	if !needsCA && !needsToken && !needsNamespace {
   391  		return false, nil
   392  	}
   393  
   394  	if liveSecret.Annotations == nil {
   395  		liveSecret.Annotations = map[string]string{}
   396  	}
   397  	if liveSecret.Data == nil {
   398  		liveSecret.Data = map[string][]byte{}
   399  	}
   400  
   401  	// Set the CA
   402  	if needsCA {
   403  		liveSecret.Data[v1.ServiceAccountRootCAKey] = e.rootCA
   404  	}
   405  	// Set the namespace
   406  	if needsNamespace {
   407  		liveSecret.Data[v1.ServiceAccountNamespaceKey] = []byte(liveSecret.Namespace)
   408  	}
   409  
   410  	// Generate the token
   411  	if needsToken {
   412  		token, err := e.token.GenerateToken(serviceaccount.LegacyClaims(*serviceAccount, *liveSecret))
   413  		if err != nil {
   414  			return false, err
   415  		}
   416  		liveSecret.Data[v1.ServiceAccountTokenKey] = []byte(token)
   417  	}
   418  
   419  	// Set annotations
   420  	liveSecret.Annotations[v1.ServiceAccountNameKey] = serviceAccount.Name
   421  	liveSecret.Annotations[v1.ServiceAccountUIDKey] = string(serviceAccount.UID)
   422  
   423  	// Save the secret
   424  	_, err = secrets.Update(context.TODO(), liveSecret, metav1.UpdateOptions{})
   425  	if apierrors.IsConflict(err) || apierrors.IsNotFound(err) {
   426  		// if we got a Conflict error, the secret was updated by someone else, and we'll get an update notification later
   427  		// if we got a NotFound error, the secret no longer exists, and we don't need to populate a token
   428  		return false, nil
   429  	}
   430  	if err != nil {
   431  		return true, err
   432  	}
   433  	return false, nil
   434  }
   435  
   436  // removeSecretReference updates the given ServiceAccount to remove a reference to the given secretName if needed.
   437  func (e *TokensController) removeSecretReference(saNamespace string, saName string, saUID types.UID, secretName string) error {
   438  	// We don't want to update the cache's copy of the service account
   439  	// so remove the secret from a freshly retrieved copy of the service account
   440  	serviceAccounts := e.client.CoreV1().ServiceAccounts(saNamespace)
   441  	serviceAccount, err := serviceAccounts.Get(context.TODO(), saName, metav1.GetOptions{})
   442  	// Ignore NotFound errors when attempting to remove a reference
   443  	if apierrors.IsNotFound(err) {
   444  		return nil
   445  	}
   446  	if err != nil {
   447  		return err
   448  	}
   449  
   450  	// Short-circuit if the UID doesn't match
   451  	if len(saUID) > 0 && saUID != serviceAccount.UID {
   452  		return nil
   453  	}
   454  
   455  	// Short-circuit if the secret is no longer referenced
   456  	if !getSecretReferences(serviceAccount).Has(secretName) {
   457  		return nil
   458  	}
   459  
   460  	// Remove the secret
   461  	secrets := []v1.ObjectReference{}
   462  	for _, s := range serviceAccount.Secrets {
   463  		if s.Name != secretName {
   464  			secrets = append(secrets, s)
   465  		}
   466  	}
   467  	serviceAccount.Secrets = secrets
   468  	_, err = serviceAccounts.Update(context.TODO(), serviceAccount, metav1.UpdateOptions{})
   469  	// Ignore NotFound errors when attempting to remove a reference
   470  	if apierrors.IsNotFound(err) {
   471  		return nil
   472  	}
   473  	return err
   474  }
   475  
   476  func (e *TokensController) getServiceAccount(ns string, name string, uid types.UID, fetchOnCacheMiss bool) (*v1.ServiceAccount, error) {
   477  	// Look up in cache
   478  	sa, err := e.serviceAccounts.ServiceAccounts(ns).Get(name)
   479  	if err != nil && !apierrors.IsNotFound(err) {
   480  		return nil, err
   481  	}
   482  	if sa != nil {
   483  		// Ensure UID matches if given
   484  		if len(uid) == 0 || uid == sa.UID {
   485  			return sa, nil
   486  		}
   487  	}
   488  
   489  	if !fetchOnCacheMiss {
   490  		return nil, nil
   491  	}
   492  
   493  	// Live lookup
   494  	sa, err = e.client.CoreV1().ServiceAccounts(ns).Get(context.TODO(), name, metav1.GetOptions{})
   495  	if apierrors.IsNotFound(err) {
   496  		return nil, nil
   497  	}
   498  	if err != nil {
   499  		return nil, err
   500  	}
   501  	// Ensure UID matches if given
   502  	if len(uid) == 0 || uid == sa.UID {
   503  		return sa, nil
   504  	}
   505  	return nil, nil
   506  }
   507  
   508  func (e *TokensController) getSecret(ns string, name string, uid types.UID, fetchOnCacheMiss bool) (*v1.Secret, error) {
   509  	// Look up in cache
   510  	obj, exists, err := e.updatedSecrets.GetByKey(makeCacheKey(ns, name))
   511  	if err != nil {
   512  		return nil, err
   513  	}
   514  	if exists {
   515  		secret, ok := obj.(*v1.Secret)
   516  		if !ok {
   517  			return nil, fmt.Errorf("expected *v1.Secret, got %#v", secret)
   518  		}
   519  		// Ensure UID matches if given
   520  		if len(uid) == 0 || uid == secret.UID {
   521  			return secret, nil
   522  		}
   523  	}
   524  
   525  	if !fetchOnCacheMiss {
   526  		return nil, nil
   527  	}
   528  
   529  	// Live lookup
   530  	secret, err := e.client.CoreV1().Secrets(ns).Get(context.TODO(), name, metav1.GetOptions{})
   531  	if apierrors.IsNotFound(err) {
   532  		return nil, nil
   533  	}
   534  	if err != nil {
   535  		return nil, err
   536  	}
   537  	// Ensure UID matches if given
   538  	if len(uid) == 0 || uid == secret.UID {
   539  		return secret, nil
   540  	}
   541  	return nil, nil
   542  }
   543  
   544  // listTokenSecrets returns a list of all of the ServiceAccountToken secrets that
   545  // reference the given service account's name and uid
   546  func (e *TokensController) listTokenSecrets(serviceAccount *v1.ServiceAccount) ([]*v1.Secret, error) {
   547  	namespaceSecrets, err := e.updatedSecrets.ByIndex("namespace", serviceAccount.Namespace)
   548  	if err != nil {
   549  		return nil, err
   550  	}
   551  
   552  	items := []*v1.Secret{}
   553  	for _, obj := range namespaceSecrets {
   554  		secret := obj.(*v1.Secret)
   555  
   556  		if apiserverserviceaccount.IsServiceAccountToken(secret, serviceAccount) {
   557  			items = append(items, secret)
   558  		}
   559  	}
   560  	return items, nil
   561  }
   562  
   563  func getSecretReferences(serviceAccount *v1.ServiceAccount) sets.String {
   564  	references := sets.NewString()
   565  	for _, secret := range serviceAccount.Secrets {
   566  		references.Insert(secret.Name)
   567  	}
   568  	return references
   569  }
   570  
   571  // serviceAccountQueueKey holds information we need to sync a service account.
   572  // It contains enough information to look up the cached service account,
   573  // or delete owned tokens if the service account no longer exists.
   574  type serviceAccountQueueKey struct {
   575  	namespace string
   576  	name      string
   577  	uid       types.UID
   578  }
   579  
   580  func makeServiceAccountKey(sa *v1.ServiceAccount) serviceAccountQueueKey {
   581  	return serviceAccountQueueKey{
   582  		namespace: sa.Namespace,
   583  		name:      sa.Name,
   584  		uid:       sa.UID,
   585  	}
   586  }
   587  
   588  func parseServiceAccountKey(key interface{}) (serviceAccountQueueKey, error) {
   589  	queueKey, ok := key.(serviceAccountQueueKey)
   590  	if !ok || len(queueKey.namespace) == 0 || len(queueKey.name) == 0 || len(queueKey.uid) == 0 {
   591  		return serviceAccountQueueKey{}, fmt.Errorf("invalid serviceaccount key: %#v", key)
   592  	}
   593  	return queueKey, nil
   594  }
   595  
   596  // secretQueueKey holds information we need to sync a service account token secret.
   597  // It contains enough information to look up the cached service account,
   598  // or delete the secret reference if the secret no longer exists.
   599  type secretQueueKey struct {
   600  	namespace string
   601  	name      string
   602  	uid       types.UID
   603  	saName    string
   604  	// optional, will be blank when syncing tokens missing the service account uid annotation
   605  	saUID types.UID
   606  }
   607  
   608  func makeSecretQueueKey(secret *v1.Secret) secretQueueKey {
   609  	return secretQueueKey{
   610  		namespace: secret.Namespace,
   611  		name:      secret.Name,
   612  		uid:       secret.UID,
   613  		saName:    secret.Annotations[v1.ServiceAccountNameKey],
   614  		saUID:     types.UID(secret.Annotations[v1.ServiceAccountUIDKey]),
   615  	}
   616  }
   617  
   618  func parseSecretQueueKey(key interface{}) (secretQueueKey, error) {
   619  	queueKey, ok := key.(secretQueueKey)
   620  	if !ok || len(queueKey.namespace) == 0 || len(queueKey.name) == 0 || len(queueKey.uid) == 0 || len(queueKey.saName) == 0 {
   621  		return secretQueueKey{}, fmt.Errorf("invalid secret key: %#v", key)
   622  	}
   623  	return queueKey, nil
   624  }
   625  
   626  // produce the same key format as cache.MetaNamespaceKeyFunc
   627  func makeCacheKey(namespace, name string) string {
   628  	return namespace + "/" + name
   629  }