Skip to content

Conversation

yob
Copy link

@yob yob commented Mar 3, 2025

Summary

Add minimal support required to generate attestations for rubygems trusted publisher support in a Buildkite job

  1. Teach sigstore-cli gem how to detect when it's running in a Buildkite job, and how to request a Buildkite OIDC token automatically
  2. Teach sigstore gem how to parse an Buildkite OIDC token and generate the identity that fulcio uses for the x509 common name in certificates for Buildkite OIDC tokens

With these changes, the following command works in a Buildkite job:

bundle exec sigstore-cli sign <somefile> --bundle bundle.sigstore.json

I've tested this using the pipeline defined in a gist: https://gist.github.com/yob/512f079e0586d49d125547ad548c08b5

The pipeline is private [1], however an example rekor log for a bundle created using this branch is at [2]

[1] https://buildkite.com/yob-opensource/sigstore-ruby-test/
[2] https://search.sigstore.dev/?logIndex=176164097

Fixes #224

Release Note

  • Adds support for signing and verifying using Buildkite OIDC tokens

"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

@yob yob force-pushed the buildkite branch 2 times, most recently from d2fcad3 to 62c1d06 Compare March 3, 2025 07:38
@yob
Copy link
Author

yob commented Mar 3, 2025

Interesting that the smoketests are failing, I don't think I changed anything that would break GitHub Actions OIDC requests.

On the topic of tests: there didn't seem to be unit tests for either of the files I changed, so I haven't added my own. Maybe the smoketests are the key automation that's being used to prevent regressions? If so, I'm open to ideas on the best way to test the Buildkite code paths. Smoke tests would require a Buildkite account which I'm sure we could arrange, but it'll be a complication to the suite.

segiddins
segiddins previously approved these changes Mar 5, 2025
Copy link
Member

@segiddins segiddins left a comment

Choose a reason for hiding this comment

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

It's probably a permissions thing, I wouldn't worry about it, but cc @woodruffw for thoughts. Currently, the GitHub codepath is exercised both by the smoke tests and the conformance test suite, so this would likely require a basic unit test for coverage

Add minimal support required to generate attestations for rubygems
trusted publisher support in a Buildkite job

1. Teach sigstore-cli gem how to detect when it's running in a Buildkite
   job, and how to request a Buildkite OIDC token automatically
2. Teach sigstore gem how to parse an Buildkite OIDC token and generate
   the identity that fulcio uses for the x509 common name in
   certificates for Buildkite OIDC tokens

With these changes, the following command works in a Buildkite job:

    bundle exec sigstore-cli sign <somefile> --bundle bundle.sigstore.json

I've tested this using the pipeline defined in a gist:
https://gist.github.com/yob/512f079e0586d49d125547ad548c08b5

The pipeline is private [1], however an example rekor log for a bundle
created using this branch is at [2]

[1] https://buildkite.com/yob-opensource/sigstore-ruby-test/
[2] https://search.sigstore.dev/?logIndex=176164097

Signed-off-by: James Healy <[email protected]>

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

Copy link
Member

@segiddins segiddins left a comment

Choose a reason for hiding this comment

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

Looks good with those two small changes!

end

def request_token
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")

status.success?
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

dentarg added a commit to spinels/slenips that referenced this pull request Mar 19, 2025
Found the sign command in rubygems/release-gem#11

Based on sigstore/sigstore-ruby#225, the
sigstore-cli sign command only works when run in GitHub Actions, right
now.

Locally, I got

    $ ruby -S gem exec sigstore-cli:0.2.1 sign slenips --bundle attestation.sigstore.json
    Fetching protobug-0.1.0.gem
    Fetching sigstore-cli-0.2.1.gem
    Fetching protobug_well_known_protos-0.1.0.gem
    Fetching protobug_googleapis_field_behavior_protos-0.1.0.gem
    Fetching protobug_sigstore_protos-0.1.0.gem
    Fetching sigstore-0.2.1.gem
    Failed to detect an ambient identity token, please provide one via --identity-token (Sigstore::Error::InvalidIdentityToken)
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.

Add support for Buildkite environment and OIDC tokens

2 participants