Skip to content

instant-labs/pulumi-oidc-buildkite-plugin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pulumi OIDC Buildkite Plugin

A Buildkite plugin that exchanges a Buildkite OIDC token for a Pulumi access token using OAuth 2.0 Token Exchange.

The resulting token is exported as PULUMI_ACCESS_TOKEN, allowing subsequent pipeline steps to authenticate with Pulumi Cloud without storing static credentials.

Prerequisites

  • Buildkite agent v3.48+ (OIDC token support)
  • curl >= 8.0.0
  • jq >= 1.5 (for -e exit status flag)
  • bash >= 4.0
  • A Pulumi Cloud organization with OIDC configured (see setup below). Available token types depend on your Pulumi edition:
    • Individual: personal tokens only
    • Team: personal and organization tokens
    • Enterprise / Business Critical: personal, organization, and team tokens

Pulumi Cloud Setup

Before using this plugin, you need to register Buildkite as an OIDC issuer in Pulumi Cloud and create an authorization policy.

1. Register Buildkite as an OIDC Issuer

  1. Navigate to Pulumi Cloud > Access Management > Settings > OIDC Issuers
  2. Click Register a new issuer
  3. Set the issuer URL to https://agent.buildkite.com
  4. Configure the max token expiration as needed

See the Pulumi OIDC client documentation for details.

2. Create an Authorization Policy

By default, all token exchange requests are denied. You must create an authorization policy that matches the Buildkite OIDC token claims.

Buildkite OIDC tokens use the following subject claim format:

organization:{ORG_SLUG}:pipeline:{PIPELINE_SLUG}:ref:{REF}:commit:{COMMIT}:step:{STEP_KEY}

Example policy allowing all pipelines in a Buildkite organization:

  • Sub claim: organization:my-buildkite-org:pipeline:*:ref:*:commit:*:step:*
  • Token type: Organization access token
  • Scope: (leave empty for default)

Configuration

Required

org_name (string)

The Pulumi organization name. Used to construct the audience (urn:pulumi:org:<org_name>) for both the Buildkite OIDC token request and the Pulumi token exchange.

Optional

lifetime (number)

The lifetime (in seconds) for the Buildkite OIDC token before it expires. Must be a non-negative integer. When set to 0 (the default), the API uses its default lifetime.

Default: 0

requested_token_type (string)

The type of Pulumi access token to request. Must be one of:

Value Description
urn:pulumi:token-type:access_token:organization Organization-scoped token (default)
urn:pulumi:token-type:access_token:team Team-scoped token (requires scope)
urn:pulumi:token-type:access_token:personal Personal token (requires scope)

Default: urn:pulumi:token-type:access_token:organization

scope (string)

Scope for the requested token. The value depends on the requested_token_type:

Token Type Scope Format Example
Organization admin (optional, for admin privileges) admin
Team team:<TEAM_NAME> team:platform-team
Personal user:<USER_LOGIN> user:jane

The authorization policy must explicitly grant the requested scope.

backend_url (string)

The Pulumi Cloud API base URL. Override this for self-hosted Pulumi Cloud deployments.

Default: https://api.pulumi.com

debug (boolean)

When true, prints the full curl command and API response for troubleshooting. Warning: this exposes both the Buildkite OIDC token and the Pulumi access token in the build log. Only use for debugging.

Default: false

Output

On success, the plugin exports:

  • PULUMI_ACCESS_TOKEN - A short-lived Pulumi access token that authenticates subsequent pulumi CLI commands.

Examples

Minimal: organization access token

steps:
  - label: ":pulumi: Deploy"
    command: "pulumi up --yes --stack my-org/my-stack/production"
    plugins:
      - instant-labs/pulumi-oidc#v0.1.0:
          org_name: "my-org"

Team-scoped access token

steps:
  - label: ":pulumi: Deploy"
    command: "pulumi up --yes --stack my-org/my-stack/production"
    plugins:
      - instant-labs/pulumi-oidc#v0.1.0:
          org_name: "my-org"
          requested_token_type: "urn:pulumi:token-type:access_token:team"
          scope: "team:platform-team"

Personal access token with custom lifetime

steps:
  - label: ":pulumi: Deploy"
    command: "pulumi up --yes --stack my-org/my-stack/production"
    plugins:
      - instant-labs/pulumi-oidc#v0.1.0:
          org_name: "my-org"
          requested_token_type: "urn:pulumi:token-type:access_token:personal"
          scope: "user:jane"
          lifetime: 3600

With Pulumi ESC for cloud credentials

After obtaining a Pulumi access token via this plugin, you can use Pulumi ESC to dynamically fetch cloud provider credentials:

steps:
  - label: ":pulumi: Deploy with ESC"
    commands:
      - eval $(pulumi env open my-org/my-project/aws-prod --format shell)
      - pulumi up --yes --stack my-org/my-stack/production
    plugins:
      - instant-labs/pulumi-oidc#v0.1.0:
          org_name: "my-org"

This uses your Pulumi access token to open an ESC environment that provides temporary AWS/Azure/GCP credentials via OIDC federation. See Configuring OIDC in ESC for environment setup.

References

Development

Run tests:

make test

Run linter:

make lint

License

MIT License. See LICENSE.

About

⚡️ Authenticate to Pulumi using a Buildkite Job OIDC token

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors