From 342329aca1c12b72a4f7ab969bd14e4385eabdcd Mon Sep 17 00:00:00 2001 From: Gabor Szakacs Date: Tue, 20 Oct 2026 17:48:53 +0200 Subject: [PATCH 1/4] Document OIDC cloud authentication for Remote Dev Environment sessions New page under RDE > Configuration covering the session subject and claims, requesting a token with the rde-id-token helper, and AWS and GCP template recipes. The OIDC overview, AWS and GCP pages point to it; their provider-side steps stay the single source for both builds and sessions. Co-Authored-By: Claude Fable 5.1 --- .../oidc-authentication-overview.mdx | 12 +- .../oidc-authentication/oidc-for-aws.mdx | 6 + .../oidc-authentication/oidc-for-gcp.mdx | 2 +- .../configuration/managing-rde-access.mdx | 2 +- .../oidc-cloud-authentication.mdx | 128 ++++++++++++++++++ docs/bitrise-rde/configuration/rde-api.mdx | 2 +- static/llms.txt | 1 + 7 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx diff --git a/docs/bitrise-platform/integrations/oidc-authentication/oidc-authentication-overview.mdx b/docs/bitrise-platform/integrations/oidc-authentication/oidc-authentication-overview.mdx index dac209a7..558ab9b0 100644 --- a/docs/bitrise-platform/integrations/oidc-authentication/oidc-authentication-overview.mdx +++ b/docs/bitrise-platform/integrations/oidc-authentication/oidc-authentication-overview.mdx @@ -17,7 +17,7 @@ The service that receives the token evaluates the token's claims against its OID Bitrise supports the use of OIDC tokens in two ways: -- To enable your Bitrise builds to authenticate to external systems such as AWS, GCP, Azure, container registries, secret management or artifact stores. +- To enable your Bitrise builds and Remote Dev Environment sessions to authenticate to external systems such as AWS, GCP, Azure, container registries, secret management or artifact stores. - To use foreign OIDC tokens to authenticate to Bitrise and receive short-lived Bitrise tokens. @@ -86,6 +86,16 @@ You can find more information about claim fields in the [AWS documentation](http | `build_number` | Build number | | `workflow` | Name of the triggered workflow | +### Identity tokens for Remote Dev Environments + +A Remote Dev Environment session can request an identity token the same way a build can. The token comes from the same issuer with the same signing keys, so a cloud provider that already trusts Bitrise for builds also trusts it for sessions. The subject describes the session instead of the build: + +```text +rde:workspace:WORKSPACE_ID:template:TEMPLATE_ID:session-owner:OWNER_TYPE:OWNER_ID +``` + +Because the subject starts with `rde:`, a trust policy written for builds never matches a session, and the other way around. For the full list of claims and how to request a token from a session, see [Cloud authentication with OIDC](/bitrise-rde/configuration/oidc-cloud-authentication). + ## Authentication to Bitrise with OIDC diff --git a/docs/bitrise-platform/integrations/oidc-authentication/oidc-for-aws.mdx b/docs/bitrise-platform/integrations/oidc-authentication/oidc-for-aws.mdx index 2efcf777..82bbc89c 100644 --- a/docs/bitrise-platform/integrations/oidc-authentication/oidc-for-aws.mdx +++ b/docs/bitrise-platform/integrations/oidc-authentication/oidc-for-aws.mdx @@ -107,6 +107,12 @@ Our guide helps you set up your AWS policy for your Bitrise builds. You can read ``` You can also use wildcards with the `StringLike` operation instead of `StringEquals`: [Wildcard matching](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_String-wildcard). + + :::info[Remote Dev Environment sessions] + + Tokens requested from a Remote Dev Environment session use a different subject, starting with `rde:`, so they need their own trust policy. See [Cloud authentication with OIDC](/bitrise-rde/configuration/oidc-cloud-authentication). + + ::: 1. When done, click **Next**. 1. Select the required permission for the role. diff --git a/docs/bitrise-platform/integrations/oidc-authentication/oidc-for-gcp.mdx b/docs/bitrise-platform/integrations/oidc-authentication/oidc-for-gcp.mdx index 3a18f11a..73d7c112 100644 --- a/docs/bitrise-platform/integrations/oidc-authentication/oidc-for-gcp.mdx +++ b/docs/bitrise-platform/integrations/oidc-authentication/oidc-for-gcp.mdx @@ -43,7 +43,7 @@ Read more about how authentication with Workload Identity Federation works on GC 1. Click **Continue**. 1. Under **Configure provider attributes**, configure the required attribute mapping values: - - The `google.subject` key is a unique identifier for the user. You can use `assertion.sub` to identify the build that requests the token. + - The `google.subject` key is a unique identifier for the user. You can use `assertion.sub` to identify the build or the Remote Dev Environment session that requests the token. Session subjects start with `rde:`; see [Cloud authentication with OIDC](/bitrise-rde/configuration/oidc-cloud-authentication). - Use the `attribute.NAME` format to add up to 50 custom attributes, each with a value in the `assertion.VALUE` format. You can find the list of available attributes in the Bitrise token here: [Information in the OIDC token](/bitrise-platform/integrations/oidc-authentication/oidc-authentication-overview#information-in-the-oidc-token). :::important[Explicit mapping required] diff --git a/docs/bitrise-rde/configuration/managing-rde-access.mdx b/docs/bitrise-rde/configuration/managing-rde-access.mdx index 11ff4b90..a1a92dbf 100644 --- a/docs/bitrise-rde/configuration/managing-rde-access.mdx +++ b/docs/bitrise-rde/configuration/managing-rde-access.mdx @@ -1,7 +1,7 @@ --- title: "Managing RDE access" description: "Grant and revoke Remote Dev Environments access for workspace members and groups from the Collaboration page, or automate it with SCIM." -sidebar_position: 6 +sidebar_position: 7 slug: /bitrise-rde/configuration/managing-rde-access sidebar_label: "Managing access" --- diff --git a/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx b/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx new file mode 100644 index 00000000..f4a73817 --- /dev/null +++ b/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx @@ -0,0 +1,128 @@ +--- +title: "Cloud authentication with OIDC" +description: "Let Remote Dev Environment sessions authenticate to AWS, GCP, and other cloud services with short-lived OIDC identity tokens instead of long-lived keys stored in templates." +sidebar_position: 5 +slug: /bitrise-rde/configuration/oidc-cloud-authentication +--- + +import GlossTerm from '@site/src/components/GlossTerm'; + +A session can request an OpenID Connect (OIDC) identity token that proves which Workspace, template, and owner it belongs to. Your cloud provider exchanges that token for its own short-lived credentials, so your templates never need to carry AWS access keys, GCP service account keys, or similar long-lived secrets. + +Remote Dev Environment sessions use the same Bitrise identity provider as CI builds: the issuer is `https://token.builds.bitrise.io`, and the token is valid for one hour. If you already set up OIDC for your builds, your cloud provider already trusts Bitrise and you only need a trust policy for sessions. For an introduction to OIDC on Bitrise, see [OIDC authentication overview](/bitrise-platform/integrations/oidc-authentication/oidc-authentication-overview). + +## How it works + +1. A process in the session runs the `rde-id-token` helper, which is preinstalled on every session machine. +1. The helper asks the Remote Dev Environments backend for a token. The request is authenticated by the session's own machine credential, so only the session itself can request its token. +1. Bitrise signs a token whose subject and claims describe the session, and returns it to the helper. +1. The helper writes the token to a file. Your cloud SDK reads the file and exchanges the token for cloud credentials. + +The developer or agent working in the session doesn't do anything: once the template is set up, the cloud CLI and SDKs authenticate on their own. + +## Information in the token + +Cloud providers decide whether to trust a token based on its claims. The token for a session contains: + +| Name | Description | +| --- | --- | +| `aud` | The audience you request, for example `sts.amazonaws.com`. | +| `sub` | The subject, in the `rde:workspace:WORKSPACE_ID:template:TEMPLATE_ID:session-owner:OWNER_TYPE:OWNER_ID` format. | +| `iss`, `exp`, `iat`, `nbf`, `jti` | Standard JWT claims: issuer, expiration, issued at, not before, and token ID. | +| `workspace_id` | The Workspace slug. | +| `session_id` | The session ID. | +| `template_id` | The ID of the template the session was created from. | +| `session_owner_type` | `user` for a session owned by a Workspace member, `workspace` for a Workspace-owned session. | +| `session_owner_id` | The user slug or Workspace slug of the session owner. | + +:::important[Limitation] + +AWS keeps only the `aud` and `sub` claims from a generic identity provider. That's why the subject contains every value you might want to match on, in a fixed order. GCP lets you map any claim to an attribute. + +::: + +All identifiers in the subject are stable: the Workspace slug and the user slug never change, and a template keeps its ID when you rename it. Find the template ID on the template's page in the [Bitrise RDE UI](/bitrise-rde/rde-options/bitrise-rde-ui) or with `rde template list` in the [CLI](/bitrise-rde/rde-options/bitrise-rde-cli). + +An example subject for a session that a user created from a template: + +```text +rde:workspace:a1b2c3d4e5f67890:template:7f3c2a10-1111-4222-8333-444455556666:session-owner:user:5a0d688e73861d6d +``` + +## Setting up your cloud provider + +The provider-side setup is the same as for CI builds, with one difference: the trust policy matches the session subject instead of the build subject. + +- For AWS, follow [OIDC for AWS](/bitrise-platform/integrations/oidc-authentication/oidc-for-aws) to add Bitrise as an identity provider and create a role with a custom trust policy. +- For GCP, follow [OIDC for GCP](/bitrise-platform/integrations/oidc-authentication/oidc-for-gcp) to create a workload identity pool and connect it to a service account. + +In the trust policy, match the subject with a wildcard so that every session created from a template can assume the role. This AWS condition allows all sessions created from one template in one Workspace: + +```json +"Condition": { + "StringEquals": { + "token.builds.bitrise.io:aud": "sts.amazonaws.com" + }, + "StringLike": { + "token.builds.bitrise.io:sub": "rde:workspace:a1b2c3d4e5f67890:template:7f3c2a10-1111-4222-8333-444455556666:*" + } +} +``` + +To restrict the role to one person, replace the trailing `*` with `session-owner:user:USER_SLUG`. To allow every template in the Workspace, put the wildcard after the Workspace slug instead. + +:::tip[Use a dedicated role] + +A trust policy written for CI builds matches subjects starting with `app:`, so it never matches a session. Create a separate role for dev environments with only the permissions developers need, rather than reusing a deployment role. + +::: + +## Requesting a token in a session + +Run the helper with the audience your cloud provider expects: + +```bash +rde-id-token --audience sts.amazonaws.com +``` + +The helper prints the token to standard output. To keep a fresh token in a file for the lifetime of the session, add `--out` and `--refresh`. The helper then runs in the background and replaces the file a few minutes before each token expires: + +```bash +rde-id-token --audience sts.amazonaws.com --out /run/rde/aws-token --refresh +``` + +Cloud SDKs re-read the token file whenever they need a new credential, so a refreshed file is picked up without restarting anything. + +## Configuring a template for AWS + +1. Store the role ARN in a [template variable](/bitrise-rde/configuration/templates), for example `AWS_ROLE_ARN`. Use a session input instead if the role differs per user. +1. Add the following to the template's startup script. + + ```bash + rde-id-token --audience sts.amazonaws.com --out /run/rde/aws-token --refresh + export AWS_WEB_IDENTITY_TOKEN_FILE=/run/rde/aws-token + export AWS_ROLE_ARN="$AWS_ROLE_ARN" + ``` + +1. Create a session from the template and run `aws sts get-caller-identity`. The AWS CLI and SDKs exchange the token through `AssumeRoleWithWebIdentity` on their own. + +## Configuring a template for GCP + +1. Download the client library configuration file from your workload identity pool, as described in [OIDC for GCP](/bitrise-platform/integrations/oidc-authentication/oidc-for-gcp), and set its `credential_source.file` to `/run/rde/gcp-token`. +1. Add the configuration file to the template, for example by writing it in the warmup script. +1. Add the following to the template's startup script, with the audience you set on the workload identity pool. + + ```bash + rde-id-token --audience YOUR_AUDIENCE --out /run/rde/gcp-token --refresh + export GOOGLE_APPLICATION_CREDENTIALS=/path/to/client-library-config.json + ``` + +1. Create a session from the template and run `gcloud auth login --cred-file="$GOOGLE_APPLICATION_CREDENTIALS"`, or let a client library pick up the file. + +## Which sessions can request a token + +- Sessions owned by a Workspace member and Workspace-owned sessions can request tokens. +- Sessions opened from a [device preview link](/bitrise-rde/devices/device-preview-links) can't, because anyone holding the link can run commands in them. +- Sessions waiting in a [warm pool](/bitrise-rde/configuration/warm-pools) can't request tokens until someone claims them. + +A token stays valid for one hour after it's issued, even if the session is terminated in the meantime. Terminating the session stops any further tokens from being issued. diff --git a/docs/bitrise-rde/configuration/rde-api.mdx b/docs/bitrise-rde/configuration/rde-api.mdx index ff752271..8cb28b99 100644 --- a/docs/bitrise-rde/configuration/rde-api.mdx +++ b/docs/bitrise-rde/configuration/rde-api.mdx @@ -1,7 +1,7 @@ --- title: "Remote Dev Environments API" description: "Manage Remote Dev Environment sessions, templates, and saved inputs programmatically over the REST API, and report on workspace usage." -sidebar_position: 5 +sidebar_position: 6 slug: /bitrise-rde/configuration/rde-api sidebar_label: "API" --- diff --git a/static/llms.txt b/static/llms.txt index 3a82d7ca..ed8b25c2 100644 --- a/static/llms.txt +++ b/static/llms.txt @@ -57,6 +57,7 @@ Every documentation page is also available as plain markdown: take the page path - [Device preview links](https://docs.bitrise.io/bitrise-rde/devices/device-preview-links.md): Sharing an app build as a browser link with no login; the Device Preview CI Step, CLI, MCP, API, limits. - [Warm pools](https://docs.bitrise.io/bitrise-rde/configuration/warm-pools.md): Keeping pre-booted sessions ready to claim in seconds (UI, CLI, MCP, API), personal vs. workspace pools, scaling on a schedule, and serving device preview links from a pool. - [GitHub integration](https://docs.bitrise.io/bitrise-rde/configuration/github-integration.md): Automatic git and GitHub CLI authentication in sessions via the Bitrise GitHub App. +- [Cloud authentication with OIDC](https://docs.bitrise.io/bitrise-rde/configuration/oidc-cloud-authentication.md): Short-lived OIDC identity tokens for sessions, the session subject and claims, and template setup for AWS and GCP. - [Managing RDE access](https://docs.bitrise.io/bitrise-rde/configuration/managing-rde-access.md): Granting and revoking the RDE User role for workspace members and groups, and via SCIM. - [RDE API](https://docs.bitrise.io/bitrise-rde/configuration/rde-api.md): Programmatic RDE operations. From 1af27f17fa451a3058d01f747d4eb182401e4d22 Mon Sep 17 00:00:00 2001 From: Gabor Szakacs Date: Tue, 20 Oct 2026 18:05:45 +0200 Subject: [PATCH 2/4] Drop the machine-credential detail from the how-it-works steps --- docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx b/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx index f4a73817..38a3cf5f 100644 --- a/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx +++ b/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx @@ -14,7 +14,7 @@ Remote Dev Environment sessions use the same Bitrise identity provider as CI bui ## How it works 1. A process in the session runs the `rde-id-token` helper, which is preinstalled on every session machine. -1. The helper asks the Remote Dev Environments backend for a token. The request is authenticated by the session's own machine credential, so only the session itself can request its token. +1. The helper asks Bitrise for a token for that session. 1. Bitrise signs a token whose subject and claims describe the session, and returns it to the helper. 1. The helper writes the token to a file. Your cloud SDK reads the file and exchanges the token for cloud credentials. From c7a19719fb8d284e4466134f2a948214b1b66453 Mon Sep 17 00:00:00 2001 From: Gabor Szakacs Date: Wed, 21 Oct 2026 10:34:49 +0200 Subject: [PATCH 3/4] Request tokens on demand through credential_process and executable-sourced credentials; drop the refresh daemon --- .../oidc-cloud-authentication.mdx | 82 +++++++++++++------ 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx b/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx index 38a3cf5f..bfdb6077 100644 --- a/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx +++ b/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx @@ -13,12 +13,12 @@ Remote Dev Environment sessions use the same Bitrise identity provider as CI bui ## How it works -1. A process in the session runs the `rde-id-token` helper, which is preinstalled on every session machine. +1. Your cloud SDK needs a credential and runs the `rde-id-token` helper, which is preinstalled on every session machine. 1. The helper asks Bitrise for a token for that session. -1. Bitrise signs a token whose subject and claims describe the session, and returns it to the helper. -1. The helper writes the token to a file. Your cloud SDK reads the file and exchanges the token for cloud credentials. +1. Bitrise signs a token whose subject and claims describe the session, and the helper prints it. +1. The SDK exchanges the token for cloud credentials and caches them until they expire, then runs the helper again. -The developer or agent working in the session doesn't do anything: once the template is set up, the cloud CLI and SDKs authenticate on their own. +The developer or agent working in the session doesn't do anything: once the template is set up, the cloud CLI and SDKs authenticate on their own. Nothing runs in the background and no token is stored on the machine. This is the same on-demand model that the [GitHub integration](/bitrise-rde/configuration/github-integration) uses for git credentials. ## Information in the token @@ -85,39 +85,75 @@ Run the helper with the audience your cloud provider expects: rde-id-token --audience sts.amazonaws.com ``` -The helper prints the token to standard output. To keep a fresh token in a file for the lifetime of the session, add `--out` and `--refresh`. The helper then runs in the background and replaces the file a few minutes before each token expires: - -```bash -rde-id-token --audience sts.amazonaws.com --out /run/rde/aws-token --refresh -``` - -Cloud SDKs re-read the token file whenever they need a new credential, so a refreshed file is picked up without restarting anything. +The helper prints the token to standard output and exits. A token is valid for one hour. Don't store it: let the cloud SDK run the helper whenever it needs a fresh one, as shown in the recipes below. ## Configuring a template for AWS -1. Store the role ARN in a [template variable](/bitrise-rde/configuration/templates), for example `AWS_ROLE_ARN`. Use a session input instead if the role differs per user. -1. Add the following to the template's startup script. +The AWS CLI and SDKs can get credentials from a program you name in `credential_process`. The program runs whenever credentials are needed, and its output is cached until the expiration it reports. + +1. Store the role ARN in a [template variable](/bitrise-rde/configuration/templates) named `RDE_AWS_ROLE_ARN`, exposed as an environment variable. Use a session input instead if the role differs per user. +1. Add the following to the template's startup script. It installs a small credential process that requests a token and exchanges it, and points the AWS CLI at it. ```bash - rde-id-token --audience sts.amazonaws.com --out /run/rde/aws-token --refresh - export AWS_WEB_IDENTITY_TOKEN_FILE=/run/rde/aws-token - export AWS_ROLE_ARN="$AWS_ROLE_ARN" + mkdir -p "$HOME/.aws" "$HOME/.local/bin" + + cat > "$HOME/.local/bin/rde-aws-credentials" <<'EOF' + #!/usr/bin/env bash + set -euo pipefail + token="$(rde-id-token --audience sts.amazonaws.com)" + env -u AWS_PROFILE aws --no-sign-request sts assume-role-with-web-identity \ + --role-arn "$RDE_AWS_ROLE_ARN" \ + --role-session-name "rde-session" \ + --web-identity-token "$token" \ + --query 'Credentials.{Version: `1`, AccessKeyId: AccessKeyId, SecretAccessKey: SecretAccessKey, SessionToken: SessionToken, Expiration: Expiration}' \ + --output json + EOF + chmod +x "$HOME/.local/bin/rde-aws-credentials" + + cat > "$HOME/.aws/config" < "$HOME/.local/bin/rde-gcp-token" <<'EOF' + #!/usr/bin/env bash + set -euo pipefail + token="$(rde-id-token --audience "YOUR_AUDIENCE")" + printf '{"version":1,"success":true,"token_type":"urn:ietf:params:oauth:token-type:jwt","id_token":"%s","expiration_time":%s}\n' \ + "$token" "$(( $(date +%s) + 3300 ))" + EOF + chmod +x "$HOME/.local/bin/rde-gcp-token" + + export GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES=1 export GOOGLE_APPLICATION_CREDENTIALS=/path/to/client-library-config.json ``` -1. Create a session from the template and run `gcloud auth login --cred-file="$GOOGLE_APPLICATION_CREDENTIALS"`, or let a client library pick up the file. +1. Create a session from the template and run `gcloud auth login --cred-file="$GOOGLE_APPLICATION_CREDENTIALS"`, or let a client library pick up the configuration file. ## Which sessions can request a token @@ -125,4 +161,4 @@ Cloud SDKs re-read the token file whenever they need a new credential, so a refr - Sessions opened from a [device preview link](/bitrise-rde/devices/device-preview-links) can't, because anyone holding the link can run commands in them. - Sessions waiting in a [warm pool](/bitrise-rde/configuration/warm-pools) can't request tokens until someone claims them. -A token stays valid for one hour after it's issued, even if the session is terminated in the meantime. Terminating the session stops any further tokens from being issued. +A token stays valid for one hour after it's issued, even if the session is terminated in the meantime. Terminating the session stops any further tokens from being issued. Because tokens are requested on demand and handed straight to the SDK, no token is kept on the machine between exchanges. From f4977cb1b51fb9d2c1603d75859f4a5685d8dd1e Mon Sep 17 00:00:00 2001 From: Gabor Szakacs Date: Wed, 21 Oct 2026 14:09:13 +0200 Subject: [PATCH 4/4] Warm pool sessions can request tokens before they are claimed --- docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx b/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx index bfdb6077..0ed95172 100644 --- a/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx +++ b/docs/bitrise-rde/configuration/oidc-cloud-authentication.mdx @@ -158,7 +158,7 @@ Google client libraries and the gcloud CLI can get the identity token from an ex ## Which sessions can request a token - Sessions owned by a Workspace member and Workspace-owned sessions can request tokens. +- Sessions in a [warm pool](/bitrise-rde/configuration/warm-pools) can request tokens while they wait to be claimed. The Workspace is the session owner in the subject until someone claims the session, then the owner changes to that user. - Sessions opened from a [device preview link](/bitrise-rde/devices/device-preview-links) can't, because anyone holding the link can run commands in them. -- Sessions waiting in a [warm pool](/bitrise-rde/configuration/warm-pools) can't request tokens until someone claims them. A token stays valid for one hour after it's issued, even if the session is terminated in the meantime. Terminating the session stops any further tokens from being issued. Because tokens are requested on demand and handed straight to the SDK, no token is kept on the machine between exchanges.