2015-04-21 03:25:56 +00:00
/ *
Copyright 2014 The Kubernetes Authors All rights reserved .
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 (
2015-07-15 12:53:21 +00:00
"bytes"
2015-04-21 03:25:56 +00:00
"fmt"
"time"
2015-08-05 22:05:17 +00:00
"github.com/golang/glog"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/api"
apierrors "k8s.io/kubernetes/pkg/api/errors"
2015-09-03 21:40:58 +00:00
"k8s.io/kubernetes/pkg/client/cache"
2016-02-05 21:58:03 +00:00
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
2015-09-03 21:43:19 +00:00
client "k8s.io/kubernetes/pkg/client/unversioned"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/controller/framework"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/registry/secret"
"k8s.io/kubernetes/pkg/runtime"
2015-12-24 21:54:40 +00:00
"k8s.io/kubernetes/pkg/serviceaccount"
2016-04-13 18:38:32 +00:00
"k8s.io/kubernetes/pkg/util/metrics"
2016-01-15 07:32:10 +00:00
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
2015-09-09 17:45:01 +00:00
"k8s.io/kubernetes/pkg/util/sets"
2015-06-02 05:36:18 +00:00
"k8s.io/kubernetes/pkg/util/wait"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/watch"
2015-04-21 03:25:56 +00:00
)
2015-10-22 02:09:05 +00:00
// RemoveTokenBackoff is the recommended (empirical) retry interval for removing
// a secret reference from a service account when the secret is deleted. It is
// exported for use by custom secret controllers.
var RemoveTokenBackoff = wait . Backoff {
Steps : 10 ,
Duration : 100 * time . Millisecond ,
Jitter : 1.0 ,
}
2015-06-02 05:36:18 +00:00
2015-04-21 03:25:56 +00:00
// TokensControllerOptions contains options for the TokensController
type TokensControllerOptions struct {
// TokenGenerator is the generator to use to create new tokens
2015-12-24 21:54:40 +00:00
TokenGenerator serviceaccount . TokenGenerator
2015-04-21 03:25:56 +00:00
// ServiceAccountResync is the time.Duration at which to fully re-list service accounts.
// If zero, re-list will be delayed as long as possible
ServiceAccountResync time . Duration
// SecretResync is the time.Duration at which to fully re-list secrets.
// If zero, re-list will be delayed as long as possible
SecretResync time . Duration
2015-06-23 22:43:59 +00:00
// This CA will be added in the secretes of service accounts
RootCA [ ] byte
2015-04-21 03:25:56 +00:00
}
// NewTokensController returns a new *TokensController.
2016-01-29 06:34:08 +00:00
func NewTokensController ( cl clientset . Interface , options TokensControllerOptions ) * TokensController {
2015-04-21 03:25:56 +00:00
e := & TokensController {
client : cl ,
token : options . TokenGenerator ,
2015-06-23 22:43:59 +00:00
rootCA : options . RootCA ,
2015-04-21 03:25:56 +00:00
}
2016-04-13 18:38:32 +00:00
if cl != nil && cl . Core ( ) . GetRESTClient ( ) . GetRateLimiter ( ) != nil {
metrics . RegisterMetricAndTrackRateLimiterUsage ( "serviceaccount_controller" , cl . Core ( ) . GetRESTClient ( ) . GetRateLimiter ( ) )
}
2015-04-21 03:25:56 +00:00
e . serviceAccounts , e . serviceAccountController = framework . NewIndexerInformer (
& cache . ListWatch {
2015-12-10 09:39:03 +00:00
ListFunc : func ( options api . ListOptions ) ( runtime . Object , error ) {
2016-02-03 21:21:05 +00:00
return e . client . Core ( ) . ServiceAccounts ( api . NamespaceAll ) . List ( options )
2015-04-21 03:25:56 +00:00
} ,
2015-12-10 09:39:03 +00:00
WatchFunc : func ( options api . ListOptions ) ( watch . Interface , error ) {
2016-02-03 21:21:05 +00:00
return e . client . Core ( ) . ServiceAccounts ( api . NamespaceAll ) . Watch ( options )
2015-04-21 03:25:56 +00:00
} ,
} ,
& api . ServiceAccount { } ,
options . ServiceAccountResync ,
framework . ResourceEventHandlerFuncs {
AddFunc : e . serviceAccountAdded ,
UpdateFunc : e . serviceAccountUpdated ,
DeleteFunc : e . serviceAccountDeleted ,
} ,
cache . Indexers { "namespace" : cache . MetaNamespaceIndexFunc } ,
)
2016-02-12 18:58:43 +00:00
tokenSelector := fields . SelectorFromSet ( map [ string ] string { api . SecretTypeField : string ( api . SecretTypeServiceAccountToken ) } )
2015-04-21 03:25:56 +00:00
e . secrets , e . secretController = framework . NewIndexerInformer (
& cache . ListWatch {
2015-12-10 09:39:03 +00:00
ListFunc : func ( options api . ListOptions ) ( runtime . Object , error ) {
options . FieldSelector = tokenSelector
2016-02-03 21:21:05 +00:00
return e . client . Core ( ) . Secrets ( api . NamespaceAll ) . List ( options )
2015-04-21 03:25:56 +00:00
} ,
2015-12-10 09:39:03 +00:00
WatchFunc : func ( options api . ListOptions ) ( watch . Interface , error ) {
options . FieldSelector = tokenSelector
2016-02-03 21:21:05 +00:00
return e . client . Core ( ) . Secrets ( api . NamespaceAll ) . Watch ( options )
2015-04-21 03:25:56 +00:00
} ,
} ,
& api . Secret { } ,
options . SecretResync ,
framework . ResourceEventHandlerFuncs {
AddFunc : e . secretAdded ,
UpdateFunc : e . secretUpdated ,
DeleteFunc : e . secretDeleted ,
} ,
cache . Indexers { "namespace" : cache . MetaNamespaceIndexFunc } ,
)
2015-05-19 09:24:17 +00:00
e . serviceAccountsSynced = e . serviceAccountController . HasSynced
e . secretsSynced = e . secretController . HasSynced
2015-04-21 03:25:56 +00:00
return e
}
// TokensController manages ServiceAccountToken secrets for ServiceAccount objects
type TokensController struct {
stopChan chan struct { }
2016-01-29 06:34:08 +00:00
client clientset . Interface
2015-12-24 21:54:40 +00:00
token serviceaccount . TokenGenerator
2015-04-21 03:25:56 +00:00
2015-06-23 22:43:59 +00:00
rootCA [ ] byte
2015-04-21 03:25:56 +00:00
serviceAccounts cache . Indexer
secrets cache . Indexer
// Since we join two objects, we'll watch both of them with controllers.
serviceAccountController * framework . Controller
secretController * framework . Controller
2015-05-19 09:24:17 +00:00
// These are here so tests can inject a 'return true'.
serviceAccountsSynced func ( ) bool
secretsSynced func ( ) bool
2015-04-21 03:25:56 +00:00
}
// Runs controller loops and returns immediately
func ( e * TokensController ) Run ( ) {
if e . stopChan == nil {
e . stopChan = make ( chan struct { } )
go e . serviceAccountController . Run ( e . stopChan )
go e . secretController . Run ( e . stopChan )
}
}
// Stop gracefully shuts down this controller
func ( e * TokensController ) Stop ( ) {
if e . stopChan != nil {
close ( e . stopChan )
e . stopChan = nil
}
}
// serviceAccountAdded reacts to a ServiceAccount creation by creating a corresponding ServiceAccountToken Secret
func ( e * TokensController ) serviceAccountAdded ( obj interface { } ) {
serviceAccount := obj . ( * api . ServiceAccount )
err := e . createSecretIfNeeded ( serviceAccount )
if err != nil {
glog . Error ( err )
}
}
// serviceAccountUpdated reacts to a ServiceAccount update (or re-list) by ensuring a corresponding ServiceAccountToken Secret exists
func ( e * TokensController ) serviceAccountUpdated ( oldObj interface { } , newObj interface { } ) {
newServiceAccount := newObj . ( * api . ServiceAccount )
err := e . createSecretIfNeeded ( newServiceAccount )
if err != nil {
glog . Error ( err )
}
}
// serviceAccountDeleted reacts to a ServiceAccount deletion by deleting all corresponding ServiceAccountToken Secrets
func ( e * TokensController ) serviceAccountDeleted ( obj interface { } ) {
serviceAccount , ok := obj . ( * api . ServiceAccount )
if ! ok {
// Unknown type. If we missed a ServiceAccount deletion, the
// corresponding secrets will be cleaned up during the Secret re-list
return
}
secrets , err := e . listTokenSecrets ( serviceAccount )
if err != nil {
glog . Error ( err )
return
}
for _ , secret := range secrets {
2015-06-18 14:41:35 +00:00
glog . V ( 4 ) . Infof ( "Deleting secret %s/%s because service account %s was deleted" , secret . Namespace , secret . Name , serviceAccount . Name )
2015-04-21 03:25:56 +00:00
if err := e . deleteSecret ( secret ) ; err != nil {
glog . Errorf ( "Error deleting secret %s/%s: %v" , secret . Namespace , secret . Name , err )
}
}
}
// secretAdded reacts to a Secret create by ensuring the referenced ServiceAccount exists, and by adding a token to the secret if needed
func ( e * TokensController ) secretAdded ( obj interface { } ) {
secret := obj . ( * api . Secret )
2015-06-18 14:42:41 +00:00
serviceAccount , err := e . getServiceAccount ( secret , true )
2015-04-21 03:25:56 +00:00
if err != nil {
glog . Error ( err )
return
}
if serviceAccount == nil {
2015-06-18 14:41:35 +00:00
glog . V ( 2 ) . Infof (
"Deleting new secret %s/%s because service account %s (uid=%s) was not found" ,
secret . Namespace , secret . Name ,
secret . Annotations [ api . ServiceAccountNameKey ] , secret . Annotations [ api . ServiceAccountUIDKey ] )
2015-04-21 03:25:56 +00:00
if err := e . deleteSecret ( secret ) ; err != nil {
glog . Errorf ( "Error deleting secret %s/%s: %v" , secret . Namespace , secret . Name , err )
}
} else {
e . generateTokenIfNeeded ( serviceAccount , secret )
}
}
// secretUpdated reacts to a Secret update (or re-list) by deleting the secret (if the referenced ServiceAccount does not exist)
func ( e * TokensController ) secretUpdated ( oldObj interface { } , newObj interface { } ) {
newSecret := newObj . ( * api . Secret )
2015-06-18 14:42:41 +00:00
newServiceAccount , err := e . getServiceAccount ( newSecret , true )
2015-04-21 03:25:56 +00:00
if err != nil {
glog . Error ( err )
return
}
if newServiceAccount == nil {
2015-06-18 14:41:35 +00:00
glog . V ( 2 ) . Infof (
"Deleting updated secret %s/%s because service account %s (uid=%s) was not found" ,
newSecret . Namespace , newSecret . Name ,
newSecret . Annotations [ api . ServiceAccountNameKey ] , newSecret . Annotations [ api . ServiceAccountUIDKey ] )
2015-04-21 03:25:56 +00:00
if err := e . deleteSecret ( newSecret ) ; err != nil {
glog . Errorf ( "Error deleting secret %s/%s: %v" , newSecret . Namespace , newSecret . Name , err )
}
} else {
e . generateTokenIfNeeded ( newServiceAccount , newSecret )
}
}
// secretDeleted reacts to a Secret being deleted by removing a reference from the corresponding ServiceAccount if needed
func ( e * TokensController ) secretDeleted ( obj interface { } ) {
secret , ok := obj . ( * api . Secret )
if ! ok {
// Unknown type. If we missed a Secret deletion, the corresponding ServiceAccount (if it exists)
// will get a secret recreated (if needed) during the ServiceAccount re-list
return
}
2015-06-18 14:42:41 +00:00
serviceAccount , err := e . getServiceAccount ( secret , false )
2015-04-21 03:25:56 +00:00
if err != nil {
glog . Error ( err )
return
}
if serviceAccount == nil {
return
}
2015-10-22 02:09:05 +00:00
if err := client . RetryOnConflict ( RemoveTokenBackoff , func ( ) error {
return e . removeSecretReferenceIfNeeded ( serviceAccount , secret . Name )
} ) ; err != nil {
2016-01-15 07:32:10 +00:00
utilruntime . HandleError ( err )
2015-04-21 03:25:56 +00:00
}
}
// createSecretIfNeeded makes sure at least one ServiceAccountToken secret exists, and is included in the serviceAccount's Secrets list
func ( e * TokensController ) createSecretIfNeeded ( serviceAccount * api . ServiceAccount ) error {
// If the service account references no secrets, short-circuit and create a new one
if len ( serviceAccount . Secrets ) == 0 {
return e . createSecret ( serviceAccount )
}
2015-06-05 18:21:28 +00:00
// We shouldn't try to validate secret references until the secrets store is synced
if ! e . secretsSynced ( ) {
return nil
}
2015-04-21 03:25:56 +00:00
// If any existing token secrets are referenced by the service account, return
allSecrets , err := e . listTokenSecrets ( serviceAccount )
if err != nil {
return err
}
referencedSecrets := getSecretReferences ( serviceAccount )
for _ , secret := range allSecrets {
if referencedSecrets . Has ( secret . Name ) {
return nil
}
}
// Otherwise create a new token secret
return e . createSecret ( serviceAccount )
}
// createSecret creates a secret of type ServiceAccountToken for the given ServiceAccount
func ( e * TokensController ) createSecret ( serviceAccount * api . ServiceAccount ) error {
2015-06-02 05:36:18 +00:00
// We don't want to update the cache's copy of the service account
// so add the secret to a freshly retrieved copy of the service account
2016-02-03 21:21:05 +00:00
serviceAccounts := e . client . Core ( ) . ServiceAccounts ( serviceAccount . Namespace )
2015-06-02 05:36:18 +00:00
liveServiceAccount , err := serviceAccounts . Get ( serviceAccount . Name )
if err != nil {
return err
}
if liveServiceAccount . ResourceVersion != serviceAccount . ResourceVersion {
// our view of the service account is not up to date
// we'll get notified of an update event later and get to try again
// this only prevent interactions between successive runs of this controller's event handlers, but that is useful
glog . V ( 2 ) . Infof ( "View of ServiceAccount %s/%s is not up to date, skipping token creation" , serviceAccount . Namespace , serviceAccount . Name )
return nil
}
2015-04-21 03:25:56 +00:00
// Build the secret
secret := & api . Secret {
ObjectMeta : api . ObjectMeta {
Name : secret . Strategy . GenerateName ( fmt . Sprintf ( "%s-token-" , serviceAccount . Name ) ) ,
Namespace : serviceAccount . Namespace ,
Annotations : map [ string ] string {
api . ServiceAccountNameKey : serviceAccount . Name ,
api . ServiceAccountUIDKey : string ( serviceAccount . UID ) ,
} ,
} ,
Type : api . SecretTypeServiceAccountToken ,
Data : map [ string ] [ ] byte { } ,
}
// Generate the token
token , err := e . token . GenerateToken ( * serviceAccount , * secret )
if err != nil {
return err
}
secret . Data [ api . ServiceAccountTokenKey ] = [ ] byte ( token )
2016-02-11 19:46:56 +00:00
secret . Data [ api . ServiceAccountNamespaceKey ] = [ ] byte ( serviceAccount . Namespace )
2015-06-23 22:43:59 +00:00
if e . rootCA != nil && len ( e . rootCA ) > 0 {
secret . Data [ api . ServiceAccountRootCAKey ] = e . rootCA
}
2015-04-21 03:25:56 +00:00
// Save the secret
2016-02-22 21:14:00 +00:00
if createdToken , err := e . client . Core ( ) . Secrets ( serviceAccount . Namespace ) . Create ( secret ) ; err != nil {
2015-04-21 03:25:56 +00:00
return err
2016-02-22 21:14:00 +00:00
} else {
// Manually add the new token to the cache store.
// This prevents the service account update (below) triggering another token creation, if the referenced token couldn't be found in the store
e . secrets . Add ( createdToken )
2015-04-21 03:25:56 +00:00
}
2015-06-02 05:36:18 +00:00
liveServiceAccount . Secrets = append ( liveServiceAccount . Secrets , api . ObjectReference { Name : secret . Name } )
2015-04-21 03:25:56 +00:00
2015-06-02 05:36:18 +00:00
_ , err = serviceAccounts . Update ( liveServiceAccount )
2015-04-21 03:25:56 +00:00
if err != nil {
2015-06-02 05:35:45 +00:00
// we weren't able to use the token, try to clean it up.
glog . V ( 2 ) . Infof ( "Deleting secret %s/%s because reference couldn't be added (%v)" , secret . Namespace , secret . Name , err )
2016-02-03 21:21:05 +00:00
if err := e . client . Core ( ) . Secrets ( secret . Namespace ) . Delete ( secret . Name , nil ) ; err != nil {
2015-06-02 05:35:45 +00:00
glog . Error ( err ) // if we fail, just log it
}
2015-04-21 03:25:56 +00:00
}
2015-06-02 05:35:45 +00:00
if apierrors . IsConflict ( err ) {
// nothing to do. We got a conflict, that means that the service account was updated. We simply need to return because we'll get an update notification later
return nil
}
return err
2015-04-21 03:25:56 +00:00
}
// generateTokenIfNeeded populates the token data for the given Secret if not already set
func ( e * TokensController ) generateTokenIfNeeded ( serviceAccount * api . ServiceAccount , secret * api . Secret ) error {
if secret . Annotations == nil {
secret . Annotations = map [ string ] string { }
}
if secret . Data == nil {
secret . Data = map [ string ] [ ] byte { }
}
2015-07-15 12:53:21 +00:00
caData := secret . Data [ api . ServiceAccountRootCAKey ]
needsCA := len ( e . rootCA ) > 0 && bytes . Compare ( caData , e . rootCA ) != 0
2016-02-11 19:46:56 +00:00
needsNamespace := len ( secret . Data [ api . ServiceAccountNamespaceKey ] ) == 0
2015-07-15 12:53:21 +00:00
tokenData := secret . Data [ api . ServiceAccountTokenKey ]
needsToken := len ( tokenData ) == 0
2016-02-11 19:46:56 +00:00
if ! needsCA && ! needsToken && ! needsNamespace {
2015-04-21 03:25:56 +00:00
return nil
}
2015-07-15 12:53:21 +00:00
// Set the CA
if needsCA {
2015-06-23 22:43:59 +00:00
secret . Data [ api . ServiceAccountRootCAKey ] = e . rootCA
}
2016-02-11 19:46:56 +00:00
// Set the namespace
if needsNamespace {
secret . Data [ api . ServiceAccountNamespaceKey ] = [ ] byte ( secret . Namespace )
}
2015-04-21 03:25:56 +00:00
// Generate the token
2015-07-15 12:53:21 +00:00
if needsToken {
token , err := e . token . GenerateToken ( * serviceAccount , * secret )
if err != nil {
return err
}
secret . Data [ api . ServiceAccountTokenKey ] = [ ] byte ( token )
2015-04-21 03:25:56 +00:00
}
2015-07-15 12:53:21 +00:00
// Set annotations
2015-04-21 03:25:56 +00:00
secret . Annotations [ api . ServiceAccountNameKey ] = serviceAccount . Name
secret . Annotations [ api . ServiceAccountUIDKey ] = string ( serviceAccount . UID )
// Save the secret
2016-02-03 21:21:05 +00:00
if _ , err := e . client . Core ( ) . Secrets ( secret . Namespace ) . Update ( secret ) ; err != nil {
2015-04-21 03:25:56 +00:00
return err
}
return nil
}
// deleteSecret deletes the given secret
func ( e * TokensController ) deleteSecret ( secret * api . Secret ) error {
2016-02-03 21:21:05 +00:00
return e . client . Core ( ) . Secrets ( secret . Namespace ) . Delete ( secret . Name , nil )
2015-04-21 03:25:56 +00:00
}
// removeSecretReferenceIfNeeded updates the given ServiceAccount to remove a reference to the given secretName if needed.
// Returns whether an update was performed, and any error that occurred
2015-10-22 02:09:05 +00:00
func ( e * TokensController ) removeSecretReferenceIfNeeded ( serviceAccount * api . ServiceAccount , secretName string ) error {
2015-04-21 03:25:56 +00:00
// We don't want to update the cache's copy of the service account
// so remove the secret from a freshly retrieved copy of the service account
2016-02-03 21:21:05 +00:00
serviceAccounts := e . client . Core ( ) . ServiceAccounts ( serviceAccount . Namespace )
2015-04-21 03:25:56 +00:00
serviceAccount , err := serviceAccounts . Get ( serviceAccount . Name )
if err != nil {
2015-10-22 02:09:05 +00:00
return err
2015-04-21 03:25:56 +00:00
}
// Double-check to see if the account still references the secret
if ! getSecretReferences ( serviceAccount ) . Has ( secretName ) {
2015-10-22 02:09:05 +00:00
return nil
2015-04-21 03:25:56 +00:00
}
secrets := [ ] api . ObjectReference { }
for _ , s := range serviceAccount . Secrets {
if s . Name != secretName {
secrets = append ( secrets , s )
}
}
serviceAccount . Secrets = secrets
_ , err = serviceAccounts . Update ( serviceAccount )
if err != nil {
2015-10-22 02:09:05 +00:00
return err
2015-04-21 03:25:56 +00:00
}
2015-10-22 02:09:05 +00:00
return nil
2015-04-21 03:25:56 +00:00
}
// getServiceAccount returns the ServiceAccount referenced by the given secret. If the secret is not
// of type ServiceAccountToken, or if the referenced ServiceAccount does not exist, nil is returned
2015-06-18 14:42:41 +00:00
func ( e * TokensController ) getServiceAccount ( secret * api . Secret , fetchOnCacheMiss bool ) ( * api . ServiceAccount , error ) {
2015-09-16 20:04:26 +00:00
name , _ := serviceAccountNameAndUID ( secret )
2015-04-21 03:25:56 +00:00
if len ( name ) == 0 {
return nil , nil
}
key := & api . ServiceAccount { ObjectMeta : api . ObjectMeta { Namespace : secret . Namespace } }
namespaceAccounts , err := e . serviceAccounts . Index ( "namespace" , key )
if err != nil {
return nil , err
}
for _ , obj := range namespaceAccounts {
serviceAccount := obj . ( * api . ServiceAccount )
2015-09-16 20:04:26 +00:00
2015-12-24 21:54:40 +00:00
if serviceaccount . IsServiceAccountToken ( secret , serviceAccount ) {
2015-09-16 20:04:26 +00:00
return serviceAccount , nil
2015-04-21 03:25:56 +00:00
}
}
2015-06-18 14:42:41 +00:00
if fetchOnCacheMiss {
2016-02-03 21:21:05 +00:00
serviceAccount , err := e . client . Core ( ) . ServiceAccounts ( secret . Namespace ) . Get ( name )
2015-06-18 14:42:41 +00:00
if apierrors . IsNotFound ( err ) {
return nil , nil
}
if err != nil {
return nil , err
}
2015-09-16 20:04:26 +00:00
2015-12-24 21:54:40 +00:00
if serviceaccount . IsServiceAccountToken ( secret , serviceAccount ) {
2015-09-16 20:04:26 +00:00
return serviceAccount , nil
2015-06-18 14:42:41 +00:00
}
}
2015-04-21 03:25:56 +00:00
return nil , nil
}
// listTokenSecrets returns a list of all of the ServiceAccountToken secrets that
// reference the given service account's name and uid
func ( e * TokensController ) listTokenSecrets ( serviceAccount * api . ServiceAccount ) ( [ ] * api . Secret , error ) {
key := & api . Secret { ObjectMeta : api . ObjectMeta { Namespace : serviceAccount . Namespace } }
namespaceSecrets , err := e . secrets . Index ( "namespace" , key )
if err != nil {
return nil , err
}
items := [ ] * api . Secret { }
for _ , obj := range namespaceSecrets {
secret := obj . ( * api . Secret )
2015-09-16 20:04:26 +00:00
2015-12-24 21:54:40 +00:00
if serviceaccount . IsServiceAccountToken ( secret , serviceAccount ) {
2015-09-16 20:04:26 +00:00
items = append ( items , secret )
2015-04-21 03:25:56 +00:00
}
}
return items , nil
}
// serviceAccountNameAndUID is a helper method to get the ServiceAccount Name and UID from the given secret
// Returns "","" if the secret is not a ServiceAccountToken secret
// If the name or uid annotation is missing, "" is returned instead
func serviceAccountNameAndUID ( secret * api . Secret ) ( string , string ) {
if secret . Type != api . SecretTypeServiceAccountToken {
return "" , ""
}
return secret . Annotations [ api . ServiceAccountNameKey ] , secret . Annotations [ api . ServiceAccountUIDKey ]
}
2015-09-09 17:45:01 +00:00
func getSecretReferences ( serviceAccount * api . ServiceAccount ) sets . String {
references := sets . NewString ( )
2015-04-21 03:25:56 +00:00
for _ , secret := range serviceAccount . Secrets {
references . Insert ( secret . Name )
}
return references
}