Understanding Service Accounts in Kubernetes
This post is part of a series of posts, where I will discuss security in Kubernetes. The aim is to take you with me on simplifying this complex concept.
Interaction with a Kubernetes cluster involves communication with the API server. This communication is in the form of requests sent to the API server. When a request is received by the API server it first tries to authenticate the request, if this authentication fails the request is treated as an anonymous request. This means that every process inside or outside the cluster, from a human typing kubectl
on his workstation to the kubelet
process running on a node must authenticate when making a request to the API server.
Kubernetes has two types of users, normal users and service account users. Humans are normal users and these users are not managed by the Kubernetes cluster. Service accounts are maintained by the Kubernetes cluster. Service accounts are meant to represent the processes running in pods in the cluster.
Normal users can be managed outside the cluster and the Kubernetes cluster can be made aware of them, (we can discuss how this is done in another post). These users are not tied to a specific namespace.
Service accounts on the other hand are tied to a specific namespace. These are created automatically by the API server or manually through API calls. The fact that a service account is tied to a specific namespace is very important. This ensures namespace isolation.
Whenever we create a pod in a cluster, Kubernetes assigns that pod a service account. This service account identifies the pod process as it interacts with the API server. However, assigning a service account to a pod or deployment is optional. This means that if our manifest file doesn’t specify a service account, our pod will be deployed and it will still be able to communicate with the API server.
The reason behind the above behaviour is that whenever we create a new namespace
in our cluster, Kubernetes creates a default service account for us in that namespace. When a pod has no service account in its manifest and is deployed to that namespace, that pod will be assigned the default service account.
What is a service account?
To understand what a service account is? we will examine the default service account created in the default
namespace of a Kubernetes cluster.
To get the service account in the default namespace run the command kubectl get serviceaccount -n default
. If you have not created any other service account in this namespace you will get a service account called default
.
To see more details about this service account run the command, kubectl get serviceaccount default -n default -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2021-01-26T09:12:15Z"
name: default
namespace: default
resourceVersion: "422"
uid: 8843bb73-e090-4d48-9cd6-6d8717740af1
secrets:
- name: default-token-srs4v
The above shows that this service account has a set of credentials mounted in a secret volume. In this particular case, the secret is called default-token-srs4v
.
To check the content of this secret run this command kubectl get secret default-token-srs4v -o yaml
apiVersion: v1
data:
ca.crt: <CONTENT-REMOVED>
namespace: ZGVmYXVsdA==
token: <CONTENT-REMOVED>
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 8843bb73-e090-4d48-9cd6-6d8717740af1
creationTimestamp: "2021-01-26T09:12:16Z"
name: default-token-srs4v
namespace: default
resourceVersion: "417"
uid: 46b2c8f4-41cc-4708-8901-15c2021ea8ac
type: kubernetes.io/service-account-token
We can see that the secret includes a ca.crt
file and a token
. The ca.crt
is the public CA of the API server and the token is a signed JSON Web Token (JWT).
These secrets are mounted into the pod for in-cluster access to the API server, however, you can use this cluster as a Bearer
token with a request from outside the cluster, this is not recommended.
Authentication with Service Account
When the process in the pod wants to communicate with the API server, the API server expects an Authorization
header with a value of Bearer THETOKEN
. The bearer token is the JWT token that is mounted to the pod as a secret.
When the API server receives a request with the correct bearer token the request is authenticated. If the authentication process fails the API server will reject the request a 401 HTTP status code.
Once a user is authenticated, the authorisation process starts. Kubernetes uses RBAC to determine whether a user is allowed to perform a particular action on a particular resource. RBAC consists of Roles
and RoleBinding
these objects set the authorization scope of a service account.
How are service accounts managed?
The API server uses the service account admission controller to check at pod creation time, whether the pod has a custom service account and it has does that account exist? If no account is specified then it assigns the default service account to the pod.
The service account admission also adds a volume to the pod with an API token for API access and a volumeSource
mounted at /var/run/secrets/kubernetes.io/serviceaccount
The API token is created and added to the secret by another component name the Token Controller whenever a service account is created. The token controller also monitors secrets and adds or removes token whenever secrets are added or removed from and from a service account.
The service account admission controller also ensures that the default service account exists in every namespace.
Conclusion
In this post, I have tried to explain the basics of a service account in Kubernetes. At its basic a service account provides the process running in a pod to authenticate and communicate with the API server.
If you enjoyed reading this blog post, please press the follow button to follow me. This way you will get notified about new interesting posts I publish. Thanks