I published my blog on docker security (Stop running an application inside a Docker container as the root user) , it attracted some viewers in reddit. There is some interesting discussion, I recommend to go through this reddit post. But I think the comment on the post by user blazedd put the best.
I totally agree with the comment. So I decided to write some more blogs on security related topics. In this blog I am trying to cover one important security features of kubernetes (there are others and RBAC is not sufficient enough to cover all edge cases, it will only close important security hole currently present in older k8s version), which will help us to securely deploy our application inside k8s cluster.
By default in non RABC enabled kubernetes cluster, k8s assign default service account to all deployed application. It also supply admin credentials to pods. This means inside kubernetes cluster, pods can run simple curl command or kubectl (if present) command to talk with kubernetes api. Since we are trying to deploy multiple application inside same cluster, if we have one application which has security loop hole and can run arbitrary set of commands it may going to affect entire cluster. We can reduce this risk by limiting access to pods and grant only permission which is required to run application.
Here I am using simple nginx application example to show this feature,
kubectl create ns goglides
Create Service Account
Save following content in serviceaccount.yaml file.
apiVersion: v1 kind: ServiceAccount metadata: labels: app: goglides name: goglides-serviceaccount namespace: goglides
Following role grant read only access to pods. Save content in role.yaml file.
kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: goglides-role namespace: goglides rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list"]
Create Role Binding
Save following content in rolebinding.yaml file.
apiVersion: rbac.authorization.k8s.io/v1beta1 kind: RoleBinding metadata: name: goglides-role namespace: goglides roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: goglides-role subjects: - kind: ServiceAccount name: goglides-serviceaccount namespace: goglides
Associate ServiceAccount with Deployment
Now we can assign service account to deployment, so thats pods will came up with only get pods access to particular namespace.
Save following content in nginx.yaml file.
kind: Deployment metadata: name: nginx-deployment namespace: goglides spec: selector: matchLabels: app: nginx replicas: 2 template: metadata: labels: app: nginx spec: serviceAccountName: goglides-serviceaccount # Use same service account you created above containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80
Now finally run following command to apply these changes in k8s cluster,
kubectl apply -f serviceaccount.yaml kubectl apply -f role.yaml kubectl apply -f rolebinding.yaml kubectl apply -f nginx.yaml
This will deploy application with RBAC rule applied. We can validate this whether it is actually working or not. Run following to get pod details,
kubectl get pods -n goglides NAME READY STATUS RESTARTS AGE nginx-deployment-3773857781-5g1p3 1/1 Running 0 18m nginx-deployment-3773857781-zjg39 1/1 Running 0 18m
Now attach to pods with following command,
kubectl exec -it nginx-deployment-3773857781-zjg39 -n goglides -- bash
Run get pods command, for this we also require kubectl inside pods. Since we are allowing list pods in our role, so you should able to list the pods.
root@nginx-deployment-3773857781-zjg39:/# ./kubectl get pods NAME READY STATUS RESTARTS AGE nginx-deployment-3773857781-5g1p3 1/1 Running 0 22m nginx-deployment-3773857781-zjg39 1/1 Running 0 22
Now try listing deployments, you will see access denied error.
Well looks like RBAC is working :)
Try it yourself and let me know how it goes in comment section. Also for future post do not forget to subscribe this blog.