๐ท๏ธ Manage role based access control (RBAC)#
RBAC
Managing Role-Based Access Control (RBAC) in Kubernetes involves defining and enforcing granular permissions for users, groups, and service accounts to ensure security and operational efficiency.
The core components of Kubernetes RBAC are Roles, ClusterRoles, RoleBindings, and ClusterRoleBindings, which are used to define and assign permissions.
Roles define permissions within a specific namespace, while ClusterRoles define permissions across the entire cluster, including access to cluster-scoped resources like nodes or persistent volumes.
A RoleBinding grants the permissions defined in a Role to a subject (user, group, or service account) within a specific namespace, whereas a ClusterRoleBinding grants those permissions cluster-wide.
User#
Create a new user.#
แ
sudo useradd -s /bin/bash DevDan
แ
sudo passwd DevDan
Create namespaces#
แ
k create ns development
แ
k create ns production
Create user certificate.#
แ
openssl genrsa -out DevDan.key 2048
แ
openssl req -new -key DevDan.key -out DevDan.csr -subj "/CN=DevDan/O=development"
แ
sudo openssl x509 -req -in DevDan.csr \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial -out DevDan.crt -days 45
Create user and context (in kubeconfig).#
แ
k config set-credentials DevDan --client-certificate=./DevDan.crt --client-key=./DevDan.key
แ
yq -r '.users[] | select (.name == "DevDan")' .kube/config
{
"name": "DevDan",
"user": {
"client-certificate": "/home/guisam/DevDan.crt",
"client-key": "/home/guisam/DevDan.key"
}
}
แ
k config get-users
NAME
DevDan
kubernetes-admin
แ
k config set-context DevDan --cluster=kubernetes \
--user=DevDan --namespace=development
แ
k config set-context ProdDan --cluster=kubernetes \
--user=DevDan --namespace=production
แ
k config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
DevDan kubernetes DevDan development
ProdDan kubernetes DevDan production
* kubernetes-admin@kubernetes kubernetes kubernetes-admin
Create roles and rolebindings.#
แ
cat <<EOF > dev-role.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: development
name: developer
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["deployments", "replicasets", "pods"]
verbs: ["list", "get", "watch", "create", "update", "patch", "delete"]
EOF
แ
cat <<EOF > rolebind.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: developer-role-binding
namespace: development
subjects:
- kind: User
name: DevDan
apiGroup: ""
roleRef:
kind: Role
name: developer
apiGroup: ""
EOF
แ
cat <<EOF > prod-role.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: production
name: dev-prod
rules:
- apiGroups: ["", "extensions", "apps"]
resources: ["deployments", "replicasets", "pods"]
verbs: ["list", "get", "watch"]
EOF
แ
cat <<EOF > prodrolebind.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: production-role-binding
namespace: production
subjects:
- kind: User
name: DevDan
apiGroup: ""
roleRef:
kind: Role
name: dev-prod
apiGroup: ""
EOF
แ
k apply -f dev-role.yaml -f rolebind.yaml -f prod-role.yaml -f prodrolebind.yaml
แ
k --context ProdDan-context run test --image=nginx
Error from server (Forbidden): pods is forbidden: User "DevDan" cannot create resource "pods" in API group "" in the namespace "production"
ServiceAccount#
ServiceAccount
A service account is a specialized identity for processes running within a Pod, providing a distinct and manageable way for workloads to authenticate and interact with the Kubernetes API server.
It is a non-human account managed by the Kubernetes API server, typically bound to a specific namespace, and exists as a ServiceAccount object within the cluster.
Service accounts are essential for enabling automated processes, such as applications, system components, or external services, to securely access cluster resources by using credentialsโspecifically, a signed JSON Web Token (JWT)โwhich are automatically mounted into Pods.
By default, every namespace includes a default service account, and Pods are assigned this default account unless explicitly configured otherwise.
The permissions granted to a service account are controlled through Role-Based Access Control (RBAC), allowing administrators to enforce the principle of least privilege by defining precise access rights.
Service Account Token#
Long-Lived Token#
Warning
Not recommended as token never expires.
Create a serviceaccount and a secret.
แ
k create sa long-lived-sa
แ
cat <<EOF > long-lived-secret.yaml
apiVersion: v1
kind: Secret
metadata:
creationTimestamp: null
name: long-lived-secret
annotations:
kubernetes.io/service-account.name: long-lived-sa
type: kubernetes.io/service-account-token
EOF
Tip
แ
k create secret generic long-lived-secret \
--dry-run=client --type=kubernetes.io/service-account-token \
-o yaml > long-lived-secret.yaml
then add annotations.kubernetes.io/service-account.name.
Create a role and a rolebinding.
แ
k create role long-lived-role \
--verb=get,list,watch --resource=pods,deployments
แ
k create rolebinding long-lived-rb \
--role=long-lived-role --serviceaccount=default:long-lived-sa
rolebinding.rbac.authorization.k8s.io/long-lived-rb created
Create pod.
แ
k run long-lived-pod --image=nginx --dry-run=client -o yaml > long-lived-pod.yaml
แ
diff -u long-lived-pod.yaml{.before,}
--- long-lived-pod.yaml.before 2025-11-03 16:59:02.724965164 +0100
+++ long-lived-pod.yaml 2025-11-03 17:00:06.517864947 +0100
@@ -12,4 +12,6 @@
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
+ serviceAccountName: long-lived-sa
+ automountServiceAccountToken: true
status: {}
แ
k apply -f long-lived-pod.yaml
Check.
แ
k exec -ti long-lived-pod -- bash
root@long-lived-pod:/# token=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
root@long-lived-pod:/# cacert=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
root@long-lived-pod:/# ns=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
root@long-lived-pod:/# apt update &> /dev/null && apt install -y jq &> /dev/null
root@long-lived-pod:/# curl -s --cacert $cacert -H "Authorization: Bearer $token" \
> https://kubernetes/api/v1/namespaces/"$ns"/pods/ | jq -r '.items[].metadata.name'
lg-lv-pod
po-test
Time Bound Token#
Create a serviceaccount and a token.
k create sa tb-sa
k create token tb-sa --duration 1h
Create a role and bind it to the serviceaccount.
k create role tb-role --verb=get,list,watch --resource=pods,deployments
k create rolebinding tb-rolebinding --role=tb-role --serviceaccount=default:tb-sa
Create a pod.
k run tb-pod --image=nginx --dry-run=client -o yaml > tb-pod.yaml
diff -u tb-pod.yaml{.before,}
--- tb-pod.yaml.before 2025-11-03 18:52:10.138414525 +0100
+++ tb-pod.yaml 2025-11-03 18:55:47.907040341 +0100
@@ -12,4 +12,5 @@
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
+ serviceAccountName: tb-sa
status: {}
k apply -f tb-pod.yaml
Same check as long-lived sa.