Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use GitHub's Artifact Attestations #3128

Open
4 tasks
sormuras opened this issue Jan 12, 2023 · 17 comments
Open
4 tasks

Use GitHub's Artifact Attestations #3128

sormuras opened this issue Jan 12, 2023 · 17 comments

Comments

@sormuras
Copy link
Member

sormuras commented Jan 12, 2023

Generate verify-able signed attestations for every artifact made with GitHub Actions.

Attestations do appear here:

TODO

@sormuras sormuras changed the title Uses sigstore-gardle-plugin to sign released JAR Use sigstore-gardle-plugin to sign released JAR files Jan 12, 2023
@marcphilipp marcphilipp changed the title Use sigstore-gardle-plugin to sign released JAR files Use sigstore-gradle-plugin to sign released JAR files Jan 13, 2023
@vcvitaly
Copy link

I can take a look.

@sormuras
Copy link
Member Author

Note to myself: update the TODO in the initial description

Next: I was waiting for some pull requests in sigstore-java to be merged first. Some of them are!

For example

@vlsi what do you think? Is about the right time to use the Gradle plugin to sign JUnit's artifacts in addition to the current PGP workflow?

@vlsi
Copy link
Contributor

vlsi commented Jan 31, 2023

A critical PR is

otherwise the generated bundle is just invalid as it misses signature field.

That would be pretty good, however, you'll need to update sigstore-java every time Fulcio/Rekor certificates change.
Automatic fetching of certificates is tracked in

@sormuras
Copy link
Member Author

Thanks for the quick reply, Vladimir!

Updating the status of this issue accordingly.

@sormuras
Copy link
Member Author

Wondering whether we can achieve the same effect (meaning, sign all JAR files) by using some GitHub Action after the build produced them? 🤔

Something similar to:

publish_artifacts:

@vlsi
Copy link
Contributor

vlsi commented Jan 31, 2023

Of course, you can sign all the jars, poms, and other files via Action.

Here's the way you can generate signatures: https://github.com/sigstore/protobuf-specs/blob/16541696de137c6281d66d075a4924d9bbd181ff/java/scripts/sign_and_bundle_release.sh#L72

@vlsi
Copy link
Contributor

vlsi commented Jan 31, 2023

Just in case, the most secure approach would be signing the files within a separate GitHub workflow, so only well-known binaries have access to signing credentials (e.g. OIDC token).

In other words:

  1. Prepare release files, and export them via "upload-artifacts" action or something like that
  2. Sign them in a separate workflow
  3. Collect all the signed files and publish them (e.g. push to Nexus)

I am afraid that sounds like a non-trivial GitHub Actions exercise.
However, I consider the above Gradle plugin as a quick win for those who want to start signing without creating complicated workflows.

@vlsi
Copy link
Contributor

vlsi commented Feb 1, 2023

One more thing: there's https://github.com/slsa-framework/slsa-github-generator effort to come up with a reusable workflow for creating the attestations.

@vlsi
Copy link
Contributor

vlsi commented Feb 1, 2023

Something similar to:

publish_artifacts:

The sad thing is that you launch Gradle with all the third-party plugins with Sonatype credentials.
In the ideal world, we would like to expose credentials to a tiny tool that pushes code to Central only. That would reduce the attack surface. However, it sounds like it makes all "Gradle release plugins" unnecessary. Frankly speaking, that is slightly disappointing since I like how many tasks are easier to manage in Gradle rather than in bash scripts.

Recently GitHub improved "reusable workflows" part, so it might be that there's a possibility to come up with a reusable workflow that you just copy&paste and get "safe and secure" sign&push to Central.

@sormuras
Copy link
Member Author

sormuras commented Jun 4, 2024

With https://github.blog/2024-05-02-introducing-artifact-attestations-now-in-public-beta/ we can achieve artitfact attestations by calling https://github.com/actions/attest-build-provenance for all our artifacts just before deployment. No build tool plugin is required - updating the issue title accordingly.

