diff --git a/slides/k8s/authn-authz.md b/slides/k8s/authn-authz.md
index 96bfc879..38bb9263 100644
--- a/slides/k8s/authn-authz.md
+++ b/slides/k8s/authn-authz.md
@@ -110,7 +110,7 @@
- TLS client certificates
- (that's what we've been doing with `kubectl` so far)
+ (that's the default for clusters provisioned with `kubeadm`)
- Bearer tokens
@@ -146,17 +146,15 @@
## Authentication with TLS certificates
-- This is enabled in most Kubernetes deployments
+- Enabled in almost all Kubernetes deployments
-- The user name is derived from the `CN` in the client certificates
+- The user name is indicated by the `CN` in the client certificate
-- The groups are derived from the `O` fields in the client certificate
+- The groups are indicated by the `O` fields in the client certificate
- From the point of view of the Kubernetes API, users do not exist
- (i.e. they are not stored in etcd or anywhere else)
-
-- Users can be created (and added to groups) independently of the API
+ (i.e. there is no resource with `kind: User`)
- The Kubernetes API can be set up to use your custom CA to validate client certs
@@ -164,44 +162,21 @@
class: extra-details
-## Viewing our admin certificate
+## Authentication for kubelet
-- Let's inspect the certificate we've been using all this time!
+- In most clusters, kubelets authenticate using certificates
-.exercise[
+ (`O=system:nodes`, `CN=system:node:name-of-the-node`)
-- This command will show the `CN` and `O` fields for our certificate:
- ```bash
- kubectl config view \
- --raw \
- -o json \
- | jq -r .users[0].user[\"client-certificate-data\"] \
- | openssl base64 -d -A \
- | openssl x509 -text \
- | grep Subject:
- ```
+- The Kubernetse API can act as a CA
-]
+ (by wrapping an X509 CSR into a CertificateSigningRequest resource)
-Let's break down that command together! 😅
+- This enables kubelets to renew their own certificates
----
+- It can also be used to issue user certificates
-class: extra-details
-
-## Breaking down the command
-
-- `kubectl config view` shows the Kubernetes user configuration
-- `--raw` includes certificate information (which shows as REDACTED otherwise)
-- `-o json` outputs the information in JSON format
-- `| jq ...` extracts the field with the user certificate (in base64)
-- `| openssl base64 -d -A` decodes the base64 format (now we have a PEM file)
-- `| openssl x509 -text` parses the certificate and outputs it as plain text
-- `| grep Subject:` shows us the line that interests us
-
-→ We are user `kubernetes-admin`, in group `system:masters`.
-
-(We will see later how and why this gives us the permissions that we have.)
+ (but it lacks flexibility; e.g. validity can't be customized)
---
@@ -215,17 +190,31 @@ class: extra-details
(if their key is compromised, or they leave the organization)
-- Option 1: re-create a new CA and re-issue everyone's certificates
-
- → Maybe OK if we only have a few users; no way otherwise
+- Issue short-lived certificates if you use them to authenticate users!
-- Option 2: don't use groups; grant permissions to individual users
-
- → Inconvenient if we have many users and teams; error-prone
+ (short-lived = a few hours)
-- Option 3: issue short-lived certificates (e.g. 24 hours) and renew them often
-
- → This can be facilitated by e.g. Vault or by the Kubernetes CSR API
+- This can be facilitated by e.g. Vault, cert-manager...
+
+---
+
+## What if a certificate is compromised?
+
+- Option 1: wait for the certificate to expire
+
+ (which is why short-lived certs are convenient!)
+
+- Option 2: remove access from that certificate's user and groups
+
+ - if that user was `bob.smith`, create a new user `bob.smith.2`
+
+ - if Bob was in groups `dev`, create a new group `dev.2`
+
+ - let's agree that this is not a great solution!
+
+- Option 3: re-create a new CA and re-issue all certificates
+
+ - let's agree that this is an even worse solution!
---
@@ -269,6 +258,95 @@ class: extra-details
class: extra-details
+## Checking our authentication method
+
+- Let's check our kubeconfig file
+
+- Do we have a certificate, a token, or something else?
+
+---
+
+class: extra-details
+
+## Inspecting a certificate
+
+If we have a certificate, let's use the following command:
+
+```bash
+kubectl config view \
+ --raw \
+ -o json \
+ | jq -r .users[0].user[\"client-certificate-data\"] \
+ | openssl base64 -d -A \
+ | openssl x509 -text \
+ | grep Subject:
+```
+
+This command will show the `CN` and `O` fields for our certificate.
+
+---
+
+class: extra-details
+
+## Breaking down the command
+
+- `kubectl config view` shows the Kubernetes user configuration
+- `--raw` includes certificate information (which shows as REDACTED otherwise)
+- `-o json` outputs the information in JSON format
+- `| jq ...` extracts the field with the user certificate (in base64)
+- `| openssl base64 -d -A` decodes the base64 format (now we have a PEM file)
+- `| openssl x509 -text` parses the certificate and outputs it as plain text
+- `| grep Subject:` shows us the line that interests us
+
+→ We are user `kubernetes-admin`, in group `system:masters`.
+
+(We will see later how and why this gives us the permissions that we have.)
+
+---
+
+class: extra-details
+
+## Inspecting a token
+
+If we have a token, let's use the following command:
+
+```bash
+kubectl config view \
+ --raw \
+ -o json \
+ | jq -r .users[0].user.token \
+ | base64 -d \
+ | cut -d. -f2 \
+ | base64 -d \
+ | jq .
+```
+
+If our token is a JWT / OIDC token, this command will show its content.
+
+---
+
+class: extra-details
+
+## Other authentication methods
+
+- Other types of tokens
+
+ - these tokens are typically shorter than JWT or OIDC tokens
+
+ - it is generally not possible to extract information from them
+
+- Plugins
+
+ - some clusters use external `exec` plugins
+
+ - these plugins typically use API keys to generate or obtain tokens
+
+ - example: the AWS EKS authenticator works this way
+
+---
+
+class: extra-details
+
## Token authentication in practice
- We are going to list existing service accounts
@@ -491,23 +569,16 @@ class: extra-details
## Running a pod
-- We will run an `alpine` pod and install `kubectl` there
+- We'll use [Nixery](https://nixery.dev/) to run a pod with `curl` and `kubectl`
+
+- Nixery automatically generates images with the requested packages
.exercise[
-- Run a one-time pod:
+- Run our pod:
```bash
kubectl run eyepod --rm -ti --restart=Never \
- --image alpine
- ```
-
-- Install `curl`, then use it to install `kubectl`:
- ```bash
- apk add --no-cache curl
- URLBASE=https://storage.googleapis.com/kubernetes-release/release
- KUBEVER=$(curl -s $URLBASE/stable.txt)
- curl -LO $URLBASE/$KUBEVER/bin/linux/amd64/kubectl
- chmod +x kubectl
+ --image nixery.dev/shell/curl/kubectl -- bash
```
]
@@ -703,7 +774,7 @@ class: extra-details
- We can list the actions that are available to us:
- ````bash
+ ```bash
kubectl auth can-i --list
```
diff --git a/slides/k8s/csr-api.md b/slides/k8s/csr-api.md
index c8121117..a63316d3 100644
--- a/slides/k8s/csr-api.md
+++ b/slides/k8s/csr-api.md
@@ -324,6 +324,7 @@ The command above generates:
name: user=jean.doe
spec:
request: $(base64 -w0 < csr.pem)
+ signerName: kubernetes.io/kube-apiserver-client
usages:
- digital signature
- key encipherment
@@ -357,6 +358,8 @@ The command above generates:
]
+*Kubernetes 1.22 supports a new `spec.expirationSeconds` field.*
+
---
## Verifying and approving the CSR