From 07ebb8a3b1a2a4c5bad5145c3fef4978c3d2c531 Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Thu, 21 Aug 2025 16:39:16 +0100 Subject: [PATCH 01/14] Add configuration reference and guide for Argo CD --- .../access-guides/access-guides.mdx | 1 + .../machine-id/access-guides/argocd.mdx | 255 ++++++++++++++++++ .../reference/machine-id/configuration.mdx | 91 +++++++ 3 files changed, 347 insertions(+) create mode 100644 docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/access-guides.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/access-guides.mdx index 447ebdc4bd5f5..0ab5eb7c5683f 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/access-guides.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/access-guides.mdx @@ -26,4 +26,5 @@ on how to do so. - [tctl](tctl.mdx): How to use Machine ID with `tctl` to manage your Teleport configuration. - [Teleport Terraform provider](../../../zero-trust-access/infrastructure-as-code/terraform-provider/dedicated-server.mdx): How to use Machine ID with the Teleport Terraform provider to manage your Teleport configuration as IaC. - [Ansible](ansible.mdx): How to use Machine ID with Ansible. +- [Argo CD](argocd.mdx): How to use Machine ID to enable Argo CD to connect to external Kubernetes clusters. - [SPIFFE](../../workload-identity/getting-started.mdx): How to use Machine ID to issue SPIFFE certificates. diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx new file mode 100644 index 0000000000000..df2615d460089 --- /dev/null +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -0,0 +1,255 @@ +--- +title: Machine ID with Argo CD +description: How to use Machine ID to enable Argo CD to connect to external Kubernetes clusters +labels: + - how-to + - mwi +--- + +Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. It +runs in Kubernetes and can deploy applications to the same cluster or to other +"external" clusters. + +In this guide, you will configure the Machine ID agent, `tbot`, to provide Argo +CD with the connection details and short-lived credentials it needs to manage +clusters using Teleport's Kubernetes Access. + +## Prerequisite + +(!docs/pages/includes/edition-prereqs-tabs.mdx!) + +- Argo CD [installed](https://argo-cd.readthedocs.io/en/latest/#quick-start) + in a Kubernetes cluster. This cluster does not need to be enrolled into + Teleport. + +- The Kubernetes cluster to which you'd like Argo CD to deploy applications. + This cluster must be enrolled into Teleport, if you have not already done this, + follow the [Enroll a Kubernetes Cluster](../../../enroll-resources/kubernetes-access/getting-started.mdx) + guide. + +- (!docs/pages/includes/tctl.mdx!) + +- To configure Kubernetes and deploy `tbot` you will need + [`kubectl`](https://kubernetes.io/docs/tasks/tools/) and + [`helm`](https://helm.sh/docs/intro/install/) installed. + +- To check clusters have been registered with Argo CD, you will need the + [`argocd` CLI](https://argo-cd.readthedocs.io/en/stable/cli_installation/) + installed. + +## Step 1/4. Configure Teleport and Kubernetes RBAC + +First, we need to configure the RBAC for both Teleport and Kubernetes in order +to grant the Machine ID agent the correct level of access. + +When forwarding requests to the Kubernetes API on behalf of a bot, the Teleport +Proxy attaches the groups configured (using `kubernetes_groups`) in the bot's +Teleport roles to the request. These groups are then used to configure a +RoleBinding or ClusterRoleBinding in Kubernetes to grant specific permissions +within the Kubernetes cluster to the bot. + +For the purpose of this guide, we will bind the `editor` group to the default +`edit` ClusterRole that is preconfigured in most Kubernetes clusters to give the +bot read and write access to resources in all the cluster namespaces. + +When configuring this in a production environment, you should consider: + +- If RoleBinding should be used instead of ClusterRoleBinding to limit the bot's + access to a specific namespace. +- If a Role should be created that grants the bot the least privileges necessary + rather than using a pre-existing general Role such as `edit`. + +To bind the `editor` group to the `edit` Cluster Role, run: + +```code +$ kubectl create clusterrolebinding teleport-editor-edit \ + --clusterrole=edit \ + --group=editor +``` + +With the appropriate RoleBinding configured in Kubernetes to grant access to a +specific group, you now need to add this group to the role that the bot will +impersonate when producing credentials. You also need to grant the bot access +through Teleport to the cluster itself. This is done by creating a role that +grants the necessary permissions and then assigning this role to the bot. + +Create a file called `role.yaml` with the following content: + +```yaml +kind: role +version: v7 +metadata: + name: example-role +spec: + allow: + kubernetes_labels: + '*': '*' + kubernetes_groups: + - editor + kubernetes_resources: + - kind: "*" + namespace: "*" + name: "*" + verbs: ["*"] +``` + +Replace `example-role` with a descriptive name related to your use case. + +Adjust the `allow` field for your environment: + +- `kubernetes_labels` should be adjusted to grant access to only the clusters + that the bot will need to access. The value shown, `'*': '*'` will grant + access to all Kubernetes clusters. +- `editor` must match the name of the group you specified in the RoleBinding or + ClusterRoleBinding. +- `kubernetes_resources` can be used to apply additional restrictions to what + the bot can access within the Kubernetes cluster. These restrictions are + layered upon the RBAC configured within the Kubernetes role itself. + +Use `tctl create -f ./role.yaml` to create the role. + +(!docs/pages/includes/create-role-using-web.mdx!) + +## Step 2/4. Create a bot + +Next, we need to create the bot. A bot is a Teleport identity for a machine or +group of machines. + +Create a file called `bot.yaml` with the following content: + +```yaml +kind: bot +version: v1 +metadata: + # name uniquely identifies the bot within Teleport + name: example-bot +spec: + # roles that will be granted to the bot. + roles: [example-role] +``` + +Make sure you replace `example-bot` with a unique, descriptive name for your Bot, +and replace `example-role` with the name of the role you created in the previous +step. + +Use `tctl create -f ./bot.yaml` to create the bot. + +## Step 3/4. Create a join token + +In order for `tbot` to be able to authenticate and join the Teleport cluster, +we need to configure a join token. There are a number of different available +[methods](../../../reference/join-methods.mdx), but for this guide we will use +the `kubernetes` method with a static JWKS. + +Please refer to the [Deploying tbot on Kubernetes](../../deployment/kubernetes.mdx) +and [Deploying tbot on Kubernetes with OIDC](../../deployment/kubernetes-oidc.mdx) +guides for more in-depth information. + +First, run the following commands to determine the JWKS-formatted public key: + +```code +$ kubectl proxy -p 8080 +$ curl http://localhost:8080/openid/v1/jwks +{"keys":[--snip--]}% +``` + +Next, create a file called `join-token.yaml` with the following content, ensuring +you insert the output from the `curl` command in `spec.kubernetes.static_jwks.jwks` +and specify the namespace in which Argo CD is running in +`spec.kubernetes.allow[0].service_account`: + +```yaml +kind: token +version: v2 +metadata: + # name will be specified in the tbot Helm chart values later + name: example-join-token +spec: + roles: [Bot] + # bot_name must match the name of the bot created earlier in this guide. + bot_name: example-bot + join_method: kubernetes + kubernetes: + # static_jwks configures the Auth Service to validate the JWT presented by + # `tbot` using the public key from a statically configured JWKS. + type: static_jwks + static_jwks: + jwks: | + # Place the data returned by the curl command here + {"keys":[--snip--]} + # allow specifies the rules by which the Auth Service determines if `tbot` + # should be allowed to join. + allow: + - service_account: "argocd:tbot" # namespace:service_account +``` + +Use `tctl create -f ./join-token.yaml` to create the join. + +## Step 4/4. Deploy `tbot` + +Finally, we'll use the official [Helm chart](../../../reference/helm-reference/tbot.mdx) +to deploy `tbot`. + +Find your cluster name by running `tctl status`. + +Create a file called `tbot-values.yaml` with the following content, ensuring you +replace the placeholder values with your cluster name, proxy address, and using +`clusterSelectors` to identify which Kubernetes clusters you'd like to expose to +Argo CD: + +```yaml +clusterName: "test.teleport.sh" +teleportProxyAddress: "test.teleport.sh:443" +token: "example-join-token" +defaultOutput: + enabled: false +argocd: + enabled: true + clusterSelectors: + - labels: + environment: production +``` + +Please refer to the [Helm chart reference](../../../reference/helm-reference/tbot.mdx#argocd) +for all of the supported configuration options. + +Install the Helm chart by running the following commands, ensuring you specify +the namespace in which Argo CD is running: + +```code +$ helm repo add teleport (=teleport.helm_repo_url=) +$ helm repo update +$ helm install tbot teleport/tbot \ + --namespace argocd \ + --values tbot-values.yaml +``` + +Once the Helm chart installation is complete (usually after a few minutes), you +should see your Kubernetes clusters in Argo CD. You can check this by running +the following command: + +```code +$ argocd cluster list +SERVER NAME +https://test.teleport.sh:443/v1/teleport/dHAxLmZsb3BweS5jbw/Ym94b2ZyYWQ1 test.teleport.sh-prod-eu-1 +https://kubernetes.default.svc in-cluster +``` + +You should also be able to see the `tbot`-managed cluster secrets in Kubernetes +when running the following command: + +```code +$ kubectl get secrets -n argocd | grep ^teleport.argocd-cluster. +teleport.argocd-cluster.e815df7b7588be17 Opaque 3 7d3h +``` + +You can now configure Argo CD to deploy applications to your Teleport-enrolled +clusters! + +If new matching clusters are added in Teleport, `tbot` will register them with +Argo CD on the bot's next certificate renewal. If needed, the `tbot` process can +be restarted or signalled (`pkill -USR1 tbot`) to trigger an immediate reload. + +Please note that, for safety, if a cluster is deleted in Teleport or no longer +matches your `clusterSelectors`, it will **not** be automatically removed from +Argo CD - but `tbot` will stop refreshing its credentials. diff --git a/docs/pages/reference/machine-id/configuration.mdx b/docs/pages/reference/machine-id/configuration.mdx index d746f178b1b24..3929e4c8f1218 100644 --- a/docs/pages/reference/machine-id/configuration.mdx +++ b/docs/pages/reference/machine-id/configuration.mdx @@ -393,6 +393,97 @@ If clusters are added or removed over time, the `kubeconfig.yaml` will be updated at the bot's normal renewal interval. You can trigger an early renewal by restarting `tbot`, or signaling it with `pkill -usr1 tbot`. +### `kubernetes/argo-cd` + +The `kubernetes/argo-cd` output type can be used to enable Argo CD to securely +connect to external Kubernetes clusters. + +It works by "declaratively" managing cluster credentials +[using Kubernetes secrets](https://argo-cd.readthedocs.io/en/release-1.8/operator-manual/declarative-setup/#clusters). +For each matching Kubernetes cluster, `tbot` will create and continuously update +a secret containing connection details and short-lived credentials, labeled with +`"argocd.argoproj.io/secret-type": "cluster"` for Argo CD to discover. + +As such, it is only intended to be used within a Kubernetes cluster. See the +[Machine ID with Argo CD guide](../../machine-workload-identity/machine-id/access-guides/argocd.mdx) +for information on how to deploy it using the Helm chart. + + + The `kubernetes/argo-cd` output type does not currently support + configurations where the Teleport proxy is behind a TLS-terminating load + balancer. + + +```yaml +type: kubernetes/argo-cd + +# selectors include one or more matching Kubernetes clusters. Each matching +# cluster that the bot has permission to access will be registered with Argo CD +# by creating a Kubernetes secret. +selectors: + # name includes an exact match by name. Note that wildcards are not currently + # supported. Multiple name selectors can be specified if desired. + - name: foo + # labels include all clusters matching all of these labels. Multiple label + # selectors can be provided if needed. + - labels: + env: dev + +# secret_namespace is the Kubernetes namespace in which Argo CD cluster secrets +# will be created. It must match the namespace where Argo CD is running. +# +# By default, `tbot` will use the `POD_NAMESPACE` environment variable, or if +# that is empty: "default". +secret_namespace: "argocd" + +# secret_name_prefix is the prefix that will be applied to Kubernetes secret +# names so they can be easily identified. The rest of the name will be derived +# from a hash of the target cluster name. +# +# By default, the prefix will be: "teleport.argocd-cluster". +secret_name_prefix: "argocd-cluster" + +# secret_labels is a set of labels that will be applied to the cluster secrets +# in addition to the "argocd.argoproj.io/secret-type" label added for Argo CD +# discovery. +secret_labels: + department: engineering + +# secret_annotations is a set of annotations that will be applied to the cluster +# secrets in addition to `tbot`'s own annotations (e.g. "teleport.dev/updated"). +secret_annotations: + creator: bob + +# project is the Argo CD project with which the Kubernetes clusters will be +# associated. +project: edge-services + +# namespaces are the namespaces within the target Kubernetes clusters to which +# Argo CD will be allowed to deploy. +namespaces: + - dev + - qa + +# cluster_resources determines whether Argo CD will be allowed to operate on +# cluster-scoped resources within the target clusters. This option is only +# applicable when `namespaces` is non-empty. +cluster_resources: true + +# The following configuration fields are available across most output types. +# Note that `roles` and `destination` are not supported for this output type. + +# credential_ttl and renewal_interval override the credential TTL and renewal +# interval for this specific output, so that you can make its certificates valid +# for shorter than `tbot`'s internal certificates. +credential_ttl: 30m +renewal_interval: 15m + +# name optionally overrides the name of the service used in logs and the `/readyz` +# endpoint. It must only contain letters, numbers, hyphens, underscores, and plus +# symbols. +name: my-service-name +``` + ### `ssh_host` The `ssh_host` output is used to generate the artifacts required to configure From 1702d377f449b020e915aa9b105b90f3da4cb4c3 Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Thu, 21 Aug 2025 17:17:10 +0100 Subject: [PATCH 02/14] Fix linting errors and broken links --- .../machine-id/access-guides/argocd.mdx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx index df2615d460089..cdaa9aeb11dea 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -21,18 +21,14 @@ clusters using Teleport's Kubernetes Access. - Argo CD [installed](https://argo-cd.readthedocs.io/en/latest/#quick-start) in a Kubernetes cluster. This cluster does not need to be enrolled into Teleport. - - The Kubernetes cluster to which you'd like Argo CD to deploy applications. This cluster must be enrolled into Teleport, if you have not already done this, follow the [Enroll a Kubernetes Cluster](../../../enroll-resources/kubernetes-access/getting-started.mdx) guide. - - (!docs/pages/includes/tctl.mdx!) - - To configure Kubernetes and deploy `tbot` you will need [`kubectl`](https://kubernetes.io/docs/tasks/tools/) and [`helm`](https://helm.sh/docs/intro/install/) installed. - - To check clusters have been registered with Argo CD, you will need the [`argocd` CLI](https://argo-cd.readthedocs.io/en/stable/cli_installation/) installed. @@ -141,8 +137,8 @@ we need to configure a join token. There are a number of different available [methods](../../../reference/join-methods.mdx), but for this guide we will use the `kubernetes` method with a static JWKS. -Please refer to the [Deploying tbot on Kubernetes](../../deployment/kubernetes.mdx) -and [Deploying tbot on Kubernetes with OIDC](../../deployment/kubernetes-oidc.mdx) +Please refer to the [Deploying tbot on Kubernetes](../deployment/kubernetes.mdx) +and [Deploying tbot on Kubernetes with OIDC](../deployment/kubernetes-oidc.mdx) guides for more in-depth information. First, run the following commands to determine the JWKS-formatted public key: From 286528c06a4c89edef52bce94b8c7ddec01a1928 Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Tue, 26 Aug 2025 13:09:43 +0100 Subject: [PATCH 03/14] Simpler way to get the JWKS --- .../machine-id/access-guides/argocd.mdx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx index cdaa9aeb11dea..90a14c1ea8e1a 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -144,8 +144,7 @@ guides for more in-depth information. First, run the following commands to determine the JWKS-formatted public key: ```code -$ kubectl proxy -p 8080 -$ curl http://localhost:8080/openid/v1/jwks +$ kubectl get --raw /openid/v1/jwks {"keys":[--snip--]}% ``` From 9c39455d253a9e9cf2977237ada241bf139d8ed9 Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Tue, 26 Aug 2025 13:13:51 +0100 Subject: [PATCH 04/14] Warn about OIDC joining --- .../machine-id/access-guides/argocd.mdx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx index 90a14c1ea8e1a..4497cc74253be 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -135,11 +135,20 @@ Use `tctl create -f ./bot.yaml` to create the bot. In order for `tbot` to be able to authenticate and join the Teleport cluster, we need to configure a join token. There are a number of different available [methods](../../../reference/join-methods.mdx), but for this guide we will use -the `kubernetes` method with a static JWKS. - -Please refer to the [Deploying tbot on Kubernetes](../deployment/kubernetes.mdx) -and [Deploying tbot on Kubernetes with OIDC](../deployment/kubernetes-oidc.mdx) -guides for more in-depth information. +the `kubernetes` method with a static JWKS. Please refer to the +[Deploying tbot on Kubernetes](../deployment/kubernetes.mdx) guide for more +in-depth information. + + +Certain cloud providers like Amazon EKS regularly rotate their OIDC signing +keys, which will cause the `static_jwks` configuration you create in this guide +to become invalid after a short period of time. + +On Kubernetes providers with OIDC support, like Amazon's Elastic Kubernetes +Service (EKS), Google Kubernetes Engine (GKE), and Azure Kubernetes Service +(AKS), consider using [Kubernetes OIDC joining](../deployment/kubernetes-oidc.mdx) +instead. + First, run the following commands to determine the JWKS-formatted public key: From 67671e8dc776bd71d503cb3db33a87770161edc2 Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Tue, 26 Aug 2025 13:18:48 +0100 Subject: [PATCH 05/14] Clarify that `tbot` will manage cluster credentials --- .../machine-id/access-guides/argocd.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx index 4497cc74253be..f2fb63cddc5a5 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -10,9 +10,9 @@ Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. It runs in Kubernetes and can deploy applications to the same cluster or to other "external" clusters. -In this guide, you will configure the Machine ID agent, `tbot`, to provide Argo -CD with the connection details and short-lived credentials it needs to manage -clusters using Teleport's Kubernetes Access. +In this guide, you will configure the Machine ID agent, `tbot`, to manage Argo +CD's cluster credentials, enabling it to securely deploy applications using +Teleport Kubernetes Access. ## Prerequisite From f82d99b8474fdf19a1c9112d917f54ad8cccce98 Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Tue, 26 Aug 2025 13:26:54 +0100 Subject: [PATCH 06/14] Document our default annotations --- docs/pages/reference/machine-id/configuration.mdx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/pages/reference/machine-id/configuration.mdx b/docs/pages/reference/machine-id/configuration.mdx index 3929e4c8f1218..a7edc5449ff2a 100644 --- a/docs/pages/reference/machine-id/configuration.mdx +++ b/docs/pages/reference/machine-id/configuration.mdx @@ -450,7 +450,13 @@ secret_labels: department: engineering # secret_annotations is a set of annotations that will be applied to the cluster -# secrets in addition to `tbot`'s own annotations (e.g. "teleport.dev/updated"). +# secrets in addition to `tbot`'s own annotations: +# +# - "teleport.dev/bot-name" - Name of the Bot +# - "teleport.dev/kubernetes-cluster-name" - Name of the Kubernetes cluster +# - "teleport.dev/updated" - RFC3339-formatted timestamp +# - "teleport.dev/tbot-version" - Version of tbot running +# - "teleport.dev/teleport-cluster-name" - Name of the Teleport cluster secret_annotations: creator: bob From 0989182ac24907447d0f68b531eaa2f0e0534330 Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Tue, 26 Aug 2025 13:27:05 +0100 Subject: [PATCH 07/14] Clarify that `namespaces` are optional --- docs/pages/reference/machine-id/configuration.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/pages/reference/machine-id/configuration.mdx b/docs/pages/reference/machine-id/configuration.mdx index a7edc5449ff2a..4221f5eb807ef 100644 --- a/docs/pages/reference/machine-id/configuration.mdx +++ b/docs/pages/reference/machine-id/configuration.mdx @@ -464,8 +464,9 @@ secret_annotations: # associated. project: edge-services -# namespaces are the namespaces within the target Kubernetes clusters to which -# Argo CD will be allowed to deploy. +# namespaces optionally restricts which namespaces within the target Kubernetes +# clusters applications may be deployed into. By default, all namespaces are +# allowed. namespaces: - dev - qa From 285f3d1013d76e9bc9579214fcdc0274a5e863d5 Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Tue, 26 Aug 2025 14:05:52 +0100 Subject: [PATCH 08/14] Document impersonation support --- .../machine-id/access-guides/argocd.mdx | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx index f2fb63cddc5a5..166de25a215d5 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -257,3 +257,60 @@ be restarted or signalled (`pkill -USR1 tbot`) to trigger an immediate reload. Please note that, for safety, if a cluster is deleted in Teleport or no longer matches your `clusterSelectors`, it will **not** be automatically removed from Argo CD - but `tbot` will stop refreshing its credentials. + +### Argo CD Impersonation + +Argo CD [supports using](https://argo-cd.readthedocs.io/en/latest/operator-manual/app-sync-using-impersonation/) +Kubernetes' user impersonation feature to give the application sync process more +restrictive privileges than the Argo control plane has generally. This can be +used to create a permission boundary where applications deployed to the same +cluster, but in different projects, cannot read or modify each other's resources. + +In order to use Argo CD impersonation with Teleport Kubernetes Access, your bot +must have a role where `kubernetes_users` contains a wildcard. For example: + +```yaml +kind: role +version: v7 +metadata: + name: kube-wildcard-access +spec: + allow: + kubernetes_users: + - '*' +``` + +If you simply enumerate the users that Argo CD is allowed to impersonate in +`kubernetes_users`, you will encounter the following error: + +``` +please select a user to impersonate, refusing to select a user due to several kubernetes_users set up for this user +``` + +This happens because Argo CD *only* sets impersonation headers on requests that +operate on application-scoped resources. Because your role has permission to +impersonate many users, it's ambiguous which one Teleport should use by default. + +When `kubernetes_users` contains a wildcard, and no specific user is being +impersonated, Kubernetes Access will fall back to sending your bot's Teleport +username by default. You should therefore create a RoleBinding or +ClusterRoleBinding granting your bot user the broader permissions needed by the +Argo CD control plane. + +```code +$ kubectl create clusterrolebinding example-bot-edit \ + --clusterrole=edit \ + --user=bot-example-bot +``` + + +When using impersonation to create a permission boundary between Argo CD +projects, remember that Kubernetes Access will automatically impersonate any +groups listed in `kubernetes_groups` by default. + +You should ensure that your bot user does not have any roles which contain +`kubernetes_groups`, otherwise the privilege isolation provided by impersonating +different users is compromised, because the application sync process will have +the combination of the impersonated user's privileges and those granted to the +groups. + From b71646f3b94b7545188d5ce409dfdb19ba0b2b1e Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Tue, 26 Aug 2025 14:06:04 +0100 Subject: [PATCH 09/14] Mention deleting the pod to trigger a reload --- .../machine-id/access-guides/argocd.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx index 166de25a215d5..b540f370db50d 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -252,7 +252,8 @@ clusters! If new matching clusters are added in Teleport, `tbot` will register them with Argo CD on the bot's next certificate renewal. If needed, the `tbot` process can -be restarted or signalled (`pkill -USR1 tbot`) to trigger an immediate reload. +be restarted by deleting the pod or signalled (`pkill -USR1 tbot`) to trigger an +immediate reload. Please note that, for safety, if a cluster is deleted in Teleport or no longer matches your `clusterSelectors`, it will **not** be automatically removed from From 3c13ada08f1607448328f42cc3f3236b1d1bf26c Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Tue, 26 Aug 2025 14:17:06 +0100 Subject: [PATCH 10/14] Clarify which cluster to create the role binding in --- .../machine-id/access-guides/argocd.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx index b540f370db50d..29edd93e162ee 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -295,8 +295,8 @@ impersonate many users, it's ambiguous which one Teleport should use by default. When `kubernetes_users` contains a wildcard, and no specific user is being impersonated, Kubernetes Access will fall back to sending your bot's Teleport username by default. You should therefore create a RoleBinding or -ClusterRoleBinding granting your bot user the broader permissions needed by the -Argo CD control plane. +ClusterRoleBinding, in your target cluster, granting your bot user the broader +permissions needed by the Argo CD control plane. ```code $ kubectl create clusterrolebinding example-bot-edit \ From 658e0654f06fab0b083698d7430ef324b60822ab Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Tue, 26 Aug 2025 15:31:48 +0100 Subject: [PATCH 11/14] Clarify which commands to run against which clusters --- .../machine-id/access-guides/argocd.mdx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx index 29edd93e162ee..99a9fef12053c 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -19,10 +19,11 @@ Teleport Kubernetes Access. (!docs/pages/includes/edition-prereqs-tabs.mdx!) - Argo CD [installed](https://argo-cd.readthedocs.io/en/latest/#quick-start) - in a Kubernetes cluster. This cluster does not need to be enrolled into - Teleport. + in a Kubernetes cluster. This cluster will be referred to as the **source + cluster** throughout this guide, it does not need to be enrolled into Teleport. - The Kubernetes cluster to which you'd like Argo CD to deploy applications. - This cluster must be enrolled into Teleport, if you have not already done this, + This cluster will be referred to as the **target cluster** throughout this + guide, it must be enrolled into Teleport, if you have not already done this, follow the [Enroll a Kubernetes Cluster](../../../enroll-resources/kubernetes-access/getting-started.mdx) guide. - (!docs/pages/includes/tctl.mdx!) @@ -55,7 +56,8 @@ When configuring this in a production environment, you should consider: - If a Role should be created that grants the bot the least privileges necessary rather than using a pre-existing general Role such as `edit`. -To bind the `editor` group to the `edit` Cluster Role, run: +To bind the `editor` group to the `edit` Cluster Role, run the following command +against both the source and target clusters: ```code $ kubectl create clusterrolebinding teleport-editor-edit \ @@ -150,7 +152,8 @@ Service (EKS), Google Kubernetes Engine (GKE), and Azure Kubernetes Service instead. -First, run the following commands to determine the JWKS-formatted public key: +First, run the following command against the source cluster, to determine the +JWKS-formatted public key: ```code $ kubectl get --raw /openid/v1/jwks @@ -217,8 +220,8 @@ argocd: Please refer to the [Helm chart reference](../../../reference/helm-reference/tbot.mdx#argocd) for all of the supported configuration options. -Install the Helm chart by running the following commands, ensuring you specify -the namespace in which Argo CD is running: +Install the Helm chart by running the following commands against the source +cluster, ensuring you specify the namespace in which Argo CD is running: ```code $ helm repo add teleport (=teleport.helm_repo_url=) @@ -295,7 +298,7 @@ impersonate many users, it's ambiguous which one Teleport should use by default. When `kubernetes_users` contains a wildcard, and no specific user is being impersonated, Kubernetes Access will fall back to sending your bot's Teleport username by default. You should therefore create a RoleBinding or -ClusterRoleBinding, in your target cluster, granting your bot user the broader +ClusterRoleBinding, in the target cluster, granting your bot user the broader permissions needed by the Argo CD control plane. ```code From e598914ab15598aaa97e220c753207ae9cd9efff Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Wed, 27 Aug 2025 17:09:18 +0100 Subject: [PATCH 12/14] Make cluster names bold --- .../machine-id/access-guides/argocd.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx index 99a9fef12053c..a02fa22bf99c6 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -57,7 +57,7 @@ When configuring this in a production environment, you should consider: rather than using a pre-existing general Role such as `edit`. To bind the `editor` group to the `edit` Cluster Role, run the following command -against both the source and target clusters: +against both the **source and target clusters**: ```code $ kubectl create clusterrolebinding teleport-editor-edit \ @@ -152,8 +152,8 @@ Service (EKS), Google Kubernetes Engine (GKE), and Azure Kubernetes Service instead. -First, run the following command against the source cluster, to determine the -JWKS-formatted public key: +First, run the following command against the **source cluster**, to determine +the JWKS-formatted public key: ```code $ kubectl get --raw /openid/v1/jwks @@ -298,8 +298,8 @@ impersonate many users, it's ambiguous which one Teleport should use by default. When `kubernetes_users` contains a wildcard, and no specific user is being impersonated, Kubernetes Access will fall back to sending your bot's Teleport username by default. You should therefore create a RoleBinding or -ClusterRoleBinding, in the target cluster, granting your bot user the broader -permissions needed by the Argo CD control plane. +ClusterRoleBinding, in the **target cluster**, granting your bot user the +broader permissions needed by the Argo CD control plane. ```code $ kubectl create clusterrolebinding example-bot-edit \ From c91adcb7819b7533843ceb3879381fd1098d478b Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Wed, 3 Sep 2025 10:24:06 +0100 Subject: [PATCH 13/14] Fix label indentation --- .../machine-id/access-guides/argocd.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx index a02fa22bf99c6..50aed6033b692 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -214,7 +214,7 @@ argocd: enabled: true clusterSelectors: - labels: - environment: production + environment: production ``` Please refer to the [Helm chart reference](../../../reference/helm-reference/tbot.mdx#argocd) From f641026c374c1c5af17aeffdab3a6b5cd6a0d76f Mon Sep 17 00:00:00 2001 From: Dan Upton Date: Wed, 3 Sep 2025 10:25:00 +0100 Subject: [PATCH 14/14] Add next steps section --- .../machine-id/access-guides/argocd.mdx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx index 50aed6033b692..06ec3c7290bd1 100644 --- a/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx +++ b/docs/pages/machine-workload-identity/machine-id/access-guides/argocd.mdx @@ -318,3 +318,10 @@ different users is compromised, because the application sync process will have the combination of the impersonated user's privileges and those granted to the groups. + +## Next steps + +- Read the [configuration reference](../../../reference/machine-id/configuration.mdx) + to explore all the available configuration options. +- Read the [Teleport Kubernetes RBAC guide](../../../enroll-resources/kubernetes-access/controls.mdx) + for more details on controlling Kubernetes access.