@sormuras sormuras changed the title Use sigstore-gradle-plugin to sign released JAR files Use GitHub's Artifact Attestations Jun 4, 2024
sormuras added a commit that referenced this issue Jun 6, 2024
Addresses part of #3128

---------

Co-authored-by: Marc Philipp <mail@marcphilipp.de>
@marcphilipp
Copy link
Member

@sormuras With #3846 merged, can we consider this done for now?

@sormuras
Copy link
Member Author

sormuras commented Jun 6, 2024

I was just about to add these items to the description:

TODO

But those could also go into dedicated issues.

@marcphilipp
Copy link
Member

I think adding them to this issue is fine. I was just wondering what's left to do, if anything.

@vlsi
Copy link
Contributor

vlsi commented Jun 6, 2024

Delete attestations generated by pull requests

In practice, you don't want allowing id-token: write for pull request builds as they might generate attestations that look like "produced by junit-team".

https://github.com/sigstore-conformance/extremely-dangerous-public-oidc-beacon exists exactly for the reason of avoiding id-token: write for PR builds and still having a valid OIDC token for the test purposes.


At the same time, you probably want to attest the generated pom files as well

@sormuras
Copy link
Member Author

sormuras commented Jun 6, 2024

In practice, you don't want allowing id-token: write for pull request builds [...]

Good to learn. Is there another way to guard against that? Like having a dedicated workflow build for attestation that only runs on behalf of the "junit-team"? Doesn't the following line already take care about that?

if: github.event_name == 'push' && github.repository == 'junit-team/junit5' && (startsWith(github.ref, 'refs/heads/releases/') || github.ref == 'refs/heads/main')

@sormuras
Copy link
Member Author

sormuras commented Jun 6, 2024

At the same time, you probably want to attest the generated pom files as well

We'll start with JAR files for the time being. Otherwise, why stop with pom files and not include hash files, Gradle modules files, etc. Mind that every type is multiplied with 19 ... the number of published packages by the JUnit 5 project.

As soon as Sonatype permits us to drop PGP/GPG for deployments to Maven Central and uses Sigstore-based attestations instead, we should consider generating attests for every and each file.

@sormuras sormuras self-assigned this Jun 6, 2024
@vlsi
Copy link
Contributor

vlsi commented Jun 6, 2024

include hash files

The attestations attest hash of the file, so creating separate attestations for hash files sounds wasteful, and it adds no value.
The same goes for PGP: you don't generate PGP signatures for .sha1 filles.
By the way, both PGP and Sigstore are cryptographic signatures, so cross-signing makes no sense.


As soon as Sonatype permits us to drop PGP/GPG for deployments to Maven Central and uses Sigstore-based attestations instead, we should consider generating attests for every and each file

I would suggest you keep publishing both PGP and Sigstore for backward compatibility reasons.
There are clients that verify PGP signatures for their dependencies, and removing PGP would be a step backwards.


Gradle modules files

There's a cyclic dependency when signing metadata.


Doesn't the following line already take care about that?

Having if branch==main is good, however, keep in mind you still execute full Gradle build with all its dependencies, and every bit of it has access to id-token.
At the same time, if you add id-token: write for the trusted branches only, then you do not need to "delete attestations generated by PRs".

In the ideal world, we execute build without id-token: write privileges, and then execute attestation for the generated files. Then only attestation step would have access to the token.
I've raised actions/attest-build-provenance#103 to check the indented usage with respect to security.


As soon as Sonatype permits us to drop PGP/GPG for deployments to Maven Central

As far as I know, Maven Central already supports uploading .sigstore.json files without the corresponding .asc PGP signatures. It does not validate the contents, however, it recognizes .sigstore.json is cryptographic enough to not require PGP.

For instance, see check out .sigstore.json files at https://repo1.maven.org/maven2/dev/sigstore/sigstore-java/0.10.0/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants