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!)