tokens_controller.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  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. "fmt"
  17. "time"
  18. "github.com/golang/glog"
  19. "k8s.io/kubernetes/pkg/api"
  20. apierrors "k8s.io/kubernetes/pkg/api/errors"
  21. "k8s.io/kubernetes/pkg/client/cache"
  22. clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
  23. client "k8s.io/kubernetes/pkg/client/unversioned"
  24. "k8s.io/kubernetes/pkg/controller/framework"
  25. "k8s.io/kubernetes/pkg/fields"
  26. "k8s.io/kubernetes/pkg/registry/secret"
  27. "k8s.io/kubernetes/pkg/runtime"
  28. "k8s.io/kubernetes/pkg/serviceaccount"
  29. "k8s.io/kubernetes/pkg/types"
  30. utilerrors "k8s.io/kubernetes/pkg/util/errors"
  31. "k8s.io/kubernetes/pkg/util/metrics"
  32. utilruntime "k8s.io/kubernetes/pkg/util/runtime"
  33. "k8s.io/kubernetes/pkg/util/sets"
  34. "k8s.io/kubernetes/pkg/util/wait"
  35. "k8s.io/kubernetes/pkg/util/workqueue"
  36. "k8s.io/kubernetes/pkg/watch"
  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(cl clientset.Interface, options TokensControllerOptions) *TokensController {
  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.Core().GetRESTClient().GetRateLimiter() != nil {
  77. metrics.RegisterMetricAndTrackRateLimiterUsage("serviceaccount_controller", cl.Core().GetRESTClient().GetRateLimiter())
  78. }
  79. e.serviceAccounts, e.serviceAccountController = framework.NewInformer(
  80. &cache.ListWatch{
  81. ListFunc: func(options api.ListOptions) (runtime.Object, error) {
  82. return e.client.Core().ServiceAccounts(api.NamespaceAll).List(options)
  83. },
  84. WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
  85. return e.client.Core().ServiceAccounts(api.NamespaceAll).Watch(options)
  86. },
  87. },
  88. &api.ServiceAccount{},
  89. options.ServiceAccountResync,
  90. framework.ResourceEventHandlerFuncs{
  91. AddFunc: e.queueServiceAccountSync,
  92. UpdateFunc: e.queueServiceAccountUpdateSync,
  93. DeleteFunc: e.queueServiceAccountSync,
  94. },
  95. )
  96. tokenSelector := fields.SelectorFromSet(map[string]string{api.SecretTypeField: string(api.SecretTypeServiceAccountToken)})
  97. e.secrets, e.secretController = framework.NewIndexerInformer(
  98. &cache.ListWatch{
  99. ListFunc: func(options api.ListOptions) (runtime.Object, error) {
  100. options.FieldSelector = tokenSelector
  101. return e.client.Core().Secrets(api.NamespaceAll).List(options)
  102. },
  103. WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
  104. options.FieldSelector = tokenSelector
  105. return e.client.Core().Secrets(api.NamespaceAll).Watch(options)
  106. },
  107. },
  108. &api.Secret{},
  109. options.SecretResync,
  110. framework.ResourceEventHandlerFuncs{
  111. AddFunc: e.queueSecretSync,
  112. UpdateFunc: e.queueSecretUpdateSync,
  113. DeleteFunc: e.queueSecretSync,
  114. },
  115. cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc},
  116. )
  117. return e
  118. }
  119. // TokensController manages ServiceAccountToken secrets for ServiceAccount objects
  120. type TokensController struct {
  121. client clientset.Interface
  122. token serviceaccount.TokenGenerator
  123. rootCA []byte
  124. serviceAccounts cache.Store
  125. secrets cache.Indexer
  126. // Since we join two objects, we'll watch both of them with controllers.
  127. serviceAccountController *framework.Controller
  128. secretController *framework.Controller
  129. // syncServiceAccountQueue handles service account events:
  130. // * ensures a referenced token exists for service accounts which still exist
  131. // * ensures tokens are removed for service accounts which no longer exist
  132. // key is "<namespace>/<name>/<uid>"
  133. syncServiceAccountQueue workqueue.RateLimitingInterface
  134. // syncSecretQueue handles secret events:
  135. // * deletes tokens whose service account no longer exists
  136. // * updates tokens with missing token or namespace data, or mismatched ca data
  137. // * ensures service account secret references are removed for tokens which are deleted
  138. // key is a secretQueueKey{}
  139. syncSecretQueue workqueue.RateLimitingInterface
  140. maxRetries int
  141. }
  142. // Runs controller blocks until stopCh is closed
  143. func (e *TokensController) Run(workers int, stopCh <-chan struct{}) {
  144. defer utilruntime.HandleCrash()
  145. // Start controllers (to fill stores, call informers, fill work queues)
  146. go e.serviceAccountController.Run(stopCh)
  147. go e.secretController.Run(stopCh)
  148. // Wait for stores to fill
  149. for !e.serviceAccountController.HasSynced() || !e.secretController.HasSynced() {
  150. time.Sleep(100 * time.Millisecond)
  151. }
  152. // Spawn workers to process work queues
  153. for i := 0; i < workers; i++ {
  154. go wait.Until(e.syncServiceAccount, 0, stopCh)
  155. go wait.Until(e.syncSecret, 0, stopCh)
  156. }
  157. // Block until stop channel is closed
  158. <-stopCh
  159. // Shut down queues
  160. e.syncServiceAccountQueue.ShutDown()
  161. e.syncSecretQueue.ShutDown()
  162. }
  163. func (e *TokensController) queueServiceAccountSync(obj interface{}) {
  164. if serviceAccount, ok := obj.(*api.ServiceAccount); ok {
  165. e.syncServiceAccountQueue.Add(makeServiceAccountKey(serviceAccount))
  166. }
  167. }
  168. func (e *TokensController) queueServiceAccountUpdateSync(oldObj interface{}, newObj interface{}) {
  169. if serviceAccount, ok := newObj.(*api.ServiceAccount); ok {
  170. e.syncServiceAccountQueue.Add(makeServiceAccountKey(serviceAccount))
  171. }
  172. }
  173. // complete optionally requeues key, then calls queue.Done(key)
  174. func (e *TokensController) retryOrForget(queue workqueue.RateLimitingInterface, key interface{}, requeue bool) {
  175. if !requeue {
  176. queue.Forget(key)
  177. return
  178. }
  179. requeueCount := queue.NumRequeues(key)
  180. if requeueCount < e.maxRetries {
  181. queue.AddRateLimited(key)
  182. return
  183. }
  184. glog.V(4).Infof("retried %d times: %#v", requeueCount, key)
  185. queue.Forget(key)
  186. }
  187. func (e *TokensController) queueSecretSync(obj interface{}) {
  188. if secret, ok := obj.(*api.Secret); ok {
  189. e.syncSecretQueue.Add(makeSecretQueueKey(secret))
  190. }
  191. }
  192. func (e *TokensController) queueSecretUpdateSync(oldObj interface{}, newObj interface{}) {
  193. if secret, ok := newObj.(*api.Secret); ok {
  194. e.syncSecretQueue.Add(makeSecretQueueKey(secret))
  195. }
  196. }
  197. func (e *TokensController) syncServiceAccount() {
  198. key, quit := e.syncServiceAccountQueue.Get()
  199. if quit {
  200. return
  201. }
  202. defer e.syncServiceAccountQueue.Done(key)
  203. retry := false
  204. defer func() {
  205. e.retryOrForget(e.syncServiceAccountQueue, key, retry)
  206. }()
  207. saInfo, err := parseServiceAccountKey(key)
  208. if err != nil {
  209. glog.Error(err)
  210. return
  211. }
  212. sa, err := e.getServiceAccount(saInfo.namespace, saInfo.name, saInfo.uid, false)
  213. switch {
  214. case err != nil:
  215. glog.Error(err)
  216. retry = true
  217. case sa == nil:
  218. // service account no longer exists, so delete related tokens
  219. glog.V(4).Infof("syncServiceAccount(%s/%s), service account deleted, removing tokens", saInfo.namespace, saInfo.name)
  220. sa = &api.ServiceAccount{ObjectMeta: api.ObjectMeta{Namespace: saInfo.namespace, Name: saInfo.name, UID: saInfo.uid}}
  221. if retriable, err := e.deleteTokens(sa); err != nil {
  222. glog.Errorf("error deleting serviceaccount tokens for %s/%s: %v", saInfo.namespace, saInfo.name, err)
  223. retry = retriable
  224. }
  225. default:
  226. // ensure a token exists and is referenced by this service account
  227. if retriable, err := e.ensureReferencedToken(sa); err != nil {
  228. glog.Errorf("error synchronizing serviceaccount %s/%s: %v", saInfo.namespace, saInfo.name, err)
  229. retry = retriable
  230. }
  231. }
  232. }
  233. func (e *TokensController) syncSecret() {
  234. key, quit := e.syncSecretQueue.Get()
  235. if quit {
  236. return
  237. }
  238. defer e.syncSecretQueue.Done(key)
  239. // Track whether or not we should retry this sync
  240. retry := false
  241. defer func() {
  242. e.retryOrForget(e.syncSecretQueue, key, retry)
  243. }()
  244. secretInfo, err := parseSecretQueueKey(key)
  245. if err != nil {
  246. glog.Error(err)
  247. return
  248. }
  249. secret, err := e.getSecret(secretInfo.namespace, secretInfo.name, secretInfo.uid, false)
  250. switch {
  251. case err != nil:
  252. glog.Error(err)
  253. retry = true
  254. case secret == nil:
  255. // If the service account exists
  256. if sa, saErr := e.getServiceAccount(secretInfo.namespace, secretInfo.saName, secretInfo.saUID, false); saErr == nil && sa != nil {
  257. // secret no longer exists, so delete references to this secret from the service account
  258. if err := client.RetryOnConflict(RemoveTokenBackoff, func() error {
  259. return e.removeSecretReference(secretInfo.namespace, secretInfo.saName, secretInfo.saUID, secretInfo.name)
  260. }); err != nil {
  261. glog.Error(err)
  262. }
  263. }
  264. default:
  265. // Ensure service account exists
  266. sa, saErr := e.getServiceAccount(secretInfo.namespace, secretInfo.saName, secretInfo.saUID, true)
  267. switch {
  268. case saErr != nil:
  269. glog.Error(saErr)
  270. retry = true
  271. case sa == nil:
  272. // Delete token
  273. glog.V(4).Infof("syncSecret(%s/%s), service account does not exist, deleting token", secretInfo.namespace, secretInfo.name)
  274. if retriable, err := e.deleteToken(secretInfo.namespace, secretInfo.name, secretInfo.uid); err != nil {
  275. glog.Errorf("error deleting serviceaccount token %s/%s for service account %s: %v", secretInfo.namespace, secretInfo.name, secretInfo.saName, err)
  276. retry = retriable
  277. }
  278. default:
  279. // Update token if needed
  280. if retriable, err := e.generateTokenIfNeeded(sa, secret); err != nil {
  281. glog.Errorf("error populating serviceaccount token %s/%s for service account %s: %v", secretInfo.namespace, secretInfo.name, secretInfo.saName, err)
  282. retry = retriable
  283. }
  284. }
  285. }
  286. }
  287. func (e *TokensController) deleteTokens(serviceAccount *api.ServiceAccount) ( /*retry*/ bool, error) {
  288. tokens, err := e.listTokenSecrets(serviceAccount)
  289. if err != nil {
  290. // don't retry on cache lookup errors
  291. return false, err
  292. }
  293. retry := false
  294. errs := []error{}
  295. for _, token := range tokens {
  296. r, err := e.deleteToken(token.Namespace, token.Name, token.UID)
  297. if err != nil {
  298. errs = append(errs, err)
  299. }
  300. if r {
  301. retry = true
  302. }
  303. }
  304. return retry, utilerrors.NewAggregate(errs)
  305. }
  306. func (e *TokensController) deleteToken(ns, name string, uid types.UID) ( /*retry*/ bool, error) {
  307. var opts *api.DeleteOptions
  308. if len(uid) > 0 {
  309. opts = &api.DeleteOptions{Preconditions: &api.Preconditions{UID: &uid}}
  310. }
  311. err := e.client.Core().Secrets(ns).Delete(name, opts)
  312. // NotFound doesn't need a retry (it's already been deleted)
  313. // Conflict doesn't need a retry (the UID precondition failed)
  314. if err == nil || apierrors.IsNotFound(err) || apierrors.IsConflict(err) {
  315. return false, nil
  316. }
  317. // Retry for any other error
  318. return true, err
  319. }
  320. // ensureReferencedToken makes sure at least one ServiceAccountToken secret exists, and is included in the serviceAccount's Secrets list
  321. func (e *TokensController) ensureReferencedToken(serviceAccount *api.ServiceAccount) ( /* retry */ bool, error) {
  322. if len(serviceAccount.Secrets) > 0 {
  323. allSecrets, err := e.listTokenSecrets(serviceAccount)
  324. if err != nil {
  325. // Don't retry cache lookup errors
  326. return false, err
  327. }
  328. referencedSecrets := getSecretReferences(serviceAccount)
  329. for _, secret := range allSecrets {
  330. if referencedSecrets.Has(secret.Name) {
  331. // A service account token already exists, and is referenced, short-circuit
  332. return false, nil
  333. }
  334. }
  335. }
  336. // We don't want to update the cache's copy of the service account
  337. // so add the secret to a freshly retrieved copy of the service account
  338. serviceAccounts := e.client.Core().ServiceAccounts(serviceAccount.Namespace)
  339. liveServiceAccount, err := serviceAccounts.Get(serviceAccount.Name)
  340. if err != nil {
  341. // Retry for any error other than a NotFound
  342. return !apierrors.IsNotFound(err), err
  343. }
  344. if liveServiceAccount.ResourceVersion != serviceAccount.ResourceVersion {
  345. // our view of the service account is not up to date
  346. // we'll get notified of an update event later and get to try again
  347. glog.V(2).Infof("serviceaccount %s/%s is not up to date, skipping token creation", serviceAccount.Namespace, serviceAccount.Name)
  348. return false, nil
  349. }
  350. // Build the secret
  351. secret := &api.Secret{
  352. ObjectMeta: api.ObjectMeta{
  353. Name: secret.Strategy.GenerateName(fmt.Sprintf("%s-token-", serviceAccount.Name)),
  354. Namespace: serviceAccount.Namespace,
  355. Annotations: map[string]string{
  356. api.ServiceAccountNameKey: serviceAccount.Name,
  357. api.ServiceAccountUIDKey: string(serviceAccount.UID),
  358. },
  359. },
  360. Type: api.SecretTypeServiceAccountToken,
  361. Data: map[string][]byte{},
  362. }
  363. // Generate the token
  364. token, err := e.token.GenerateToken(*serviceAccount, *secret)
  365. if err != nil {
  366. // retriable error
  367. return true, err
  368. }
  369. secret.Data[api.ServiceAccountTokenKey] = []byte(token)
  370. secret.Data[api.ServiceAccountNamespaceKey] = []byte(serviceAccount.Namespace)
  371. if e.rootCA != nil && len(e.rootCA) > 0 {
  372. secret.Data[api.ServiceAccountRootCAKey] = e.rootCA
  373. }
  374. // Save the secret
  375. createdToken, err := e.client.Core().Secrets(serviceAccount.Namespace).Create(secret)
  376. if err != nil {
  377. // retriable error
  378. return true, err
  379. }
  380. // Manually add the new token to the cache store.
  381. // This prevents the service account update (below) triggering another token creation, if the referenced token couldn't be found in the store
  382. e.secrets.Add(createdToken)
  383. liveServiceAccount.Secrets = append(liveServiceAccount.Secrets, api.ObjectReference{Name: secret.Name})
  384. if _, err = serviceAccounts.Update(liveServiceAccount); err != nil {
  385. // we weren't able to use the token, try to clean it up.
  386. glog.V(2).Infof("deleting secret %s/%s because reference couldn't be added (%v)", secret.Namespace, secret.Name, err)
  387. deleteOpts := &api.DeleteOptions{Preconditions: &api.Preconditions{UID: &createdToken.UID}}
  388. if deleteErr := e.client.Core().Secrets(createdToken.Namespace).Delete(createdToken.Name, deleteOpts); deleteErr != nil {
  389. glog.Error(deleteErr) // if we fail, just log it
  390. }
  391. if apierrors.IsConflict(err) || apierrors.IsNotFound(err) {
  392. // if we got a Conflict error, the service account was updated by someone else, and we'll get an update notification later
  393. // if we got a NotFound error, the service account no longer exists, and we don't need to create a token for it
  394. return false, nil
  395. }
  396. // retry in all other cases
  397. return true, err
  398. }
  399. // success!
  400. return false, nil
  401. }
  402. func (e *TokensController) secretUpdateNeeded(secret *api.Secret) (bool, bool, bool) {
  403. caData := secret.Data[api.ServiceAccountRootCAKey]
  404. needsCA := len(e.rootCA) > 0 && bytes.Compare(caData, e.rootCA) != 0
  405. needsNamespace := len(secret.Data[api.ServiceAccountNamespaceKey]) == 0
  406. tokenData := secret.Data[api.ServiceAccountTokenKey]
  407. needsToken := len(tokenData) == 0
  408. return needsCA, needsNamespace, needsToken
  409. }
  410. // generateTokenIfNeeded populates the token data for the given Secret if not already set
  411. func (e *TokensController) generateTokenIfNeeded(serviceAccount *api.ServiceAccount, cachedSecret *api.Secret) ( /* retry */ bool, error) {
  412. // Check the cached secret to see if changes are needed
  413. if needsCA, needsNamespace, needsToken := e.secretUpdateNeeded(cachedSecret); !needsCA && !needsToken && !needsNamespace {
  414. return false, nil
  415. }
  416. // We don't want to update the cache's copy of the secret
  417. // so add the token to a freshly retrieved copy of the secret
  418. secrets := e.client.Core().Secrets(cachedSecret.Namespace)
  419. liveSecret, err := secrets.Get(cachedSecret.Name)
  420. if err != nil {
  421. // Retry for any error other than a NotFound
  422. return !apierrors.IsNotFound(err), err
  423. }
  424. if liveSecret.ResourceVersion != cachedSecret.ResourceVersion {
  425. // our view of the secret is not up to date
  426. // we'll get notified of an update event later and get to try again
  427. glog.V(2).Infof("secret %s/%s is not up to date, skipping token population", liveSecret.Namespace, liveSecret.Name)
  428. return false, nil
  429. }
  430. needsCA, needsNamespace, needsToken := e.secretUpdateNeeded(liveSecret)
  431. if !needsCA && !needsToken && !needsNamespace {
  432. return false, nil
  433. }
  434. if liveSecret.Annotations == nil {
  435. liveSecret.Annotations = map[string]string{}
  436. }
  437. if liveSecret.Data == nil {
  438. liveSecret.Data = map[string][]byte{}
  439. }
  440. // Set the CA
  441. if needsCA {
  442. liveSecret.Data[api.ServiceAccountRootCAKey] = e.rootCA
  443. }
  444. // Set the namespace
  445. if needsNamespace {
  446. liveSecret.Data[api.ServiceAccountNamespaceKey] = []byte(liveSecret.Namespace)
  447. }
  448. // Generate the token
  449. if needsToken {
  450. token, err := e.token.GenerateToken(*serviceAccount, *liveSecret)
  451. if err != nil {
  452. return false, err
  453. }
  454. liveSecret.Data[api.ServiceAccountTokenKey] = []byte(token)
  455. }
  456. // Set annotations
  457. liveSecret.Annotations[api.ServiceAccountNameKey] = serviceAccount.Name
  458. liveSecret.Annotations[api.ServiceAccountUIDKey] = string(serviceAccount.UID)
  459. // Save the secret
  460. _, err = secrets.Update(liveSecret)
  461. if apierrors.IsConflict(err) || apierrors.IsNotFound(err) {
  462. // if we got a Conflict error, the secret was updated by someone else, and we'll get an update notification later
  463. // if we got a NotFound error, the secret no longer exists, and we don't need to populate a token
  464. return false, nil
  465. }
  466. if err != nil {
  467. return true, err
  468. }
  469. return false, nil
  470. }
  471. // removeSecretReference updates the given ServiceAccount to remove a reference to the given secretName if needed.
  472. func (e *TokensController) removeSecretReference(saNamespace string, saName string, saUID types.UID, secretName string) error {
  473. // We don't want to update the cache's copy of the service account
  474. // so remove the secret from a freshly retrieved copy of the service account
  475. serviceAccounts := e.client.Core().ServiceAccounts(saNamespace)
  476. serviceAccount, err := serviceAccounts.Get(saName)
  477. // Ignore NotFound errors when attempting to remove a reference
  478. if apierrors.IsNotFound(err) {
  479. return nil
  480. }
  481. if err != nil {
  482. return err
  483. }
  484. // Short-circuit if the UID doesn't match
  485. if len(saUID) > 0 && saUID != serviceAccount.UID {
  486. return nil
  487. }
  488. // Short-circuit if the secret is no longer referenced
  489. if !getSecretReferences(serviceAccount).Has(secretName) {
  490. return nil
  491. }
  492. // Remove the secret
  493. secrets := []api.ObjectReference{}
  494. for _, s := range serviceAccount.Secrets {
  495. if s.Name != secretName {
  496. secrets = append(secrets, s)
  497. }
  498. }
  499. serviceAccount.Secrets = secrets
  500. _, err = serviceAccounts.Update(serviceAccount)
  501. // Ignore NotFound errors when attempting to remove a reference
  502. if apierrors.IsNotFound(err) {
  503. return nil
  504. }
  505. return err
  506. }
  507. func (e *TokensController) getServiceAccount(ns string, name string, uid types.UID, fetchOnCacheMiss bool) (*api.ServiceAccount, error) {
  508. // Look up in cache
  509. obj, exists, err := e.serviceAccounts.GetByKey(makeCacheKey(ns, name))
  510. if err != nil {
  511. return nil, err
  512. }
  513. if exists {
  514. sa, ok := obj.(*api.ServiceAccount)
  515. if !ok {
  516. return nil, fmt.Errorf("expected *api.ServiceAccount, got %#v", sa)
  517. }
  518. // Ensure UID matches if given
  519. if len(uid) == 0 || uid == sa.UID {
  520. return sa, nil
  521. }
  522. }
  523. if !fetchOnCacheMiss {
  524. return nil, nil
  525. }
  526. // Live lookup
  527. sa, err := e.client.Core().ServiceAccounts(ns).Get(name)
  528. if apierrors.IsNotFound(err) {
  529. return nil, nil
  530. }
  531. if err != nil {
  532. return nil, err
  533. }
  534. // Ensure UID matches if given
  535. if len(uid) == 0 || uid == sa.UID {
  536. return sa, nil
  537. }
  538. return nil, nil
  539. }
  540. func (e *TokensController) getSecret(ns string, name string, uid types.UID, fetchOnCacheMiss bool) (*api.Secret, error) {
  541. // Look up in cache
  542. obj, exists, err := e.secrets.GetByKey(makeCacheKey(ns, name))
  543. if err != nil {
  544. return nil, err
  545. }
  546. if exists {
  547. secret, ok := obj.(*api.Secret)
  548. if !ok {
  549. return nil, fmt.Errorf("expected *api.Secret, got %#v", secret)
  550. }
  551. // Ensure UID matches if given
  552. if len(uid) == 0 || uid == secret.UID {
  553. return secret, nil
  554. }
  555. }
  556. if !fetchOnCacheMiss {
  557. return nil, nil
  558. }
  559. // Live lookup
  560. secret, err := e.client.Core().Secrets(ns).Get(name)
  561. if apierrors.IsNotFound(err) {
  562. return nil, nil
  563. }
  564. if err != nil {
  565. return nil, err
  566. }
  567. // Ensure UID matches if given
  568. if len(uid) == 0 || uid == secret.UID {
  569. return secret, nil
  570. }
  571. return nil, nil
  572. }
  573. // listTokenSecrets returns a list of all of the ServiceAccountToken secrets that
  574. // reference the given service account's name and uid
  575. func (e *TokensController) listTokenSecrets(serviceAccount *api.ServiceAccount) ([]*api.Secret, error) {
  576. namespaceSecrets, err := e.secrets.ByIndex("namespace", serviceAccount.Namespace)
  577. if err != nil {
  578. return nil, err
  579. }
  580. items := []*api.Secret{}
  581. for _, obj := range namespaceSecrets {
  582. secret := obj.(*api.Secret)
  583. if serviceaccount.IsServiceAccountToken(secret, serviceAccount) {
  584. items = append(items, secret)
  585. }
  586. }
  587. return items, nil
  588. }
  589. // serviceAccountNameAndUID is a helper method to get the ServiceAccount Name and UID from the given secret
  590. // Returns "","" if the secret is not a ServiceAccountToken secret
  591. // If the name or uid annotation is missing, "" is returned instead
  592. func serviceAccountNameAndUID(secret *api.Secret) (string, string) {
  593. if secret.Type != api.SecretTypeServiceAccountToken {
  594. return "", ""
  595. }
  596. return secret.Annotations[api.ServiceAccountNameKey], secret.Annotations[api.ServiceAccountUIDKey]
  597. }
  598. func getSecretReferences(serviceAccount *api.ServiceAccount) sets.String {
  599. references := sets.NewString()
  600. for _, secret := range serviceAccount.Secrets {
  601. references.Insert(secret.Name)
  602. }
  603. return references
  604. }
  605. // serviceAccountQueueKey holds information we need to sync a service account.
  606. // It contains enough information to look up the cached service account,
  607. // or delete owned tokens if the service account no longer exists.
  608. type serviceAccountQueueKey struct {
  609. namespace string
  610. name string
  611. uid types.UID
  612. }
  613. func makeServiceAccountKey(sa *api.ServiceAccount) interface{} {
  614. return serviceAccountQueueKey{
  615. namespace: sa.Namespace,
  616. name: sa.Name,
  617. uid: sa.UID,
  618. }
  619. }
  620. func parseServiceAccountKey(key interface{}) (serviceAccountQueueKey, error) {
  621. queueKey, ok := key.(serviceAccountQueueKey)
  622. if !ok || len(queueKey.namespace) == 0 || len(queueKey.name) == 0 || len(queueKey.uid) == 0 {
  623. return serviceAccountQueueKey{}, fmt.Errorf("invalid serviceaccount key: %#v", key)
  624. }
  625. return queueKey, nil
  626. }
  627. // secretQueueKey holds information we need to sync a service account token secret.
  628. // It contains enough information to look up the cached service account,
  629. // or delete the secret reference if the secret no longer exists.
  630. type secretQueueKey struct {
  631. namespace string
  632. name string
  633. uid types.UID
  634. saName string
  635. // optional, will be blank when syncing tokens missing the service account uid annotation
  636. saUID types.UID
  637. }
  638. func makeSecretQueueKey(secret *api.Secret) interface{} {
  639. return secretQueueKey{
  640. namespace: secret.Namespace,
  641. name: secret.Name,
  642. uid: secret.UID,
  643. saName: secret.Annotations[api.ServiceAccountNameKey],
  644. saUID: types.UID(secret.Annotations[api.ServiceAccountUIDKey]),
  645. }
  646. }
  647. func parseSecretQueueKey(key interface{}) (secretQueueKey, error) {
  648. queueKey, ok := key.(secretQueueKey)
  649. if !ok || len(queueKey.namespace) == 0 || len(queueKey.name) == 0 || len(queueKey.uid) == 0 || len(queueKey.saName) == 0 {
  650. return secretQueueKey{}, fmt.Errorf("invalid secret key: %#v", key)
  651. }
  652. return queueKey, nil
  653. }
  654. // produce the same key format as cache.MetaNamespaceKeyFunc
  655. func makeCacheKey(namespace, name string) string {
  656. return namespace + "/" + name
  657. }