Exercise
In this exercise, you’ll manage RBAC rules based on the role of your team’s members.
Let’s assume:
- You’re an admin
- A team has the following members: Alice, Bob, Charlie, Dave. Each with different responsibilities
- Create the Namespaces and RBAC resources
The following table lists the role of each team member
| User | Role | Access |
|---|---|---|
| Alice | Developer | Full access to dev namespace |
| Bob | QA/Tester | Can view & list pods in dev |
| Charlie | DevOps | Can deploy applications in staging |
| Dave | Security Analyst | Read-only to all namespaces |
- Create the ?amespaces: dev, staging
- Create the Roles and RoleBindings for each user
- Simulate access using impersonation
- Adding Another Developer (Eve)
Eve joins as Developer. Modify the corresponding RoleBinding to include Eve as well.
- DevOps Needs Access to Production Temporarily
Charlie (DevOps) needs to roll back production.
- Grant access to prod namespace, with time-based audit note
- Create a separate RoleBinding with expiration annotation
- Add a label or an annotation for easy audit
- Revoke Access for Dave
Dave moves to a different team. Remove his RoleBindings.
Documentation
https://kubernetes.io/docs/reference/access-authn-authz/rbac/
Solution
- Create the Namespaces and RBAC resources
- Creation of the .amespaces
kubectl create namespace dev
kubectl create namespace staging
kubectl create namespace prod- Creation of a Role for Alice (full access to dev Namespace):
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: dev
name: developer
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
EOF- Creation of a RoleBinding for Alice:
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: alice-developer
namespace: dev
subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer
apiGroup: rbac.authorization.k8s.io
EOF- Creation of a Role for Bob (view Pods in dev):
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: dev
name: qa-tester
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/log", "pods/status"]
verbs: ["get", "list"]
EOF- Creation of a RoleBinding for Bob:
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: bob-qa
namespace: dev
subjects:
- kind: User
name: bob
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: qa-tester
apiGroup: rbac.authorization.k8s.io
EOF- Creation of a Role for Charlie (can deploy applications in staging):
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: staging
name: devops
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets", "statefulset", "daemonset"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "scale"]
EOF- Creation of a RoleBinding for Charlie:
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: charlie-devops
namespace: staging
subjects:
- kind: User
name: charlie
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: devops
apiGroup: rbac.authorization.k8s.io
EOF- Creation of a ClusterRole for Dave (read access to all namespaces):
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: security-analyst
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch"]
EOF- Creation of a ClusterRoleBinding for Dave:
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: dave-security-analyst
subjects:
- kind: User
name: dave
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: security-analyst
apiGroup: rbac.authorization.k8s.io
EOFUse the following commands to test the access using impersonation:
- Testing Alice’s access (should work)
kubectl auth can-i create pods --namespace=dev --as=alice
kubectl auth can-i delete deployments --namespace=dev --as=alice- Testing Bob’s access (should only view pods)
kubectl auth can-i get pods --namespace=dev --as=bob
kubectl auth can-i create pods --namespace=dev --as=bob # Should not be authorized- Testing Charlie’s access (can deploy applications in staging)
kubectl auth can-i create deployments --namespace=staging --as=charlie
kubectl auth can-i create deployments --namespace=dev --as=charlie # Should not be authorized
kubectl auth can-i create configmaps --namespace=dev --as=charlie # Should not be authorized- Tetsing Dave’s access (read-only in all Namespaces)
kubectl auth can-i get pods --namespace=dev --as=dave
kubectl auth can-i get pods --namespace=staging --as=dave
kubectl auth can-i delete pods --namespace=dev --as=dave # Should not be authorized- Adding Another Developer (Eve)
Modify the existing RoleBinding to include Eve:
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: alice-eve-developers
namespace: dev
subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
- kind: User
name: eve
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer
apiGroup: rbac.authorization.k8s.io
EOFTesting Eve’s access:
kubectl auth can-i create pods --namespace=dev --as=eve
kubectl auth can-i delete deployments --namespace=dev --as=eve
kubectl auth can-i create pods --namespace=staging --as=eve # Should not be authorized- DevOps Needs Access to Production Temporarily
Creation of the devops role in prod namespace:
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: prod
name: devops
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "scale"]
EOFFirst, we define an expiration date. The command is different if you’re using MacOS or a Linux machine.
expires_at=$(if [[ "$OSTYPE" == "darwin"* ]]; then
date -u -v+1d '+%Y%m%dT%H%M%S'
else
date -u -d '+1 day' '+%Y%m%dT%H%M%S'
fi)Next, we create a RoleBinding for Charlie in prod Namespace. We’re using a specific annotation to keep track of the expiration date that we could verify in an external script.
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: charlie-prod-temp
namespace: prod
labels:
access-type: temporary
user: charlie
annotations:
expires-at: "${expires_at}"
subjects:
- kind: User
name: charlie
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: devops
apiGroup: rbac.authorization.k8s.io
EOFThen, we test Charlie’s access to the prod Namespace:
kubectl auth can-i create deployments --namespace=prod --as=charlieThe following are example commands to audit this temporary access:
- Listing all temporary access bindings
kubectl get rolebindings -A -l access-type=temporary- Checking Charlie’s specific access
kubectl get rolebindings -A -l user=charlie- Revoking Access
First, we search for Dave in RoleBindings (there should not be any):
kubectl get rolebindings -A -o json | jq -r '.items[] | select(.subjects[]?.name == "dave") | "\(.metadata.namespace)/\(.metadata.name)"'Next, we search for Dave in ClusterRoleBindings:
kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.subjects[]?.name == "dave") | .metadata.name'Next, we remove Dave’s access:
kubectl delete clusterrolebinding dave-security-analystThen, we verify Dave’s access is revoked:
kubectl auth can-i get pods --namespace=dev --as=dave # Should not be authorized
kubectl auth can-i get deployment --namespace=staging --as=dave # Should not be authorized