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.
Setting the Stage
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
Meet Alice and Bob
We’ll need two test subjects (pun intended). I’ve put together a Kubernetes config that:
- Creates two service accounts,
- Grants both
bobpermissions to view Kubernetes jobs
alicepermissions to create new jobs
You 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
Testing out our permissions
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
We can use the Job definition in this Gist to test it out.
Let’s try creating a job with
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
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
Next, lets try viewing the job as
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
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.