GitHub Actions action that exchanges a workflow's OIDC token for credentials via Keycard STS.
Keycard is an identity broker for non-human workloads — it issues short-lived, scoped credentials to a workflow (or service, or agent) based on the identity it can prove it has.
Workflows present their OIDC identity to Keycard and get back scoped credentials. No static secrets in repo settings, no secrets: inherit blast radius, audit per credential per run.
Prerequisite: a Keycard zone configured to trust GitHub's OIDC provider. See Setup.
permissions:
id-token: write
contents: read
steps:
- uses: keycardai/gha-keycard-auth@<sha>
with:
zone-url: https://<id>.keycard.cloud
credentials: |
- resource: urn:fly:app:my-app:deploy-token
type: env
env-name: FLY_API_TOKEN
scope: deploy:write
- run: flyctl deployFor credentials that need to be on disk (e.g. a PEM private key), use type: file:
credentials: |
- resource: urn:secret:gh-app-key
type: file
file-path: gh-app.pem # resolved under $RUNNER_TEMP/keycard-auth/
file-mode: "0400" # must be quoted — see file-mode notes belowBeyond raw env/file distribution, the action can broker credentials to specific downstream identity providers. A provider takes the Keycard zone JWT, performs the second-hop exchange with the downstream IdP (e.g. RFC 8693 token exchange to Pulumi), and exports the resulting credential into the workflow's environment. The workflow author writes one step; the Keycard zone controls the JWT's claims; the downstream's allow policy controls what the resulting credential can do.
Supported providers:
| Type | Downstream | Default output env var |
|---|---|---|
pulumi |
Pulumi Cloud (RFC 8693 to /api/oauth/token) |
PULUMI_ACCESS_TOKEN |
steps:
- uses: keycardai/gha-keycard-auth@<sha>
with:
zone-url: https://<id>.keycard.cloud
credentials: |
- resource: urn:pulumi:org:keycardlabs
type: pulumi
pulumi:
organization: keycardlabs
- run: pulumi preview --stack acme/prod| Field | Required | Notes |
|---|---|---|
pulumi.organization |
yes | Pulumi organization the issued token is scoped to. Becomes audience=urn:pulumi:org:<org> in the exchange request. |
pulumi.token-type |
no | organization (default), team, or personal. Maps to urn:pulumi:token-type:access_token:<value>. |
pulumi.cloud-url |
no | Pulumi API origin, default https://api.pulumi.com. Must be https; path is stripped. |
Downstream setup: register the Keycard zone as an OIDC issuer in Pulumi Cloud (Settings → Access Management → OIDC Issuers), and add an allow policy matching aud=urn:pulumi:org:<org> plus the sub/client_id claim shape Keycard mints for your workflows. This replaces pulumi/auth-actions in workflows that want credential issuance + audit flowing through Keycard.
Providers ship inside this action — there is no runtime plugin mechanism. See CONTRIBUTING.md for the step-by-step.
| Input | Required | Description |
|---|---|---|
zone-url |
yes | Base URL of the Keycard zone. |
audience |
no | Audience for the GHA OIDC token. Defaults to zone-url. |
credentials |
yes | YAML list of credential specs (see below). |
| Field | Required | Notes |
|---|---|---|
resource |
yes | Keycard resource URN. |
type |
yes | env, file, or a provider type. |
scope |
no | OAuth scope to request on the resource. |
env-name |
when type=env |
Env var to set. Must match ^[A-Z_][A-Z0-9_]*$ and is not allowed to be a reserved name (e.g. PATH, NODE_OPTIONS, LD_PRELOAD, anything starting with GITHUB_/RUNNER_/ACTIONS_/INPUT_). Providers also accept this field as an optional override of their default env var. |
file-path |
when type=file |
Path on disk. Resolved against an action-managed directory under $RUNNER_TEMP; absolute paths and .. traversal are rejected. |
file-mode |
no | Octal mode for file, default 0600. Must be a quoted string ("0600") — unquoted YAML coerces it to a decimal integer. Must be owner-only; group/world bits are rejected (so 0640, 0644, etc. fail). |
<provider> |
when type=<provider> |
Provider-specific config block. See Providers. |
You need a Keycard zone with GitHub Actions configured as a trusted OIDC provider, plus an application and resource to authorize. See the Keycard documentation for the step-by-step (console and Terraform).
This is a 0.x release line — the API may change between minor versions. Pin to a 40-character commit SHA:
uses: keycardai/gha-keycard-auth@<40-char-sha> # v0.1.0Dependabot understands the # v0.1.0 trailing comment and will open PRs to bump the SHA when a new release lands. To resolve the SHA for a given release manually, use git rev-parse v0.1.0 or look up the release on GitHub.
External contributions welcome via forks and pull requests. See CONTRIBUTING. For vulnerabilities see SECURITY — please do not file public issues for security reports.