diff --git a/cli/lib/sigstore/cli/id_token.rb b/cli/lib/sigstore/cli/id_token.rb index 6877c44..6700a77 100644 --- a/cli/lib/sigstore/cli/id_token.rb +++ b/cli/lib/sigstore/cli/id_token.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "open3" + class Sigstore::CLI class IdToken include Sigstore::Loggable @@ -9,9 +11,9 @@ class AmbientCredentialError < Sigstore::Error def self.detect_credential [ - GitHub + GitHub, + Buildkite # detect_gcp, - # detect_buildkite, # detect_gitlab, # detect_circleci ].each do |detector| @@ -85,5 +87,33 @@ def call end end end + + class Buildkite < IdToken + def call + logger.debug { "looking for OIDC credentials" } + unless ENV["BUILDKITE"] + logger.debug { "environment doesn't look like Buildkite; giving up" } + return + end + + raise AmbientCredentialError, "buildkite-agent executable not found" unless buildkite_agent_found? + + request_token + end + + private + + def buildkite_agent_found? + _, status = Open3.capture2("which buildkite-agent") + status.success? + end + + def request_token + token, status = Open3.capture2("buildkite-agent oidc request-token --audience sigstore") + raise AmbientCredentialError, "error requesting Buildkite OIDC token" unless status.success? + + token.strip + end + end end end diff --git a/lib/sigstore/oidc.rb b/lib/sigstore/oidc.rb index 77918a9..6ee9e8f 100644 --- a/lib/sigstore/oidc.rb +++ b/lib/sigstore/oidc.rb @@ -20,7 +20,8 @@ module OIDC "https://accounts.google.com" => "email", "https://oauth2.sigstore.dev/auth" => "email", "https://oauth2.sigstage.dev/auth" => "email", - "https://token.actions.githubusercontent.com" => "job_workflow_ref" + "https://token.actions.githubusercontent.com" => "job_workflow_ref", + "https://agent.buildkite.com" => "pipeline_slug" }.freeze private_constant :KNOWN_OIDC_ISSUERS @@ -47,8 +48,20 @@ def initialize(raw_token) end @identity = @unverified_claims[identity_claim] - # https://github.com/sigstore/fulcio/blob/8311f93c01ea5b068a86d37c4bb51573289bfd69/pkg/identity/github/principal.go#L92 - @identity = "https://github.com/#{@identity}" if issuer == "https://token.actions.githubusercontent.com" + case issuer + when "https://token.actions.githubusercontent.com" + # https://github.com/sigstore/fulcio/blob/8311f93c01ea5b068a86d37c4bb51573289bfd69/pkg/identity/github/principal.go#L92 + @identity = "https://github.com/#{@identity}" + when "https://agent.buildkite.com" + # https://github.com/sigstore/fulcio/blob/ec8a1d7a96125a1a624b9e69df892f987bebc41c/config/identity/config.yaml#L241 + org_slug = @unverified_claims["organization_slug"] + if org_slug.nil? + raise Error::InvalidIdentityToken, + "identity token is missing required claim: organization_slug" + end + + @identity = "https://buildkite.com/#{org_slug}/#{@identity}" + end else @identity = @unverified_claims["sub"] end