Is it secure to deploy multiple application inside the Kubernetes cluster?

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.