Joining Services via Kubernetes ServiceAccount Token
This guide will explain how to use the Kubernetes join method to configure Teleport services to join your Teleport cluster without sharing any secrets when running in the same Kubernetes cluster as the Auth Service.
How it works
When a Teleport service wants to be part of the cluster, it needs to prove its identity to the Teleport Auth Service before receiving its certificates. Kubernetes issues signed proof to each pod describing which Kubernetes ServiceAccount they can assume. When using the Kubernetes join method, Teleport uses this Kubernetes proof to become part of the cluster.
The Kubernetes join method is not available in Teleport Enterprise Cloud as it requires the joining service to run in the same Kubernetes cluster as the Auth Service.
The Kubernetes join method is available in self-hosted versions of Teleport. It supports joining any Teleport service running in the same Kubernetes cluster as the Auth Service.
Prerequisites
- A running Teleport cluster in Kubernetes. For details on how to set this up, see Guides for running Teleport using Helm.
- Editor access to the Kubernetes cluster running the Teleport cluster. You must be able to create Namespaces and Deployments.
- A Teleport user with
accessrole, or any other role that allows access to applications with the labelapp: demo-app - Either the Teleport
editorrole or the ability tokubectl execinto your existing Teleport Auth Service pods. - The Auth Service ServiceAccount must be granted the
system:auth-delegatorClusterRole. Clusters deployed with theteleport-clusterHelm chart have the correct role by default. - One of the following client tools for managing Teleport resources:
- The
tctlCLI, which you can install along with Teleport on your workstation (documentation) on your workstation. - Teleport Terraform provider
- Teleport Kubernetes operator
- The
Step 1/5. Create a Kubernetes join token
Configure your Teleport Auth Service with a join token (also called provision token) to allow Teleport services hosted in the Kubernetes cluster to join your Teleport cluster.
Under the hood, Teleport instances will prove to the Auth Service that
they are running in the same Kubernetes cluster by sending a signed ServiceAccount
token that matches an allow rule configured in your Kubernetes join token.
Create a file called token.yaml with the following content, which includes
an allow rule specifying the Kubernetes namespace and Kubernetes
ServiceAccount in which your Teleport services are running.
# token.yaml
kind: token
version: v2
metadata:
# The token name is not a secret as the Kubernetes join method relies on the
# Kubernetes signature to establish trust and not on the join token name.
name: kubernetes-token
# set a long expiry time, the default for tokens is only 30 minutes
expires: "2050-01-01T00:00:00Z"
spec:
# Use the minimal set of system roles required.
roles: [App]
# set the join method allowed for this token
join_method: kubernetes
kubernetes:
# If type is not specified, it defaults to in_cluster
type: in_cluster
allow:
# Service account names follow the format "namespace:serviceaccountname".
- service_account: "teleport-agent:teleport-app-service"
Kubernetes join tokens can be used by any Teleport service besides the Auth Service, such as the Proxy Service and SSH Service. In this guide, we restrict the token to joining an Application Service instance.
It is not recommended to use a single token that can join everything. You should
restrict the token to the roles used by the joining instance. For example, a Teleport
instance running both the Application Service and Database Service should use a token with
roles: [App, Db].
You can create the token with tctl as well as the Teleport Terraform provider
or Kubernetes operator:
- tctl
- Terraform
- Kubernetes
Create the token:
tctl create token.yaml
Finally, validate the token was created:
tctl get token/kubernetes-token
kind: tokenmetadata: expires: "3000-01-01T00:00:00Z" name: kubernetes-tokenspec: join_method: kubernetes roles: - Appversion: v2
Add the following resource to your Terraform configuration, replacing values as indicated:
resource "teleport_provision_token" "kube-token" {
version = "v2"
metadata = {
name = "kube-token"
}
labels = {
// This label is added on the Teleport side by default
"teleport.dev/origin" = "dynamic"
}
spec = {
// use the minimal set of roles required (e.g. Node, Proxy, App, Kube, DB, WindowsDesktop)
roles = ["App"]
join_method = "kubernetes"
kubernetes = {
# If type is not specified, it defaults to in_cluster
type = "in_cluster"
allow = [
{
# Service account names follow the format "namespace:serviceaccountname".
service_account = "teleport-agent:teleport-app-service"
},
]
}
}
}
Add the following Kubernetes resource manifest, replacing values as indicated:
apiVersion: "resources.teleport.dev/v2"
kind: TeleportProvisionToken
metadata:
name: "kube-token"
labels:
# This label is added on the Teleport side by default
"teleport.dev/origin": "dynamic"
spec:
# use the minimal set of roles required (e.g. Node, Proxy, App, Kube, DB, WindowsDesktop)
roles: [App]
# set the join method allowed for this token
join_method: kubernetes
kubernetes:
# If type is not specified, it defaults to in_cluster
type: in_cluster
allow:
# Service account names follow the format "namespace:serviceaccountname".
- service_account: "teleport-agent:teleport-app-service"
Step 2/5. Deploy a demonstration HTTP app
In this step, we deploy a demonstration HTTP application and don't expose it publicly. Instead, we will manage access to this application with the Teleport Application Service, which we will register with Teleport using the Kubernetes join method.
kubectl create namespace demo-appnamespace/demo-app createdkubectl create deployment --image=nginx --namespace demo-app --port=80 demo-appdeployment.apps/demo-app createdkubectl expose deployment demo-app -n demo-app --port=80 --target-port=80 --selector='app=demo-app'service/demo-app exposed
Validate the application pods are running and ready with the following command:
kubectl get pods -n demo-appNAME READY STATUS RESTARTS AGEdemo-app-7664d59cb8-bv888 1/1 Running 0 67s
Step 3/5. Configure the Application Service
Configure the teleport-kube-agent chart to deploy Teleport instances running
the Application Service by creating a values.yaml file with the
following content:
# values.yaml
# Public address of the Teleport cluster with port.
# You must replace the placeholder with your proxy address.
proxyAddr: "teleport.example.com:443"
# Comma-separated list of services the `teleport-kube-agent` chart must run
# (supported values are: kube,db,app,discovery)
# In this guide we only deploy app access.
# Adding more services here also requires to add role to the provision token created in step 1.
roles: app
joinParams:
method: "kubernetes"
# this must match the provision token created in Step 1.
tokenName: "kubernetes-token"
apps:
- name: demo-app
uri: "http://demo-app.demo-app.svc.cluster.local:80"
Step 4/5. Deploy the Application Service
To use the token created in Step 1, the joining instance must run in the same
Kubernetes cluster as the Auth Service and have a Kubernetes ServiceAccount
token mounted.
The teleport-kube-agent chart that you will install in this section will take care of this by default.
Deploy the Teleport Application Service by running the following command:
helm install teleport-app-service teleport/teleport-kube-agent -n teleport-agent --create-namespace -f values.yaml
Then, validate the pod is running after a couple of seconds:
kubectl get pods -n teleport-agentNAME READY STATUS RESTARTS AGEteleport-app-service-0 1/1 Running 0 23s
Finally, validate you can see the application in the Teleport Web UI, or using the command line:
tsh apps lsApplication Description Type Public Address Labels ----------- ----------- ---- -------------------- ------------------- demo-app HTTP teleport.example.com teleport.dev/origin
Step 5/5. Clean up
Uninstall the teleport-app-service Helm release and delete both the demo-app
and teleport-agent namespaces.
helm delete -n teleport-agent teleport-app-servicerelease "teleport-app-service" uninstalledkubectl delete namespaces demo-app teleport-agentnamespace "demo-app" deletednamespace "teleport-agent" deleted
Going further
- The possible values for
teleport-kube-agentchart are documented in its reference. - See Application Access guides
- See Database Access Guides