diff --git a/docs/config.json b/docs/config.json
index 73f74494e991f..960f0d629da19 100644
--- a/docs/config.json
+++ b/docs/config.json
@@ -575,6 +575,11 @@
"title": "Joining Nodes via Azure",
"slug": "/management/guides/joining-nodes-azure/"
},
+ {
+ "title": "Joining Services via Kubernetes ServiceAccount",
+ "slug": "/management/guides/joining-services-kubernetes-serviceaccount/",
+ "forScopes": ["oss", "enterprise"]
+ },
{
"title": "Using Teleport's CA with GitHub",
"slug": "/management/guides/ssh-key-extensions/"
diff --git a/docs/pages/includes/config-reference/instance-wide.yaml b/docs/pages/includes/config-reference/instance-wide.yaml
index ab070976f0782..f2e51212114b3 100644
--- a/docs/pages/includes/config-reference/instance-wide.yaml
+++ b/docs/pages/includes/config-reference/instance-wide.yaml
@@ -40,9 +40,9 @@ teleport:
join_params:
# When `method` is set to "token", it is the equivalent to using `auth_token` above.
# You should only use either auth_token or join_params.
- method: "token"|"ec2"|"iam"
+ method: "token"|"ec2"|"iam"|"github"|"circleci"|"kubernetes"
- # If method is "iam" or "ec2", token_name will be will be the name of
+ # If method is not "token", token_name will be will be the name of
# the joining token resource, e.g., "ec2-token" or "iam-token" as created
# in the Joining Nodes via EC2 or IAM guides.
@@ -117,4 +117,3 @@ teleport:
format:
output: text
extra_fields: [level, timestamp, component, caller]
-
diff --git a/docs/pages/management/guides.mdx b/docs/pages/management/guides.mdx
index e5e9a3891f23e..b3be7a7651b9c 100644
--- a/docs/pages/management/guides.mdx
+++ b/docs/pages/management/guides.mdx
@@ -11,6 +11,8 @@ layout: tocless-doc
- [Joining Nodes via AWS IAM Role](./guides/joining-nodes-aws-iam.mdx). Use the IAM join method to add Nodes to your Teleport cluster on AWS.
- [Joining Nodes via AWS EC2 Identity Document](./guides/joining-nodes-aws-ec2.mdx). Use the EC2 join method to add Nodes to your Teleport cluster on AWS.
+ - [Joining Services via Kubernetes ServiceAccount](./guides/joining-services-kubernetes-serviceaccount.mdx).
+ Use Kubernetes ServiceAccount tokens to join services running in the same Kubernetes cluster as the Auth Service.
- [Joining Nodes via Azure](./guides/joining-nodes-azure.mdx) Use the Azure join method to add Nodes to your Teleport cluster on Azure.
- [Using Teleport's Certificate Authority with GitHub](./guides/ssh-key-extensions.mdx). Use Teleport's short-lived certificates with GitHub's Certificate Authority.
diff --git a/docs/pages/management/guides/joining-services-kubernetes-serviceaccount.mdx b/docs/pages/management/guides/joining-services-kubernetes-serviceaccount.mdx
new file mode 100644
index 0000000000000..8eb9c69ed62b2
--- /dev/null
+++ b/docs/pages/management/guides/joining-services-kubernetes-serviceaccount.mdx
@@ -0,0 +1,275 @@
+---
+title: Joining Services via Kubernetes ServiceAccount Token
+description: Use Kubernetes ServiceAccount tokens to join services running in the same Kubernetes cluster as the Auth Service.
+---
+
+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.
+
+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 12+.
+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](../../deploy-a-cluster/helm-deployments.mdx).
+- Editor access to the Kubernetes cluster running the Teleport cluster.
+ You must be able to create Namespaces and Deployments.
+- A Teleport user with `access` role, or any other role that allows access to
+ applications with the label `app: demo-app`
+- Either the Teleport `editor` role or the ability to `kubectl exec` into your
+ existing Teleport Auth Service pods.
+- The Auth Service ServiceAccount must be granted the `system:auth-delegator`
+ ClusterRole. Clusters deployed with the [`teleport-cluster` Helm
+ chart](../../reference/helm-reference/teleport-cluster.mdx) version 12 or
+ higher have the correct role by default.
+
+## 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.
+
+```yaml
+# 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.
+ # Common roles are:
+ # - "Node" for SSH Service
+ # - "Proxy" for Proxy Service
+ # - "Kube" for Kubernetes Service
+ # - "App" for Application Service
+ # - "Db" for Database Service
+ # - "WindowsDesktop" for Windows Desktop Service
+ # - "Discovery" for Discovery Service
+ roles: [App]
+
+ # set the join method allowed for this token
+ join_method: kubernetes
+
+ kubernetes:
+ 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]`.
+Follow the instructions below to create the token depending on whether you have administrative access to the Auth Service pod:
+
+
+Make sure your local `tctl` is at least at version 12 with `tctl version`.
+
+Create the token:
+
+```code
+$ tctl create token.yaml
+```
+
+Finally, validate the token was created:
+
+```code
+$ tctl get token/kubernetes-token
+
+kind: token
+metadata:
+ expires: "3000-01-01T00:00:00Z"
+ name: kubernetes-token
+spec:
+ join_method: kubernetes
+ roles:
+ - App
+version: v2
+```
+
+
+
+Retrieve the name and namespace of the Auth Service deployment:
+
+```code
+$ kubectl get namespaces
+NAME STATUS AGE
+cert-manager Active 40d
+default Active 40d
+kube-system Active 40d
+teleport Active 40d
+
+# We look for deployments in the "teleport" namespace
+$ kubectl get deployments -n teleport
+NAME READY UP-TO-DATE AVAILABLE AGE
+teleport-auth 2/2 2 2 6d20h
+teleport-proxy 2/2 2 2 6d20h
+
+# Here, the deployment name is "teleport-auth".
+```
+
+Then run the following command to execute the `tctl create` command from inside
+one of the Auth Service pods:
+
+```code
+$ kubectl exec -i -n teleport deployment/teleport-auth -- tctl create < token.yaml
+```
+
+Finally, validate the token was successfully created:
+
+```code
+$ kubectl exec -i -n teleport deployment/teleport-auth tctl get token/kubernetes-token
+
+kind: token
+metadata:
+ expires: "3000-01-01T00:00:00Z"
+ name: kubernetes-token
+spec:
+ join_method: kubernetes
+ roles:
+ - App
+version: v2
+```
+
+
+
+
+## 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.
+
+```code
+$ kubectl create namespace demo-app
+namespace/demo-app created
+
+$ kubectl create deployment --image=nginx --namespace demo-app --port=80 demo-app
+deployment.apps/demo-app created
+
+$ kubectl 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:
+
+```code
+$ kubectl get pods -n demo-app
+NAME READY STATUS RESTARTS AGE
+demo-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:
+
+```yaml
+# 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)
+# 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:
+
+```code
+$ 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:
+
+```code
+$ kubectl get pods -n teleport-agent
+NAME READY STATUS RESTARTS AGE
+teleport-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:
+
+```code
+$ tsh apps ls
+Application 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.
+
+```code
+$ helm delete -n teleport-agent teleport-app-service
+release "teleport-app-service" uninstalled
+
+$ kubectl delete namespaces demo-app teleport-agent
+namespace "demo-app" deleted
+namespace "teleport-agent" deleted
+```
+
+## Going further
+
+- The possible values for `teleport-kube-agent` chart are documented
+ [in its reference](../../reference/helm-reference/teleport-kube-agent.mdx).
+- See [Application Access Guides](../../application-access/guides.mdx)
+- See [Database Access Guides](../../database-access/guides.mdx)