diff --git a/README.md b/README.md
index 431a8b6..4da4e4b 100644
--- a/README.md
+++ b/README.md
@@ -5,15 +5,15 @@ open-source cosign OCI container image signing tool for your containers.
For more information about cosign, please refer to their
[documentation](https://docs.sigstore.dev/cosign/overview).
-**Important notes**:
+**Important notes**
-To be certain you know what you're signing:
+To ensure you know what you're signing:
-- It's best to have this plugin run as part of the image ci build step (where the
+- It's best to have this plugin run as part of the image CI build step (where the
built image is stored locally) and not as a separate step (signing a remote image).
-
-- It's strongly recommended to use image digest instead of image tag. Otherwise,
-you might get a warning from cosign, or it may even refuse to sign the image:
+- It's strongly recommended to use image digest instead of image tag (plugin will
+automatically try to infer and use digest based on the provided image tag).
+Otherwise, you might get a warning from cosign, or it may even refuse to sign the image:
>WARNING: Image reference ghcr.io/my-project/my-image:v1.2.3 uses a tag, not a
digest, to identify the image to sign.
This can lead you to sign a different image than the intended one. Please use a
@@ -28,8 +28,13 @@ digest, to identify the image to sign.
## Basic signing examples
-The following code snippet demonstrates how to use the plugin in a pipeline
-step with the default plugin configuration parameters:
+The following code snippets demonstrates how to use the plugin in a pipeline
+step with the configuration parameters and upload the signature to the same
+repository as the container image.
+
+### Keyless signing
+
+#### Using the Public-Good Sigstore Instance
```yml
steps:
@@ -38,11 +43,7 @@ steps:
image: "ghcr.io/my-project/my-image@sha256:1e1e4f97dd84970160975922715909577d6c12eaaf6047021875674fa7166c27"
```
-This will use the `keyless` signing with the `Public-Good` Sigstore Instance by
-default and upload the signature to the same repository as the container image.
-
-The following code snippet demonstrates how to use the plugin for `keyless` signing
-with specified `custom` Sigstore instance URLs:
+#### Using a custom Sigstore Instance
```yml
steps:
@@ -52,8 +53,39 @@ steps:
keyless-config:
tuf-mirror-url: "https://tuf.my-sigstore.dev"
tuf-root-url: "https://tuf.my-sigstore.dev/root.json"
+ rekor-url: "https://rekor.my-sigstore.dev"
fulcio-url: "https://fulcio.my-sigstore.dev"
+```
+
+### Keyed signing
+
+Note: Currently, only the file-based keyed signing is supported.
+
+#### Using the Public-Good Sigstore Instance
+
+```yml
+steps:
+ - plugins:
+ - equinixmetal-buildkite/cosign#v0.1.0:
+ image: "ghcr.io/my-project/my-image@sha256:1e1e4f97dd84970160975922715909577d6c12eaaf6047021875674fa7166c27"
+ keyless: false
+ keyed-config:
+ key: "/path-to/cosign.key"
+```
+
+#### Using a custom Sigstore Instance
+
+```yml
+steps:
+ - plugins:
+ - equinixmetal-buildkite/cosign#v0.1.0:
+ image: "ghcr.io/my-project/my-image@sha256:1e1e4f97dd84970160975922715909577d6c12eaaf6047021875674fa7166c27"
+ keyless: false
+ keyed-config:
+ tuf-mirror-url: "https://tuf.my-sigstore.dev"
+ tuf-root-url: "https://tuf.my-sigstore.dev/root.json"
rekor-url: "https://rekor.my-sigstore.dev"
+ key: "/path-to/cosign.key"
```
## Configuration
@@ -81,12 +113,12 @@ parameters to sign the container image:
- `tuf-root-url` (Optional, string):
The URL of the TUF root JSON file to use. If not specified, the plugin will use
the default TUF root JSON file URL of the Public-Good Sigstore Instance.
-- `fulcio_url` (Optional, string):
- The URL of the Fulcio server to use. If not specified, the plugin will use
- the default Fulcio URL of the Public-Good Sigstore Instance.
- `rekor_url` (Optional, string):
The URL of the Rekor server to use. If not specified, the plugin will use
the default Rekor URL of the Public-Good Sigstore Instance.
+- `fulcio_url` (Optional, string):
+ The URL of the Fulcio server to use. If not specified, the plugin will use
+ the default Fulcio URL of the Public-Good Sigstore Instance.
- `oidc-issuer` (Optional, string):
The URL of the OIDC issuer. If not specified, the plugin will use
the default OIDC issuer URL of the Public-Good Sigstore Instance.
@@ -99,6 +131,15 @@ parameters to sign the container image:
If `keyless` is set to `false`, the plugin will use the following configuration
parameters to sign the image:
+- `tuf-mirror-url` (Optional, string):
+ The URL of the TUF server to use. If not specified, the plugin will use
+ the default TUF URL of the Public-Good Sigstore Instance.
+- `tuf-root-url` (Optional, string):
+ The URL of the TUF root JSON file to use. If not specified, the plugin will use
+ the default TUF root JSON file URL of the Public-Good Sigstore Instance.
+- `rekor_url` (Optional, string):
+ The URL of the Rekor server to use. If not specified, the plugin will use
+ the default Rekor URL of the Public-Good Sigstore Instance.
- `key` (Required, string): The path to the private key to use.
### `cosign-version` (Optional, string)
diff --git a/hooks/post-command b/hooks/post-command
index c91e173..1d00f2c 100755
--- a/hooks/post-command
+++ b/hooks/post-command
@@ -33,134 +33,132 @@ display_success() {
buildkite-agent annotate --style success "$message
" --context "$ctx"
}
-# Parameters
-############
+# if the supplied image reference does not contain a digest,
+# try getting the local image digest to use it instead, and
+# if that fails, warn then continue using the supplied image reference
+use_image_digest() {
+ if [[ $image != *"@sha256:"* ]]; then
+ echo "--- :docker: Getting the local image digest for ${image}"
+
+ local digest
+ digest=$(docker inspect --format='{{index .RepoDigests 0}}' "${image}")
-# This is a required parameter
+ status=$?
+ if [[ $status -ne 0 ]]; then
+ display_error "docker inspect" "Failed to get the local image digest, will continue using supplied image reference ${image}"
+ else
+ display_success "docker inspect" "Will continue using ${digest}"
+ image="${digest}"
+ fi
+ fi
+}
+
+# Common parameters
+###################
+
+# image is a required parameter
image=${BUILDKITE_PLUGIN_COSIGN_IMAGE}
if [[ -z "${image}" ]]; then
- fail_with_message "cosign" "No image specified"
+ fail_with_message "cosign" "Image not specified"
fi
+use_image_digest
+
+# flags for the cosign sign command
+sign_flags=("-y" "--output-signature" "out.sig")
is_keyless=${BUILDKITE_PLUGIN_COSIGN_KEYLESS:-true}
# Hook functions
################
-cosign_keyless() {
- echo "--- :key: Cosign keyless signing"
-
- rm -f out.sig
+# if provided, initialise cosign with a custom TUF configuration
+cosign_init() {
+ echo "--- :key: Init cosign"
# flags for the cosign initialize command
init_flags=()
- local tuf_mirror_url=${BUILDKITE_PLUGIN_COSIGN_KEYLESS_CONFIG_TUF_MIRROR_URL}
+ if [[ "${is_keyless}" == true ]]; then
+ local tuf_mirror_url=${BUILDKITE_PLUGIN_COSIGN_KEYLESS_CONFIG_TUF_MIRROR_URL}
+ local tuf_root_url=${BUILDKITE_PLUGIN_COSIGN_KEYLESS_CONFIG_TUF_ROOT_URL}
+ else
+ local tuf_mirror_url=${BUILDKITE_PLUGIN_COSIGN_KEYED_CONFIG_TUF_MIRROR_URL}
+ local tuf_root_url=${BUILDKITE_PLUGIN_COSIGN_KEYED_CONFIG_TUF_ROOT_URL}
+ fi
+
if [[ -n "${tuf_mirror_url}" ]]; then
init_flags+=("--mirror" "${tuf_mirror_url}")
fi
- local tuf_root_url=${BUILDKITE_PLUGIN_COSIGN_KEYLESS_CONFIG_TUF_ROOT_URL}
if [[ -n "${tuf_root_url}" ]]; then
init_flags+=("--root" "${tuf_root_url}")
fi
- # if supplied, initialise cosign with a custom TUF configuration
if [ ${#init_flags[@]} -gt 0 ]; then
- echo "--- :key: Initialising cosign with the custom TUF configuration provided"
cosign initialize "${init_flags[@]}"
status=$?
if [[ $status -ne 0 ]]; then
fail_with_message "cosign" "Failed to initialise"
fi
+ display_success "cosign" "Successfully initialised"
+ else
+ display_success "cosign" "Initialisation not required, skipping"
fi
+}
- # flags for the cosign sign command
- sign_flags=()
-
- local fulcio_url=${BUILDKITE_PLUGIN_COSIGN_KEYLESS_CONFIG_FULCIO_URL}
- if [[ -n "${fulcio_url}" ]]; then
- sign_flags+=("--fulcio-url" "${fulcio_url}")
- fi
+setup_keyless() {
+ echo "--- :key: Setup cosign keyless signing"
local rekor_url=${BUILDKITE_PLUGIN_COSIGN_KEYLESS_CONFIG_REKOR_URL}
if [[ -n "${rekor_url}" ]]; then
sign_flags+=("--rekor-url" "${rekor_url}")
fi
+ local fulcio_url=${BUILDKITE_PLUGIN_COSIGN_KEYLESS_CONFIG_FULCIO_URL}
+ if [[ -n "${fulcio_url}" ]]; then
+ sign_flags+=("--fulcio-url" "${fulcio_url}")
+ fi
+
local oidc_issuer=${BUILDKITE_PLUGIN_COSIGN_KEYLESS_CONFIG_OIDC_ISSUER}
if [[ -n "${oidc_issuer}" ]]; then
sign_flags+=("--oidc-issuer" "${oidc_issuer}")
fi
local oidc_provider=${BUILDKITE_PLUGIN_COSIGN_KEYLESS_CONFIG_OIDC_PROVIDER:-"buildkite-agent"}
- sign_flags+=("--oidc-provider" "${oidc_provider}")
-
- # if the supplied image reference does not contain a digest, try getting the local image digest to use it instead
- if [[ $image != *"@sha256:"* ]]; then
- echo "--- :docker: Getting the local image digest for ${image}"
-
- local digest
- digest=$(docker inspect --format='{{index .RepoDigests 0}}' "${image}")
-
- status=$?
- if [[ $status -ne 0 ]]; then
- display_error "docker inspect" "Failed to get the local image digest, will continue using supplied image reference ${image}"
- else
- display_success "docker inspect" "Will continue using ${digest}"
- image="${digest}"
- fi
+ if [[ -n "${oidc_provider}" ]]; then
+ sign_flags+=("--oidc-provider" "${oidc_provider}")
fi
+}
- # sign the image
- cosign sign \
- -y \
- "${sign_flags[@]}" \
- --output-signature=out.sig \
- "${image}"
+setup_keyed() {
+ echo "--- :key: Setup cosign keyed signing"
- status=$?
- if [[ $status -ne 0 ]]; then
- fail_with_message "cosign" "Failed to sign image"
+ local rekor_url=${BUILDKITE_PLUGIN_COSIGN_KEYED_CONFIG_REKOR_URL}
+ if [[ -n "${rekor_url}" ]]; then
+ sign_flags+=("--rekor-url" "${rekor_url}")
fi
- local signature
- signature=$(cat out.sig)
-
- display_success "cosign" "Successfully signed image."
- cat <