Exercise 4: Service Accounts and RBAC

Task 1: Create Service Accounts and RBAC Roles

RBAC is used to control who can access what resources in your Kubernetes cluster. Let’s set up some RBAC rules:

  1. Create a namespace for our RBAC example:

    kubectl create namespace rbac-demo
    kubectl create namespace rbac-demo
  2. Create a service account:

    kubectl create serviceaccount developer -n rbac-demo
    kubectl create serviceaccount developer -n rbac-demo
  3. Create a role that allows read-only access to pods:

    $podReaderRoleYaml = @"
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
        namespace: rbac-demo
        name: pod-reader
    rules:
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["get", "watch", "list"]
    "@
    
    $podReaderRoleYaml | kubectl apply -f -
    cat << EOF | kubectl apply -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
        namespace: rbac-demo
        name: pod-reader
    rules:
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["get", "watch", "list"]
    EOF
  4. Create a role binding to assign the role to the service account:

    $roleBindingYaml = @"
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
        name: read-pods
        namespace: rbac-demo
    subjects:
    - kind: ServiceAccount
      name: developer
      namespace: rbac-demo
    roleRef:
      kind: Role
      name: pod-reader
      apiGroup: rbac.authorization.k8s.io
    "@
    
    $roleBindingYaml | kubectl apply -f -
    cat << EOF | kubectl apply -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
        name: read-pods
        namespace: rbac-demo
    subjects:
    - kind: ServiceAccount
      name: developer
      namespace: rbac-demo
    roleRef:
      kind: Role
      name: pod-reader
      apiGroup: rbac.authorization.k8s.io
    EOF

Task 2: Test RBAC Permissions

  1. Create a pod to test RBAC:

    kubectl run nginx --image=nginx -n rbac-demo
    kubectl run nginx --image=nginx -n rbac-demo
  2. Create a pod that uses the developer service account:

    $rbacTestPodYaml = @"
    apiVersion: v1
    kind: Pod
    metadata:
        name: rbac-test
        namespace: rbac-demo
    spec:
        serviceAccountName: developer
        containers:
        - name: curl
          image: k8sonazureworkshoppublic.azurecr.io/curlimages/curl
          command: ["sleep", "3600"]
    "@
    
    $rbacTestPodYaml | kubectl apply -f -
    cat << EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
        name: rbac-test
        namespace: rbac-demo
    spec:
        serviceAccountName: developer
        containers:
        - name: curl
          image: k8sonazureworkshoppublic.azurecr.io/curlimages/curl
          command: ["sleep", "3600"]
    EOF
  3. Wait for the pod to be running:

    kubectl wait --for=condition=Ready pod/rbac-test -n rbac-demo
    kubectl wait --for=condition=Ready pod/rbac-test -n rbac-demo
  4. Test that the service account can list pods:

kubectl exec -it rbac-test -n rbac-demo -- sh -c 'curl https://kubernetes.default.svc/api/v1/namespaces/rbac-demo/pods -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" -k'
kubectl exec -it rbac-test -n rbac-demo -- sh -c 'curl https://kubernetes.default.svc/api/v1/namespaces/rbac-demo/pods -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" -k'

This should return a filtered list showing the names of pods in the namespace.

  1. Test that the service account cannot create pods:

    kubectl exec -it rbac-test -n rbac-demo -- sh -c 'TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) && curl -s -k -H "Authorization: Bearer $TOKEN" -X POST -H "Content-Type: application/json" -d "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"test-pod\"},\"spec\":{\"containers\":[{\"name\":\"nginx\",\"image\":\"nginx\"}]}}" https://kubernetes.default.svc/api/v1/namespaces/rbac-demo/pods'
    kubectl exec -it rbac-test -n rbac-demo -- sh -c 'TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) && curl -s -k -H "Authorization: Bearer $TOKEN" -X POST -H "Content-Type: application/json" -d "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"test-pod\"},\"spec\":{\"containers\":[{\"name\":\"nginx\",\"image\":\"nginx\"}]}}" https://kubernetes.default.svc/api/v1/namespaces/rbac-demo/pods'

    This should return an error indicating that the operation is forbidden.

Task 3: Clean Up

  1. Delete the namespace and all resources created:

    kubectl delete namespace rbac-demo
    kubectl delete namespace rbac-demo