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.
RBAC
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.
Book for further reading on Kubernetes: Up and Running: Dive into the Future of Infrastructure
Here I am using simple nginx application example to show this feature,
Create namespace
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
Create Role
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.