tokens_controller.go 26 KB

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