mirror of
https://github.com/gravitational/teleport
synced 2024-10-21 01:34:01 +00:00
Universal kubeconfig provisioning script (#4086)
This script is similar to `examples/gke-auth/get-kubeconfig.sh` but should work for any k8s setup. It uses a service account bearer token for authentication instead of TLS key/cert. These tokens shouldn't expire and are more appropriate for automation. It also fetches the CA cert from the service account secret, which is more reliable than assuming a `kube-dns` pod exists in the cluster. In addition, this script sets up the needed k8s RBAC objects for impersonation, saving the user a few extra steps.
This commit is contained in:
parent
05d7acd267
commit
de9f9b9ce9
|
@ -94,18 +94,63 @@ proxy_service:
|
|||
|
||||
![teleport-ssh-kubernetes-integration](img/teleport-kubernetes-outside.svg)
|
||||
|
||||
To retrieve the Kubernetes credentials for the Teleport proxy service, you have to
|
||||
authenticate against your Kubernetes cluster directly then copy the file to `/path/to/.kube/config`
|
||||
on the Teleport proxy server.
|
||||
To generate the `kubeconfig_file` for the Teleport proxy service:
|
||||
1. Configure your `kubectl` to point at the Kubernetes cluster and have admin-level access.
|
||||
2. Use [this
|
||||
script](https://github.com/gravitational/teleport/blob/master/examples/k8s-auth/get-kubeconfig.sh)
|
||||
to generate `kubeconfig`:
|
||||
```bash
|
||||
# Download the script.
|
||||
$ curl -o get-kubeconfig.sh https://github.com/gravitational/teleport/blob/master/examples/k8s-auth/get-kubeconfig.sh
|
||||
|
||||
!!! tip "Google Cloud - GKE Users"
|
||||
# Make it executable.
|
||||
$ chmod +x get-kubeconfig.sh
|
||||
|
||||
Unfortunately for Google Cloud GKE users, GKE requires its own client-side extensions
|
||||
to authenticate, so we've created a [simple script](https://github.com/gravitational/teleport/blob/master/examples/gke-auth/get-kubeconfig.sh) you can run to generate a `kubeconfig` file for
|
||||
the Teleport proxy service.
|
||||
# Run the script, it will write the generated kubeconfig to the current
|
||||
# directory.
|
||||
$ ./get-kubeconfig.sh
|
||||
|
||||
# Check that the generated kubeconfig has the right permissions.
|
||||
# The output should look similar to this.
|
||||
$ kubectl --kubeconfig kubeconfig auth can-i --list
|
||||
Resources Non-Resource URLs Resource Names Verbs
|
||||
selfsubjectaccessreviews.authorization.k8s.io [] [] [create create]
|
||||
selfsubjectrulesreviews.authorization.k8s.io [] [] [create create]
|
||||
[/api/*] [] [get]
|
||||
[/api] [] [get]
|
||||
[/apis/*] [] [get]
|
||||
[/apis] [] [get]
|
||||
[/healthz] [] [get]
|
||||
[/healthz] [] [get]
|
||||
[/openapi/*] [] [get]
|
||||
[/openapi] [] [get]
|
||||
[/version/] [] [get]
|
||||
[/version/] [] [get]
|
||||
[/version] [] [get]
|
||||
[/version] [] [get]
|
||||
groups [] [] [impersonate]
|
||||
serviceaccounts [] [] [impersonate]
|
||||
users [] [] [impersonate]
|
||||
```
|
||||
3. Copy the generated `kubeconfig` file to the host running the Teleport proxy
|
||||
service.
|
||||
4. Update `kubeconfig_file` path in `teleport.yaml` to where you copied the
|
||||
`kubeconfig`.
|
||||
|
||||
Alternatively, you can use your existing local config from `~/.kube/config`.
|
||||
However, it will result in Teleport proxy using your personal Kubernetes
|
||||
credentials. This is risky: your credentials can expire or get revoked (such as
|
||||
when leaving your company).
|
||||
|
||||
## Impersonation
|
||||
|
||||
!!! note
|
||||
|
||||
If you used [the script from Option
|
||||
2](https://github.com/gravitational/teleport/blob/master/examples/k8s-auth/get-kubeconfig.sh)
|
||||
above, you can skip this step. The script already configured impersonation
|
||||
permissions.
|
||||
|
||||
The next step is to configure the Teleport Proxy to be able to impersonate Kubernetes principals within a given group
|
||||
using [Kubernetes Impersonation Headers](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation).
|
||||
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
|
||||
set -eu -o pipefail
|
||||
|
||||
echo "---"
|
||||
echo "This script is obsolete!"
|
||||
echo "Please use https://github.com/gravitational/teleport/blob/master/examples/k8s-auth/get-kubeconfig.sh instead."
|
||||
echo "---"
|
||||
|
||||
# Allow passing in common name and username in environment. If not provided,
|
||||
# use default.
|
||||
CN=${CN:-teleport}
|
||||
|
|
1
examples/k8s-auth/.gitignore
vendored
Normal file
1
examples/k8s-auth/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/kubeconfig
|
139
examples/k8s-auth/get-kubeconfig.sh
Executable file
139
examples/k8s-auth/get-kubeconfig.sh
Executable file
|
@ -0,0 +1,139 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright 2020 Gravitational, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# This script creates a new k8s Service Account and generates a kubeconfig with
|
||||
# its credentials. This Service Account has all the necessary permissions for
|
||||
# Teleport. The kubeconfig is written in the current directory.
|
||||
#
|
||||
# You must configure your local kubectl to point to the right k8s cluster and
|
||||
# have admin-level access.
|
||||
#
|
||||
# Note: all of the k8s resources are created in namespace "teleport". If you
|
||||
# delete any of these objects, Teleport will stop working.
|
||||
#
|
||||
# You can override the default namespace "teleport" using the
|
||||
# TELEPORT_NAMESPACE environment variable.
|
||||
# You can override the default service account name "teleport-sa" using the
|
||||
# TELEPORT_SA_NAME environment variable.
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
# Allow passing in common name and username in environment. If not provided,
|
||||
# use default.
|
||||
TELEPORT_SA=${TELEPORT_SA_NAME:-teleport-sa}
|
||||
NAMESPACE=${TELEPORT_NAMESPACE:-teleport}
|
||||
|
||||
# Set OS specific values.
|
||||
if [[ "$OSTYPE" == "linux-gnu" ]]; then
|
||||
BASE64_DECODE_FLAG="-d"
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
BASE64_DECODE_FLAG="-D"
|
||||
elif [[ "$OSTYPE" == "linux-musl" ]]; then
|
||||
BASE64_DECODE_FLAG="-d"
|
||||
else
|
||||
echo "Unknown OS ${OSTYPE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Creating the Kubernetes Service Account with minimal RBAC permissions."
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: teleport
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: ${TELEPORT_SA}
|
||||
namespace: ${NAMESPACE}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: teleport-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- users
|
||||
- groups
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- impersonate
|
||||
- apiGroups:
|
||||
- "authorization.k8s.io"
|
||||
resources:
|
||||
- selfsubjectaccessreviews
|
||||
- selfsubjectrulesreviews
|
||||
verbs:
|
||||
- create
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: teleport-crb
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: teleport-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: ${TELEPORT_SA}
|
||||
namespace: ${NAMESPACE}
|
||||
EOF
|
||||
# Get the service account token and CA cert.
|
||||
SA_SECRET_NAME=$(kubectl get -n teleport sa/${TELEPORT_SA} -o "jsonpath={.secrets[0]..name}")
|
||||
# Note: service account token is stored base64-encoded in the secret but must
|
||||
# be plaintext in kubeconfig.
|
||||
SA_TOKEN=$(kubectl get -n teleport secrets/${SA_SECRET_NAME} -o "jsonpath={.data['token']}" | base64 ${BASE64_DECODE_FLAG})
|
||||
CA_CERT=$(kubectl get -n teleport secrets/${SA_SECRET_NAME} -o "jsonpath={.data['ca\.crt']}")
|
||||
|
||||
# Extract cluster IP from the current context
|
||||
CURRENT_CONTEXT=$(kubectl config current-context)
|
||||
CURRENT_CLUSTER=$(kubectl config view -o jsonpath="{.contexts[?(@.name == \"${CURRENT_CONTEXT}\"})].context.cluster}")
|
||||
CURRENT_CLUSTER_ADDR=$(kubectl config view -o jsonpath="{.clusters[?(@.name == \"${CURRENT_CLUSTER}\"})].cluster.server}")
|
||||
|
||||
echo "Writing kubeconfig."
|
||||
cat > kubeconfig <<EOF
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: ${CA_CERT}
|
||||
server: ${CURRENT_CLUSTER_ADDR}
|
||||
name: ${CURRENT_CLUSTER}
|
||||
contexts:
|
||||
- context:
|
||||
cluster: ${CURRENT_CLUSTER}
|
||||
user: ${TELEPORT_SA}
|
||||
name: ${CURRENT_CONTEXT}
|
||||
current-context: ${CURRENT_CONTEXT}
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: ${TELEPORT_SA}
|
||||
user:
|
||||
token: ${SA_TOKEN}
|
||||
EOF
|
||||
|
||||
echo "---
|
||||
Done!
|
||||
|
||||
Copy the generated kubeconfig file to your Teleport Proxy server, and set the
|
||||
kubeconfig_file parameter in your teleport.yaml config file to point to this
|
||||
kubeconfig file.
|
||||
|
||||
Note: Kubernetes RBAC rules for Teleport were created, you won't need to create them manually."
|
Loading…
Reference in a new issue