Skip to content

[RDE-534] Document OIDC cloud authentication for RDE sessions - #382

Merged
zoltan-baba merged 19 commits into
mainfrom
rde-oidc
Oct 29, 2026
Merged

zoltan-baba merged 19 commits into
mainfrom
rde-oidc

Conversation

@gaborszakacs

@gaborszakacs gaborszakacs commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

RDE-534

Draft until the rde-agent id-token verbs ship. The backend mint is bitrise-io/bitrise-codespaces#380, the agent install on every session is bitrise-io/bitrise-codespaces#386, and the verbs themselves are the next PR; the command names and flags on the page follow the agreed design and get a final check against the shipped --help before this merges.

TLDR

  • New page: Cloud authentication with OIDC, under RDE › Configuration
  • OIDC overview gains a short "Identity tokens for Remote Dev Environments" section with the session subject format
  • AWS and GCP pages get a one-admonition pointer; their provider-side steps stay the single source for both CI and RDE. On the GCP page the Grant access example is corrected (the filter value is the subject string, not the literal sub) and a dropped link is restored
  • New page listed in static/llms.txt

Tokens are requested on demand through rde-agent id-token

The preinstalled rde-agent command does the work: id-token get prints the token, id-token aws exchanges it with STS itself and prints credential_process output, id-token gcp wraps it for Google's executable-sourced credentials. The recipes are therefore one line in the warmup script for AWS (aws configure set credential_process ...) and a credential configuration file written to the application default credentials location for GCP, with gcloud activated in the same step. Nothing runs in the background and no identity token is kept on the machine; the SDKs cache the exchanged credential until it expires and call the command again. This is the same pull model as the git credential helper the GitHub integration uses, and it came out of the review thread on the RFC: https://bitrise.atlassian.net/wiki/spaces/ENGI/pages/5293735999

The GCP recipe is console-only and came out of a staging run: the token audience is the provider's allowed audience (not the configuration file's audience), and the service account grant has to match session identities, so the recipe maps workspace_id to a provider attribute and filters on it.

Two things on the page are deliberate and worth a glance: the GCP variables are exposed template variables rather than script exports, since exports never reach a session's terminals; and both recipes live in the warmup script, since the files they write survive restores.

The provider-side setup (IAM identity provider, trust policy, workload identity pool) is identical for builds and sessions, so it stays on the existing AWS and GCP pages rather than being duplicated.

No changelog entry yet; it gets added when this merges so the date is right.

Testing

  • npm run build: passes for both locales; the only broken-anchor warnings are pre-existing ones on four /ja/ pages this PR does not touch

🤖 Generated with Claude Code

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 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

gaborszakacs and others added 14 commits October 20, 2026 18:05
The preinstalled rde-agent command gains id-token subcommands: get prints
the token, aws exchanges it with STS into credential_process output, gcp
wraps it for executable-sourced credentials. The AWS recipe becomes one
aws configure set line in the warmup script; the GCP recipe names the
command in the credential configuration and sets the two Google
variables as exposed template variables, since script exports never
reach the session's terminals.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The template does the setup; activate the GCP credential for gcloud in
the warmup script so a session starts with gcloud working too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…a path

Exposed template values are not shell-expanded and the home directory
differs per stack, so a GOOGLE_APPLICATION_CREDENTIALS path was fragile.
The application default credentials location needs no variable.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The three commands become a list with the command on its own line; the
options table gets fixed column widths through a command-table class in
custom.css, following the build-machine-types table.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…t the config file's audience

The configuration file's audience (//iam.googleapis.com/...) names the pool for
the exchange; the aud claim Google checks defaults to the provider's resource
name with an https: prefix. A staging run with the // form failed with
invalid_grant.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A CI-style binding does not cover RDE subjects; show mapping a claim to an
attribute and granting a principalSet, and name the error a missing binding
produces.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Map workspace_id (and optionally template_id) to provider attributes and filter
on them in Grant access. On the CI page, the filter example said to set the
attribute value to the literal sub; it has to be the subject string itself, and
the dangling 'here:' gets its link back.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The provider section now has an AWS and a GCP subsection, each saying to follow
the CI guide and listing what to do differently for sessions. The GCP template
section only covers the template again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Authenticating with AWS / GCP each hold the provider setup and the template
recipe; the rde-agent command reference moves to the end as a reference, since
the recipes already carry the exact commands.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@gaborszakacs
gaborszakacs marked this pull request as ready for review October 28, 2026 17:53
@zoltan-baba

