Deploying the Kubernetes Dashboard is quite easy. There's a Helm chart with good documentation. It gets harder when you want to limit the access to this dashboard. This post provides a way to setup readonly access to the dashboard.

Prerequisites

  • Kubernetes cluster
  • Vault setup

Different ways of authentication

The Kubernetes Dashboard application supports many authentication methods. The most common used ones are:

  • Basic Auth
  • Kubeconfig file
  • Bearer Token

The Basic Auth method is disabled by default. The reason is that Kubernetes API server needs to be configured with authorization mode ABAC and --basic-auth-file flag provided.

The Kubeconfig file method is provided for convenience. You can see it as an authentication method for a Dashboard PoC.

The Bearer Token method is the one we will use in this guide.

Let's deploy the dashboard

I've chosen to deploy the Dashboard via Helm. How Helm works, is out of scope for this blog post, but there's extensive documentation to be found on the internet. As said in the beginning, we're going to setup readonly access, so let's provide a necessary configuration value to the Helm chart:

rbac:
  clusterReadOnlyRole: true

This instructs Helm to create a readonly ClusterRole. This ClusterRole allows the ServiceAccount via a ClusterRoleBinding to read all Kubernetes objects, like pods, services, ...

When Helm is ready provisioning the dashboard, you should be greeted with the following screen:

Dashboard login

You could now test the functionality of the dashboard by logging in with your kubeconfig file.

Prepare the Vault secrets engine

The Kubernetes secretes engine requires a ServiceAccount on the Kubernetes cluster, with enough permissions to create ServiceAccount tokens. The ServiceAccount can be created in any namespace, as it will have a ClusterRole attached to it, which is not a namespaced object.

Let's start with the creation of a namespace for the ServiceAccount:

apiVersion: v1
kind: Namespace
metadata:
  name: vault

Then we create the ServiceAccount in the new namespace:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: vault
  namespace: vault

Next, we need a ClusterRole that allows to create ServiceAccount tokens:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: create-service-account-tokens
rules:
- apiGroups: [""]
  resources: ["serviceaccounts/token"]
  verbs: ["create"]

To be able to attach this ClusterRole to a ServiceAccount, we need a ClusterRoleBinding:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: create-service-account-tokens-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: create-service-account-tokens
subjects:
- kind: ServiceAccount
  name: vault
  namespace: vault

We can now apply all these manifests to the cluster with kubectl apply.

Now that the vault ServiceAccount is provisioned, we need to create a token for it, so the Kubernetes secrets engine can use this ServiceAccount:

kubectl create token vault --namespace vault --duration=31536000s

The duration equals 1 year, as we don't want to reconfigure the secrets engine all the time.

With all the preparations done at the Kubernetes side, we can setup the secret engine for real in Vault. The first step is to enable the secrets engine itself.

vault secrets enable kubernetes

Next, we need to configure this secrets engine. We need to point it to the Kubernetes API, provide the certificate to authenticate to the API and give it a service_account_jwt attached to the vault ServiceAccount we created earlier.

vault write kubernetes/config kubernetes_host=https://<ADDRESS>:<PORT> kubernetes_ca_cert="@ca.crt" service_account_jwt=<TOKEN>

The final step it to create a Vault role that can generate ServiceAccount tokens for the readonly ServiceAccount that the Helm chart created.

vault write kubernetes/roles/dashboard allowed_kubernetes_namespaces=<KUBERNETES_DASHBOARD_NAMESPACE> service_account_name=<SERVICE_ACCOUNT_NAME>

Create a token

Finally, we can create a token to use to login to the dashboard:

vault write -field=service_account_token kubernetes/creds/dashboard kubernetes_namespace=<KUBERNETES_DASHBOARD_NAMESPACE>

The authorization of who can use the kubernetes/creds/dashboard endpoint is configured by Vault policies, but thats out of scope for this guide. A successful request returns a token that you can use on the dashboard login page.