diff --git a/docs/pages/enroll-resources/workload-identity/aws-roles-anywhere.mdx b/docs/pages/enroll-resources/workload-identity/aws-roles-anywhere.mdx index f6b6970a96691..3d3d3e49b4113 100644 --- a/docs/pages/enroll-resources/workload-identity/aws-roles-anywhere.mdx +++ b/docs/pages/enroll-resources/workload-identity/aws-roles-anywhere.mdx @@ -1,6 +1,6 @@ --- -title: Configuring Workload ID and AWS Roles Anywhere -description: Configuring AWS to accept Workload ID certificates as authentication using AWS Roles Anywhere +title: Configuring Workload Identity and AWS Roles Anywhere +description: Configuring AWS to accept Workload Identity certificates as authentication using AWS Roles Anywhere --- @@ -27,8 +27,9 @@ AWS APIs in a few ways: - Requests to AWS are not proxied through the Teleport Proxy Service, meaning reduced latency but also less visibility, as these requests will not be recorded in Teleport's audit log. -- Workload ID works with any AWS client, including the command-line tool but also - their SDKs +- Workload Identity works with any AWS client, including the command-line tool + but also + their SDKs. - Using the Teleport Application Service to access AWS does not work with Machine ID and therefore cannot be used when a machine needs to authenticate with AWS. @@ -59,7 +60,7 @@ If you have already deployed Teleport Workload Identity, then you will already have a SPIFFE ID structure in place. If you have not, then you will need to decide on a structure for your SPIFFE IDs. -If you are only using Teleport Workload ID with AWS Roles Anywhere, you way +If you are only using Teleport Workload Identity with AWS Roles Anywhere, you may structure your SPIFFE IDs so that they explicitly specify the AWS role they are allowed to assume. However, it often makes more sense to name the workload or person that will use the SPIFFE ID. See the @@ -168,6 +169,8 @@ Click "Create profile". Now we need to configure Teleport to allow a X.509 certificate to be issued containing the SPIFFE ID we have chosen. +Create `role.yaml` with the following content: + ```yaml kind: role version: v6 @@ -184,6 +187,12 @@ Replace: - `my-workload-roles-anywhere` with a descriptive name for the role. - `/my-workload` with the path part of the SPIFFE ID you have chosen. +Apply this role to your Teleport cluster using `tctl`: + +```code +$ tctl create -f role.yaml +``` + If you intend this SPIFFE ID to be issued by a human, you now need to assign this role to their user: @@ -199,7 +208,7 @@ this role to the bot: $ tctl bots update my-bot --add-roles my-workload-roles-anywhere ``` -## Step 3/4. Issue Workload ID certificates +## Step 3/4. Issue Workload Identity certificates ### For machines using `tbot` diff --git a/docs/pages/enroll-resources/workload-identity/gcp-workload-identity-federation-jwt.mdx b/docs/pages/enroll-resources/workload-identity/gcp-workload-identity-federation-jwt.mdx new file mode 100644 index 0000000000000..7feec924773a6 --- /dev/null +++ b/docs/pages/enroll-resources/workload-identity/gcp-workload-identity-federation-jwt.mdx @@ -0,0 +1,388 @@ +--- +title: Configuring Workload Identity and GCP Workload Identity Federation with JWTs +description: Configuring GCP to accept Workload Identity JWTs as authentication using Workload Identity Federation +--- + + +Teleport Workload Identity is currently in Preview. This means that some +features may be missing. We're actively looking for design partners to help us +shape the future of Workload Identity and would love to +[hear your feedback](mailto:product@goteleport.com). + + +Teleport Workload Identity issues flexible short-lived identities in JWT format. +GCP Workload Identity Federation allows you to use these JWTs to authenticate to +GCP services. + +This can be useful in cases where a machine needs to securely authenticate with +GCP services without the use of a long-lived credential. This is because the +machine can authenticate with Teleport without using any shared secrets by +using one of our delegated join methods. + +In this guide, we'll configure Teleport Workload Identity and GCP to allow our +workload to authenticate to the GCP Cloud Storage API and upload content to a +bucket. + +## How it works + +This implementation differs from using the Teleport Application Service to protect +GCP APIs in a few ways: + +- Requests to GCP are not proxied through the Teleport Proxy Service, meaning + reduced latency but also less visibility, as these requests will not be + recorded in Teleport's audit log. +- Workload Identity works with any GCP client, including the command-line tool + but also their SDKs. +- Using the Teleport Application Service to access GCP does not work with Machine ID + and therefore cannot be used when a machine needs to authenticate with AWS. + +## Prerequisites + +(!docs/pages/includes/edition-prereqs-tabs.mdx!) + +- (!docs/pages/includes/tctl.mdx!) +- `tbot` must already be installed and configured on the host where the +workloads which need to access Teleport Workload Identity will run. For more +information, see the [deployment guides](../machine-id/deployment.mdx). + +### Deciding on a SPIFFE ID structure + +Within Teleport Workload Identity, all identities are represented using a +SPIFFE ID. This is a URI that uniquely identifies the entity that the identity +represents. The scheme is always `spiffe://`, and the host will be the name of +your Teleport cluster. The structure of the path of this URI is up to you. + +For the purposes of this guide, we will be granting access to GCP to the +`spiffe://example.teleport.sh/svc/example-service` SPIFFE ID. + +If you have already deployed Teleport Workload Identity, then you will already +have a SPIFFE ID structure in place. If you have not, then you will need to +decide on a structure for your SPIFFE IDs. + +If you are only using Teleport Workload Identity with GCP Workload Identity +Federation, you may structure your SPIFFE IDs so that they explicitly specify +the GCP service account they are allowed to assume. However, it often makes more +sense to name the workload or person that will use the SPIFFE ID. See the +[best practices guide](./best-practices.mdx) for further advice. + +## Step 1/4. Configure GCP + +Configuring GCP Workload Identity Federation for the first time involves a few +steps. Some of these may not be necessary if you have previously configured GCP +Workload Identity Federation for your Teleport cluster. + +### Create a Workload Identity Pool and OIDC Provider + +First, you'll need to create a workload identity pool and an OIDC provider +within this pool in GCP. A workload identity pool is an entity for managing +how external workload identities are represented within GCP. + +The provider configures how the external identities should authenticate to the +pool. Since Teleport Workload Identity issues OIDC compatible JWT-SVIDs, you'll +use the OIDC provider type. + +When configuring the pool, you need to choose a name to identify it. This name +should uniquely identify the source of the workload identities. It may make +sense to name it after your Teleport cluster. In this example, it will be called +`workload-id-pool`. + +When configuring the provider, you need to specify the issuer URI. This will be +the public address of your Teleport Proxy Service with the path +`/workload-identity` appended. Your Teleport Proxy Service must be accessible +by GCP in order for OIDC federation to work. + +You'll also specify an "attribute mapping". This determines how GCP will map the +identity within the JWT to a principal in GCP. Since we're using SVIDs, we'll +map the `sub` claim within the JWT to the `google.subject` attribute to +be able to use the workload's SPIFFE ID to make authorization decisions in GCP. + + + + +```hcl +data "google_project" "project" {} + +resource "google_iam_workload_identity_pool" "workload_identity" { + workload_identity_pool_id = "workload-id-pool" +} + +resource "google_iam_workload_identity_pool_provider" "workload_identity_oidc" { + workload_identity_pool_id = google_iam_workload_identity_pool.workload_identity.workload_identity_pool_id + workload_identity_pool_provider_id = "workload-id-oidc" + attribute_mapping = { + // Maps the `sub` claim within the JWT to the `google.subject` attribute. + // This will allow it to be used to make Authz decisions in GCP. + "google.subject" = "assertion.sub" + } + oidc { + // Replace example.teleport.sh with the hostname of your Proxy Service's + // public address. + issuer_uri = "https://example.teleport.sh/workload-identity" + } +} +``` + + + +Use the `gcloud` CLI to create a workload identity pool: + +```code +# Replace "workload-id-pool" with a meaningful, unique name. +$ gcloud iam workload-identity-pools create workload-id-pool \ + --location="global" +``` + +Use the `gcloud` CLI to create a workload identity provider: + +```code +# Replace "workload-id-pool" with the name of the pool you just created and +# "workload-id-oidc" with a meaningful, unique name. +$ gcloud iam workload-identity-pools providers create-oidc workload-id-oidc \ + --location="global" \ + # This should match the name of the pool you just created. + --workload-identity-pool="workload-id-pool" \ + # Replace example.teleport.sh with the hostname of your Proxy Service's + # public address. + --issuer-uri="https://example.teleport.sh/workload-identity" \ + # Maps the `sub` claim within the JWT to the `google.subject` attribute. + # This will allow it to be used to make Authz decisions in GCP. + --attribute-mapping="google.subject=assertion.sub" +``` + + + + + +### Create a storage bucket and RBAC + +For the purposes of this guide, we'll be granting the workload access to a +GCP storage bucket. You can substitute this step to grant access to a different +service within GCP of your choice. + +We'll be granting our workload identity direct access to the resource without +the workload assuming a service account. + +To do this, we use the principal that is generated by the workload identity +federation pool based on the attribute mapping that we have already configured. +This principal can be used directly in IAM policies to grant privileges to a +workload identity. The principal contains the GCP project number, the name of +the workload identity pool and the SPIFFE ID. It takes the following format: + +`principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_NAME/subject/$SPIFFE_ID` + +It is also possible to grant a workload the ability to assume a service account. +This is not covered within this guide, but, can be useful in scenarios where you +already have a service account created with the necessary privileges and now +wish to allow the workload to use this without the use of a long-lived shared +secret. + + + + +```hcl +resource "google_storage_bucket" "demo" { + // Replace with a meaningful, unique name. + name = "example" + location = "EU" + force_destroy = true + + uniform_bucket_level_access = true +} + +locals { + // Replace with the SPIFFE ID of the workload that will access the bucket. + allow_spiffe_id = "spiffe://example.teleport.sh/svc/example-service" +} + +resource "google_storage_bucket_iam_binding" "binding" { + bucket = google_storage_bucket.demo.name + role = "roles/storage.admin" + members = [ + "principal://iam.googleapis.com/projects/${data.google_project.project.number}/locations/global/workloadIdentityPools/${google_iam_workload_identity_pool.leaf_cluster.workload_identity_pool_id}/subject/${local.allow_spiffe_id}", + ] +} +``` + + + + +Create a storage bucket using the `gcloud` CLI: + +```code +# Replace "example" with a meaningful, unique name. +$ gcloud storage buckets create gs://example \ + --location=EU \ + --uniform-bucket-level-access +``` + +Use the `gcloud` CLI to grant our workload access to the bucket: + +```code +$ ROLE="roles/storage.admin" +# Replace PROJECT_NUMBER with your GCP project number. +$ PROJECT_NUMBER="123456789000" +# Replace POOL_ID with the ID of the Workload Identity Pool you created. +$ POOL_ID="workload-id-pool" +# Replace SPIFFE_ID with the SPIFFE ID of the workload that will access the bucket. +$ SPIFFE_ID="spiffe://example.teleport.sh/svc/example-service" +$ MEMBER="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL_ID}/subject/${SPIFFE_ID}" +$ gcloud storage buckets add-iam-policy-binding gs://example --member=$MEMBER --role=$ROLE +``` + + + + +## Step 2/4. Configure Teleport RBAC + +Now we need to configure Teleport to allow a JWT to be issued containing the +SPIFFE ID we have chosen. + +Create `role.yaml` with the following content: + +```yaml +kind: role +version: v6 +metadata: + name: my-workload-gcp +spec: + allow: + spiffe: + - path: /svc/example-service +``` + +Replace: + +- `my-workload-gcp` with a descriptive name for the role. +- `/svc/example-service` with the path part of the SPIFFE ID you have chosen. + +Apply this role to your Teleport cluster using `tctl`: + +```code +$ tctl create -f role.yaml +``` + +You now need to assign this role to the bot: + +```code +$ tctl bots update my-bot --add-roles my-workload-gcp +``` + +## Step 3/4. Issue Workload Identity JWTs + +You'll now configure `tbot` to issue and renew the short-lived JWT SVIDs for +your workload. It'll write the JWT as a file on disk, where you can then +configure GCP clients and SDKs to read it. + +Before configuring this, you'll need to determine the correct audience to +request in the JWT SVIDs. This is specific to the Workload Identity Federation +configuration you have just created and contains three components: + +- The project number of your GCP project +- The name of your Workload Identity Federation pool as configured in GCP +- The name of your Workload Identity Federation provider as configured in GCP + +It has the following format: `https://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_NAME/providers/$PROVIDER_NAME`. + +Take your already deployed `tbot` service and configure it to issue SPIFFE SVIDs +by adding the following to the `tbot` configuration file: + +```yaml +outputs: + - type: spiffe-svid + destination: + type: directory + path: /opt/workload-identity + svid: + path: /svc/example-service + jwts: + - audience: https://iam.googleapis.com/projects/123456789000/locations/global/workloadIdentityPools/workload-id-pool/providers/workload-id-oidc + file_name: gcp-jwt +``` + +Replace: + +- `123456789000` with your GCP project number. +- `workload-id-pool` with the name of your Workload Identity Federation pool. +- `workload-id-oidc` with the name of your Workload Identity Federation provider. + +Restart your `tbot` service to apply the new configuration. You should see a +file created at `/opt/workload-identity/gcp-jwt` containing the JWT. + +## Step 4/4. Configure GCP CLIs and SDKs + +Finally, you need to create a configuration file to configure the GCP CLIs and +SDKs to authenticate using Workload Identity. This configuration file will +specify the path to the JWT file that `tbot` is writing and will specify which +Workload Identity Federation pool and provider to use. + +You can generate this configuration file using the `gcloud` CLI: + +```code +$ gcloud iam workload-identity-pools create-cred-config \ + projects/123456789000/locations/global/workloadIdentityPools/workload-id-pool/providers/workload-id-oidc \ + --output-file=gcp-workload-identity.json \ + --credential-source-file=/opt/workload-identity/gcp-jwt \ + --credential-source-type=text +``` + +Replace: + +- `123456789000` with your GCP project number. +- `workload-id-pool` with the name of your Workload Identity Federation pool. +- `workload-id-oidc` with the name of your Workload Identity Federation provider. +- `/opt/workload-identity/gcp-jwt` with the path to the JWT file that `tbot` is + writing. + +The command should have created a file called `gcp-workload-identity.json` in +the current directory. + +### `gcloud` CLI + +To configure the `gcloud` CLI to authenticate using Workload Identity, you use +the `gcloud auth login` command and specify the path to the configuration file +that you have just created: + +```code +$ gcloud auth login --cred-file gcp-workload-identity.json +``` + +You can now test authenticating to the GCP Storage API. Create a file which +you can upload to your bucket: + +```code +$ echo "Hello, World!" > hello.txt +``` + +Now, use the `gcloud` CLI to upload this file to your bucket: + +```code +$ gcloud storage cp hello.txt gs://example +``` + +If everything is configured correctly, you should see this file uploaded to your +bucket. Inspecting the audit logs on GCP should indicate that the request was +authenticated using Workload Identity and specify the SPIFFE ID of the workload +that made the request. + +### GCP SDKs + +To configure the GCP SDKs to authenticate using Workload Identity, you need to +set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the path of the +configuration file that you have just created: + +```code +$ export GOOGLE_APPLICATION_CREDENTIALS=gcp-workload-identity.json +``` + +## Next steps + +- [GCP Workload Identity Federation documentation](https://cloud.google.com/iam/docs/workload-identity-federation): +The official GCP documentation for Workload Identity Federation. +- [Workload Identity Overview](./introduction.mdx): Overview of Teleport +Workload Identity. +- [JWT SVID Overview](./jwt-svids.mdx): Overview of the JWT SVIDs issued by +Teleport Workload Identity. +- [Best Practices](./best-practices.mdx): Best practices for using Workload +Identity in Production. +- Read the [configuration reference](../../reference/machine-id/configuration.mdx) to explore +all the available configuration options. diff --git a/docs/pages/enroll-resources/workload-identity/introduction.mdx b/docs/pages/enroll-resources/workload-identity/introduction.mdx index a29288662e654..2c1af78ce8e87 100644 --- a/docs/pages/enroll-resources/workload-identity/introduction.mdx +++ b/docs/pages/enroll-resources/workload-identity/introduction.mdx @@ -142,16 +142,23 @@ The SPIFFE Workload API is implemented as a configurable service within the need to request SVIDs, and they can then use the Workload API exposed by `tbot` to fetch SVIDs and Trust Bundles. -Teleport's Workload Identity currently only supports issuing X.509-SVIDs. +Teleport's Workload Identity supports issuing X.509-SVIDs and JWT-SVIDs. ## Next steps -- [Getting Started](./getting-started.mdx): How to configure Teleport for Workload Identity. -- [Best Practices](./best-practices.mdx): Best practices for using Workload Identity in Production. +Learn more about 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 + +Learn how to configure Teleport Workload Identity for specific use-cases: + +- [Getting Started](./getting-started.mdx): How to configure Teleport for Workload Identity. - [TSH Support](./tsh.mdx): How to use `tsh` with Workload Identity to issue SVIDs to users. - [AWS Roles Anywhere](./aws-roles-anywhere.mdx): Configuring AWS to accept Workload ID certificates as authentication using AWS Roles Anywhere. +- [GCP Workload Identity Federation](./gcp-workload-identity-federation-jwt.mdx): Configuring GCP to accept Workload ID JWTs as authentication using GCP Workload Identity Federation. ### Other resources diff --git a/docs/pages/enroll-resources/workload-identity/jwt-svids.mdx b/docs/pages/enroll-resources/workload-identity/jwt-svids.mdx new file mode 100644 index 0000000000000..d4d376b89a0a9 --- /dev/null +++ b/docs/pages/enroll-resources/workload-identity/jwt-svids.mdx @@ -0,0 +1,73 @@ +--- +title: JWT SVIDs +description: An overview of the JWT SVIDs issued by Teleport Workload Identity +--- + + +Teleport Workload Identity is currently in Preview. This means that some +features may be missing. We're actively looking for design partners to help us +shape the future of Workload Identity and would love to +[hear your feedback](mailto:product@goteleport.com). + + +One type of credential that can be issued by Teleport Workload Identity is a +JWT SVID. This is a short-lived JSON Web Token (JWT) that contains the identity +of the workload and is signed by the Teleport Workload Identity CA. + +## Claims + +The JWT contains the following claims: + +- `sub`: The SPIFFE ID of the workload. +- `aud`: The audience of the JWT. This indicates the intended recipient and + limits the potential for token reuse. +- `exp`: The expiration time of the JWT. By default, Teleport issues JWT-SVIDs + with a 5-minute expiration lifetime. +- `iat`: The time at which the JWT was issued. +- `jti`: A unique identifier for this JWT. This allows a JWT-SVID to be + correlated with audit logs pertaining to its issuance. +- `iss`: The issuer of the JWT. This is the host extracted from the public + address configured for your Teleport Proxy Service. + +The JWT-SVID can be useful in scenarios where X509-SVIDs are not suitable. +For example, when the workload needs to authenticate to another workload which +is behind a TLS-terminating load balancer. + +## OIDC Compatibility + +The JWT SVIDs issued by Teleport Workload Identity are compatible with the +specification for OIDC ID Tokens. This means that they can be used by workloads +to authenticate to services that accept OIDC ID tokens as a form of +authentication. + +The OIDC compatibility is powered by two endpoints exposed by the Teleport +Proxy Service: + +- `/workload-identity/.well-known/openid-configuration`: This endpoint exposes + the OIDC configuration for the Teleport Workload Identity CA. This includes + the issuer URL and the supported signing algorithms. +- `/workload-identity/jwt-jwks.json`: This endpoint exposes the public signing + keys for the Teleport Workload Identity CA. + +In order for OIDC federation to function correctly, these two endpoints must be +accessible from the service that you intend to use the JWT SVIDs to +authenticate to. + +Teleport Workload Identity uses the publicly configured address for your +Teleport Proxy service as the issuer URL for OIDC configuration. + +We have tested Teleport Workload Identity issued JWT-SVIDs with the following +platforms: + +- AWS +- [Google Cloud Platform](./gcp-workload-identity-federation-jwt.mdx) +- Azure + +## Next steps + +- [Workload Identity Overview](./introduction.mdx): Overview of Teleport +Workload Identity. +- [Best Practices](./best-practices.mdx): Best practices for using Workload +Identity in Production. +- Read the [configuration reference](../../reference/machine-id/configuration.mdx) to explore +all the available configuration options. diff --git a/docs/pages/reference/machine-id/configuration.mdx b/docs/pages/reference/machine-id/configuration.mdx index 5f22c534f1b6e..e571de8dc5d19 100644 --- a/docs/pages/reference/machine-id/configuration.mdx +++ b/docs/pages/reference/machine-id/configuration.mdx @@ -322,6 +322,11 @@ The output generates the following artifacts: - `svid.key`: the private key associated with the X509 SVID. - `bundle.pem`: the X509 bundle that contains the trust domain CAs. + +An artifact will also be generated for each entry within the `jwts` list. This +will be named according to `file_name`. This artifact will contain only the +JWT-SVID with the audience specified in `audience`. + See [Workload Identity](../../enroll-resources/workload-identity/introduction.mdx) for more information on how to use SPIFFE SVIDs. @@ -342,6 +347,17 @@ svid: # ip specifies the IP SANs. If omitted, no IP SANs are included. ip: - 10.0.0.1 + # jwts controls the output of JWT-SVIDs. Each entry will be generated as a + # separate artifact. If omitted, no JWT-SVIDs are generated. + jwts: + # audience specifies the audience that the JWT-SVID should be issued for. + # this typically identifies the service that the JWT-SVID will be used to + # authenticate to. + - audience: https://example.com + # file_name specifies the name of the file that the JWT-SVID should be + # written to. + file_name: example-jwt + (!docs/pages/includes/machine-id/common-output-config.yaml!) ```