Skip to content

Latest commit

 

History

History
236 lines (191 loc) · 7.25 KB

File metadata and controls

236 lines (191 loc) · 7.25 KB

rbac, namespaces and cluster roles

Now we have learnt how to secure our pods, its a good idea to separate our applications from each other via namespaces and give them the appropriate level of access
within the cluster to run. So we will first look at namespaces to separate our applications.

Namespaces

Lets look at the default namespaces available to us.
We do this by issuing kubectl get namespaces In the last lab we deployed our deployment to the default namespace as we did not define anything. Kubernetes will place any pods in the default namespace unless another one is specified.

For the next part of the lab we will create a namespace to use for the rest of the lab. We will do that by issuing

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
  name: webapp-namespace
EOF

Then if we check our namespaces again via kubectl get namespaces if we were successful then we should see the new namespace.

Cluster roles, Service accounts and Role bindings

Now we have our namespace set up we are going to create a service account and give it full access to that namespace only.

We are now going to create a service account for the namespace that we created earlier.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: webapp-service-account
  namespace: webapp-namespace
EOF

Then we will create a role giving us full permissions to the namespace

cat <<EOF | kubectl apply -f -
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: webapp-role
  namespace: webapp-namespace
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]
EOF

Then we will create a role binding to tie it all together

cat <<EOF | kubectl apply -f -
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: webapp-role-binding
  namespace: webapp-namespace
subjects:
  - kind: ServiceAccount
    name: webapp-service-account
    namespace: webapp-namespace
roleRef:
  kind: Role
  name: webapp-role
  apiGroup: rbac.authorization.k8s.io
EOF

Now lets deploy our application into our new namespace.

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: webapp-deployment
  namespace: webapp-namespace
spec:
  selector:
    matchLabels:
      app: webapp
  replicas: 1
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: scottyc/webapp:latest
        ports:
        - containerPort: 3000
          hostPort: 3000
EOF

Then we can check our pods simulating the privileges of the service-account we will set up our kubeconfig to only use our service account We will first get the secret for that service account
SECRET_NAME=$(kubectl get sa webapp-service-account --namespace webapp-namespace -o json | jq -r .secrets[].name)

Then create a ca certificate kubectl get secret --namespace webapp-namespace "${SECRET_NAME}" -o json | jq -r '.data["ca.crt"]' | base64 --decode > ca.crt

Then get the user token from our secret USER_TOKEN=$(kubectl get secret --namespace webapp-namespace "${SECRET_NAME}" -o json | jq -r '.data["token"]' | base64 --decode)

Now will will setup our kubeconfig file

context=$(kubectl config current-context)
CLUSTER_NAME=$(kubectl config get-contexts "$context" | awk '{print $3}' | tail -n 1)
ENDPOINT=$(kubectl config view -o jsonpath="{.clusters[?(@.name == \"${CLUSTER_NAME}\")].cluster.server}")
kubectl config set-cluster "${CLUSTER_NAME}" --kubeconfig=admin.conf --server="${ENDPOINT}" --certificate-authority=ca.crt --embed-certs=true
kubectl config set-credentials "webapp-service-account-webapp-namespace-${CLUSTER_NAME}" --kubeconfig=admin.conf --token="${USER_TOKEN}"
kubectl config set-context "webapp-service-account-webapp-namespace-${CLUSTER_NAME}" --kubeconfig=admin.conf --cluster="${CLUSTER_NAME}" --user="webapp-service-account-webapp-namespace-${CLUSTER_NAME}" --namespace webapp-namespace
kubectl config use-context "webapp-service-account-webapp-namespace-${CLUSTER_NAME}" --kubeconfig="${KUBECFG_FILE_NAME}"

note if you want to cheat there is a shell script here

We will then load the file in our terminal, make sure you use tmux or a seperate terminal export KUBECONFIG=admin.conf

Now let's check our permissions by seeing if we can list pods in the default namespace kubectl get pods

Now let's check our namespace kubectl get pods --namespace=webapp-namespace

(Check here for more info about rbac subjects)

Now we have limited the blast radius of our application to only the namespace that it resides in. So there will be no way that we can leak configmaps or secrets from other applications that are not in this namespace.

Users and Certificates

ServiceAcccounts are for services inside Kubernetes, to authenticate Users we can use "User" instead

cat <<EOF | kubectl apply -f -
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: webapp-role-binding
  namespace: webapp-namespace
subjects:
  - kind: User
    name: alice
    namespace: webapp-namespace
roleRef:
  kind: Role
  name: webapp-role
  apiGroup: rbac.authorization.k8s.io
EOF

kubectl get pods --namespace=webapp-namespace --as alice

Generate Certificate

Create a private key for alice:

openssl genrsa -out alice.key 2048

Create certificate sign request for alice:

openssl req -new -key alice.key -out alice.csr -subj "/CN=alice/O=myorg"

Sign the certificate for alice:

Play with Kubernetes

openssl x509 -req -in alice.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out alice.crt -days 365

Minikube

openssl x509 -req -in alice.csr -CA ~/.minikube/ca.crt -CAkey ~/.minikube/ca.key -CAcreateserial -out alice.crt -days 365

Create Alice Context in Kubectl

Create alice User in kubectl:

kubectl config set-credentials alice --client-certificate="$(pwd)/alice.crt"  --client-key="$(pwd)/alice.key"

Create alice Context in kubectl:

Play with Kubernetes

kubectl config set-context alice --cluster=kubernetes --user=alice

Minikube

Firstly get your minikube cluster ip address

echo $(minikube ip)

Then use the ip as the address in the server flag. Mine is 192.168.99.100

kubectl config set-context alice --cluster=minikube --server=https://192.168.99.100:8443 --user=alice

Retrieve Contexts:

$ kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
*         alice                         kubernetes   alice
          kubernetes-admin@kubernetes   kubernetes   kubernetes-admin

Now lets change the kubectl context to use Alice

kubectl config use-context alice

For a test now use this context and see what you have access to.

Clean up

kubectl delete -n webapp-namespace deployments.apps webapp-deployment
kubectl delete -n webapp-namespace rolebindings.rbac.authorization.k8s.io webapp-role-binding
kubectl delete -n webapp-namespace roles.rbac.authorization.k8s.io webapp-role 
kubectl delete -n webapp-namespace serviceaccounts webapp-service-account