Skip to content

Commit

Permalink
Universal kubeconfig provisioning script (#4086)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Andrew Lytvynov committed Jul 21, 2020
1 parent 05d7acd commit de9f9b9
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 8 deletions.
61 changes: 53 additions & 8 deletions docs/4.3/kubernetes_ssh.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

!!! tip "Google Cloud - GKE Users"
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
# Make it executable.
$ chmod +x get-kubeconfig.sh
# 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`.

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.
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).

Expand Down
5 changes: 5 additions & 0 deletions examples/gke-auth/get-kubeconfig.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
1 change: 1 addition & 0 deletions examples/k8s-auth/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/kubeconfig
139 changes: 139 additions & 0 deletions examples/k8s-auth/get-kubeconfig.sh
Original file line number Diff line number Diff line change
@@ -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."

0 comments on commit de9f9b9

Please sign in to comment.