others-how to how to get token from service account in kubernetes?

1. Purpose

In this post, I would demo how to get token from service account in kubernetes.

2. Environment

  • Kubernetes 1.18+

3. The solution

3.1 What is a service account token in k8s ?

According to this document , a token is just one of the authentication methods that k8s api server supports.

Kubernetes uses client certificates, bearer tokens… to authenticate API requests through authentication plugins

So, we can use certificates or tokens to make an authentication request to the kubernetes cluster.

image-20210522181438219

But what is a bearer token in HTTP request?

Bearer Token:

It is an HTTP authentication scheme that involves security tokens called bearer tokens. As the name depicts “Bearer Authentication” gives access to the bearer of this token. The bearer token is a cryptic string, usually generated by the server in response to a login request.

Bearer authentication (also called token authentication) is an HTTP authentication scheme that involves security tokens called bearer tokens. The name “Bearer authentication” can be understood as “give access to the bearer of this token.” The bearer token is a cryptic string, usually generated by the server in response to a login request. The client must send this token in the Authorization header when making requests to protected resources:

You must include this header in your HTTP request:

Authorization: Bearer <token>

The below picture is a bearer token example:

image-20210522182109438

You can learn more about the Bearer token from this document.

3.2 Solution : Use kubectl describe

Suppose we have a service account named admin-user in namespace kubernetes-dashboard, now we want to get token from it:

root@controlplane:~# kubectl describe sa admin-user -n kubernetes-dashboard
Name:                admin-user
Namespace:           kubernetes-dashboard
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   admin-user-token-gkxkf
Tokens:              admin-user-token-gkxkf
Events:              <none>

The token admin-user-token-gkxkf listed above is actually a k8s secret , let’s describe it:

root@controlplane:~# kubectl describe secret admin-user-token-gkxkf -n kubernetes-dashboard
Name:         admin-user-token-gkxkf
Namespace:    kubernetes-dashboard
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: admin-user
              kubernetes.io/service-account.uid: 3418cd15-b2c9-4712-af26-bc8b2110ead4


Type:  kubernetes.io/service-account-token


Data
====
ca.crt:     1066 bytes
namespace:  20 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IjlqYU4wS3RwcFNlYzJCNXdGVmpHbkdKRVlTTGZJZUZIUTdtTHI5d2NUdVUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLWdreGtmIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIzNDE4Y2QxNS1iMmM5LTQ3MTItYWYyNi1iYzhiMjExMGVhZDQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.ujlezMuecFutETEDFhk1PBlcVCLj0IKjfBVjOpFwZMAtOndiutAd2o9j8ei-LIKi7p-BLvqeDshUjqjkWRvUaMsVAA-GyGapn9xU0hf3CjoHQgk-umIXdkE1dkxi9ay_nFgmfi-o9gTCk9wd_B6Ydi4V9gvJECcIAo6EQjVG28FF_bqJwtLr2zhcm-rUfOt69-7iduV0iJBXg00ASrFcEwdvz-9hCQOzwBgUDy3AnY52VGcCUMSYrmm2gOuXxzqZg3ui8zizYTxN-cJmiw0CNFr3drcVOtx-aUW7-_TDi8ZyypnK5EA00HgpOT34UEYNQ2-cqepbiPlb0anW5FUf1g
root@controlplane:~#

The above token starts with ‘eyJhbGc…’ is a base64-decoded string, you can just use it as a bearer token in your request.

But if you want the original base64-formatted token string ,you can add option -o wide, just as follows:

root@controlplane:~# kubectl get secret admin-user-token-gkxkf -n kubernetes-dashboard -o yaml
apiVersion: v1
data:
  ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1EVXlNVEF4TXprME5Wb1hEVE14TURVeE9UQXhNemswTlZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTUhjCjUzNjBkc1pOK2RiYUIwR2FtWDNERXRyM3kzcE9nbnYxNDUrUEthYklwTUZuUUErRWVLUWx0OUNaZ1VxdE8zWHgKUnZjdnBSQVAzUlFwZjdyZW9vekNnUWp6Y0QrUk5ZaXJTcGZyV3lDT0Rxa2lhNzRnTkhhNmhPRXVOTk4vcVk1cwo5UnZxZ0R5RlNQYTA4OTJqWXpUZG0xVkJYNW4xOFNZMXcwa3hEVlE4UHh1eVlJbXZDYTRQN2d2RWJqcllrZCtmClRsYWR3UnNzcjVaa2R4eCtMQ1BIMEwzOHp5bzdMK0lKaFBYNzl0ZzRSajYwOE0xZXFpMERTNDBiZWlsanlGbG8KWUUwRlozYWR4TjNxUzdIUFpMaHZISURnNGU2Q0Q5dDV2ZkM3Nmg1K0hLMXZCMWxPbTd4VUdCSWNnbktjalBMSQpIeFZLdGZpOWNQTHlDYmFlbC9NQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZQVXlkZVN6WktVNVRKNytQejZQV2dqc2xuZHhNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFDWGFaL3RmVnZMK3BPa0Q5cVlwN3JMRFV1Z0FOcTJrenJodjF2N0NWWnlYa1ZuSmIvVQpJUjQ3bVJYekNCcXM4eTNoVDRmTHZNNVltaUVVV1Fja1Z2ejd4cTVLUWczcVFKcnRLa0t5eitVc0REL3FBOHZoCkRGM2RYNllWbkMwMW9zTDQvVVRhaVZZV0FTS0QzelE3N3hzOE9GVlF6UXdlYjhsZW5aK09XMDJEaVRDSjlLMUIKRFhDNHdZNytKejdjbVZJdSswMmNBUDN4amxmcjg1ek9IM0NUNHY3ZS9zNFEreURGalkzZW5HRVlqL2xWcENIbApjRnh5WnVFUTdoR3NzQWpSU1Y2TkhySWl2VzlZR2FtVXl4Vko3QmhubitzeExkakJhS1B3MFpWcUExMmZnY1dSCkRnUERTNDFJTUhma1pwVWhieGRoTFRUM3p6eThuYVliTHhPVAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
  namespace: a3ViZXJuZXRlcy1kYXNoYm9hcmQ=
  token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklqbHFZVTR3UzNSd2NGTmxZekpDTlhkR1ZtcEhia2RLUlZsVFRHWkpaVVpJVVRkdFRISTVkMk5VZFZVaWZRLmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUpyZFdKbGNtNWxkR1Z6TFdSaGMyaGliMkZ5WkNJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZqY21WMExtNWhiV1VpT2lKaFpHMXBiaTExYzJWeUxYUnZhMlZ1TFdkcmVHdG1JaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpYSjJhV05sTFdGalkyOTFiblF1Ym1GdFpTSTZJbUZrYldsdUxYVnpaWElpTENKcmRXSmxjbTVsZEdWekxtbHZMM05sY25acFkyVmhZMk52ZFc1MEwzTmxjblpwWTJVdFlXTmpiM1Z1ZEM1MWFXUWlPaUl6TkRFNFkyUXhOUzFpTW1NNUxUUTNNVEl0WVdZeU5pMWlZemhpTWpFeE1HVmhaRFFpTENKemRXSWlPaUp6ZVhOMFpXMDZjMlZ5ZG1salpXRmpZMjkxYm5RNmEzVmlaWEp1WlhSbGN5MWtZWE5vWW05aGNtUTZZV1J0YVc0dGRYTmxjaUo5LnVqbGV6TXVlY0Z1dEVURURGaGsxUEJsY1ZDTGowSUtqZkJWak9wRndaTUF0T25kaXV0QWQybzlqOGVpLUxJS2k3cC1CTHZxZURzaFVqcWprV1J2VWFNc1ZBQS1HeUdhcG45eFUwaGYzQ2pvSFFnay11bUlYZGtFMWRreGk5YXlfbkZnbWZpLW85Z1RDazl3ZF9CNllkaTRWOWd2SkVDY0lBbzZFUWpWRzI4RkZfYnFKd3RMcjJ6aGNtLXJVZk90NjktN2lkdVYwaUpCWGcwMEFTckZjRXdkdnotOWhDUU96d0JnVUR5M0FuWTUyVkdjQ1VNU1lybW0yZ091WHh6cVpnM3VpOHppellUeE4tY0ptaXcwQ05GcjNkcmNWT3R4LWFVVzctX1REaThaeXlwbks1RUEwMEhncE9UMzRVRVlOUTItY3FlcGJpUGxiMGFuVzVGVWYxZw==
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: admin-user
    kubernetes.io/service-account.uid: 3418cd15-b2c9-4712-af26-bc8b2110ead4
  creationTimestamp: "2021-05-21T01:56:05Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:ca.crt: {}
        f:namespace: {}
        f:token: {}
      f:metadata:
        f:annotations:
          .: {}
          f:kubernetes.io/service-account.name: {}
          f:kubernetes.io/service-account.uid: {}
      f:type: {}
    manager: kube-controller-manager
    operation: Update
    time: "2021-05-21T01:56:05Z"
  name: admin-user-token-gkxkf
  namespace: kubernetes-dashboard
  resourceVersion: "1715"
  uid: 8724317f-acde-430e-9365-48420dfdec42
