-
Notifications
You must be signed in to change notification settings - Fork 3
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
Enable signing using a custom sigstore instance #9
Conversation
012129e
to
685c014
Compare
This PR extends plugin schema to allow users to specify a custom, ie, non-Public-Good Sigstore Instance to use, including the TUF URLs (used to initialise cosign). Sensible defaults use the Public-Good Sigstore Instance with their current URLs (known to cosign) and the buildkite-agent as the OIDC provider. Documentation was amended to emphasise usage of image digest vs tag and to add more examples for both keyless and keyed signing using the Public-Good and a custom sigstore instance. Bonus: - fix BUILDKITE_PLUGIN_COSIGN variables names - remove the need to explicitly state the Public-Good Sigstore Instance default params (ie, the URLs) - those might change and cosign would know them - refactor code to group and then reuse the common logic, increase readability - bump cosign default version to 2.2.4 - bump plugin-tester to version 4.1.1 - use specific plugin-linter version 2.1.0 instead of latest - fix tests/pre-checkout.bats to work with v2.1.0
@JAORMX as you originally wrote the plugin, i would much appreciate if you can review as well |
Will do! |
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.
Just a question about the defaults, otherwise the script looks good to me
setup_keyless() { | ||
echo "--- :key: Setup cosign keyless signing" | ||
|
||
local rekor_url=${BUILDKITE_PLUGIN_COSIGN_KEYLESS_CONFIG_REKOR_URL} |
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.
Do you need to set a default URL here?
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.
thanks @tenyo !
the default values for the public-good sigstore instance are baked into the cosign binary (that we download and use while plugin is run), and i think we should relay on those in cosign, rather than having our own hardcoded values, that might change at some point - eg, this comment:
// TODO: change this back to api.SigstorePublicServerURL after the v1 migration is complete.
so, for rekor, it's defined here then used as the flag's default value here
for eg, tuf, it's here, etc.
sign_flags+=("--rekor-url" "${rekor_url}") | ||
fi | ||
|
||
local fulcio_url=${BUILDKITE_PLUGIN_COSIGN_KEYLESS_CONFIG_FULCIO_URL} |
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.
Same for this - maybe these are set automatically by cosign
but figured I'd ask.
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.
same as above - for fulcio, it's defined here
hooks/post-command
Outdated
if [[ $status -ne 0 ]]; then | ||
fail_with_message "cosign" "Failed to sign image" | ||
# flags for the cosign initialize command | ||
init_flags=() |
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.
Nitpick: Can this be made a local variable? (i.e., local init_flags=()
)
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.
yeah, we could do that
hooks/post-command
Outdated
|
||
rm out.sig || true | ||
status=$? |
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.
Nitpick: Can status
be made a local variable?
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.
amended
hooks/post-command
Outdated
\`\`\` | ||
EOF | ||
if [ ${#init_flags[@]} -gt 0 ]; then | ||
rm -rf ~/.sigstore |
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 am wondering if we need to delete the whole directory. It would be unfortunate if there are other important things in there. The documentation for cosign initialize
seems to claim that it updates the tuf thing:
Any updated TUF repository will be written to $HOME/.sigstore/root/.
https://github.com/sigstore/cosign/blob/main/doc/cosign_initialize.md
It looks like it gets overwritten:
$ rm -rf ~/.sigstore/
$ cosign initialize --mirror https://foo.com --root https://foo.com/root.json
(...)
$ ls -l ~/.sigstore/root/
total 10
-rw------- 1 x x 56 Jun 18 21:31 remote.json
drwx------ 2 x x 5 Jun 18 21:31 targets
drwxr-xr-x 2 x x 8 Jun 18 21:31 tuf.db
$ date
Tue Jun 18 21:31:55 UTC 2024
$ date
Tue Jun 18 21:32:02 UTC 2024
$ cosign initialize --mirror https://foo.com --root https://foo.com/root.json
(...)
$ ls -l ~/.sigstore/root/
total 10
-rw------- 1 x x 56 Jun 18 21:32 remote.json
drwx------ 2 x x 5 Jun 18 21:31 targets
drwxr-xr-x 2 x x 9 Jun 18 21:32 tuf.db
$ ls -l ~/.sigstore/root/tuf.db/
total 16
-rw-r--r-- 1 x x 2955 Jun 18 21:32 000004.ldb
-rw-r--r-- 1 x x 4928 Jun 18 21:32 000007.log
-rw-r--r-- 1 x x 16 Jun 18 21:32 CURRENT
-rw-r--r-- 1 x x 16 Jun 18 21:32 CURRENT.bak
-rw-r--r-- 1 x x 0 Jun 18 21:31 LOCK
-rw-r--r-- 1 x x 2264 Jun 18 21:32 LOG
-rw-r--r-- 1 x x 87 Jun 18 21:32 MANIFEST-000008
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.
it is not expected to find ~/.sigstore/
there - this is more to ensure that there isn't one
docs suggest removing the whole dir and so that's probably a good idea:
https://docs.sigstore.dev/system_config/public_deployment/#usage and https://docs.sigstore.dev/system_config/public_deployment/#revert-back-to-production
hooks/post-command
Outdated
\`\`\` | ||
EOF | ||
if [ ${#init_flags[@]} -gt 0 ]; then | ||
rm -rf ~/.sigstore |
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.
Does this mean this plugin can only run serially on a given host? Is there a variable one can set to control this directory? Would be ideal if it were unique per plugin run.
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.
good point, thanks!
looks like that's not directly exposed/customisable by cosign initialize
(via flags) but the sigstore tuf client
reads the TUF_ROOT
env var to figure out the location, so i'll try to use that:
// TufRootEnv is the name of the environment variable that locates an alternate local TUF root location.
TufRootEnv = "TUF_ROOT"
similarly, i made the out.sig
filename "dynamic" (pseudo-random) for the same reasons (ie, to avoid potential race condition over the output file between multiple plugin runs on the same host)
waiting for the build (using this plugin) to complete and i'll share results back
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.
yep, looks like that worked:
🔑 Init cosign
Root status:
{
"local": "/var/lib/buildkite-agent/.sigstore-13508/root",
"remote": "https://<REDACTED>",
"metadata": {
"root.json": {
"version": 1,
"len": 2178,
"expiration": "01 Dec 24 19:08 UTC",
"error": ""
},
"snapshot.json": {
"version": 1,
"len": 618,
"expiration": "01 Dec 24 19:08 UTC",
"error": ""
},
"targets.json": {
"version": 1,
"len": 1373,
"expiration": "01 Dec 24 19:08 UTC",
"error": ""
},
"timestamp.json": {
"version": 1,
"len": 619,
"expiration": "01 Dec 24 19:08 UTC",
"error": ""
}
},
"targets": [
"ctfe.pub",
"fulcio_v1.crt.pem",
"rekor.pub"
]
}
Successfully initialised
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.
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.
fwiw, I used @prezha's TUF_ROOT
environment variable finding in a separate project to run multiple instances of cosign
simultaneously on the same computer. Prior to making that change, I was experiencing "resource busy" errors due to each cosign process modifying / writing files in ~/.sigstore
. I think this emulates the same kind of situation we would see in a Buildkite CI runner.
In other words: @prezha's change appears to prevent cosign from stepping on other cosign processes.
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.
thanks @sfox-equinix for checking and confirming!
@JAORMX is there anything additional you think should be addressed?
as per @stephen-fox's suggestion, i've amended the pr so that i think this might be a reasonable "trade-off" - ie, we could add another config option (like use-public-instance or similar, set to false by default), that would require to be even more explicit, but not sure if that'd be justifiable atm, as i don't think there are that many private sigstore instances in the wild (yet): open to suggestions, if people think we should do it that ("proper") way now or improve reasonably later, when appropriate UPDATE: i have practically reverted the last change described in this comment but kept the warnings i've added in the readme, and the reasons are:
|
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.
LGTM, thanks @prezha
@prezha this makes sense as we could have downstream users which we are unaware of given the public nature of this project and it could be a big breaking change for them. Changing the defaults would not prevent user to make a mistake which degrades the original intention for the change. We can look into ways to deal with the |
thanks for the review! |
This PR extends plugin schema to allow users to specify a custom/private, ie, non-Public-Good Sigstore Instance to use, including the TUF URLs (used to initialise cosign).
Sensible defaults use the Public-Good Sigstore Instance with their current URLs (known to cosign) and the buildkite-agent as the OIDC provider.
Documentation was amended to emphasise usage of image digest vs tag and to add more examples for both keyless and keyed signing using the Public-Good and a custom/private Sigstore instance.
Bonus: