service_account_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  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. // This file tests authentication and (soon) authorization of HTTP requests to a master object.
  15. // It does not use the client in pkg/client/... because authentication and authorization needs
  16. // to work for any client of the HTTP interface.
  17. import (
  18. "context"
  19. "crypto/rand"
  20. "crypto/rsa"
  21. "fmt"
  22. "net/http"
  23. "net/http/httptest"
  24. "testing"
  25. "time"
  26. v1 "k8s.io/api/core/v1"
  27. apiequality "k8s.io/apimachinery/pkg/api/equality"
  28. apierrors "k8s.io/apimachinery/pkg/api/errors"
  29. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  30. "k8s.io/apimachinery/pkg/runtime/schema"
  31. "k8s.io/apimachinery/pkg/util/sets"
  32. "k8s.io/apimachinery/pkg/util/wait"
  33. "k8s.io/apiserver/pkg/authentication/authenticator"
  34. "k8s.io/apiserver/pkg/authentication/request/bearertoken"
  35. "k8s.io/apiserver/pkg/authentication/request/union"
  36. serviceaccountapiserver "k8s.io/apiserver/pkg/authentication/serviceaccount"
  37. "k8s.io/apiserver/pkg/authentication/user"
  38. "k8s.io/apiserver/pkg/authorization/authorizer"
  39. "k8s.io/client-go/informers"
  40. clientset "k8s.io/client-go/kubernetes"
  41. restclient "k8s.io/client-go/rest"
  42. "k8s.io/kubernetes/pkg/controller"
  43. serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
  44. "k8s.io/kubernetes/pkg/serviceaccount"
  45. serviceaccountadmission "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount"
  46. "k8s.io/kubernetes/test/integration/framework"
  47. )
  48. const (
  49. rootUserName = "root"
  50. rootToken = "root-user-token" // Fake value for testing.
  51. readOnlyServiceAccountName = "ro"
  52. readWriteServiceAccountName = "rw"
  53. )
  54. func TestServiceAccountAutoCreate(t *testing.T) {
  55. c, _, stopFunc, err := startServiceAccountTestServer(t)
  56. defer stopFunc()
  57. if err != nil {
  58. t.Fatalf("failed to setup ServiceAccounts server: %v", err)
  59. }
  60. ns := "test-service-account-creation"
  61. // Create namespace
  62. _, err = c.CoreV1().Namespaces().Create(context.TODO(), &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}}, metav1.CreateOptions{})
  63. if err != nil {
  64. t.Fatalf("could not create namespace: %v", err)
  65. }
  66. // Get service account
  67. defaultUser, err := getServiceAccount(c, ns, "default", true)
  68. if err != nil {
  69. t.Fatalf("Default serviceaccount not created: %v", err)
  70. }
  71. // Delete service account
  72. err = c.CoreV1().ServiceAccounts(ns).Delete(context.TODO(), defaultUser.Name, nil)
  73. if err != nil {
  74. t.Fatalf("Could not delete default serviceaccount: %v", err)
  75. }
  76. // Get recreated service account
  77. defaultUser2, err := getServiceAccount(c, ns, "default", true)
  78. if err != nil {
  79. t.Fatalf("Default serviceaccount not created: %v", err)
  80. }
  81. if defaultUser2.UID == defaultUser.UID {
  82. t.Fatalf("Expected different UID with recreated serviceaccount")
  83. }
  84. }
  85. func TestServiceAccountTokenAutoCreate(t *testing.T) {
  86. c, _, stopFunc, err := startServiceAccountTestServer(t)
  87. defer stopFunc()
  88. if err != nil {
  89. t.Fatalf("failed to setup ServiceAccounts server: %v", err)
  90. }
  91. ns := "test-service-account-token-creation"
  92. name := "my-service-account"
  93. // Create namespace
  94. _, err = c.CoreV1().Namespaces().Create(context.TODO(), &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}}, metav1.CreateOptions{})
  95. if err != nil {
  96. t.Fatalf("could not create namespace: %v", err)
  97. }
  98. // Create service account
  99. _, err = c.CoreV1().ServiceAccounts(ns).Create(context.TODO(), &v1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: name}}, metav1.CreateOptions{})
  100. if err != nil {
  101. t.Fatalf("Service Account not created: %v", err)
  102. }
  103. // Get token
  104. token1Name, token1, err := getReferencedServiceAccountToken(c, ns, name, true)
  105. if err != nil {
  106. t.Fatal(err)
  107. }
  108. // Delete token
  109. err = c.CoreV1().Secrets(ns).Delete(context.TODO(), token1Name, nil)
  110. if err != nil {
  111. t.Fatalf("Could not delete token: %v", err)
  112. }
  113. // Get recreated token
  114. token2Name, token2, err := getReferencedServiceAccountToken(c, ns, name, true)
  115. if err != nil {
  116. t.Fatal(err)
  117. }
  118. if token1Name == token2Name {
  119. t.Fatalf("Expected new auto-created token name")
  120. }
  121. if token1 == token2 {
  122. t.Fatalf("Expected new auto-created token value")
  123. }
  124. // Trigger creation of a new referenced token
  125. serviceAccount, err := c.CoreV1().ServiceAccounts(ns).Get(context.TODO(), name, metav1.GetOptions{})
  126. if err != nil {
  127. t.Fatal(err)
  128. }
  129. serviceAccount.Secrets = []v1.ObjectReference{}
  130. _, err = c.CoreV1().ServiceAccounts(ns).Update(context.TODO(), serviceAccount, metav1.UpdateOptions{})
  131. if err != nil {
  132. t.Fatal(err)
  133. }
  134. // Get rotated token
  135. token3Name, token3, err := getReferencedServiceAccountToken(c, ns, name, true)
  136. if err != nil {
  137. t.Fatal(err)
  138. }
  139. if token3Name == token2Name {
  140. t.Fatalf("Expected new auto-created token name")
  141. }
  142. if token3 == token2 {
  143. t.Fatalf("Expected new auto-created token value")
  144. }
  145. // Delete service account
  146. err = c.CoreV1().ServiceAccounts(ns).Delete(context.TODO(), name, nil)
  147. if err != nil {
  148. t.Fatal(err)
  149. }
  150. // Wait for tokens to be deleted
  151. tokensToCleanup := sets.NewString(token1Name, token2Name, token3Name)
  152. err = wait.Poll(time.Second, 10*time.Second, func() (bool, error) {
  153. // Get all secrets in the namespace
  154. secrets, err := c.CoreV1().Secrets(ns).List(context.TODO(), metav1.ListOptions{})
  155. // Retrieval errors should fail
  156. if err != nil {
  157. return false, err
  158. }
  159. for _, s := range secrets.Items {
  160. if tokensToCleanup.Has(s.Name) {
  161. // Still waiting for tokens to be cleaned up
  162. return false, nil
  163. }
  164. }
  165. // All clean
  166. return true, nil
  167. })
  168. if err != nil {
  169. t.Fatalf("Error waiting for tokens to be deleted: %v", err)
  170. }
  171. }
  172. func TestServiceAccountTokenAutoMount(t *testing.T) {
  173. c, _, stopFunc, err := startServiceAccountTestServer(t)
  174. defer stopFunc()
  175. if err != nil {
  176. t.Fatalf("failed to setup ServiceAccounts server: %v", err)
  177. }
  178. ns := "auto-mount-ns"
  179. // Create "my" namespace
  180. _, err = c.CoreV1().Namespaces().Create(context.TODO(), &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}}, metav1.CreateOptions{})
  181. if err != nil && !apierrors.IsAlreadyExists(err) {
  182. t.Fatalf("could not create namespace: %v", err)
  183. }
  184. // Get default token
  185. defaultTokenName, _, err := getReferencedServiceAccountToken(c, ns, serviceaccountadmission.DefaultServiceAccountName, true)
  186. if err != nil {
  187. t.Fatal(err)
  188. }
  189. // Pod to create
  190. protoPod := v1.Pod{
  191. ObjectMeta: metav1.ObjectMeta{Name: "protopod"},
  192. Spec: v1.PodSpec{
  193. Containers: []v1.Container{
  194. {
  195. Name: "container-1",
  196. Image: "container-1-image",
  197. },
  198. {
  199. Name: "container-2",
  200. Image: "container-2-image",
  201. VolumeMounts: []v1.VolumeMount{
  202. {Name: "empty-dir", MountPath: serviceaccountadmission.DefaultAPITokenMountPath},
  203. },
  204. },
  205. },
  206. Volumes: []v1.Volume{
  207. {
  208. Name: "empty-dir",
  209. VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}},
  210. },
  211. },
  212. },
  213. }
  214. // Pod we expect to get created
  215. defaultMode := int32(0644)
  216. expectedServiceAccount := serviceaccountadmission.DefaultServiceAccountName
  217. expectedVolumes := append(protoPod.Spec.Volumes, v1.Volume{
  218. Name: defaultTokenName,
  219. VolumeSource: v1.VolumeSource{
  220. Secret: &v1.SecretVolumeSource{
  221. SecretName: defaultTokenName,
  222. DefaultMode: &defaultMode,
  223. },
  224. },
  225. })
  226. expectedContainer1VolumeMounts := []v1.VolumeMount{
  227. {Name: defaultTokenName, MountPath: serviceaccountadmission.DefaultAPITokenMountPath, ReadOnly: true},
  228. }
  229. expectedContainer2VolumeMounts := protoPod.Spec.Containers[1].VolumeMounts
  230. createdPod, err := c.CoreV1().Pods(ns).Create(context.TODO(), &protoPod, metav1.CreateOptions{})
  231. if err != nil {
  232. t.Fatal(err)
  233. }
  234. if createdPod.Spec.ServiceAccountName != expectedServiceAccount {
  235. t.Fatalf("Expected %s, got %s", expectedServiceAccount, createdPod.Spec.ServiceAccountName)
  236. }
  237. if !apiequality.Semantic.DeepEqual(&expectedVolumes, &createdPod.Spec.Volumes) {
  238. t.Fatalf("Expected\n\t%#v\n\tgot\n\t%#v", expectedVolumes, createdPod.Spec.Volumes)
  239. }
  240. if !apiequality.Semantic.DeepEqual(&expectedContainer1VolumeMounts, &createdPod.Spec.Containers[0].VolumeMounts) {
  241. t.Fatalf("Expected\n\t%#v\n\tgot\n\t%#v", expectedContainer1VolumeMounts, createdPod.Spec.Containers[0].VolumeMounts)
  242. }
  243. if !apiequality.Semantic.DeepEqual(&expectedContainer2VolumeMounts, &createdPod.Spec.Containers[1].VolumeMounts) {
  244. t.Fatalf("Expected\n\t%#v\n\tgot\n\t%#v", expectedContainer2VolumeMounts, createdPod.Spec.Containers[1].VolumeMounts)
  245. }
  246. }
  247. func TestServiceAccountTokenAuthentication(t *testing.T) {
  248. c, config, stopFunc, err := startServiceAccountTestServer(t)
  249. defer stopFunc()
  250. if err != nil {
  251. t.Fatalf("failed to setup ServiceAccounts server: %v", err)
  252. }
  253. myns := "auth-ns"
  254. otherns := "other-ns"
  255. // Create "my" namespace
  256. _, err = c.CoreV1().Namespaces().Create(context.TODO(), &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: myns}}, metav1.CreateOptions{})
  257. if err != nil && !apierrors.IsAlreadyExists(err) {
  258. t.Fatalf("could not create namespace: %v", err)
  259. }
  260. // Create "other" namespace
  261. _, err = c.CoreV1().Namespaces().Create(context.TODO(), &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: otherns}}, metav1.CreateOptions{})
  262. if err != nil && !apierrors.IsAlreadyExists(err) {
  263. t.Fatalf("could not create namespace: %v", err)
  264. }
  265. // Create "ro" user in myns
  266. _, err = c.CoreV1().ServiceAccounts(myns).Create(context.TODO(), &v1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: readOnlyServiceAccountName}}, metav1.CreateOptions{})
  267. if err != nil {
  268. t.Fatalf("Service Account not created: %v", err)
  269. }
  270. roTokenName, roToken, err := getReferencedServiceAccountToken(c, myns, readOnlyServiceAccountName, true)
  271. if err != nil {
  272. t.Fatal(err)
  273. }
  274. roClientConfig := config
  275. roClientConfig.BearerToken = roToken
  276. roClient := clientset.NewForConfigOrDie(&roClientConfig)
  277. doServiceAccountAPIRequests(t, roClient, myns, true, true, false)
  278. doServiceAccountAPIRequests(t, roClient, otherns, true, false, false)
  279. err = c.CoreV1().Secrets(myns).Delete(context.TODO(), roTokenName, nil)
  280. if err != nil {
  281. t.Fatalf("could not delete token: %v", err)
  282. }
  283. // wait for delete to be observed and reacted to via watch
  284. wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
  285. sa, err := c.CoreV1().ServiceAccounts(myns).Get(context.TODO(), readOnlyServiceAccountName, metav1.GetOptions{})
  286. if err != nil {
  287. return false, err
  288. }
  289. for _, secretRef := range sa.Secrets {
  290. if secretRef.Name == roTokenName {
  291. return false, nil
  292. }
  293. }
  294. return true, nil
  295. })
  296. doServiceAccountAPIRequests(t, roClient, myns, false, false, false)
  297. // Create "rw" user in myns
  298. _, err = c.CoreV1().ServiceAccounts(myns).Create(context.TODO(), &v1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: readWriteServiceAccountName}}, metav1.CreateOptions{})
  299. if err != nil {
  300. t.Fatalf("Service Account not created: %v", err)
  301. }
  302. _, rwToken, err := getReferencedServiceAccountToken(c, myns, readWriteServiceAccountName, true)
  303. if err != nil {
  304. t.Fatal(err)
  305. }
  306. rwClientConfig := config
  307. rwClientConfig.BearerToken = rwToken
  308. rwClient := clientset.NewForConfigOrDie(&rwClientConfig)
  309. doServiceAccountAPIRequests(t, rwClient, myns, true, true, true)
  310. doServiceAccountAPIRequests(t, rwClient, otherns, true, false, false)
  311. // Get default user and token which should have been automatically created
  312. _, defaultToken, err := getReferencedServiceAccountToken(c, myns, "default", true)
  313. if err != nil {
  314. t.Fatalf("could not get default user and token: %v", err)
  315. }
  316. defaultClientConfig := config
  317. defaultClientConfig.BearerToken = defaultToken
  318. defaultClient := clientset.NewForConfigOrDie(&defaultClientConfig)
  319. doServiceAccountAPIRequests(t, defaultClient, myns, true, false, false)
  320. }
  321. // startServiceAccountTestServer returns a started server
  322. // It is the responsibility of the caller to ensure the returned stopFunc is called
  323. func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclient.Config, func(), error) {
  324. // Listener
  325. h := &framework.MasterHolder{Initialized: make(chan struct{})}
  326. apiServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  327. <-h.Initialized
  328. h.M.GenericAPIServer.Handler.ServeHTTP(w, req)
  329. }))
  330. // Anonymous client config
  331. clientConfig := restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}}
  332. // Root client
  333. // TODO: remove rootClient after we refactor pkg/admission to use the clientset.
  334. rootClientset := clientset.NewForConfigOrDie(&restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, BearerToken: rootToken})
  335. externalRootClientset := clientset.NewForConfigOrDie(&restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}, BearerToken: rootToken})
  336. externalInformers := informers.NewSharedInformerFactory(externalRootClientset, controller.NoResyncPeriodFunc())
  337. informers := informers.NewSharedInformerFactory(rootClientset, controller.NoResyncPeriodFunc())
  338. // Set up two authenticators:
  339. // 1. A token authenticator that maps the rootToken to the "root" user
  340. // 2. A ServiceAccountToken authenticator that validates ServiceAccount tokens
  341. rootTokenAuth := authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) {
  342. if token == rootToken {
  343. return &authenticator.Response{User: &user.DefaultInfo{Name: rootUserName}}, true, nil
  344. }
  345. return nil, false, nil
  346. })
  347. serviceAccountKey, _ := rsa.GenerateKey(rand.Reader, 2048)
  348. serviceAccountTokenGetter := serviceaccountcontroller.NewGetterFromClient(
  349. rootClientset,
  350. externalInformers.Core().V1().Secrets().Lister(),
  351. externalInformers.Core().V1().ServiceAccounts().Lister(),
  352. externalInformers.Core().V1().Pods().Lister(),
  353. )
  354. serviceAccountTokenAuth := serviceaccount.JWTTokenAuthenticator(serviceaccount.LegacyIssuer, []interface{}{&serviceAccountKey.PublicKey}, nil, serviceaccount.NewLegacyValidator(true, serviceAccountTokenGetter))
  355. authenticator := union.New(
  356. bearertoken.New(rootTokenAuth),
  357. bearertoken.New(serviceAccountTokenAuth),
  358. )
  359. // Set up a stub authorizer:
  360. // 1. The "root" user is allowed to do anything
  361. // 2. ServiceAccounts named "ro" are allowed read-only operations in their namespace
  362. // 3. ServiceAccounts named "rw" are allowed any operation in their namespace
  363. authorizer := authorizer.AuthorizerFunc(func(attrs authorizer.Attributes) (authorizer.Decision, string, error) {
  364. username := ""
  365. if user := attrs.GetUser(); user != nil {
  366. username = user.GetName()
  367. }
  368. ns := attrs.GetNamespace()
  369. // If the user is "root"...
  370. if username == rootUserName {
  371. // allow them to do anything
  372. return authorizer.DecisionAllow, "", nil
  373. }
  374. // If the user is a service account...
  375. if serviceAccountNamespace, serviceAccountName, err := serviceaccountapiserver.SplitUsername(username); err == nil {
  376. // Limit them to their own namespace
  377. if serviceAccountNamespace == ns {
  378. switch serviceAccountName {
  379. case readOnlyServiceAccountName:
  380. if attrs.IsReadOnly() {
  381. return authorizer.DecisionAllow, "", nil
  382. }
  383. case readWriteServiceAccountName:
  384. return authorizer.DecisionAllow, "", nil
  385. }
  386. }
  387. }
  388. return authorizer.DecisionNoOpinion, fmt.Sprintf("User %s is denied (ns=%s, readonly=%v, resource=%s)", username, ns, attrs.IsReadOnly(), attrs.GetResource()), nil
  389. })
  390. // Set up admission plugin to auto-assign serviceaccounts to pods
  391. serviceAccountAdmission := serviceaccountadmission.NewServiceAccount()
  392. serviceAccountAdmission.SetExternalKubeClientSet(externalRootClientset)
  393. serviceAccountAdmission.SetExternalKubeInformerFactory(externalInformers)
  394. masterConfig := framework.NewMasterConfig()
  395. masterConfig.GenericConfig.EnableIndex = true
  396. masterConfig.GenericConfig.Authentication.Authenticator = authenticator
  397. masterConfig.GenericConfig.Authorization.Authorizer = authorizer
  398. masterConfig.GenericConfig.AdmissionControl = serviceAccountAdmission
  399. _, _, kubeAPIServerCloseFn := framework.RunAMasterUsingServer(masterConfig, apiServer, h)
  400. // Start the service account and service account token controllers
  401. stopCh := make(chan struct{})
  402. stop := func() {
  403. close(stopCh)
  404. kubeAPIServerCloseFn()
  405. apiServer.Close()
  406. }
  407. tokenGenerator, err := serviceaccount.JWTTokenGenerator(serviceaccount.LegacyIssuer, serviceAccountKey)
  408. if err != nil {
  409. return rootClientset, clientConfig, stop, err
  410. }
  411. tokenController, err := serviceaccountcontroller.NewTokensController(
  412. informers.Core().V1().ServiceAccounts(),
  413. informers.Core().V1().Secrets(),
  414. rootClientset,
  415. serviceaccountcontroller.TokensControllerOptions{TokenGenerator: tokenGenerator},
  416. )
  417. if err != nil {
  418. return rootClientset, clientConfig, stop, err
  419. }
  420. go tokenController.Run(1, stopCh)
  421. serviceAccountController, err := serviceaccountcontroller.NewServiceAccountsController(
  422. informers.Core().V1().ServiceAccounts(),
  423. informers.Core().V1().Namespaces(),
  424. rootClientset,
  425. serviceaccountcontroller.DefaultServiceAccountsControllerOptions(),
  426. )
  427. if err != nil {
  428. return rootClientset, clientConfig, stop, err
  429. }
  430. informers.Start(stopCh)
  431. externalInformers.Start(stopCh)
  432. go serviceAccountController.Run(5, stopCh)
  433. return rootClientset, clientConfig, stop, nil
  434. }
  435. func getServiceAccount(c *clientset.Clientset, ns string, name string, shouldWait bool) (*v1.ServiceAccount, error) {
  436. if !shouldWait {
  437. return c.CoreV1().ServiceAccounts(ns).Get(context.TODO(), name, metav1.GetOptions{})
  438. }
  439. var user *v1.ServiceAccount
  440. var err error
  441. err = wait.Poll(time.Second, 10*time.Second, func() (bool, error) {
  442. user, err = c.CoreV1().ServiceAccounts(ns).Get(context.TODO(), name, metav1.GetOptions{})
  443. if apierrors.IsNotFound(err) {
  444. return false, nil
  445. }
  446. if err != nil {
  447. return false, err
  448. }
  449. return true, nil
  450. })
  451. return user, err
  452. }
  453. func getReferencedServiceAccountToken(c *clientset.Clientset, ns string, name string, shouldWait bool) (string, string, error) {
  454. tokenName := ""
  455. token := ""
  456. findToken := func() (bool, error) {
  457. user, err := c.CoreV1().ServiceAccounts(ns).Get(context.TODO(), name, metav1.GetOptions{})
  458. if apierrors.IsNotFound(err) {
  459. return false, nil
  460. }
  461. if err != nil {
  462. return false, err
  463. }
  464. for _, ref := range user.Secrets {
  465. secret, err := c.CoreV1().Secrets(ns).Get(context.TODO(), ref.Name, metav1.GetOptions{})
  466. if apierrors.IsNotFound(err) {
  467. continue
  468. }
  469. if err != nil {
  470. return false, err
  471. }
  472. if secret.Type != v1.SecretTypeServiceAccountToken {
  473. continue
  474. }
  475. name := secret.Annotations[v1.ServiceAccountNameKey]
  476. uid := secret.Annotations[v1.ServiceAccountUIDKey]
  477. tokenData := secret.Data[v1.ServiceAccountTokenKey]
  478. if name == user.Name && uid == string(user.UID) && len(tokenData) > 0 {
  479. tokenName = secret.Name
  480. token = string(tokenData)
  481. return true, nil
  482. }
  483. }
  484. return false, nil
  485. }
  486. if shouldWait {
  487. err := wait.Poll(time.Second, 10*time.Second, findToken)
  488. if err != nil {
  489. return "", "", err
  490. }
  491. } else {
  492. ok, err := findToken()
  493. if err != nil {
  494. return "", "", err
  495. }
  496. if !ok {
  497. return "", "", fmt.Errorf("No token found for %s/%s", ns, name)
  498. }
  499. }
  500. return tokenName, token, nil
  501. }
  502. type testOperation func() error
  503. func doServiceAccountAPIRequests(t *testing.T, c *clientset.Clientset, ns string, authenticated bool, canRead bool, canWrite bool) {
  504. testSecret := &v1.Secret{
  505. ObjectMeta: metav1.ObjectMeta{Name: "testSecret"},
  506. Data: map[string][]byte{"test": []byte("data")},
  507. }
  508. readOps := []testOperation{
  509. func() error {
  510. _, err := c.CoreV1().Secrets(ns).List(context.TODO(), metav1.ListOptions{})
  511. return err
  512. },
  513. func() error {
  514. _, err := c.CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{})
  515. return err
  516. },
  517. }
  518. writeOps := []testOperation{
  519. func() error {
  520. _, err := c.CoreV1().Secrets(ns).Create(context.TODO(), testSecret, metav1.CreateOptions{})
  521. return err
  522. },
  523. func() error { return c.CoreV1().Secrets(ns).Delete(context.TODO(), testSecret.Name, nil) },
  524. }
  525. for _, op := range readOps {
  526. err := op()
  527. unauthorizedError := apierrors.IsUnauthorized(err)
  528. forbiddenError := apierrors.IsForbidden(err)
  529. switch {
  530. case !authenticated && !unauthorizedError:
  531. t.Fatalf("expected unauthorized error, got %v", err)
  532. case authenticated && unauthorizedError:
  533. t.Fatalf("unexpected unauthorized error: %v", err)
  534. case authenticated && canRead && forbiddenError:
  535. t.Fatalf("unexpected forbidden error: %v", err)
  536. case authenticated && !canRead && !forbiddenError:
  537. t.Fatalf("expected forbidden error, got: %v", err)
  538. }
  539. }
  540. for _, op := range writeOps {
  541. err := op()
  542. unauthorizedError := apierrors.IsUnauthorized(err)
  543. forbiddenError := apierrors.IsForbidden(err)
  544. switch {
  545. case !authenticated && !unauthorizedError:
  546. t.Fatalf("expected unauthorized error, got %v", err)
  547. case authenticated && unauthorizedError:
  548. t.Fatalf("unexpected unauthorized error: %v", err)
  549. case authenticated && canWrite && forbiddenError:
  550. t.Fatalf("unexpected forbidden error: %v", err)
  551. case authenticated && !canWrite && !forbiddenError:
  552. t.Fatalf("expected forbidden error, got: %v", err)
  553. }
  554. }
  555. }