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.
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:
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.