-
Notifications
You must be signed in to change notification settings - Fork 95
docs: proposal for signing and verifying OSS release assets #1265
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
Closed
JeyJeyGao
wants to merge
8
commits into
notaryproject:main
from
JeyJeyGao:docs/notation_signing_github_release
Closed
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
b1b1226
docs: sign and verify github release assets
JeyJeyGao 760cb74
fix: update blob spec
JeyJeyGao 743524e
fix: update blob.md
JeyJeyGao 308e26a
fix: update
JeyJeyGao 7c25ef9
fix: add ux for notation-signer plugin
JeyJeyGao 3a9c488
fix: update
JeyJeyGao b7e7fc3
fix: update
JeyJeyGao 4d6587a
fix: update
JeyJeyGao File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| ## Proposal for Signing and Verifying OSS Release Assets | ||
|
|
||
| ### Overview | ||
|
|
||
| This document proposes enhancing Notation's capabilities for signing and verifying Open Source Software (OSS) community released assets. It outlines the design for a new vendor-neutral `notation-signer` plugin and introduces a simplified, stateless verification mode for the `notation blob verify` command. | ||
|
|
||
| ### Problem Statement & Motivation | ||
|
|
||
| The existing issues highlight potential customer needs for notation: | ||
| - [Sign Notation CLI release assets with Notation GitHub Actions](https://github.com/notaryproject/notation/issues/973) | ||
| - [Support using signing key from GitHub Encrypted Secret](https://github.com/notaryproject/notation/issues/905) | ||
| - [Signing with local private keys](https://github.com/notaryproject/notation/issues/539) | ||
| - [UX: broken default `notation verify` experience](https://github.com/notaryproject/notation/issues/430) | ||
|
|
||
| To summarize the existing issues, we have two pain points: | ||
| 1. A challenge is the lack of a vendor-neutral Notation plugin to sign with a local encrypted key; existing plugins are cloud-provider specific (AKV, AWS), while the OSS community often prefers neutral solutions. | ||
| 2. Furthermore, the key challenge is the standard verification process is overly complex for typical community users whose primary need is simple verification of a downloaded file and its signature. This complexity, requiring multiple manual steps (adding certificates to a trust store, configuring trust policies) for each publisher, hinders adoption for simple asset verification use cases. | ||
|
|
||
| Considering Notation v2.0.0-alpha.1 introduced blob signing, enabling the signing of assets like GitHub releases is possible. Addressing these challenges is crucial to significantly broaden Notation's use case and improve its adoption within the OSS community for asset signing. | ||
|
|
||
| **Goals:** | ||
|
|
||
| * Provide a vendor-neutral signing solution for OSS publishers. | ||
| * Simplify the verification experience for OSS users needing to verify downloaded assets and their signatures. | ||
| * Significantly broaden the use case and improve adoption of Notation within the OSS community for asset signing. | ||
|
|
||
| **Non-Goals:** | ||
|
|
||
| * Overhaul the general Notation trust store and trust policy management system for complex or persistent verification scenarios. | ||
| * Address signing or verification of container images (as blob signing specifically targets arbitrary files). | ||
|
|
||
| ### Background & Context | ||
|
|
||
| Notation's existing blob signing feature provides the foundational capability to sign arbitrary files. However, the initial implementation focused on cloud-specific key management solutions like AKV and AWS, leaving a gap for users seeking a more universally deployable or self-hosted signing method. Simultaneously, the standard `notation verify` command workflow, designed for robust and policy-driven verification, presents a barrier to entry for users with straightforward, one-off verification needs. | ||
|
|
||
| ### Scenarios | ||
|
|
||
| **OSS Publishers:** A publisher needs a reliable, automated way to sign release binaries or tarballs before uploading them to platforms like GitHub Releases. They require a signing solution that is easily integrated into CI/CD and doesn't depend on specific cloud providers, ideally supporting keys stored securely (e.g., encrypted locally or in secrets) and certificates publicly available (e.g., in the code repository). | ||
|
|
||
| **OSS Users:** A user downloads an asset file and its detached signature from an OSS project release page. They need a simple command-line tool to quickly verify the file's authenticity and integrity using the signature file and publicly available certificate information (like a URL, fingerprint, and trusted identity). | ||
|
|
||
| ### Impact to Users and Ecosystem | ||
|
|
||
| Implementing a vendor-neutral signer plugin would empower a wider range of OSS projects to adopt Notation for signing their releases without relying on specific cloud infrastructure, fostering a more diverse signing ecosystem. The simplified verification workflow will dramatically lower the barrier to entry for users wanting to verify OSS downloads, increasing confidence in the provenance of community-released software and potentially improving overall supply chain security practices within the OSS space. | ||
|
|
||
| ### Existing Solutions or Expectations | ||
|
|
||
| Currently, verifying a detached blob signature with Notation requires users to manually download the root certificate, add it to their local trust store, define a trust policy referencing the trust store, and then execute the `notation verify` command. This multi-step process, involving at least 4-5 commands, is cumbersome for one-time verifications. Users often expect a simpler mechanism, perhaps a single command, to check the signature of a downloaded file against a publicly available certificate and identity claim. | ||
|
|
||
| ### Proposal | ||
|
|
||
| This proposal suggests two key enhancements: | ||
|
|
||
| 1. **Notation Signer Plugin (`notation-signer`)**: A new plugin implementation allowing users to sign blobs or artifacts using a locally stored key and certificate bundle. The key would ideally be encrypted, with the password manageable via environment variables or secure inputs (e.g., GitHub Actions secrets). The certificate could be stored alongside the signed assets or in the code repository for easy public access. This provides a vendor-neutral signing option. | ||
|
|
||
| **Desired User Experience / CLI Operation:** | ||
| 1. The publisher obtains a private key `notation.key` with a certificate bundle `notation.pem`, either self-signed or CA-issued. | ||
| 2. Download the `notation-signer` plugin locally, and call `encrypt` command with password to get an encrypted key `notation.key.enc`. | ||
| ```sh | ||
| # on local machine | ||
| notation-signer encrypt notation.key | ||
| ``` | ||
| 3. The publisher adds the content of the encrypted key `notation.key.enc` and the password to the CI workflow secret (GitHub Action Secret), then exports them as environment variables `NOTATION_SIGNER_KEY` and `NOTATION_SIGNER_KEY_PASSWORD` later for the `notation` binary. | ||
| 4. Configure the release workflow to set up `notation` with the `notation-signer` plugin. | ||
| 5. Export the secrets as environment variables for notation and call the `notation blob sign` command to sign the release asset: | ||
| ```sh | ||
| # on CI workflow | ||
| notation blob sign --id signer --plugin signer \ | ||
| --plugin-config certificate_bundle_path=./notation.pem \ | ||
| <release-asset-path> | ||
| ``` | ||
| 6. The publisher attaches the assets, along with their signatures, to the release page. | ||
|
|
||
| 2. **Simplified Notation Blob Verify Command (`notation blob verify`)**: This proposes adding flags to the existing `notation blob verify` command to enable a simplified, stateless verification mode for blob signatures. These flags are: | ||
| * `--certificate-url <url>`: A URL to the root certificate. | ||
| * `--certificate-sha256-fingerprint <fingerprint>`: A SHA256 fingerprint of the root certificate to verify the downloaded file. | ||
| * `--certificate-path <path>`: *Alternatively*, provide a local root certificate file path instead of a remote URL and fingerprint. | ||
| * `--trusted-identity <identity>`: A trusted identity claim for the signing certificate (e.g., `x509.subject:...`). | ||
|
|
||
| When these flags are provided, the command will operate in a **stateless mode**: | ||
| * If `--certificate-url` is used, download the root certificate and verify its SHA256 fingerprint against the specified value. If `--certificate-path` is used, load the local certificate. | ||
| * Create an in-memory trust store containing the verified root certificate. | ||
| * Create an in-memory, temporary trust policy based on the provided trusted identity and the in-memory trust store. | ||
| * Perform the signature verification of the target file using the signature file against the in-memory trust store and policy. | ||
| * Report success or failure. | ||
|
|
||
| This approach eliminates the need for users to manage persistent trust stores or policy files for simple verification tasks. | ||
|
|
||
| **Desired User Experience / CLI Operation:** | ||
|
|
||
| ```bash | ||
| SIGNATURE=<signature-path> | ||
| TARGET_FILE=<signed-target-file-path> | ||
|
|
||
| # Using remote certificate | ||
| notation blob verify \ | ||
| --certificate-url "https://raw.githubusercontent.com/JeyJeyGao/notation-local-signer/refs/tags/v0.1.0/notation.crt" \ | ||
| --certificate-sha256-fingerprint "F3:5E:B5:3F:6A:BF:55:89:BA:51:EB:39:7B:1A:BA:3A:0A:30:77:14:2C:12:BD:86:EF:5F:CD:54:C5:BE:8B:C4" \ | ||
| --trusted-identity "x509.subject: C = US, ST = Redmond, L = Redmond, O = notation, CN = notation-local-signer" \ | ||
| --signature $SIGNATURE \ | ||
| $TARGET_FILE | ||
|
|
||
| # Or using a local certificate file | ||
| notation blob verify \ | ||
| --certificate-path "./notation.crt" \ | ||
| --trusted-identity "x509.subject: C = US, ST = Redmond, L = Redmond, O = notation, CN = notation-local-signer" \ | ||
| --signature $SIGNATURE \ | ||
| $TARGET_FILE | ||
| ``` | ||
|
|
||
| **Security Considerations for Stateless Verification:** | ||
|
|
||
| The security of the stateless verification process heavily relies on the user providing correct and trustworthy values for the certificate source (URL/path and fingerprint) and the trusted identity. The certificate fingerprint check (when using a URL) is a critical step to mitigate risks associated with downloading the certificate from a potentially compromised location. Publishers must ensure these values are accurate. Providing these verification details from a source separate from where the signed asset and signature are hosted (e.g., the project's official website rather than just the GitHub release page) can enhance trust by avoiding reliance on a single point of compromise. | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do have a concern regarding step 1, where user needs to bring their own private key. A leak of this private key could be a severe security issue. I'm thinking if we can give
notation-signerthe capability to generate a key pair, so that the signer can generate their key pair in the CI release pipeline on the fly. This private key is short-lived and won't be stored anywhere in the whole process.Take GitHub release as an example:
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand your concern, so we have step 2 to encrypt the key. After step 2, the original key can be removed. The risk of leaking the key will be low as we have password encryption.
Regarding your suggestion, I think the critical issue is ensuring authenticity. Every release has a new certificate, which serves as the trust anchor and proves authenticity. Publishing the signature with the certificate is very risky. As you know, our signature includes the certificate chain, so using the certificate published with the signature is similar to using the certificate in the signature directly. We should put the signature and certificate in different trust sources.
If we prefer a short-lived certificate, we should have a way to ensure authenticity. OIDC is a solution since the signing step needs to authenticate the signer's identity, but that is another story.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The nature of letting the user deal with their own private key is not secure. This is the fundamental reason that we use key vaults in other Notation plugins. In addition, it is more convenient to generate the key pair on the fly. User won't need to worry about how to store/remove their private keys.
What do you mean by
Publishing the signature with the certificate is very risky? The verifier needs the public key to verify the signature, the certificate chain contains the signing certificate and is published along with the signature right (as an unprotected header)?