Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions cli/lib/sigstore/cli/id_token.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require "open3"

class Sigstore::CLI
class IdToken
include Sigstore::Loggable
Expand All @@ -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|
Expand Down Expand Up @@ -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?
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using open3 from stdlib is a handy way to avoid using globals and still check the exist status, but I'm open to alternatives if you'd prefer

end

def request_token
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can delete buildkite_agent_found? entirely if request_token is made to rescue Errno::ENOENT and Errno::EACCES and then re-raises AmbientCredentialError

token, status = Open3.capture2("buildkite-agent oidc request-token --audience sigstore")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
token, status = Open3.capture2("buildkite-agent oidc request-token --audience sigstore")
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
19 changes: 16 additions & 3 deletions lib/sigstore/oidc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we actually need two claims to generate the full identity for a Buildkite fulcio certificate. I do that further down, which is a bit messy

}.freeze
private_constant :KNOWN_OIDC_ISSUERS

Expand All @@ -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
Expand Down
Loading