🔑 Update RBAC section

We won't always have a kubeconfig with a TLS cert in it.
Let's break down different methods to analyze kubeconfig
depending on whether there is a TLS cert or a token in it.
This commit is contained in:
Jérôme Petazzoni
2021-11-07 16:23:29 +01:00
parent 97735bafa8
commit 753324cc89
2 changed files with 134 additions and 60 deletions

View File

@@ -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
<br/>
→ 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
<br/>
→ 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
<br/>
→ 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
```

View File

@@ -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