Copy link
Copy Markdown
Collaborator

Two things in oidc-cloud-authentication.mdx that I'd double-check against bitrise-io/bitrise-codespaces#388 (the rde-agent id-token implementation):

1. "No identity token is stored on the machine" (How it works)
True for OIDC tokens: the agent mints one per call and prints it. But on every boot the agent writes the session's machine token to ~/.config/bitrise/rde-agent.env (mode 0600), so processes that don't inherit the boot environment (an SSH terminal, an IDE, an SDK's credential process) can still call rde-agent id-token. A security-minded reader may want the page to say that a session credential does live on the machine, and that it is what lets the command mint tokens.

2. "rde-agent is on the PATH of every session" (The rde-agent id-token commands)
The boot script links the binary into /usr/local/bin with sudo ln -sfn. If that fails, the boot log prints could not link rde-agent into /usr/local/bin: call it as /opt/bitrise/rde/bin/rde-agent and the session boots anyway. That's an edge case, but the page could mention the fallback path, or soften "every session".

Source: backend/internal/instancemanager/script_agent.go on feat/rde-agent-id-token.

@gaborszakacs

Copy link
Copy Markdown
Collaborator Author

Two things in oidc-cloud-authentication.mdx that I'd double-check against bitrise-io/bitrise-codespaces#388 (the rde-agent id-token implementation):

1. "No identity token is stored on the machine" (How it works) True for OIDC tokens: the agent mints one per call and prints it. But on every boot the agent writes the session's machine token to ~/.config/bitrise/rde-agent.env (mode 0600), so processes that don't inherit the boot environment (an SSH terminal, an IDE, an SDK's credential process) can still call rde-agent id-token. A security-minded reader may want the page to say that a session credential does live on the machine, and that it is what lets the command mint tokens.

2. "rde-agent is on the PATH of every session" (The rde-agent id-token commands) The boot script links the binary into /usr/local/bin with sudo ln -sfn. If that fails, the boot log prints could not link rde-agent into /usr/local/bin: call it as /opt/bitrise/rde/bin/rde-agent and the session boots anyway. That's an edge case, but the page could mention the fallback path, or soften "every session".

Source: backend/internal/instancemanager/script_agent.go on feat/rde-agent-id-token.

Good callouts:

  1. It's tricky, it's technically true that no OIDC token lives on the machine but one can generate a new one with the session's "machine token". It can get confusing if we try to explain how it works, I'd simply delete these two sentences and let the security conscious customers reach out if they're interested in how it exactly works.

Nothing runs in the background, and no identity token is stored on the machine. This is the same on-demand model that the GitHub integration uses for git credentials.

  1. This is true but shouldn't happen (or if it does, we should fix it rapidly), so I wouldn't confuse the reader with this scenario.

gaborszakacs and others added 4 commits October 29, 2026 10:21
The session's own credential is on the machine for its lifetime; readers asked
what lets the command request tokens.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… session requirements

- How it works: split into a once-per-template setup and the runtime steps
- AWS and GCP setup sections are numbered procedures with deep links; each
  provider section gets an intro
- Subject claim gets its own sub-section
- Command reference is one table (command and option in one cell) with the
  audience, duration, session name, and region rules, exit codes, and --help
- Session requirements are two lists: can request a token, can't
- Drop the claims about what is stored on the machine
- CSS: no bottom margin on the last block of a procedure step; widths of the
  command table for three columns

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The intros explained OIDC only in terms of CI builds. Explain what OIDC does,
then list CI builds and Remote Dev Environment sessions as the two uses, and
update the page descriptions to match.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Replace the single command table with a subsection for get, aws, and gcp.
Each has an intro, a usage line, and a table of its options. The flag
descriptions are unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@zoltan-baba
zoltan-baba merged commit 50e2589 into main Oct 29, 2026
4 checks passed
@zoltan-baba
zoltan-baba deleted the rde-oidc branch October 29, 2026 15:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants