{"token_count": 5714}

# Register a Kubernetes Cluster with a Static kubeconfig

While you can register a Kubernetes cluster with Teleport by running the Teleport Kubernetes Service [on that cluster](https://goteleport.com/docs/enroll-resources/kubernetes-access/getting-started.md), you can also run the Teleport Kubernetes Service on a Linux host outside the cluster. This is useful if you want to decouple your Teleport deployment from the Kubernetes clusters you want to manage access to.

In this guide, you will enroll the Teleport Kubernetes Service with Teleport and configure the service to proxy a Kubernetes cluster with a static `kubeconfig`.

## How it works

In this setup, the Teleport Kubernetes Service uses a `kubeconfig` file to authenticate to the API server of your chosen Kubernetes cluster.

## Prerequisites

- A running Teleport cluster accessible at a hostname with a valid TLS certificate. If you want to get started with Teleport, [sign up](https://goteleport.com/signup) for a free trial or [set up a demo environment](https://goteleport.com/docs/get-started/deploy-community.md).

- The `tctl` and `tsh` clients.

  Installing `tctl` and `tsh` clients

  1. Determine the version of your Teleport cluster. The `tctl` and `tsh` clients must be at most one major version behind your Teleport cluster version. Send a GET request to the Proxy Service at `/v1/webapi/find` and use a JSON query tool to obtain your cluster version. Replace teleport.example.com:443 with the web address of your Teleport Proxy Service:

     **Mac/Linux**

     ```
     $ TELEPORT_DOMAIN=teleport.example.com:443
     $ TELEPORT_VERSION="$(curl -s https://$TELEPORT_DOMAIN/v1/webapi/find | jq -r '.server_version')"
     ```

     **Windows - Powershell**

     ```
     $ $TELEPORT_DOMAIN = "teleport.example.com:443"
     $ $TELEPORT_VERSION = (Invoke-RestMethod -Uri "https://${TELEPORT_DOMAIN}/v1/webapi/find").server_version
     ```

  2. Follow the instructions for your platform to install `tctl` and `tsh` clients:

     **Mac**

     Download the signed macOS .pkg installer for Teleport, which includes the `tctl` and `tsh` clients:

     ```
     $ curl -O https://cdn.teleport.dev/teleport-${TELEPORT_VERSION?}.pkg
     ```

     In Finder double-click the `pkg` file to begin installation.

     ---

     DANGER

     Using Homebrew to install Teleport is not supported. The Teleport package in Homebrew is not maintained by Teleport and we can't guarantee its reliability or security.

     ---

     **Windows - Powershell**

     ```
     $ curl.exe -O https://cdn.teleport.dev/teleport-v$TELEPORT_VERSION-windows-amd64-bin.zip
     Unzip the archive and move the `tctl` and `tsh` clients to your %PATH%
     NOTE: Do not place the `tctl` and `tsh` clients in the System32 directory, as this can cause issues when using WinSCP.
     Use %SystemRoot% (C:\Windows) or %USERPROFILE% (C:\Users\<username>) instead.
     ```

     **Linux**

     All of the Teleport binaries in Linux installations include the `tctl` and `tsh` clients. For more options (including RPM/DEB packages and downloads for i386/ARM/ARM64) see our [installation page](https://goteleport.com/docs/installation/single-machine.md).

     ```
     $ curl -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ tar -xzf teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ cd teleport
     $ sudo ./install
     Teleport binaries have been copied to /usr/local/bin
     ```

  Connecting with TLS routing disabled

  This guide's commands assume your Teleport cluster uses TLS routing (`proxy_listener_mode: multiplex`), where the `tctl` and `tsh` clients reach every Teleport service through the Proxy Service's web address on port `443`. If you're not sure whether this applies to your cluster, check with whoever manages it.

  If your cluster uses separate listener ports instead, adjust ports as follows:

  - **`tsh` commands** (e.g., `tsh login --proxy=...`): continue using the Proxy Service web address on port `3080` (or `443` if behind a load balancer). Do not change these to port `3025`.

  - **Direct `tctl` or Auth Service API commands**: use port `3025` for the Auth Service gRPC listener:

    ```
    $ tctl status --auth-server=teleport.example.com:3025
    ```

* A Kubernetes cluster you would like to access.

* A Linux host deployed on your own infrastructure to run the Teleport Kubernetes Service. This can run outside of your Kubernetes cluster.

* The [`kubectl`](https://kubernetes.io/docs/reference/kubectl/) command line tool installed on your workstation.

* Check that you can connect to your Teleport cluster and verify that you can run `tctl` and `tsh` commands using your current credentials.

  1. Assign teleport.example.com to the domain name of the Teleport Proxy Service in your cluster and email\@example.com to your Teleport username.

  2. Authenticate to your Teleport cluster. This depends on whether your shell is interactive or not.

     **In an interactive shell:** Run the following command. By default, this triggers a multi-factor authentication prompt:

     ```
     $ tsh login --proxy=teleport.example.com --user=email@example.com
     $ tctl status
     Cluster  teleport.example.com
     Version  18.10.0
     CA pin   sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678
     ```

     **On non-interactive environments:** If you are running `tsh` and `tctl` as an AI agent, in a CI/CD environment, or similar, make sure the `TELEPORT_IDENTITY_FILE` environment variable is assigned to a valid file path with credentials for your cluster. `tsh` and `tctl` read the file path from the environment variable and do not require a separate authentication step. If there is no identity file available, we recommend that you [set up Machine ID](https://goteleport.com/docs/machine-workload-identity/getting-started.md) to provision one automatically.

     When executing `tctl` commands with an identity file, you must pass the `--auth-server` flag to provide the Teleport Auth Service address, which is not included in the identity file. If you provide the Proxy Service address, `tctl` connects to the Proxy Service, which forwards traffic to and from the Teleport Auth Service. Update 443 to `3025` if you are contacting the Auth Service directly with `tctl`:

     ```
     $ tctl status --auth-server=teleport.example.com:443
     ```

     For `tsh` commands that read an identity file, you must pass the `--proxy` flag, which points `tsh` to the address of the Teleport Proxy Service:

     ```
     $ tsh status --proxy=teleport.example.com
     ```

     Ensure client commands can access your identity file. Replace path/to/identity/file with the path to your identity file:

     ```
     $ export TELEPORT_IDENTITY_FILE="${TELEPORT_IDENTITY_FILE:-path/to/identity/file}"
     ```

     Add the `--auth-server` or `--proxy` flags to all subsequent `tctl` and `tsh` commands.

  If you can connect to the cluster and run the `tctl status` command, you can use your current credentials to run subsequent `tctl` commands from your workstation. If you host your own Teleport cluster, you can also run `tctl` commands on the computer that hosts the Teleport Auth Service for full permissions.

Best practices for production security

When running Teleport in production, you should adhere to the following best practices to avoid security incidents:

- Avoid using `sudo` in production environments unless it's necessary.
- Create new, non-root, users and use test instances for experimenting with Teleport.
- Run Teleport's services as a non-root user unless required. Only the SSH Service requires root access. Note that you will need root permissions (or the `CAP_NET_BIND_SERVICE` capability) to make Teleport listen on a port numbered < `1024` (e.g. `443`).
- Follow the **principle of least privilege**. Don't give users permissive roles when more a restrictive role will do. For example, don't assign users the built-in `access,editor` roles, which give them permissions to access and edit all cluster resources. Instead, define roles with the minimum required permissions for each user and configure **Access Requests** to provide temporary elevated permissions.
- When you enroll Teleport resources—for example, new databases or applications—you should save the invitation token to a file. If you enter the token directly on the command line, a malicious user could view it by running the `history` command on a compromised system.

You should note that these practices aren't necessarily reflected in the examples used in documentation. Examples in the documentation are primarily intended for demonstration and for development environments.

## Step 1/4. Generate a kubeconfig file

The Teleport Kubernetes Service uses a `kubeconfig` file to authenticate to your Kubernetes cluster. In this section, we will generate a `kubeconfig` file so we can configure the Teleport Kubernetes Service to use it later in this guide.

### Ensure your context is correct

First, configure your local `kubectl` command to point at the Kubernetes cluster you want to register. You can use the following command to verify that the correct cluster is selected:

```
$ kubectl config get-contexts
```

Use this command to switch to the cluster assigned to context-name:

```
e.g., my-context
$ kubectl config use-context context-name
```

### Run the script

On your workstation, download Teleport's `get-kubeconfig.sh` script, which you will use to generate the `kubeconfig` file:

```
$ curl -OL \
https://raw.githubusercontent.com/gravitational/teleport/v18.10.0/examples/k8s-auth/get-kubeconfig.sh
```

`get-kubeconfig.sh` creates a service account for the Teleport Kubernetes Service that can get Kubernetes pods as well as impersonate users, groups, and other service accounts. The Teleport Kubernetes Service uses this service account to manage access to resources in your Kubernetes cluster. The script also ensures that there is a Kubernetes `Secret` in your cluster to store service account credentials.

`get-kubeconfig.sh` also creates a namespace called `teleport` for the resources it deploys, though you can choose a different name by assigning the `TELEPORT_NAMESPACE` environment variable in the shell where you run the script.

After creating resources, `get-kubeconfig.sh` writes a new `kubeconfig` file called `kubeconfig` in the directory where you run the script.

Run the `get-kubeconfig.sh` script:

```
$ bash get-kubeconfig.sh
```

The script is successful if you see this message:

```
Done!

```

Move the `kubeconfig` file to the host you are using to run the Teleport Kubernetes Service. We will assume that the `kubeconfig` file exists at `/var/lib/teleport/kubeconfig`.

Connecting multiple Kubernetes clusters?

You can connect multiple Kubernetes clusters to Teleport from one `kubeconfig` file if it contains multiple entries. Use [merge-kubeconfigs.sh](https://github.com/gravitational/teleport/blob/branch/v18/examples/k8s-auth/merge-kubeconfigs.sh) to combine multiple `kubeconfig` files generated by `get-kubeconfig.sh`.

## Step 2/4. Set up the Teleport Kubernetes Service

In this step, you will install the Teleport Kubernetes Service and configure it to use the `kubeconfig` file you generated to access a Kubernetes cluster.

### Get a join token

Establish trust between your Teleport cluster and your new Kubernetes Service instance by creating a join token:

```
$ tctl tokens add --type=kube --format=text --ttl=1h
abcd123-insecure-do-not-use-this
```

Assign join-token to your join token. On the host where you are running the Teleport Kubernetes Service, create a file called `/tmp/token` that consists only of your token:

```
$ echo join-token | sudo tee /tmp/token
```

### Install the Teleport Kubernetes Service

Run the following commands on the host where you will install the Teleport Kubernetes Service:

To install Teleport binaries on your Linux server, the recommended installation method is the cluster install script. It will select the correct version, edition, and installation mode for your cluster.

1. Remove any existing Teleport binaries on your system:

   ```
   $ sudo rm -f /usr/local/bin/{tsh,teleport,tctl,tbot,fdpass-teleport,teleport-update}
   ```

2. Assign teleport.example.com:443 to your Teleport cluster hostname and port, but not the scheme (https\://).

3. Run your cluster's install script:

   ```
   $ curl "https://teleport.example.com:443/scripts/install.sh" | sudo bash
   ```

### Configure the Teleport Kubernetes Service

Assign teleport.example.com:443 with the host and port of your Teleport Proxy Service or Teleport Cloud tenant, e.g., `mytenant.teleport.sh:443`. On the host where you will run the Teleport Kubernetes Service, create a file at `/etc/teleport.yaml` with the following content:

```
version: v3
teleport:
  join_params:
    token_name: "/tmp/token"
    method: token
  proxy_server: teleport.example.com:443
auth_service:
  enabled: false
proxy_service:
  enabled: false
ssh_service:
  enabled: false
kubernetes_service:
  enabled: true
  kubeconfig_file: "/var/lib/teleport/kubeconfig"
  labels:
    "region": "us-east-1"

```

---

WARNING

When using `kubeconfig_file`, Amazon EKS users may need to replace illegal characters in the `context` names. Supported characters are alphanumeric characters, `.`, `_`, and `-`. EKS typically includes `:` and `@` in their `kubeconfig` files, which are not allowed in Teleport.

---

### Start the Teleport Kubernetes Service

Start the Teleport Kubernetes Service. The instructions depend on how you installed the Teleport Kubernetes Service and whether your system supports systemd:

**Package Manager**

Configure the Teleport Kubernetes Service to start automatically when the host boots up by creating a systemd service for it. On the host where you will run the Teleport Kubernetes Service, enable and start Teleport:

```
$ sudo systemctl enable teleport
$ sudo systemctl start teleport
```

You can check the status of the Teleport Kubernetes Service with `systemctl status teleport` and view its logs with `journalctl -fu teleport`.

**TAR Archive**

Configure the Teleport Kubernetes Service to start automatically when the host boots up by creating a systemd service for it. On the host where you will run the Teleport Kubernetes Service, create a systemd service configuration for Teleport, enable the Teleport service, and start Teleport:

```
$ sudo teleport install systemd -o /etc/systemd/system/teleport.service
$ sudo systemctl enable teleport
$ sudo systemctl start teleport
```

You can check the status of the Teleport Kubernetes Service with `systemctl status teleport` and view its logs with `journalctl -fu teleport`.

**No systemd**

On the host where you will run the Teleport Kubernetes Service, start Teleport:

```
$ sudo teleport start --config=/etc/teleport.yaml
```

Teleport runs in the foreground and outputs logs for the services it is running.

## Step 3/4. Grant access to your Teleport user

Enable your Teleport user to access resources in your Kubernetes cluster so you can connect to the cluster later in this guide.

To authenticate to a Kubernetes cluster via Teleport, your Teleport user's roles must allow access as at least one Kubernetes user or group.

1. Retrieve a list of your current user's Teleport roles. The example below requires the `jq` utility for parsing JSON:

   ```
   $ CURRENT_ROLES=$(tsh status -f json | jq -r '.active.roles | join ("\n")')
   ```

2. Retrieve the Kubernetes groups your roles allow you to access:

   ```
   $ echo "$CURRENT_ROLES" | xargs -I{} tctl get roles/{} --format json | \
     jq '.[0].spec.allow.kubernetes_groups[]?'
   ```

3. Retrieve the Kubernetes users your roles allow you to access:

   ```
   $ echo "$CURRENT_ROLES" | xargs -I{} tctl get roles/{} --format json | \
     jq '.[0].spec.allow.kubernetes_users[]?'
   ```

4. If the output of one of the previous two commands is non-empty, your user can access at least one Kubernetes user or group, so you can proceed to the next step.

5. If both lists are empty, create a Teleport role for the purpose of this guide that can view Kubernetes resources in your cluster.

   Create a file called `kube-access.yaml` with the following content:

   ```
   kind: role
   metadata:
     name: kube-access
   version: v7
   spec:
     allow:
       kubernetes_labels:
         '*': '*'
       kubernetes_resources:
         - kind: '*'
           namespace: '*'
           name: '*'
           verbs: ['*']
       kubernetes_groups:
       - viewers
     deny: {}

   ```

6. Apply your changes:

   ```
   $ tctl create -f kube-access.yaml
   ```

   ---

   TIP

   You can also create and edit roles using the Web UI. Go to **Access -> Roles** and click **Create New Role** or pick an existing role to edit.

   ---

7. Assign the `kube-access` role to your Teleport user. The commands to run depend on how you authenticate to Teleport, that is, whether you have a local Teleport user, a single sign-on authentication connector, or a non-interactive user:

   **Local User**

   1. Retrieve your local user's roles as a comma-separated list:

      ```
      $ ROLES=$(tsh status -f json | jq -r '.active.roles | join(",")')
      ```

   2. Edit your local user to add the new role:

      ```
      $ tctl users update $(tsh status -f json | jq -r '.active.username') \
        --set-roles "${ROLES?},kube-access"
      ```

   3. Sign out of the Teleport cluster and sign in again to assume the new role.

   **GitHub**

   1. Open your `github` authentication connector in a text editor:

      ```
      $ tctl edit github/github
      ```

   2. Edit the `github` connector, adding `kube-access` to the `teams_to_roles` section.

      The team you should map to this role depends on how you have designed your organization's role-based access controls (RBAC). However, the team must include your user account and should be the smallest team possible within your organization.

      Here is an example:

      ```
        teams_to_roles:
          - organization: octocats
            team: admins
            roles:
              - access
      +       - kube-access

      ```

   3. Apply your changes by saving and closing the file in your editor.

   4. Sign out of the Teleport cluster and sign in again to assume the new role.

   **SAML**

   1. Retrieve your `saml` configuration resource:

      ```
      $ tctl get --with-secrets saml/mysaml > saml.yaml
      ```

      Note that the `--with-secrets` flag adds the value of `spec.signing_key_pair.private_key` to the `saml.yaml` file. Because this key contains a sensitive value, you should remove the saml.yaml file immediately after updating the resource.

   2. Edit `saml.yaml`, adding `kube-access` to the `attributes_to_roles` section.

      The attribute you should map to this role depends on how you have designed your organization's role-based access controls (RBAC). However, the group must include your user account and should be the smallest group possible within your organization.

      Here is an example:

      ```
        attributes_to_roles:
          - name: "groups"
            value: "my-group"
            roles:
              - access
      +       - kube-access

      ```

   3. Apply your changes:

      ```
      $ tctl create -f saml.yaml
      ```

   4. Sign out of the Teleport cluster and sign in again to assume the new role.

   **OIDC**

   1. Retrieve your `oidc` configuration resource:

      ```
      $ tctl get oidc/myoidc --with-secrets > oidc.yaml
      ```

      Note that the `--with-secrets` flag adds the value of `spec.signing_key_pair.private_key` to the `oidc.yaml` file. Because this key contains a sensitive value, you should remove the oidc.yaml file immediately after updating the resource.

   2. Edit `oidc.yaml`, adding `kube-access` to the `claims_to_roles` section.

      The claim you should map to this role depends on how you have designed your organization's role-based access controls (RBAC). However, the group must include your user account and should be the smallest group possible within your organization.

      Here is an example:

      ```
        claims_to_roles:
          - name: "groups"
            value: "my-group"
            roles:
              - access
      +       - kube-access

      ```

   3. Apply your changes:

      ```
      $ tctl create -f oidc.yaml
      ```

   4. Sign out of the Teleport cluster and sign in again to assume the new role.

   **Non-Interactive**

   For non-interactive users such as AI agents and CI/CD runners, follow these steps.

   If you are using Machine ID to issue identity files to your user:

   1. Add the new role to your bot. Assign mybot to the name of the Machine ID bot that issues your certificate:

      ```
      $ tctl bots update mybot --add-roles kube-access
      ```

   2. Force `tbot` to regenerate the certificate:

      ```
      $ pkill -HUP tbot
      ```

      The bot will also generate a certificate with the new role on its next renewal.

   Otherwise, update your user and regenerate your identity file:

   1. Retrieve your local user's roles as a comma-separated list. Make sure username is the Teleport user you want to assign the new role to.

      ```
      $ ROLES=$(tctl get user/username --format=json | jq -r '.[].spec.roles | join(",")')
      ```

   2. Edit your local user to add the new role:

      ```
      $ tctl users update username \
        --set-roles "${ROLES?},kube-access"
      ```

   3. Regenerate the identity file. Make sure path/to/identity/file corresponds to the correct output path:

      ```
      $ tctl auth sign \
        --user=username \
        --out=path/to/identity/file \
        --overwrite
      ```

8. Configure the `viewers` group in your Kubernetes cluster to have the built-in `view` ClusterRole. When your Teleport user assumes the `kube-access` role and sends requests to the Kubernetes API server, the Teleport Kubernetes Service impersonates the `viewers` group and proxies the requests.

   Create a file called `viewers-bind.yaml` with the following contents, binding the built-in `view` ClusterRole with the `viewers` group you enabled your Teleport user to access:

   ```
   apiVersion: rbac.authorization.k8s.io/v1
   kind: ClusterRoleBinding
   metadata:
     name: viewers-crb
   subjects:
   - kind: Group
     # Bind the group "viewers", corresponding to the kubernetes_groups we assigned our "kube-access" role above
     name: viewers
     apiGroup: rbac.authorization.k8s.io
   roleRef:
     kind: ClusterRole
     # "view" is a default ClusterRole that grants read-only access to resources
     # See: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles
     name: view
     apiGroup: rbac.authorization.k8s.io

   ```

9. Apply the `ClusterRoleBinding` with `kubectl`:

   ```
   $ kubectl apply -f viewers-bind.yaml
   ```

## Step 4/4. Access your Kubernetes cluster

After Teleport starts with the above config, you should be able to see all new clusters:

```
$ tsh kube ls
Kube Cluster Name                       Labels           Selected
--------------------------------------- ------           --------
my-cluster                              region=us-east-1
```

To access your cluster, run the following command, replacing `my-cluster` with the name of the cluster you would like to access:

```
$ tsh kube login my-cluster
Logged into kubernetes cluster "my-cluster". Try 'kubectl version' to test the connection.
```
