Docs: Update Kubernetes Dashboard Guide (#2759) (#2795)

* update dashboard guide...
This new version takes advantage of the RBAC options the Pomerium Helm chart now makes available

* Update docs/guides/kubernetes-dashboard.md

Co-authored-by: Travis Groth <travisgroth@users.noreply.github.com>

* edit intro para

* Apply suggestions from code review

Co-authored-by: cmo-pomerium <91488121+cmo-pomerium@users.noreply.github.com>

* remvove numbered list of one

* Update docs/guides/kubernetes-dashboard.md

Co-authored-by: cmo-pomerium <91488121+cmo-pomerium@users.noreply.github.com>

* typo correction

Co-authored-by: Travis Groth <travisgroth@users.noreply.github.com>
Co-authored-by: cmo-pomerium <91488121+cmo-pomerium@users.noreply.github.com>

Co-authored-by: Alex Fornuto <afornuto@pomerium.com>
Co-authored-by: Travis Groth <travisgroth@users.noreply.github.com>
Co-authored-by: cmo-pomerium <91488121+cmo-pomerium@users.noreply.github.com>
This commit is contained in:
backport-actions-token[bot] 2021-12-01 11:13:56 -06:00 committed by GitHub
parent 0678a5e619
commit cc8ffed694
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 324 deletions

Binary file not shown.

View file

@ -10,363 +10,104 @@ description: >-
# Securing Kubernetes Dashboard
The following guide covers how to secure [Kubernetes Dashboard] using Pomerium. Kubernetes Dashboard is a powerful, web-based UI for managing Kubernetes clusters. Pomerium can act as a **forward-auth provider** _and_ as an independent **identity-aware access proxy** improving and adding single-sign-on to Kubernetes Dashboard's default access control. This guide aims to demonstrate a concrete example of those two methods of access control.
The following guide covers how to secure [Kubernetes Dashboard] using Pomerium. Kubernetes Dashboard is a powerful, web-based UI for managing Kubernetes clusters. Pomerium can act as an independent **identity-aware access proxy** improving and adding single-sign-on to Kubernetes Dashboard's default access control. This is in contrast to most deployments, which use static tokens for access.
![fresh kubernetes dashboard install](./img/k8s-fresh-dashboard.png)
This tutorial covers:
- Installing [Helm] a package manager for Kubernetes
- Deploying [NGINX Ingress Controller]
- Install and configure [Cert-Manager] to issue [LetsEncrypt] certificates
- Deploying Pomerium
- Deploying [Kubernetes Dashboard]
- Secure Kubernetes Dashboard access:
- _directly_, using Pomerium's proxy component
- _indirectly_, using Pomerium as a [forward-auth] provider
- Deploying [Kubernetes Dashboard] using [Helm]
- Establishing secure Kubernetes Dashboard access through Pomerium
:::warning
nginx-ingress [version 0.26.2](https://github.com/helm/charts/issues/20001) contains a regression that breaks external auth and results in an infinite loop.
:::
## Before You Begin
This guide builds off of existing articles and guides. It assumes you have deployed Pomerium to your cluster using our Helm charts, configured a certificate solution like [cert-manager], and set up secure access to the Kubernetes API. Follow the instructions in these pages before you continue:
- [Install Pomerium using Helm]
- [Securing Kubernetes]
## Background
Though securing [kubernetes dashboard] as an example may seem contrived, the damages caused by an unsecured dashboard is a real threat vector. In late 2018, Telsa [determined](https://redlock.io/blog/cryptojacking-tesla) that the hackers who were running [crypto-mining malware](https://arstechnica.com/information-technology/2018/02/tesla-cloud-resources-are-hacked-to-run-cryptocurrency-mining-malware/) on their cloud accounts came in through an unsecured [Kubernetes Dashboard] instance.
Though securing [Kubernetes Dashboard] as an example may seem contrived, the damages caused by an unsecured dashboard is a real threat vector. In late 2018, Tesla [determined](https://redlock.io/blog/cryptojacking-tesla) that the hackers who were running [crypto-mining malware](https://arstechnica.com/information-technology/2018/02/tesla-cloud-resources-are-hacked-to-run-cryptocurrency-mining-malware/) on their cloud accounts came in through an unsecured [Kubernetes Dashboard] instance.
![tesla hacked from kubernetes dashboard](./img/k8s-tesla-hacked.png)
## Helm
First, we will install [Helm]. Helm is a package manager similar to `apt-get` or `brew` but for Kubernetes and it's what we'll use to install Pomerium, nginx-ingress, cert-manager, and the dashboard.
### Install
There are two parts to Helm: the client, and the server. This guide will cover the most common installation path. Please refer to the [Helm install] instructions for more details, and other options.
#### Client
We'll install by installing the helm client on our client on our local machine.
OSX via [homebrew].
```bash
brew install kubernetes-helm
```
Linux via [snap].
```bash
sudo snap install helm --classic
```
A script for the [trusting](https://sysdig.com/blog/friends-dont-let-friends-curl-bash/) 😉.
```bash
curl -L https://git.io/get_helm.sh | bash
```
Add the default repository
```bash
helm repo add pomerium https://helm.pomerium.io
```
## NGINX Ingress
[NGINX ingress controller] is a [Kubernetes Ingress] based on [NGINX] the is a very popular, full-feature reverse-proxy. We will use NGINX in two configurations: as a fronting proxy, and as proxy that delegates every request's access-control decision to Pomerium using forward-auth.
Also, please note that while this guide uses [NGINX Ingress Controller], Pomerium can act as a forward auth-provider alongside other fronting ingresses like [Traefik](https://docs.traefik.io/middlewares/forwardauth/), [Ambassador](https://www.getambassador.io/reference/services/auth-service/), and [envoy](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/security/ext_authz_filter.html) in a similar fashion.
### Install
NGINX Ingress controller can be installed via [Helm] from the official charts repository. To install the chart with the release name `helm-nginx-ingress`:
```bash
helm repo add stable https://kubernetes-charts.storage.googleapis.com
helm repo update # important to make sure we get >.30
helm install helm-nginx-ingress stable/nginx-ingress
```
```bash
NAME: helm-nginx-ingress
....
NAMESPACE: default
STATUS: DEPLOYED
```
Confirm the ingress has been installed, and that an external `LoadBalancer` IP has been set.
```sh
$kubectl get svc
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helm-nginx-ingress-controller LoadBalancer 10.99.182.128 localhost 80:31059/TCP,443:32402/TCP 15m
helm-nginx-ingress-default-backend ClusterIP 10.108.251.51 <none> 80/TCP 15m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 93m
```
We now have a kubernetes ingress resource that can be used to delegate access control decisions to or front-proxy for Pomerium.
## Certificates
[Cert-manager] is a Kubernetes plugin that helps automate issuance of TLS certificates. In our case, we will use cert-manager to retrieve certs to each of our configured routes.
### Install
Like in previous steps, we will use [Helm] to install [Cert-manager].
```sh
# Install the CustomResourceDefinition resources separately
$ kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.12.0/cert-manager.yaml
# Create the namespace for cert-manager
$ kubectl create namespace cert-manager
# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io
# Update your local Helm chart repository cache
helm repo update
# Install the cert-manager Helm chart
helm install \
--namespace cert-manager \
--version v0.12.0 \
cert-manager \
jetstack/cert-manager
```
And we'll confirm cert-manager is up and running.
```
$ kubectl get pods --namespace cert-manager
```
```
NAME READY STATUS RESTARTS AGE
cert-manager-756d9f56d6-brv6z 1/1 Running 0 23s
cert-manager-cainjector-74bb68d67c-7jdw6 1/1 Running 0 23s
cert-manager-webhook-645b8bdb7-8kgc9 1/1 Running 0 23s
```
### Configure
Now that cert-manager is installed, we need to make one more configuration to be able to retrieve certificates. We need to add a [http-01 issuer](https://letsencrypt.org/docs/challenge-types/) for use with [LetsEncrypt].
```sh
$ kubectl apply -f docs/recipes/yml/letsencrypt-prod.yaml
```
<<< @/examples/yml/letsencrypt-prod.yaml
And confirm your issuer is set up correctly.
```bash
$ kubectl describe issuer
```
```bash
Name: letsencrypt-prod
...
API Version: cert-manager.io/v1alpha2
Kind: Issuer
Metadata:
Spec:
Acme:
Private Key Secret Ref:
Name: letsencrypt-prod
Server: https://acme-v02.api.letsencrypt.org/directory
Solvers:
Http 01:
Ingress:
Class: nginx
Selector:
Status:
Acme:
Last Registered Email: ....
Uri: https://acme-v02.api.letsencrypt.org/acme/acct/69070883
Conditions:
Message: The ACME account was registered with the ACME server
Reason: ACMEAccountRegistered
Status: True
Type: Ready
```
If you see something like the above, cert-manager should be all set to help issue you new certificates when you create a new `https` protected ingress. Note, if you need wild-card certificates, you may also need a [DNS-01](https://docs.cert-manager.io/en/latest/tasks/issuers/setup-acme/dns01/) type issuer.
## Dashboard
## Install Kubernetes Dashboard
[Kubernetes Dashboard] is a general purpose, web-based UI for Kubernetes clusters. It allows users to manage applications running in the cluster and troubleshoot them, as well as manage the cluster itself.
![kubernetes dashboard login page](./img/k8s-dashboard-login.png)
### Install
As with the previous steps, we can use [Helm] to install our instance of [Kubernetes Dashboard].
```sh
helm install \
helm-dashboard \
stable/kubernetes-dashboard \
--set ingress.enabled="false" \
--set enableSkipLogin="true"
```
That's it. We've now configured kubernetes dashboard to use the default service account, if none-is provided. We've also explicitly told helm that we are going to deploy our own custom, nginx / Pomerium / cert-manager enabled ingress.
## Pomerium
Pomerium is an identity-aware access proxy that can used to serve as an identity-aware reverse proxy, or as a forward-auth provider.
### Configure
Before installing, we will configure Pomerium's configuration settings in `values.yaml`. Other than the typical configuration settings covered in the quick-start guides, we will add a few settings that will make working with Kubernetes Dashboard easier.
We can retrieve the token to add to our proxied policy's authorization header as follows.
```sh
$ kubectl describe secret helm-dashboard
```
Use [Helm] to install a new instance of [Kubernetes Dashboard]:
```bash
Name: dashboard-kubernetes-dashboard-token-bv9jq
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: dashboard-kubernetes-dashboard
kubernetes.io/service-account.uid: 18ab35ee-eca1-11e9-8c75-025000000001
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 7 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.......
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
helm install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard\
--set ingress.enabled="false"
```
The above token then needs to be assigned to our route configuration and policy.
That's it. We've now configured the Kubernetes Dashboard in our cluster. We've also explicitly told Helm that we are going to deploy our own custom access to the service through Pomerium instead of a standard ingress.
```yaml
# values.yaml
authenticate:
idp:
provider: "google"
clientID: YOUR_CLIENT_ID
clientSecret: YOUR_SECRET
## Add a Route
forwardAuth:
enabled: true
Following the configuration defined in [Install Pomerium using Helm], add a route for the Kubernetes Dashboard.
config:
sharedSecret: YOUR_SHARED_SECRET
cookieSecret: YOUR_COOKIE_SECRET
1. Modify `pomerium-values.yaml` with the following route:
routes:
# this route is directly proxied by pomerium & injects the authorization header
- from: https://dashboard-proxied.domain.example
to: https://helm-dashboard-kubernetes-dashboard
```yaml
- from: https://dashboard.localhost.pomerium.io
to: https://kubernetes-dashboard.default.svc.cluster.local
tls_skip_verify: true
allow_spdy: true
tls_skip_verify: true
kubernetes_service_account_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
policy:
- allow:
or:
- email:
is: user@domain.example
tls_skip_verify: true # dashboard uses self-signed certificates in its default configuration
set_request_headers:
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.....
- domain:
is: pomerium.com
```
# this route is indirectly checked for access using forward-auth
- from: https://dashboard-forwardauth.domain.example
to: https://helm-dashboard-kubernetes-dashboard
policy:
- allow:
or:
- email:
is: user@domain.example
ingress:
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/issuer: "letsencrypt-prod" # see `le.issuer.yaml`
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
secretName: pomerium-ingress-tls
```
### Install
The service account token used for `kubernetes_service_account_token_file` is defined by our [helm chart]. Modify the policy to match your configuration.
Finally, we get to install Pomerium! 🎉 Once again, we will use Helm to deploy Pomerium.
1. Access to the dashboard for a user is authorized by the cluster role binding defined in role-based access control (**RBAC**) permissions. Following the [User Permissions] section of [Securing Kubernetes], you should already have permissions for your user, or you can create a new RBAC definition following this example (`rbac-someuser.yaml`):
```bash
helm install \
"helm-pomerium" \
pomerium/pomerium \
--values values.yaml
```
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-admin-crb
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: someuser@example.com
```
## Putting it all together
Apply the permissions with `kubectl apply -f rbac-someuser.yaml`.
Now we just need to tell external traffic how to route everything by deploying the following ingresses.
1. Apply the new route to Pomerium with Helm:
```sh
$kubectl apply -f docs/recipes/yml/dashboard-forwardauth.ingress.yaml
```
<<< @/examples/yml/dashboard-forwardauth.ingress.yaml
```sh
$kubectl apply -f docs/recipes/yml/dashboard-proxied.ingress.yaml
```
<<< @/examples/yml/dashboard-proxied.ingress.yaml
And finally, check that the ingresses are up and running.
```sh
$kubectl get ingress
```
```sh
NAME HOSTS ADDRESS PORTS AGE
dashboard-forwardauth dashboard-forwardauth.domain.example 80, 443 42h
dashboard-proxied dashboard-proxied.domain.example 80, 443 42h
helm-pomerium *.domain.example,authenticate.domain.example 80, 443 42h
```
You'll notice this is the step where we put everything together. We've got [nginx] handling the initial requests, [cert-manager] handling our public certificates, and Pomerium handling access control.
```bash
helm upgrade --install pomerium pomerium/pomerium --values pomerium-values.yaml
```
## Conclusion
Though the net result will be similar between using forward-auth and direct proxying, there are a few differences:
Because we've defined RBAC for our users, they can authenticate with Pomerium and Kubernetes will recognize that user in the Dashboard:
- By having Pomerium **directly proxy the requests**, you as an administrator have control control over the underlying request. In this example, we are able to inject an authenticating bearer token header to the downstream request which arguably makes for a better user experience.
<video controls muted="" playsinline="" width="100%" height="600" control=""><source src="./img/k8s-dashboard-user.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
<video controls muted="" playsinline="" width="100%" height="600" control=""><source src="./img/k8s-proxied-example.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
🎉🍾🎊 **Congratulations!** 🎉🍾🎊 You now have a single-sign-on enabled [Kubernetes Dashboard] protected by Pomerium.
* Conversely, going the **forward-auth** route potentially means using the ingress / reverse proxy you are are already accustomed to or have already modified to support your particular deployment.
<video controls muted="" playsinline="" width="100%" height="600" control=""><source src="./img/k8s-fwd-auth-example.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
In the end, you should choose whichever option makes the most sense for your use-case and environment.
Whichever option you choose to go with, 🎉🍾🎊 **congratulations** 🎉🍾🎊! You now have a single-sign-on enabled [Kubernetes Dashboard] protected by Pomerium and automatically renewing [LetsEncrypt] certificates.
[bearer token]: https://kubernetes.io/docs/admin/authentication/
[cert-manager]: https://github.com/jetstack/cert-manager
[command line proxy]: https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#command-line-proxy
[creating sample users]: https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md
[dashboard ui]: https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#deploying-the-dashboard-ui
[dns01 challenge provider]: https://docs.cert-manager.io/en/latest/tasks/issuers/setup-acme/dns01/index.html
[forward-auth]: ../reference/readme.md#forward-auth
[helm install]: https://helm.sh/docs/using_helm/#installing-the-helm-client
[helm]: https://helm.sh
[homebrew]: https://brew.sh
[cert-manager]: https://cert-manager.io/docs/
[helm chart]: https://github.com/pomerium/pomerium-helm
[Helm]: https://helm.sh
[Install Pomerium using Helm]: /docs/k8s/helm.md
[kubernetes dashboard]: https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/
[kubernetes ingress]: https://kubernetes.io/docs/concepts/services-networking/ingress/
[kubernetes securing a cluster]: https://kubernetes.io/docs/tasks/administer-cluster/securing-a-cluster/
[letsencrypt]: https://letsencrypt.org
[nginx ingress controller]: https://github.com/kubernetes/ingress-nginx
[nginx]: https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-subrequest-authentication/
[securing your helm installation]: https://helm.sh/docs/using_helm/#securing-your-helm-installation
[snap]: https://github.com/snapcrafters/helm
[with pomerium]: ../reference/readme.md#forward-auth
[your dashboard]: http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login
[Securing Kubernetes]: /guides/kubernetes.md
[User Permissions]: /guides/kubernetes.md#user-permissions