{"id":848,"date":"2025-01-09T04:59:08","date_gmt":"2025-01-09T04:59:08","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=848"},"modified":"2025-01-09T04:59:08","modified_gmt":"2025-01-09T04:59:08","slug":"kubernetes-api-access-service-account","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=848","title":{"rendered":"How to Create a Service Account Token and For Cluster API Access"},"content":{"rendered":"<p>This tutorial will guide you through the process of creating the service account, role, role binding and secret to have API access to the Kubernetes cluster using long lived token.<\/p>\n<p>The best and recommended way to allow API access to the <a href=\"https:\/\/devopscube.com\/setup-kubernetes-cluster-kubeadm\/\" rel=\"noreferrer noopener\">Kubernetes cluster<\/a> is through service accounts with long lived tokens following the <strong>principle of least privilege<\/strong> (PoLP).<\/p>\n<h2 id=\"use-cases\">Use Cases<\/h2>\n<p>Following are the example use cases of Kubernetes service account for external API access.<\/p>\n<ol>\n<li>Allowing third-party <a href=\"https:\/\/devopscube.com\/best-opensource-monitoring-tools\/\" rel=\"noreferrer noopener\">monitoring tools<\/a> to access Kubernetes data<\/li>\n<li>External applications to access kubernetes resources.<\/li>\n<\/ol>\n<p>Now, why would you need this access?<\/p>\n<p>Lets take an example of <a href=\"https:\/\/devopscube.com\/setup-prometheus-monitoring-on-kubernetes\/\" rel=\"noreferrer noopener\">Prometheus monitoring<\/a> stack.<\/p>\n<p>Prometheus <strong>needs read access to cluster API<\/strong> to get information from metrics server, read pods, etc.<\/p>\n<p>When you deploy Prometheus, you add cluster read permissions to the default service account where the Prometheus pods are deployed. This way, Prometheus pods get read access to cluster resources.<\/p>\n<h2 id=\"setup-kubernetes-api-access-using-service-account-token\">Setup Kubernetes API Access Using Service Account Token<\/h2>\n<p>Follow the steps given below to create a <a href=\"https:\/\/devopscube.com\/create-kubernetes-role\/\" rel=\"noreferrer\">service account<\/a> token for API access.<\/p>\n<h3 id=\"step-1-create-service-account-in-a-namespace\">Step 1: Create service account in a namespace<\/h3>\n<p>We will create a service account in a custom namespace rather than the default namespace for demonstration purposes.<\/p>\n<p>Create a <code>devops-tools<\/code> namespace.<\/p>\n<pre><code>kubectl create namespace devops-tools<\/code><\/pre>\n<p>Create a service account named &#8220;<code>api-service-account<\/code>&#8221; in <code>devops-tools<\/code> namespace<\/p>\n<p>kubectl create serviceaccount api-service-account -n devops-tools<\/p>\n<p>or use the following manifest.<\/p>\n<pre><code>cat &lt;&lt;EOF | kubectl apply -f -\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: api-service-account\n  namespace: devops-tools\nEOF<\/code><\/pre>\n<h3 id=\"step-2-create-a-cluster-role\">Step 2: Create a Cluster Role<\/h3>\n<p>Assuming that the service account needs access to the entire cluster resources, we will create a cluster role with a list of allowed access.<\/p>\n<p>Create a clusterRole named <code>api-cluster-role<\/code> with the following manifest file.<\/p>\n<pre><code>cat &lt;&lt;EOF | kubectl apply -f -\n---\napiVersion: rbac.authorization.k8s.io\/v1\nkind: ClusterRole\nmetadata:\n  name: api-cluster-role\n  namespace: devops-tools\nrules:\n  - apiGroups:\n        - \"\"\n        - apps\n        - autoscaling\n        - batch\n        - extensions\n        - policy\n        - rbac.authorization.k8s.io\n    resources:\n      - pods\n      - componentstatuses\n      - configmaps\n      - daemonsets\n      - deployments\n      - events\n      - endpoints\n      - horizontalpodautoscalers\n      - ingress\n      - jobs\n      - limitranges\n      - namespaces\n      - nodes\n      - pods\n      - persistentvolumes\n      - persistentvolumeclaims\n      - resourcequotas\n      - replicasets\n      - replicationcontrollers\n      - serviceaccounts\n      - services\n    verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\", \"patch\", \"delete\"]\nEOF<\/code><\/pre>\n<p>The above YAML declaration has a <code>ClusterRole<\/code> with full access to all cluster resources and a role binding to &#8220;<code>api-service-account<\/code>&#8220;.<\/p>\n<p>It is not recommended to create a service account with all cluster component access without any requirement.<\/p>\n<p>To get the list of available API resources execute the following command.<\/p>\n<pre><code>kubectl api-resources<\/code><\/pre>\n<h3 id=\"step-3-create-a-cluserrole-binding\">Step 3: Create a CluserRole Binding<\/h3>\n<p>Now that we have the ClusterRole and service account, it needs to be mapped together.<\/p>\n<p>Bind the <code>cluster-api-role<\/code> to <code>api-service-account<\/code> using a <code>RoleBinding<\/code><\/p>\n<pre><code>cat &lt;&lt;EOF | kubectl apply -f -\n---\napiVersion: rbac.authorization.k8s.io\/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: api-cluster-role-binding\nsubjects:\n- namespace: devops-tools \n  kind: ServiceAccount\n  name: api-service-account \nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: api-cluster-role \nEOF<\/code><\/pre>\n<h3 id=\"step-4-validate-service-account-access-using-kubectl\">Step 4: Validate Service Account Access Using kubectl<\/h3>\n<p>To validate the clusterrole binding,  we can use <code>can-i<\/code> commands to validate the API access assuming a service account in a specific namespace.<\/p>\n<p>For example, the following command checks if the <code>api-service-account<\/code> in the <code>devops-tools<\/code> namespace can list the pods.<\/p>\n<pre><code>kubectl auth can-i get pods --as=system:serviceaccount:devops-tools:api-service-account<\/code><\/pre>\n<p>Here is another example, to check if the service account has permissions to delete deployments.<\/p>\n<pre><code>kubectl auth can-i delete deployments --as=system:serviceaccount:devops-tools:api-service-account<\/code><\/pre>\n<h3 id=\"step-5-associate-a-secret-with-service-account\">Step 5: Associate a Secret With Service Account<\/h3>\n<p>To use a service account with an HTTP call, you need to have the <strong>long lived token<\/strong> associated with the service account. A <strong>long-lived token<\/strong> in Kubernetes is an authentication token that does not expire quickly, allowing continuous access to the Kubernetes API for an extended period.<\/p>\n<p>For that, you <strong>need to create a secret <\/strong>for the service account.<\/p>\n<p>Create a file named <code>sa-token.yaml<\/code>, and copy the following content.<\/p>\n<pre><code>apiVersion: v1\nkind: Secret\ntype: kubernetes.io\/service-account-token\nmetadata:\n  name: api-service-account-token\n  namespace: devops-tools\n  annotations:\n    kubernetes.io\/service-account.name: api-service-account<\/code><\/pre>\n<p>Then, create the secret by running the following command.<\/p>\n<pre><code>kubectl apply -f sa-token.yaml<\/code><\/pre>\n<p>Once the secret is created, use the following command to get the base64 decoded token. It will be used as a bearer token in the API call.<\/p>\n<pre><code>kubectl get secret api-service-account-token -o=jsonpath='{.data.token}' -n devops-tools | base64 --decode<\/code><\/pre>\n<p>Get the cluster endpoint to validate the API access. The following command will display the cluster endpoint (IP, DNS).<\/p>\n<pre><code>kubectl get endpoints | grep kubernetes<\/code><\/pre>\n<h3 id=\"step-6-validate-service-account-access-using-api-call\">Step 6: Validate Service Account Access Using API call<\/h3>\n<p>Now that you have the cluster endpoint and the service account token, you can test the API connectivity using the CURL or the Postman app.<\/p>\n<p>For example, list all the namespaces in the cluster using curl. Use the token after <code>Authorization: Bearer<\/code> section.<\/p>\n<pre><code>curl -k  https:\/\/35.226.193.217\/api\/v1\/namespaces -H \"Authorization: Bearer eyJhbGcisdfsdfsdfiJ9.eyJpc3MiOisdfsdfVhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3sdf3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImFwaS1zZXJ2aWNlsdfglkjoer876Y3BmNWYiLsdfsdfRlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmFwaS1zZXJ2aWNlLWFjY291bnQifQ.u5jgk2px_lEs3f5e5lh_UfS40fndtDKMTY5UvsdfrtsuhtgjrUj-ezrRXeLS8SLOae4DuOGGGbInSg_gIo6oO7bLHhCixWOBJNOA5gzrLVioof_kHDR8gH5crrsWoR-GSSsdfgsdfg6fA_LDOqdxzqMC0WlXt6tgHfrwIHerPPvkI6NWLyCqX9tn_akpcihd-bL6GwOKlph17l_ND710FnTkE7kBfdXtQWWxaPPe06UEmoKK9t-0gsOCBxJxViwhHkvwqetr987q9enkadfgd_2cY_CA\"<\/code><\/pre>\n<p>You can also try that same API call in Postman.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-150.png\" class=\"kg-image\" alt=\"Testing Kubernetes Service account token for Cluster API access.\" loading=\"lazy\" width=\"1020\" height=\"781\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-150.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-150.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-150.png 1020w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>The <code>ClusterRole<\/code> we created can be attached to pods\/deployments as well.<\/p>\n<p>You can also use the token to login to the Kubernetes dashboard.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>When using Kubernetes service account for API access from third party applications, ensure you add only required roles to the service account.<\/p>\n<p>Also, never attach a clusterRole to a default service account because the pods get the default service account by default. Meaning all the pods in the namespace have access to the clusterRole.<\/p>\n<p>Also, use a secret management tool like <a href=\"https:\/\/devopscube.com\/setup-hashicorp-vault-beginners-guide\/\" rel=\"noreferrer noopener\">Hashicorp vault<\/a> to store, retrieve, and share secret tokens.<\/p>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/kubernetes-api-access-service-account\/\" target=\"_blank\" rel=\"noopener noreferrer\">How to Create a Service Account Token and For Cluster API Access \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/kubernetes-api-access-service-account\/<\/p>\n","protected":false},"author":1,"featured_media":849,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-848","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/848","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=848"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/848\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/849"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=848"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=848"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=848"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}