mirror of
https://github.com/jpetazzo/container.training.git
synced 2026-07-19 04:49:19 +00:00
Merge pull request #329 from jpetazzo/kubectlproxy
Revamp section about kubectl proxy
This commit is contained in:
@@ -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
|
||||
<br/>
|
||||
(that's what we've used so far)
|
||||
|
||||
- HTTP basic password authentication
|
||||
<br/>
|
||||
(from a static file; not recommended)
|
||||
|
||||
- various token mechanisms
|
||||
<br/>
|
||||
(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!
|
||||
<br/>
|
||||
(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/<namespace>/services/<service>/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
|
||||
|
||||
Reference in New Issue
Block a user