Published on Nov 15, 2020 in #kubernetes
They say a bash one-liner is worth a thousand words, or something like that…
kubectl --as system:serviceaccount:default:myapp get pods
# Error from server (Forbidden): pods is forbidden: User
# "system:serviceaccount:default:myapp" cannot list resource
# "pods" in API group "" in the namespace "default"
Recently I found myself setting up a Kubernetes service account to give my application read access to some Kubernetes resources. Following the principle of least privilege, I wanted to ensure my application had the absolute minimum access it needed.
As I prepared the Kubernetes YAML files, I wondered how I could test these locally before deploying. Follow along below to see the process I used.
First, we’ll need a Kubernetes cluster to test on.
I’m going to use minikube to create a test cluster on my laptop, but any Kubernetes cluster will work.
minikube start
# 😄 minikube v1.15.0 on Darwin 10.15.5
# ✨ Automatically selected the docker driver. Other choices: hyperkit, virtualbox
# 👍 Starting control plane node minikube in cluster minikube
# .....
# 🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
We’ll need two test subjects (pun intended). I’ve put together a Kubernetes config that:
alice and bobalice and bob permissions to view Kubernetes jobsalice permissions to create new jobsYou can view the gist on Github. We’ll apply it to our Minikube cluster:
kubectl apply -f https://gist.githubusercontent.com/darrenclark/1e0810a0e864efe9bb712d3d0dd991c7/raw/83458fdf93c3aea1be292506e28a26c73e68e9db/service-accounts-and-permissions.yaml
# serviceaccount/alice created
# serviceaccount/bob created
# role.rbac.authorization.k8s.io/jobs-viewer created
# role.rbac.authorization.k8s.io/jobs-manager created
# rolebinding.rbac.authorization.k8s.io/alice-and-bob-jobs-viewer created
# rolebinding.rbac.authorization.k8s.io/alice-jobs-manager created
Let’s test out the permissions on our newly created service accounts. Lucky for us, kubectl has the perfect tool for the job. From the man page:
--as="" Username to impersonate for the operation
This allows us to run kubectl as if we were alice or bob.
We can use the Job definition in this Gist to test it out.
alice’s permissionsLet’s try creating a job with alice:
kubectl create \
--as=system:serviceaccount:default:alice \
-f https://gist.githubusercontent.com/darrenclark/1e0810a0e864efe9bb712d3d0dd991c7/raw/83458fdf93c3aea1be292506e28a26c73e68e9db/job.yaml
# job.batch/echo-job-jv8jh created
And viewing that job as alice:
kubectl --as=system:serviceaccount:default:alice get jobs
# NAME COMPLETIONS DURATION AGE
# echo-job-jv8jh 1/1 3s 39s
No surprises here, as we granted alice read and write access to jobs.
bob’s permissionsNext, lets try viewing the job as bob:
kubectl --as=system:serviceaccount:default:bob get jobs
# NAME COMPLETIONS DURATION AGE
# echo-job-jv8jh 1/1 3s 3m25s
Looks good. What happens when we try to create a job as bob?
kubectl create \
--as=system:serviceaccount:default:bob \
-f https://gist.githubusercontent.com/darrenclark/1e0810a0e864efe9bb712d3d0dd991c7/raw/83458fdf93c3aea1be292506e28a26c73e68e9db/job.yaml
# Error from server (Forbidden): error when creating "https://gist.githubusercontent.com/darrenclark/1e0810a0e864efe9bb712d3d0dd991c7/raw/83458fdf93c3aea1be292506e28a26c73e68e9db/job.yaml":
# jobs.batch is forbidden: User "system:serviceaccount:default:bob"
# cannot create resource "jobs" in API group "batch" in the namespace
# "default"
As we expected! We gave bob read-only access to jobs, so it makes sense we got an error back.
I was quite happy to learn about the --as argument. It made it really easy to test the permissions for my service account, and I could be confident I was giving it the minimum required permissions.