diff --git a/docs/config.json b/docs/config.json
index f8ff91ae673e6..d83320bdb36d7 100644
--- a/docs/config.json
+++ b/docs/config.json
@@ -289,6 +289,11 @@
"destination": "/reference/operator-resources/resources-teleport-dev-users/",
"permanent": true
},
+ {
+ "source": "/enroll-resources/workload-identity/workload-attestation/",
+ "destination": "/reference/workload-identity/workload-identity-api-and-workload-attestation/",
+ "permanent": true
+ },
{
"source": "/access-controls/guides/role-templates/",
"destination": "/admin-guides/access-controls/guides/role-templates/",
diff --git a/docs/cspell.json b/docs/cspell.json
index 34b72ddd456da..f32242348e11f 100644
--- a/docs/cspell.json
+++ b/docs/cspell.json
@@ -1003,6 +1003,7 @@
"webproxy",
"webui",
"westeurope",
+ "WIMSE",
"winadj",
"windowsaccountname",
"windowsdesktop",
diff --git a/docs/pages/enroll-resources/workload-identity/introduction.mdx b/docs/pages/enroll-resources/workload-identity/introduction.mdx
index b3737e1997f52..3087572d86c08 100644
--- a/docs/pages/enroll-resources/workload-identity/introduction.mdx
+++ b/docs/pages/enroll-resources/workload-identity/introduction.mdx
@@ -97,10 +97,11 @@ Teleport Proxy is not used for securing workload-to-workload communication.
Learn more about Teleport Workload Identity:
- [SPIFFE](./spiffe.mdx): Learn about the SPIFFE specification and how it is implemented by Teleport Workload Identity.
-- [Workload Attestation](./workload-attestation.mdx): Learn about using Workload Attestation to securely issue SVIDs to specific workloads.
- [Federation](./federation.mdx): Learn about using Federation to allow workloads to trust workloads from other trust domains.
- [JWT SVIDs](./jwt-svids.mdx): Learn about the short-lived JWTs issued by Workload Identity.
- [Best Practices](./best-practices.mdx): Best practices for using Workload Identity in Production.
+- [WorkloadIdentity Resource](../../reference/workload-identity/workload-identity-resource.mdx): The full reference for the WorkloadIdentity resource.
+- [Workload Identity API and Workload Attestation](../../reference/workload-identity/workload-identity-api-and-workload-attestation.mdx): To learn more about the Workload Identity API and Workload Attestation.
Learn how to configure Teleport Workload Identity for specific use-cases:
diff --git a/docs/pages/includes/machine-id/workload-identity-selector-config.yaml b/docs/pages/includes/machine-id/workload-identity-selector-config.yaml
new file mode 100644
index 0000000000000..1c8bd0ef46ee4
--- /dev/null
+++ b/docs/pages/includes/machine-id/workload-identity-selector-config.yaml
@@ -0,0 +1,12 @@
+# Selector is used to control which WorkloadIdentity resource will be used to
+# issue the workload identity credential. The selector can either be the name of
+# a specific WorkloadIdentity resource or a label selector that can match
+# multiple WorkloadIdentity resources.
+#
+# The selector must be set to either a name or labels, but not both.
+selector:
+ # Name is used to select a specific WorkloadIdentity resource by its name.
+ name: foo
+ # Labels is used to select multiple WorkloadIdentity resources by their labels.
+ labels:
+ app: [foo, bar]
diff --git a/docs/pages/reference/cli/tbot.mdx b/docs/pages/reference/cli/tbot.mdx
index 46b303846c946..9360e70644b44 100644
--- a/docs/pages/reference/cli/tbot.mdx
+++ b/docs/pages/reference/cli/tbot.mdx
@@ -509,8 +509,87 @@ command supports these additional flags:
| `--username` | The database user name. The bot user must have permission to connect as this user. Required. |
| `--database` | The name of the database available in the requested service. Required. |
+## tbot start workload-identity-x509
+
+Issues an X509 workload identity credential using Teleport Workload Identity and
+writes this credential to a specified destination.
+
+See [TODO] for further information about the workload identity credential output
+and the YAML configuration file format.
+
+### Flags
+
+In addition to the [common `tbot start` flags](#common-start-flags), this
+command supports these additional flags:
+
+| Flag | Description |
+|------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `--destination` | A destination URI, such as file:///foo/bar. See [Destination URIs](#destination-uris) for more info. Required. |
+| `--reader-user` | An additional user name or UID that should be allowed by ACLs to read this destination. Only valid for file destinations on Linux. |
+| `--reader-group` | An additional group name or GID that should be allowed by ACLs to read this destination. Only valid for file destinations on Linux. |
+| `--[no-]include-federated-trust-bundles` | If set, include federated trust bundles in the output |
+| `--name-selector` | Specifies a WorkloadIdentity resource by name to use when issuing the X509 for a workload. Mutually exclusive with `--label-selector`. |
+| `--label-selector` | Specifies a set of labels to use when selecting WorkloadIdentity resources to use when issuing the X509 for a workload. Mutually exclusive with `--name-selector`. |
+
+## tbot start workload-identity-jwt
+
+Issues a JWT workload identity credential using Teleport Workload Identity and
+writes this credential to a specified destination.
+
+The JWT workload identity credential is compatible with the [SPIFFE JWT SVID
+specification](https://github.com/spiffe/spiffe/blob/main/standards/JWT-SVID.md).
+
+See [TODO] for further information about the workload identity credential output
+and the YAML configuration file format.
+
+### Flags
+
+In addition to the [common `tbot start` flags](#common-start-flags), this
+command supports these additional flags:
+
+| Flag | Description |
+|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `--destination` | A destination URI, such as file:///foo/bar. See [Destination URIs](#destination-uris) for more info. Required. |
+| `--reader-user` | An additional user name or UID that should be allowed by ACLs to read this destination. Only valid for file destinations on Linux. |
+| `--reader-group` | An additional group name or GID that should be allowed by ACLs to read this destination. Only valid for file destinations on Linux. |
+| `--name-selector` | Specifies a WorkloadIdentity resource by name to use when issuing the X509 for a workload. Mutually exclusive with `--label-selector`. |
+| `--label-selector` | Specifies a set of labels to use when selecting WorkloadIdentity resources to use when issuing the X509 for a workload. Mutually exclusive with `--name-selector`. |
+| `--audience` | The audience for the JWT. Can be provided multiple times to produce a JWT with multiple audiences. At least one audience must be provided. |
+
+## tbot start workload-identity-api
+
+Starts the `tbot` agent and opens a listener for the local workload identity
+API.
+
+The configuration for this service can be complex, and therefore, it is
+recommended that you leverage the YAML configuration.
+
+See [Workload Identity API & Workload Attestation](../workload-identity/workload-identity-api-and-workload-attestation.mdx)
+for further information about the local workload identity API and the YAML
+configuration.
+
+### Flags
+
+In addition to the [common `tbot start` flags](#common-start-flags), this
+command supports these additional flags:
+
+| Flag | Description |
+|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `--listen` | A socket URI to listen on, e.g. `tcp://localhost:1234` or `unix:///opt/workload-identity.sock`. Required. |
+| `--name-selector` | Specifies a WorkloadIdentity resource by name to use when issuing the X509 for a workload. Mutually exclusive with `--label-selector`. |
+| `--label-selector` | Specifies a set of labels to use when selecting WorkloadIdentity resources to use when issuing the X509 for a workload. Mutually exclusive with `--name-selector`. |
+
## tbot start spiffe-svid
+
+The use of this command has been deprecated as part of the introduction of the
+new Workload Identity configuration experience. You can replace the use of this
+command with the new `tbot start workload-identity-x509` command.
+
+For further information, see [the new Workload Identity configuration experience
+and how to migrate](../workload-identity/configuration-resource-migration.mdx).
+
+
### Flags
In addition to the [common `tbot start` flags](#common-start-flags), this
diff --git a/docs/pages/reference/machine-id/configuration.mdx b/docs/pages/reference/machine-id/configuration.mdx
index 6b21fceb51462..8d97964dd1ec2 100644
--- a/docs/pages/reference/machine-id/configuration.mdx
+++ b/docs/pages/reference/machine-id/configuration.mdx
@@ -311,8 +311,70 @@ principals:
(!docs/pages/includes/machine-id/common-output-config.yaml!)
```
+### `workload-identity-x509`
+
+The `workload-identity-x509` output is used to issue an X509 workload identity
+credential and write this to a configured destination.
+
+The output generates the following artifacts:
+
+- `svid.pem`: the X509 SVID.
+- `svid.key`: the private key associated with the X509 SVID.
+- `bundle.pem`: the X509 bundle that contains the trust domain CAs.
+
+See [Workload Identity introduction](../../enroll-resources/workload-identity/introduction.mdx)
+for more information on Workload Identity functionality.
+
+```yaml
+# type specifies the type of the output. For the X509 Workload Identity output,
+# this will always be `workload-identity-x509`.
+type: workload-identity-x509
+(!docs/pages/includes/machine-id/workload-identity-selector-config.yaml!)
+(!docs/pages/includes/machine-id/common-output-config.yaml!)
+```
+
+### `workload-identity-jwt`
+
+The `workload-identity-jwt` output is used to issue a JWT workload identity
+credential and write this to a configured destination.
+
+The JWT workload identity credential is compatible with the [SPIFFE JWT SVID
+specification](https://github.com/spiffe/spiffe/blob/main/standards/JWT-SVID.md).
+
+The output generates the following artifacts:
+
+- `jwt_svid`: the JWT SVID.
+
+See [Workload Identity introduction](../../enroll-resources/workload-identity/introduction.mdx)
+for more information on Workload Identity functionality.
+
+```yaml
+# type specifies the type of the output. For the JWT Workload Identity output,
+# this will always be `workload-identity-jwt`.
+type: workload-identity-jwt
+# audiences specifies the values that should be included in the `aud` claim of
+# the JWT. Typically, this identifies the intended recipient of the JWT and
+# contains a single value.
+#
+# At least one audience value must be specified.
+audiences:
+ - example.com
+ - foo.example.com
+(!docs/pages/includes/machine-id/workload-identity-selector-config.yaml!)
+(!docs/pages/includes/machine-id/common-output-config.yaml!)
+```
+
### `spiffe-svid`
+
+The use of this service has been deprecated as part of the introduction of the
+new Workload Identity configuration experience. You can replace the use of this
+output with the new `workload-identity-x509` or `workload-identity-jwt` service.
+
+For further information, see [the new Workload Identity configuration experience
+and how to migrate](../workload-identity/configuration-resource-migration.mdx).
+
+
The `spiffe-svid` output is used to generate a SPIFFE X509 SVID and write this
to a configured destination.
@@ -367,8 +429,26 @@ Outputs, they may not necessarily generate artifacts. Typically, services
provide supporting functionality for machine to machine access, for example,
opening tunnels or providing APIs.
+### `workload-identity-api`
+
+The `workload-identity-api` services opens a listener that provides a local
+workload identity API, intended to serve workload identity credentials
+(e.g X509/JWT SPIFFE SVIDs) to workloads running on the same host.
+
+For more information about this, see the
+[Workload Identity API and Workload Attestation reference](../workload-identity/workload-identity-api-and-workload-attestation.mdx)
+
### `spiffe-workload-api`
+
+The use of this service has been deprecated as part of the introduction of the
+new Workload Identity configuration experience. You can replace the use of this
+service with the new `workload-identity-api` service.
+
+For further information, see [the new Workload Identity configuration experience
+and how to migrate](../workload-identity/configuration-resource-migration.mdx).
+
+
The `spiffe-workload-api` service opens a listener for a service that implements
the SPIFFE Workload API. This service is used to provide SPIFFE SVIDs to
workloads.
@@ -500,10 +580,10 @@ service, three additional special names can be used to aid configuration:
- `default`: `tbot` will return the default SVID for the workload.
- `ROOTCA`: `tbot` will return the trust bundle for the trust domain that the
- workload is a member of.
+workload is a member of.
- `ALL`: `tbot` will return the trust bundle for the trust domain that the
- workload is a member of, as well as the trust bundles of any trust domain
- that the trust domain is federated with.
+workload is a member of, as well as the trust bundles of any trust domain
+that the trust domain is federated with.
The following is an example Envoy configuration that sources a certificate
and trust bundle from the `spiffe-workload-api` service listening on
diff --git a/docs/pages/reference/workload-identity/attributes.mdx b/docs/pages/reference/workload-identity/attributes.mdx
new file mode 100644
index 0000000000000..8ef2587cc1df7
--- /dev/null
+++ b/docs/pages/reference/workload-identity/attributes.mdx
@@ -0,0 +1,255 @@
+---
+title: Workload Identity Attributes
+description: Information about the attributes that can be used in templating and rules in the WorkloadIdentity resource.
+---
+
+Attributes are features of an identity which you can use with the
+[WorkloadIdentity](./workload-identity-resource.mdx) resource to create rules
+and template values.
+
+These attributes come from a variety of sources, such as workload attestations
+performed by `tbot` or the attestation performed by the control plane when
+`tbot` joins.
+
+## Join attributes
+
+Join attributes are sourced from the join process that the Bot underwent. These
+typically allow you to identify the machine that the `tbot` agent is running on.
+
+### `join.meta`
+
+The `join.meta` attributes are not related to any specific join method, and
+instead typically provide information about the join token that was used to
+join.
+
+| Field | Description |
+|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `join.meta.join_token_name` | The name of the join token that was used to join. This field is omitted if the join token that was used to join was of the `token` method as in this case, the name of the join token is sensitive. Example: `my-gitlab-join-token` |
+| `join.meta.join_method` | The name of the join method that was used to join. Example: `gitlab` |
+
+### `join.azure`
+
+These attributes are present if the Bot joined using the Azure join method.
+
+| Field | Description |
+|-----------------------------|--------------------------------------------------------------------------------|
+| `join.azure.subscription` | The subscription ID of the Azure account that the joining entity is a part of. |
+| `join.azure.resource_group` | The resource group of the Azure account that the joining entity is a part of. |
+
+### `join.bitbucket`
+
+These attributes are present if the Bot joined using the BitBucket join method.
+
+They are mapped from the JWT issued by BitBucket, for which further
+documentation is available at https://support.atlassian.com/bitbucket-cloud/docs/integrate-pipelines-with-resource-servers-using-oidc/
+
+| Field | Description |
+|----------------------------------------------|-------------------------------------------------------------------------|
+| `join.bitbucket.sub` | The `sub` claim of the Bitbucket JWT that was used to join. |
+| `join.bitbucket.step_uuid` | The UUID of the pipeline step. |
+| `join.bitbucket.repository_uuid` | The UUID of the repository the pipeline step is running within. |
+| `join.bitbucket.pipeline_uuid` | The UUID of the pipeline the step is running within. |
+| `join.bitbucket.workspace_uuid` | The UUID of the workspace the pipeline belongs to. |
+| `join.bitbucket.deployment_environment_uuid` | The UUID of the deployment environment the pipeline is running against. |
+| `join.bitbucket.branch_name` | The name of the branch the pipeline is running against. |
+
+### `join.circleci`
+
+These attributes are present if the Bot joined using the CircleCI join method.
+
+They are mapped from the JWT issued by CircleCI, for which further documentation
+is available at https://circleci.com/docs/openid-connect-tokens/
+
+| Field | Description |
+|-----------------------------|------------------------------------------------------------|
+| `join.circleci.sub` | The `sub` claim of the CircleCI JWT that was used to join. |
+| `join.circleci.context_ids` | The UUIDs of the contexts used in the job. |
+| `join.circleci.project_id` | The UUID of the project in which the job is running.. |
+
+### `join.gcp`
+
+These attributes are present if the Bot joined using the Google Cloud Project
+(GCP) join method.
+
+They are mapped from the JWT issued by GCP, for which further documentation is
+available at https://cloud.google.com/compute/docs/instances/verifying-instance-identity#payload
+
+The attributes beneath `join.gcp.gce` are only present if the Bot is running on
+a Google Compute Engine (GCE) instance.
+
+| Field | Description |
+|-----------------------------|-----------------------------------------------------------------------------------|
+| `join.gcp.service_account` | The service account email of the service account that the instance is running as. |
+| `join.gcp.gce.name` | The name of the GCE instance that the joining entity is running on. |
+| `join.gcp.gce.zone` | The zone of the GCE instance that the joining entity is running on. |
+| `join.gcp.gce.zone.id` | The ID of the GCE instance that the joining entity is running on. |
+| `join.gcp.gce.zone.project` | The project ID of the GCP project that the instance is running within. |
+
+### `join.github`
+
+These attributes are present if the Bot joined using the GitHub join method.
+
+They are mapped from the JWT issued by GitHub, for which further documentation is
+available at https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect#understanding-the-oidc-token
+
+| Field | Description |
+|--------------------------------|------------------------------------------------------------------------------|
+| `join.github.sub` | The `sub` claim of the GitHub JWT that was used to join. |
+| `join.github.actor` | The username of the actor that initiated the workflow run. |
+| `join.github.environment` | The name of the environment that the workflow is running against, if any. |
+| `join.github.ref` | The ref that the workflow is running against.. |
+| `join.github.ref_type` | The type of ref that the workflow is running against. For example, `branch`. |
+| `join.github.repository` | The name of the repository that the workflow is running within. |
+| `join.github.repository_owner` | The name of the owner of the repository that the workflow is running within. |
+| `join.github.workflow` | The name of the workflow that is running. |
+| `join.github.event_name` | The name of the event that triggered the workflow run.. |
+| `join.github.sha` | The SHA of the commit that triggered the workflow run. |
+| `join.github.run_id` | The ID of this GitHub actions workflow run. |
+
+### `join.gitlab`
+
+These attributes are present if the Bot joined using the GitLab join method.
+
+They are mapped from the JWT issued by GitLab, for which further documentation is
+available at https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html#token-payload
+
+| Field | Description |
+|-------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
+| `join.gitlab.sub` | The `sub` claim of the GitLab JWT that was used to join. For example: `project_path:mygroup/my-project:ref_type:branch:ref:main` |
+| `join.gitlab.ref` | The ref that the pipeline is running against. For example: `main` |
+| `join.gitlab.ref_type` | The type of ref that the pipeline is running against. This is typically `branch` or `tag`. |
+| `join.gitlab.ref_protected` | Whether or not the ref that the pipeline is running against is protected. |
+| `join.gitlab.namespace_path` | The path of the namespace of the project that the pipeline is running within. |
+| `join.gitlab.project_path` | The full qualified path of the project that the pipeline is running within. For example: `mygroup/my-project` |
+| `join.gitlab.user_login` | The name of the user that triggered the pipeline run. |
+| `join.gitlab.user_email` | The email of the user that triggered the pipeline run. |
+| `join.gitlab.pipeline_id` | The ID of the pipeline. |
+| `join.gitlab.pipeline_source` | The source of the pipeline. For example: `push` or `web` |
+| `join.gitlab.environment` | The environment the pipeline is running against, if any. |
+| `join.gitlab.environment_protected` | Whether or not the pipeline is running against a protected environment. |
+| `join.gitlab.runner_id` | The ID of the runner that this pipeline is running on. |
+| `join.gitlab.runner_environment` | The type of runner that is processing the pipeline. Either `gitlab-hosted` or `self-hosted`. |
+| `join.gitlab.sha` | The SHA of the commit that triggered the pipeline run. |
+| `join.gitlab.ci_config_ref_uri` | The ref URI of the CI config configuring the pipeline. |
+| `join.gitlab.ci_config_sha` | The Git SHA of the CI config ref configuring the pipeline. |
+
+### `join.iam`
+
+These attributes are present if the Bot joined using the AWS IAM join method.
+
+| Field | Description |
+|--------------------|-----------------------------------------------------------------------------------------------------------------------------|
+| `join.iam.account` | The identifier of the account that the joining entity is a part of. For example: `123456789012`. |
+| `join.iam.arn` | The AWS ARN of the joining entity. For example: `arn:aws:sts::123456789012:assumed-role/my-role-name/my-role-session-name`. |
+
+### `join.kubernetes`
+
+These attributes are present if the Bot joined using the Kubernetes join method.
+
+The attributes under `join.kubernetes.pod` are only present if the bot is
+running in a Kubernetes cluster with Projected Service Account Token support.
+
+| Field | Description |
+|---------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `join.kubernetes.subject` | The fully qualified identifier of the entity based on the Kubernetes token. For a service account, this takes the form of `system:serviceaccount::`. |
+| `join.kubernetes.service_account.name` | The name of the service account that the joining entity is running as. |
+| `join.kubernetes.service_account.namespace` | The namespace of the service account that the joining entity is running as. |
+| `join.kubernetes.pod.name` | The name of the pod that the joining entity is running in. |
+
+### `join.spacelift`
+
+These attributes are present if the Bot joined using the Spacelift join method.
+
+They are mapped from the JWT issued by Spacelift, for which further documentation
+is available at https://docs.spacelift.io/integrations/cloud-providers/oidc/#standard-claims
+
+| Field | Description |
+|------------------------------|------------------------------------------------------------------------------------|
+| `join.spacelift.sub` | The `sub` claim of the Spacelift JWT that was used to join.. |
+| `join.spacelift.space_id` | The ID of the space in which the run is executing. |
+| `join.spacelift.caller_type` | The type of the caller that owns the run, either `stack` or `module`. |
+| `join.spacelift.caller_id` | The ID of the caller that generated the run. |
+| `join.spacelift.run_type` | The type of the run, either `PROPOSED`, `TRACKED`, `TASK`, `TESTING` or `DESTROY`. |
+| `join.spacelift.run_id` | The ID of the run. |
+| `join.spacelift.scope` | The configured scope of the token, either `read` or `write`. |
+
+### `join.terraform_cloud`
+
+These attributes are present if the Bot joined using the Terraform Cloud join
+method.
+
+They are mapped from the JWT issued by Terraform Cloud, for which further
+documentation is available at https://developer.hashicorp.com/terraform/enterprise/workspaces/dynamic-provider-credentials/workload-identity-tokens
+
+| Field | Description |
+|------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|
+| `join.terraform_cloud.sub` | The `sub` claim of the Terraform Cloud JWT that was used to join. |
+| `join.terraform_cloud.organization_name` | The name of the organization the project and workspace belong to. |
+| `join.terraform_cloud.project_name` | The name of the project the workspace belongs to. |
+| `join.terraform_cloud.workspace_name` | The name of the workspace that the plan/apply is running within. |
+| `join.terraform_cloud.full_workspace` | The fully qualified workspace path, including the organization and project name. For example: `organization::project::workspace:` |
+| `join.terraform_cloud.run_id` | The ID of the run that is being executed.. |
+| `join.terraform_cloud.run_phase` | The phase of the run that is being executed, either `plan` or `apply`. |
+
+### `join.tpm`
+
+These attributes are present if the Bot joined using the TPM join method.
+
+| Field | Description |
+|-----------------------------|------------------------------------------------------------------------------------------------------------------|
+| `join.tpm.ek_pub_hash` | The SHA256 hash of the PKIX formatted EK public key, encoded in hex. This effectively identifies a specific TPM. |
+| `join.tpm.ek_cert_serial` | The serial number of the EK certificate, if present. |
+| `join.tpm.ek_cert_verified` | Whether or not the EK certificate was verified against a certificate authority. |
+
+## Workload attributes
+
+Workload attributes are sourced from workload attestations performed by `tbot`
+when a workload requests an identity via the workload API. They may not be
+present depending on your configuration of `tbot`. See the
+[Workload Attestation reference](./workload-identity-api-and-workload-attestation.mdx) for more
+information.
+
+### `workload.unix`
+
+Attributes sourced from the Unix workload attestor.
+
+See the
+[Workload API and Workload Attestation reference](./workload-identity-api-and-workload-attestation.mdx#Unix)
+for more information.
+
+| Attribute | Description |
+|--------------------------|-----------------------------------------------|
+| `workload.unix.attested` | Whether the workload passed Unix attestation. |
+| `workload.unix.pid` | The PID of the workload process. |
+| `workload.unix.gid` | The primary user ID of the workload process. |
+| `workload.unix.uid` | The primary group ID of the workload process. |
+
+### `workload.kubernetes`
+
+Attributes sourced from the Kubernetes workload attestor.
+
+See the
+[Workload API and Workload Attestation reference](./workload-identity-api-and-workload-attestation.mdx#Kubernetes)
+for more information.
+
+| Attribute | Description |
+|---------------------------------------|-----------------------------------------------------|
+| `workload.kubernetes.attested` | Whether the workload passed Kubernetes attestation. |
+| `workload.kubernetes.namespace` | The namespace of the workload pod. |
+| `workload.kubernetes.pod_name` | The name of the workload pod. |
+| `workload.kubernetes.service_account` | The service account of the workload pod. |
+| `workload.kubernetes.pod_uid` | The UID of the workload pod. |
+| `workload.kubernetes.labels` | The labels of the workload pod. |
+
+## User attributes
+
+User attributes are sourced from the Bot or User that is requesting the
+issuance of the workload identity credential.
+
+| Attribute | Description |
+|------------------------|---------------------------------------------------|
+| `user.name` | The name of the user. |
+| `user.is_bot` | Whether the user is a bot. |
+| `user.bot_name` | If the user is a bot, the name of the bot. |
+| `user.bot_instance_id` | If the user is a bot, the instance ID of the bot. |
+| `user.labels` | Labels of the user. |
diff --git a/docs/pages/reference/workload-identity/configuration-resource-migration.mdx b/docs/pages/reference/workload-identity/configuration-resource-migration.mdx
new file mode 100644
index 0000000000000..295b629273588
--- /dev/null
+++ b/docs/pages/reference/workload-identity/configuration-resource-migration.mdx
@@ -0,0 +1,61 @@
+---
+title: WorkloadIdentity Configuration Resource migration
+description: Migrating to the new WorkloadIdentity resource configuration
+---
+
+The way that you configure Teleport Workload Identity is changing. If you are
+currently using Workload Identity, you will need to migrate to the new
+configuration experience by V19.0.0 when support for the old configuration
+will be removed.
+
+## Overview
+
+Previously, the details of the credentials (e.g X509 SVID/JWT SVID) you wished
+to issue were defined directly within `tbot`. Controlling what credentials were
+allowed to be issued was done by configuring the `spec.allow.spiffe` field of
+the role resource.
+
+The new configuration experience introduces a new resource type, `WorkloadIdentity`,
+which allows you to define the structure of an identity credential that can be
+issued to workloads and the rules around what workloads it can be issued to.
+
+This provides the following benefits over the previous configuration experience:
+
+- Centralized control of the structure of the identity credential, which
+ simplifies the configuration of `tbot`.
+- The ability to specify rules based on the attributes of the workload, such as
+ the name of the Kubernetes namespace or service account, that is more fine
+ grained than the previous configuration.
+- The ability to use templating to dynamically generate elements of the identity
+ credential - allowing a single WorkloadIdentity resource to be used to serve
+ multiple workloads.
+
+You can read the full details of the new WorkloadIdentity resource in the
+[WorkloadIdentity Resource](./workload-identity-resource.mdx) reference.
+
+## Migrating `tbot`
+
+The following CLI commands have been replaced:
+
+- `tbot start spiffe-svid` is now `tbot start workload-identity-x509`.
+
+The following new additional CLI commands have been introduced:
+
+- `tbot start workload-identity-api` to start a listener for the Workload
+ Identity API.
+- `tbot start workload-identity-jwt` to issue a JWT SVID.
+
+You can read more about the new CLI commands in the
+[`tbot` CLI reference](../cli/tbot.mdx).
+
+The following service types have been replaced:
+
+- `spiffe-workload-api` is now `workload-identity-api`.
+- `spiffe-x509-svid` is now `workload-identity-x509`.
+
+The following new additional service types have been introduced:
+
+- `workload-identity-jwt` to issue JWT SVIDs.
+
+You can read more about the new service types in the
+[`tbot` configuration reference](../machine-id/configuration.mdx).
\ No newline at end of file
diff --git a/docs/pages/reference/workload-identity/workload-identity-api-and-workload-attestation.mdx b/docs/pages/reference/workload-identity/workload-identity-api-and-workload-attestation.mdx
new file mode 100644
index 0000000000000..7c6a23ba2fef8
--- /dev/null
+++ b/docs/pages/reference/workload-identity/workload-identity-api-and-workload-attestation.mdx
@@ -0,0 +1,418 @@
+---
+title: Workload Identity API & Workload Attestation
+description: Information about the `tbot` Workload Identity API service and Workload Attestation functionality
+---
+
+The Workload Identity API service (`workload-identity-api`) is a configurable
+`tbot` service that allows workloads to request JWT and X509 workload identity
+credentials on-the-fly.
+
+It's a more secure alternative to writing credentials to disk and supports
+performing a process known as workload attestation to determine attributes of
+the workload before issuing credentials.
+
+The Workload Identity API is compatible with two standards:
+
+- [SPIFFE Workload API](https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE_Workload_API.md)
+- [Envoy SDS](https://www.envoyproxy.io/docs/envoy/latest/configuration/security/secret)
+
+In addition to issuing credentials to workloads, the Workload Identity API can
+also provide the trust bundle necessary for workloads to validate the
+credentials of other workloads.
+
+## Configuration
+
+```yaml
+# type specifies the type of the service. For the Workload Identity API service,
+# this will always be `workload-identity-api`.
+type: workload-identity-api
+# listen specifies the address that the service should listen on.
+#
+# Two types of listener are supported:
+# - TCP: `tcp://:`
+# - Unix socket: `unix:///`
+listen: unix:///opt/machine-id/workload.sock
+# attestors allows Workload Attestation to be configured for this Workload
+# API.
+attestors:
+ # kubernetes is configuration for the Kubernetes Workload Attestor. See
+ # the Kubernetes Workload Attestor section for more information.
+ kubernetes:
+ # enabled specifies whether the Kubernetes Workload Attestor should be
+ # enabled. If unspecified, this defaults to false.
+ enabled: true
+ # kubelet holds configuration relevant to the Kubernetes Workload Attestors
+ # interaction with the Kubelet API.
+ kubelet:
+ # read_only_port is the port on which the Kubelet API is exposed for
+ # read-only operations. Since Kubernetes 1.16, the read-only port is
+ # typically disabled by default and secure_port should be used instead.
+ read_only_port: 10255
+ # secure_port is the port on which the attestor should connect to the
+ # Kubelet secure API. If unspecified, this defaults to `10250`. This is
+ # mutually exclusive with ReadOnlyPort.
+ secure_port: 10250
+ # token_path is the path to the token file that the Kubelet API client
+ # should use to authenticate with the Kubelet API. If unspecified, this
+ # defaults to `/var/run/secrets/kubernetes.io/serviceaccount/token`.
+ token_path: "/var/run/secrets/kubernetes.io/serviceaccount/token"
+ # ca_path is the path to the CA file that the Kubelet API client should
+ # use to validate the Kubelet API server's certificate. If unspecified,
+ # this defaults to `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`.
+ ca_path: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
+ # skip_verify is used to disable verification of the Kubelet API server's
+ # certificate. If unspecified, this defaults to false.
+ #
+ # If specified, the value specified in ca_path is ignored.
+ #
+ # This is useful in cases where the Kubelet API server has not been issued
+ # with a certificate signed by the Kubernetes cluster's CA. This is fairly
+ # common with a number of Kubernetes distributions.
+ skip_verify: true
+ # anonymous is used to disable authentication with the Kubelet API. If
+ # unspecified, this defaults to false. If set, the token_path field is
+ # ignored.
+ anonymous: false
+(!docs/pages/includes/machine-id/workload-identity-selector-config.yaml!)
+```
+
+## SPIFFE Workload API
+
+The Workload Identity API implements the SPIFFE Workload API, a standardized
+API for workloads to request workload identity credentials and trust bundles.
+
+Via this API, both JWT and X509 workload identity credentials can be issued.
+
+## Workload Attestation
+
+Workload Attestation is the process completed by `tbot` to assert the identity
+of a workload that has connected to the Workload API and requested credentials.
+
+Workload Attestors are the individual components that perform this attestation.
+They use the process ID of the workload to gather information about the workload
+from platform-specific APIs. For example, the Kubernetes Workload Attestor
+queries the local Kubelet API to determine which Kubernetes pod the process
+belongs to.
+
+The result of this attestation process is known as attestation metadata. This
+attestation metadata can be included in the rules or templates you configure as
+part of a WorkloadIdentity resource.
+
+### Unix
+
+The Unix Workload Attestor is the most basic attestor and allows you to restrict
+the issuance of workload identities to specific Unix processes based on a range
+of criteria.
+
+#### Support for non-standard procfs mounting
+
+To resolve information about a process from the PID, the Unix Workload Attestor
+reads information from the procfs filesystem. By default, it expects procfs to
+be mounted at `/proc`.
+
+If procfs is mounted at a different location, you must configure the Unix
+Workload Attestor to read from that alternative location by setting the
+`HOST_PROC` environment variable.
+
+This is a sensitive configuration option, and you should ensure that it is
+set correctly or not set at all. If misconfigured, an attacker could provide
+falsified information about processes, and this could lead to the issuance of
+SVIDs to unauthorized workloads.
+
+### Kubernetes
+
+The Kubernetes Workload Attestor allows you to restrict the issuance of workload
+identities to specific Kubernetes workloads based on a range of criteria.
+
+It works by first determining the pod ID for a given process ID and then by
+querying the local kubelet API for details about that pod.
+
+#### Deployment Guidance
+
+To use Kubernetes Workload Attestation, `tbot` must be deployed as a daemon
+set. This is because the unix domain socket can only be accessed by pods on the
+same node as the agent. Additionally, the daemon set must have the `hostPID`
+property set to `true` to allow the agent to access information about
+processes within other containers.
+
+The daemon set must also have a service account assigned that allows it to query
+the Kubelet API. This is an example role with the required RBAC:
+
+```yaml
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: tbot
+rules:
+ - resources: ["pods","nodes","nodes/proxy"]
+ apiGroups: [""]
+ verbs: ["get"]
+```
+
+Mapping the Workload API Unix domain socket into the containers of workloads
+can be done in two ways:
+
+- Directly configuring a hostPath volume for the `tbot` daemonset and workloads
+which will need to connect to it.
+- Using [spiffe-csi-driver](https://github.com/spiffe/spiffe-csi).
+
+Example manifests for required Kubernetes resources:
+
+```yaml
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: tbot
+rules:
+ - resources: ["pods","nodes","nodes/proxy"]
+ apiGroups: [""]
+ verbs: ["get"]
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: tbot
+subjects:
+ - kind: ServiceAccount
+ name: tbot
+ namespace: default
+roleRef:
+ kind: ClusterRole
+ name: tbot
+ apiGroup: rbac.authorization.k8s.io
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: tbot
+ namespace: default
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: tbot-config
+ namespace: default
+data:
+ tbot.yaml: |
+ version: v2
+ onboarding:
+ join_method: kubernetes
+ # replace with the name of a join token you have created.
+ token: example-token
+ storage:
+ type: memory
+ # ensure this is configured to the address of your Teleport Proxy Service.
+ proxy_server: example.teleport.sh:443
+ services:
+ - type: workload-identity-api
+ listen: unix:///run/tbot/sockets/workload.sock
+ attestor:
+ kubernetes:
+ enabled: true
+ kubelet:
+ # skip verification of the Kubelet API certificate as this is not
+ # usually issued by the cluster CA.
+ skip_verify: true
+ selector:
+ name: example-workload-identity
+---
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+ name: tbot
+spec:
+ selector:
+ matchLabels:
+ app: tbot
+ template:
+ metadata:
+ labels:
+ app: tbot
+ spec:
+ securityContext:
+ runAsUser: 0
+ runAsGroup: 0
+ hostPID: true
+ containers:
+ - name: tbot
+ image: public.ecr.aws/gravitational/tbot-distroless:(=teleport.version=)
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ privileged: true
+ args:
+ - start
+ - -c
+ - /config/tbot.yaml
+ - --log-format
+ - json
+ volumeMounts:
+ - mountPath: /config
+ name: config
+ - mountPath: /var/run/secrets/tokens
+ name: join-sa-token
+ - name: tbot-sockets
+ mountPath: /run/tbot/sockets
+ readOnly: false
+ env:
+ - name: TELEPORT_NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.nodeName
+ - name: KUBERNETES_TOKEN_PATH
+ value: /var/run/secrets/tokens/join-sa-token
+ serviceAccountName: tbot
+ volumes:
+ - name: tbot-sockets
+ hostPath:
+ path: /run/tbot/sockets
+ type: DirectoryOrCreate
+ - name: config
+ configMap:
+ name: tbot-config
+ - name: join-sa-token
+ projected:
+ sources:
+ - serviceAccountToken:
+ path: join-sa-token
+ # 600 seconds is the minimum that Kubernetes supports. We
+ # recommend this value is used.
+ expirationSeconds: 600
+ # `example.teleport.sh` must be replaced with the name of
+ # your Teleport cluster.
+ audience: example.teleport.sh
+```
+
+## Envoy SDS
+
+The `workload-identity-api` service endpoint also implements the Envoy SDS API.
+This allows it to act as a source of certificates and certificate authorities
+for the Envoy proxy.
+
+As a forward proxy, Envoy can be used to attach an X.509 SVID to an outgoing
+connection from a workload that is not SPIFFE-enabled.
+
+As a reverse proxy, Envoy can be used to terminate mTLS connections from
+SPIFFE-enabled clients. Envoy can validate that the client has presented a valid
+X.509 SVID and perform enforcement of authorization policies based on the SPIFFE
+ID contained within the SVID.
+
+When acting as a reverse proxy for certain protocols, Envoy can be configured
+to attach a header indicating the identity of the client to a request before
+forwarding it to the service. This can then be used by the service to make
+authorization decisions based on the client's identity.
+
+When configuring Envoy to use the SDS API exposed by the `workload-identity-api`
+service, three additional special names can be used to aid configuration:
+
+- `default`: `tbot` will return the default SVID for the workload.
+- `ROOTCA`: `tbot` will return the trust bundle for the trust domain that the
+workload is a member of.
+- `ALL`: `tbot` will return the trust bundle for the trust domain that the
+workload is a member of, as well as the trust bundles of any trust domain
+that the trust domain is federated with.
+
+The following is an example Envoy configuration that sources a certificate
+and trust bundle from the `workload-identity-api` service listening on
+`unix:///opt/machine-id/workload.sock`. It requires that a connecting client
+presents a valid SPIFFE SVID and forwards this information to the backend
+service in the `x-forwarded-client-cert` header.
+
+```yaml
+node:
+ id: "my-envoy-proxy"
+ cluster: "my-cluster"
+static_resources:
+ listeners:
+ - name: test_listener
+ enable_reuse_port: false
+ address:
+ socket_address:
+ address: 0.0.0.0
+ port_value: 8080
+ filter_chains:
+ - filters:
+ - name: envoy.filters.network.http_connection_manager
+ typed_config:
+ "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
+ common_http_protocol_options:
+ idle_timeout: 1s
+ forward_client_cert_details: sanitize_set
+ set_current_client_cert_details:
+ uri: true
+ stat_prefix: ingress_http
+ route_config:
+ name: local_route
+ virtual_hosts:
+ - name: my_service
+ domains: ["*"]
+ routes:
+ - match:
+ prefix: "/"
+ route:
+ cluster: my_service
+ http_filters:
+ - name: envoy.filters.http.router
+ typed_config:
+ "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
+ transport_socket:
+ name: envoy.transport_sockets.tls
+ typed_config:
+ "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
+ common_tls_context:
+ # configure the certificate that the reverse proxy should present.
+ tls_certificate_sds_secret_configs:
+ # `name` can be replaced with the desired SPIFFE ID if multiple
+ # SVIDs are available.
+ - name: "default"
+ sds_config:
+ resource_api_version: V3
+ api_config_source:
+ api_type: GRPC
+ transport_api_version: V3
+ grpc_services:
+ envoy_grpc:
+ cluster_name: tbot_agent
+ # combined validation context "melds" two validation contexts
+ # together. This is handy for extending the validation context
+ # from the SDS source.
+ combined_validation_context:
+ default_validation_context:
+ # You can use match_typed_subject_alt_names to configure
+ # rules that only allow connections from specific SPIFFE IDs.
+ match_typed_subject_alt_names: []
+ validation_context_sds_secret_config:
+ name: "ALL" # This can also be replaced with the trust domain name
+ sds_config:
+ resource_api_version: V3
+ api_config_source:
+ api_type: GRPC
+ transport_api_version: V3
+ grpc_services:
+ envoy_grpc:
+ cluster_name: tbot_agent
+ clusters:
+ # my_service is the example service that Envoy will forward traffic to.
+ - name: my_service
+ type: strict_dns
+ load_assignment:
+ cluster_name: my_service
+ endpoints:
+ - lb_endpoints:
+ - endpoint:
+ address:
+ socket_address:
+ address: 127.0.0.1
+ port_value: 8090
+ - name: tbot_agent
+ http2_protocol_options: {}
+ load_assignment:
+ cluster_name: tbot_agent
+ endpoints:
+ - lb_endpoints:
+ - endpoint:
+ address:
+ pipe:
+ # Configure the path to the socket that `tbot` is
+ # listening on.
+ path: /opt/machine-id/workload.sock
+```
\ No newline at end of file
diff --git a/docs/pages/reference/workload-identity/workload-identity-resource.mdx b/docs/pages/reference/workload-identity/workload-identity-resource.mdx
new file mode 100644
index 0000000000000..b47662a92ccac
--- /dev/null
+++ b/docs/pages/reference/workload-identity/workload-identity-resource.mdx
@@ -0,0 +1,276 @@
+---
+title: WorkloadIdentity Resource
+description: Information about the WorkloadIdentity resource
+---
+
+The WorkloadIdentity resource is used to define the structure of an identity
+credentials that can be issued to workloads and the rules around what workloads
+it can be issued to.
+
+It supports templating using attributes of the workload, such as the name of the
+Kubernetes namespace or service account, which allows the WorkloadIdentity
+resource to be used in a generic way for multiple distinct workloads.
+
+## Configuration
+
+```yaml
+kind: workload_identity
+version: v1
+metadata:
+ # The name of the WorkloadIdentity resource. This can be used to directly
+ # request the issuance of a credential for this identity.
+ name: my-workload
+ # Key-value labels that can be used to group and filter WorkloadIdentity
+ # resources when requesting issuance.
+ labels:
+ example: foo
+spec:
+ # Configuration relevant to issuing SPIFFE-compatible workload identity
+ # credentials.
+ spiffe:
+ # The path element of the SPIFFE ID that will be included in credentials
+ # issued for this identity.
+ #
+ # This must be prefixed with a forward-slash (`/`).
+ #
+ # Required. Supports templating.
+ id: /foo/bar/{{ join.kubernetes.pod.name }}/{{ join.kubernetes.service_account.name }}
+ # The hint field allows a string to be passed to workloads along with a
+ # credential issued for this identity. This can be used to help workloads
+ # differentiate between multiple identities that they may have
+ # (e.g `internal` vs `external`).
+ #
+ # Optional. Supports templating.
+ hint: An example hint
+ # Grouped configuration for X.509 credentials.
+ x509:
+ # The DNS Subject Alternative Names (SANs) that should be included in any
+ # X509-SVID issued using this WorkloadIdentity.
+ #
+ # Each individual element of this list supports templating and after
+ # templating must be a valid DNS name.
+ #
+ # Optional, if not provided then no DNS SANs will be included in the X.509
+ # credential.
+ dns_sans:
+ - example.com
+ # Controls the subject distinguished name of an X509 workload identity
+ # credential issued using this identity. If unspecified, a blank subject
+ # will be used.
+ #
+ # In most circumstances, it is recommended to prefer relying on the
+ # SPIFFE ID encoded in the URI SAN. However, the Subject DN may be needed
+ # to support legacy systems designed for X.509 and not SPIFFE/WIMSE.
+ subject_template:
+ # The common name (CN - 2.5.4.3) of the subject distinguished name.
+ # Supports templating. If not provided, the common name will be omitted.
+ common_name: my-common-name
+ # The organization (O - 2.5.4.10) of the subject distinguished name.
+ # Supports templating. If not provided, the organization will be omitted.
+ organization: my-organization
+ # The organizational unit (OU - 2.5.4.11) of the subject distinguished
+ # name. Supports templating. If not provided, the organizational unit
+ # will be omitted.
+ organizational_unit: my-organizational-unit
+ # The rules control when this WorkloadIdentity can be used to issue a
+ # credential.
+ rules:
+ # When allow rules are specified, at least one must pass in order for the
+ # WorkloadIdentity to be used to issue a credential. This effectively
+ # creates an OR relationship between the rules.
+ #
+ # If no allow rules are specified, then the WorkloadIdentity can be issued
+ # to any workload with the correct workload_identity_labels within their
+ # role set.
+ allow:
+ # Each rule consists of a set of conditions. All conditions must pass in
+ # order for the rule to be considered a match. This effectively creates an
+ # AND relationship between the conditions.
+ #
+ # A more detailed explanation of the available operators can be found under
+ # the "Rules" section of this page.
+ - conditions:
+ - attribute: join.kubernetes.pod.name
+ eq:
+ value: my-pod
+ - attribute: join.kubernetes.namespace
+ not_eq:
+ value: kube-system
+```
+
+## Templating
+
+The WorkloadIdentity resource supports templating in certain fields, this allows
+you to customize elements of the workload identity credential issued to
+workloads with attested attributes.
+
+For example, you can use templating to insert the name of the Kubernetes
+namespace and service account into the SPIFFE ID of the workload identity
+credential:
+
+```yaml
+kind: workload_identity
+version: v1
+metadata:
+ name: my-kubernetes-workload
+spec:
+ spiffe:
+ id: /k8s/{{ workload.kubernetes.namespace }}/{{ workload.kubernetes.service_account }}
+```
+
+Would result in a SPIFFE ID of `spiffe://example.teleport.sh/k8s/default/foo`
+for a workload running in the `default` namespace with the service account `foo`.
+
+When an attribute is specified in a template, this value must be present in the
+attributes of the workload in order for the workload identity credential to be
+issued. For example, if `workload.kubernetes.namespace` is used in a template,
+then a workload that is not running in Kubernetes would not be issued a
+credential.
+
+The following fields within the WorkloadIdentity resource support templating:
+
+- `spec.spiffe.id`
+- `spec.spiffe.hint`
+- `spec.spiffe.x509.dns_sans`
+- `spec.spiffe.x509.subject_template.common_name`
+- `spec.spiffe.x509.subject_template.organization`
+- `spec.spiffe.x509.subject_template.organizational_unit`
+
+You can find a full list of the supported attributes on the
+[Attributes reference](./attributes.mdx) page.
+
+## Rules
+
+By default, a WorkloadIdentity resource can be used to issue a credential by any
+User or Bot that holds a role that with `workload_identity_labels` that match
+the labels on the WorkloadIdentity resource.
+
+However, you can further restrict the issuance of credentials based on the
+attributes of the workload using the rules mechanism.
+
+Each rule consists of a set of conditions, and all conditions within that rule
+must pass in order for the rule to be considered a pass. If you specify
+multiple rules, then at least one rule must pass in order for the
+WorkloadIdentity to be allowed to be issued.
+
+For example, to restrict the issuance of a credential to only workloads running
+in the `default` namespace with the service account `foo`:
+
+```yaml
+kind: workload_identity
+version: v1
+metadata:
+ name: rules-example
+spec:
+ spiffe:
+ id: /my-awesome-workload
+ rules:
+ allow:
+ - conditions:
+ - attribute: workload.kubernetes.namespace
+ eq:
+ value: default
+ - attribute: workload.kubernetes.service_account
+ eq:
+ value: foo
+```
+
+### Operators
+
+#### `eq`
+
+`eq` (equals) checks that the specified attribute equals the specified value:
+
+```yaml
+kind: workload_identity
+version: v1
+metadata:
+ name: rules-example
+spec:
+ spiffe:
+ id: /my-awesome-workload
+ rules:
+ allow:
+ - conditions:
+ - attribute: workload.kubernetes.namespace
+ eq:
+ value: default
+```
+
+#### `not_eq`
+
+`not_eq` (not equals) checks that the specified attribute does not equal the
+specified value:
+
+```yaml
+kind: workload_identity
+version: v1
+metadata:
+ name: rules-example
+spec:
+ spiffe:
+ id: /my-awesome-workload
+ rules:
+ allow:
+ - conditions:
+ - attribute: workload.kubernetes.namespace
+ not_eq:
+ value: default
+```
+
+#### `in`
+
+`in` (includes) checks that the specified attribute equals one of the specified
+values:
+
+```yaml
+kind: workload_identity
+version: v1
+metadata:
+ name: rules-example
+spec:
+ spiffe:
+ id: /my-awesome-workload
+ rules:
+ allow:
+ - conditions:
+ - attribute: workload.kubernetes.namespace
+ in:
+ values: [default, kube-system]
+```
+
+#### `not_in`
+
+`not_in` (not includes) checks that the specified attribute does not equal any
+of the specified values:
+
+```yaml
+kind: workload_identity
+version: v1
+metadata:
+ name: rules-example
+spec:
+ spiffe:
+ id: /my-awesome-workload
+ rules:
+ allow:
+ - conditions:
+ - attribute: workload.kubernetes.namespace
+ not_in:
+ values: [foo, bar]
+```
+
+### Casting
+
+When comparing attributes which are not a string (e.g a boolean or number),
+the value in the attribute will be transferred to a string representation.
+
+## Infrastructure as Code
+
+In addition to the YAML representation which can be managed with `tctl`, the
+WorkloadIdentity resource can also be managed using Infrastructure as Code
+tools.
+
+For further information see:
+
+- [Terraform provider reference: teleport_workload_identity](../terraform-provider/resources/workload_identity.mdx)
diff --git a/docs/pages/reference/workload-identity/workload-identity.mdx b/docs/pages/reference/workload-identity/workload-identity.mdx
new file mode 100644
index 0000000000000..8c758da15bd17
--- /dev/null
+++ b/docs/pages/reference/workload-identity/workload-identity.mdx
@@ -0,0 +1,6 @@
+---
+title: Workload Identity References
+description: Configuration and CLI reference for Teleport Workload Identity
+---
+
+(!toc!)