diff --git a/slides/k8s/kubectlproxy.md b/slides/k8s/kubectlproxy.md
index 6ae9f4c5..883f6e50 100644
--- a/slides/k8s/kubectlproxy.md
+++ b/slides/k8s/kubectlproxy.md
@@ -1,4 +1,71 @@
-# Accessing internal services with `kubectl proxy`
+# Accessing the API with `kubectl proxy`
+
+- The API requires us to authenticate.red[¹]
+
+- There are many authentication methods available, including:
+
+ - TLS client certificates
+
+ (that's what we've used so far)
+
+ - HTTP basic password authentication
+
+ (from a static file; not recommended)
+
+ - various token mechanisms
+
+ (detailed in the [documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#authentication-strategies))
+
+.red[¹]OK, we lied. If you don't authenticate, you are considered to
+be user `system:anonymous`, which doesn't have any access rights by default.
+
+---
+
+## Accessing the API directly
+
+- Let's see what happens if we try to access the API directly with `curl`
+
+.exercise[
+
+- Retrieve the ClusterIP allocated to the `kubernetes` service:
+ ```bash
+ kubectl get svc kubernetes
+ ```
+
+- Replace the IP below and try to connect with `curl`:
+ ```bash
+ curl -k https://`10.96.0.1`/
+ ```
+
+]
+
+The API will tell us that user `system:anonymous` cannot access this path.
+
+---
+
+## Authenticating to the API
+
+If we wanted to talk to the API, we would need to:
+
+- extract our TLS key and certificate information from `~/.kube/config`
+
+ (the information is in PEM format, encoded in base64)
+
+- use that information to present our certificate when connecting
+
+ (for instance, with `openssl s_client -key ... -cert ... -connect ...`)
+
+- figure out exactly which credentials to use
+
+ (once we start juggling multiple clusters)
+
+- change that whole process if we're using another authentication method
+
+🤔 There has to be a better way!
+
+---
+
+## Using `kubectl proxy` for authentication
- `kubectl proxy` runs a proxy in the foreground
@@ -10,15 +77,40 @@
- This is a great tool to learn and experiment with the Kubernetes API
-- The Kubernetes API also gives us a proxy to HTTP and HTTPS services
+- ... And for serious usages as well (suitable for one-shot scripts)
-- Therefore, we can use `kubectl proxy` to access internal services
-
- (Without using a `NodePort` or similar service)
+- For unattended use, it is better to create a [service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/)
---
-## Secure by default
+## Trying `kubectl proxy`
+
+- Let's start `kubectl proxy` and then do a simple request with `curl`!
+
+.exercise[
+
+- Start `kubectl proxy` in the background:
+ ```bash
+ kubectl proxy &
+ ```
+
+- Access the API's default route:
+ ```bash
+ curl localhost:8001
+ ```
+
+- Terminate the proxy:
+ ```bash
+ kill %1
+ ```
+
+]
+
+The output is a list of available API routes.
+
+---
+
+## `kubectl proxy` is intended for local use
- By default, the proxy listens on port 8001
@@ -34,84 +126,54 @@
- This is great when running `kubectl proxy` locally
-- Not-so-great when running it on a remote machine
+- Not-so-great when you want to connect to the proxy from a remote machine
---
## Running `kubectl proxy` on a remote machine
-- We are going to bind to `INADDR_ANY` instead of `127.0.0.1`
+- If we wanted to connect to the proxy from another machine, we would need to:
-- We are going to accept connections from any address
+ - bind to `INADDR_ANY` instead of `127.0.0.1`
-.exercise[
+ - accept connections from any address
-- Run an open proxy to the Kubernetes API:
+- This is achieved with:
```
kubectl proxy --port=8888 --address=0.0.0.0 --accept-hosts=.*
```
-]
-
-.warning[Anyone can now do whatever they want with our Kubernetes cluster!
-
-(Don't do this on a real cluster!)]
+.warning[Do not do this on a real cluster: it opens full unauthenticated access!]
---
-## Viewing available API routes
+## Security considerations
-- The default route (i.e. `/`) shows a list of available API endpoints
+- Running `kubectl proxy` openly is a huge security risk
-.exercise[
+- It is slightly better to run the proxy where you need it
-- Point your browser to the IP address of the node running `kubectl proxy`, port 8888
+ (and copy credentials, e.g. `~/.kube/config`, to that place)
-]
-
-The result should look like this:
-```json
-{
- "paths": [
- "/api",
- "/api/v1",
- "/apis",
- "/apis/",
- "/apis/admissionregistration.k8s.io",
- …
-```
+- It is even better to use a limited account with reduced permissions
---
-## Connecting to a service through the proxy
+## Good to know ...
-- The API can proxy HTTP and HTTPS requests by accessing a special route:
+- `kubectl proxy` also gives access to all internal services
+
+- Specifically, services are exposed as such:
```
- /api/v1/namespaces/`name_of_namespace`/services/`name_of_service`/proxy
+ /api/v1/namespaces//services//proxy
```
-- Since we now have access to the API, we can use this special route
+- We can use `kubectl proxy` to access an internal service in a pinch
-.exercise[
+ (or, for non HTTP services, `kubectl port-forward`)
-- Access the `hasher` service through the special proxy route:
- ```open
- http://`X.X.X.X`:8888/api/v1/namespaces/default/services/hasher/proxy
- ```
+- This is not very useful when running `kubectl` directly on the cluster
-]
-
-You should see the banner of the hasher service: `HASHER running on ...`
-
----
-
-## Stopping the proxy
-
-- Remember: as it is running right now, `kubectl proxy` gives open access to our cluster
-
-.exercise[
-
-- Stop the `kubectl proxy` process with Ctrl-C
-
-]
+ (since we could connect to the services directly anyway)
+- But it is very powerful as soon as you run `kubectl` from a remote machine