Securing applications, CRDs and Monitoring
Let’s begin the new series. We’ll start with what is arguably the most important topic for securing a multi-user or automated Kubernetes environment: access control.
Securing applications, CRDs and Monitoring
Let’s begin the new series. We’ll start with what is arguably the most important topic for securing a multi-user or automated Kubernetes environment: access control.
So far, you’ve been interacting with your
minikubecluster as a superuser or cluster administrator. You have the power to create, delete, and modify anything you want, anywhere in the cluster. In a real-world scenario, this is a massive security risk. You wouldn’t give every developer, or every automated CI/CD script, the keys to the entire kingdom.
The central challenge is granting just enough permission for a user or application to do its job, and nothing more. This is known as the Principle of Least Privilege.
In Kubernetes, this is managed through Role-Based Access Control (RBAC). RBAC is the standard mechanism that allows you to define granular permissions for who can do what.
RBAC is built on four key API objects. Understanding them is understanding RBAC.
Role: A Role is a set of permissions for resources within a single namespace. A Role contains a list of rules, where each rule defines:
verbs: What actions are allowed (e.g., get, list, watch, create, delete, update).resources: Which objects the verbs apply to (e.g., pods, deployments, services, configmaps).apiGroups: The API group the resource belongs to (e.g., "" for core resources, apps for Deployments, batch for Jobs).ClusterRole: A ClusterRole is exactly like a Role, but it is not namespaced. You use it for two main reasons:
nodes or namespaces themselves).pods) across all namespaces in the cluster.User and Group: These represent human users. Kubernetes does not have its own user objects; these identities are assumed to come from an external source, like a client certificate or a cloud provider’s IAM system.ServiceAccount: This provides an identity for processes running inside Pods. This is the primary way you give permissions to your applications so they can interact with the Kubernetes API securely.Defining a Role does nothing on its own. You have to grant that Role to a subject.
RoleBinding: This object grants a Role to a subject (User, Group, or ServiceAccount) within a specific namespace. A RoleBinding essentially says: “In the dev namespace, give the pod-reader Role to the limited-user ServiceAccount.”ClusterRoleBinding: This grants a ClusterRole to a subject. This is used to grant cluster-wide permissions.Create a Workspace First, let’s create a new namespace to keep our work clean.
kubectl create namespace rbac-testNow, let’s create a ServiceAccount that will act as our limited user.
kubectl create serviceaccount limited-user -n rbac-testDefine a Role
We will create a Role that only grants permission to read Pods and their logs within the rbac-test namespace.
Create a file named pod-reader-role.yaml:
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:namespace: rbac-testname: pod-readerrules:- apiGroups: [""] # The empty string "" indicates the core API groupresources: ["pods", "pods/log"]verbs: ["get", "list", "watch"]Apply it to the cluster:
kubectl apply -f pod-reader-role.yamlBind the Role to the ServiceAccount
Now we need to connect our limited-user to our pod-reader role using a RoleBinding.
Create a file named pod-reader-binding.yaml:
apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:name: read-pods-bindingnamespace: rbac-testsubjects:# This is the "who" - our limited user- kind: ServiceAccountname: limited-usernamespace: rbac-testroleRef:# This is the "what" - the role we are grantingkind: Rolename: pod-readerapiGroup: rbac.authorization.k8s.ioApply the binding:
kubectl apply -f pod-reader-binding.yamlAt this point, our limited-user ServiceAccount now has read-only access to Pods, and only in the rbac-test namespace.
Test the Permissions
How can we check if this worked? kubectl has a fantastic subcommand, auth can-i, that lets you impersonate a user to check their permissions.
Let’s test an allowed action: Can our user list pods in the rbac-test namespace?
kubectl auth can-i list pods --as=system:serviceaccount:rbac-test:limited-user -n rbac-testThe output will be: yes
Now for denied actions:
Can our user delete pods in the correct namespace?
kubectl auth can-i delete pods --as=system:serviceaccount:rbac-test:limited-user -n rbac-testOutput: no (Correct! The role doesn’t include the delete verb.)
Can our user list deployments?
kubectl auth can-i list deployments --as=system:serviceaccount:rbac-test:limited-user -n rbac-testOutput: no (Correct! The role doesn’t include the deployments resource.)
Can our user list pods in the default namespace?
kubectl auth can-i list pods --as=system:serviceaccount:rbac-test:limited-user -n defaultOutput: no (Correct! The RoleBinding is only for the rbac-test namespace.)
Clean Up
We can delete the namespace, which will also delete the ServiceAccount, Role, and RoleBinding we created within it.
kubectl delete namespace rbac-testRoles (namespaced) and ClusterRoles (cluster-wide).Users, ServiceAccounts) via RoleBindings and ClusterRoleBindings.ServiceAccount provides an identity for your applications, allowing them to securely interact with the Kubernetes API using RBAC permissions.This is a fundamental security concept. Let me know when you’re ready, and we’ll build on this by looking at how to secure network traffic in Chapter 2: Securing Network Traffic with Network Policies.