type: kubernetes.io/service-account-token
root@controlplane:~#

The above token is a base64 encoded string, so we should decode it :

root@controlplane:~# echo -n "ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklqbHFZVTR3UzNSd2NGTmxZekpDTlhkR1ZtcEhia2RLUlZsVFRHWkpaVVpJVVRkdFRISTVkMk5VZFZVaWZRLmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUpyZFdKbGNtNWxkR1Z6TFdSaGMyaGliMkZ5WkNJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZqY21WMExtNWhiV1VpT2lKaFpHMXBiaTExYzJWeUxYUnZhMlZ1TFdkcmVHdG1JaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpYSjJhV05sTFdGalkyOTFiblF1Ym1GdFpTSTZJbUZrYldsdUxYVnpaWElpTENKcmRXSmxjbTVsZEdWekxtbHZMM05sY25acFkyVmhZMk52ZFc1MEwzTmxjblpwWTJVdFlXTmpiM1Z1ZEM1MWFXUWlPaUl6TkRFNFkyUXhOUzFpTW1NNUxUUTNNVEl0WVdZeU5pMWlZemhpTWpFeE1HVmhaRFFpTENKemRXSWlPaUp6ZVhOMFpXMDZjMlZ5ZG1salpXRmpZMjkxYm5RNmEzVmlaWEp1WlhSbGN5MWtZWE5vWW05aGNtUTZZV1J0YVc0dGRYTmxjaUo5LnVqbGV6TXVlY0Z1dEVURURGaGsxUEJsY1ZDTGowSUtqZkJWak9wRndaTUF0T25kaXV0QWQybzlqOGVpLUxJS2k3cC1CTHZxZURzaFVqcWprV1J2VWFNc1ZBQS1HeUdhcG45eFUwaGYzQ2pvSFFnay11bUlYZGtFMWRreGk5YXlfbkZnbWZpLW85Z1RDazl3ZF9CNllkaTRWOWd2SkVDY0lBbzZFUWpWRzI4RkZfYnFKd3RMcjJ6aGNtLXJVZk90NjktN2lkdVYwaUpCWGcwMEFTckZjRXdkdnotOWhDUU96d0JnVUR5M0FuWTUyVkdjQ1VNU1lybW0yZ091WHh6cVpnM3VpOHppellUeE4tY0ptaXcwQ05GcjNkcmNWT3R4LWFVVzctX1REaThaeXlwbks1RUEwMEhncE9UMzRVRVlOUTItY3FlcGJpUGxiMGFuVzVGVWYxZw=="|base64 —decode

eyJhbGciOiJSUzI1NiIsImtpZCI6IjlqYU4wS3RwcFNlYzJCNXdGVmpHbkdKRVlTTGZJZUZIUTdtTHI5d2NUdVUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLWdreGtmIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIzNDE4Y2QxNS1iMmM5LTQ3MTItYWYyNi1iYzhiMjExMGVhZDQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.ujlezMuecFutETEDFhk1PBlcVCLj0IKjfBVjOpFwZMAtOndiutAd2o9j8ei-LIKi7p-BLvqeDshUjqjkWRvUaMsVAA-GyGapn9xU0hf3CjoHQgk-umIXdkE1dkxi9ay_nFgmfi-o9gTCk9wd_B6Ydi4V9gvJECcIAo6EQjVG28FF_bqJwtLr2zhcm-rUfOt69-7iduV0iJBXg00ASrFcEwdvz-9hCQOzwBgUDy3AnY52VGcCUMSYrmm2gOuXxzqZg3ui8zizYTxN-cJmiw0CNFr3drcVOtx-aUW7-_TDi8ZyypnK5EA00HgpOT34UEYNQ2-cqepbiPlb0anW5FUf1groot@controlplane:~#

The core command is:

echo -n "xxx"|base64 -decode

In the above command, we use -n option to omit echoing trailing new lines.

Now it works!

4. Summary

In this post, I demonstrated how to get token from service account in kubernetes.