From b529625eb49c61b45d9ebe9e595399eac5001990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ravier?= Date: Fri, 24 Nov 2023 15:53:18 +0100 Subject: [PATCH] Add support for signing with Sigstore Fixes: https://github.com/redhat-actions/push-to-registry/issues/89 --- README.md | 1 + action.yml | 3 +++ src/generated/inputs-outputs.ts | 6 ++++++ src/index.ts | 27 +++++++++++++++++++++++++++ 4 files changed, 37 insertions(+) diff --git a/README.md b/README.md index 8d37010..cba3c8f 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Refer to the [`podman push`](http://docs.podman.io/en/latest/markdown/podman-man | password | Password, encrypted password, or access token to use to log in to the registry. Required unless already logged in to the registry. | None | tls-verify | Verify TLS certificates when contacting the registry. Set to `false` to skip certificate verification. | `true` | digestfile | After copying the image, write the digest of the resulting image to the file. The contents of this file are the digest output. | Auto-generated from image and tag +| sigstore-private-key | Sigstore private key to use to sign container images | None | extra-args | Extra args to be passed to podman push. Separate arguments by newline. Do not use quotes. | None diff --git a/action.yml b/action.yml index 4953e72..d076ea3 100644 --- a/action.yml +++ b/action.yml @@ -33,6 +33,9 @@ inputs: By default, the filename will be determined from the image and tag. The contents of this file are the digest output. required: false + sigstore-private-key: + description: 'Sigstore private key to use to sign container images' + required: false extra-args: description: | Extra args to be passed to podman push. diff --git a/src/generated/inputs-outputs.ts b/src/generated/inputs-outputs.ts index 73a2b29..6ef6ec4 100644 --- a/src/generated/inputs-outputs.ts +++ b/src/generated/inputs-outputs.ts @@ -52,6 +52,12 @@ export enum Inputs { * Default: None. */ USERNAME = "username", + /** + * Sigstore private key to use to sign container images + * Required: false + * Default: None. + */ + SIGSTORE_PRIVATE_KEY = "sigstore-private-key", } export enum Outputs { diff --git a/src/index.ts b/src/index.ts index bc537e8..78e7d2b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -209,6 +209,20 @@ async function run(): Promise { } } + const sigstorePrivateKey = core.getInput(Inputs.SIGSTORE_PRIVATE_KEY); + const sigstorePrivateKeyFile = path.join(process.env.RUNNER_TEMP || "", "sigstore_private_key"); + if (sigstorePrivateKey) { + // Write sigstore private key to a temporary file in $RUNNER_TEMP that + // will be removed after the image is pushed. + try { + await fs.promises.writeFile(sigstorePrivateKeyFile, sigstorePrivateKey); + } + catch (err) { + throw new Error(`Could not write sigstore private key to temporary file ` + + `"${sigstorePrivateKeyFile}": ${err}`); + } + } + let pushMsg = `⏳ Pushing "${sourceImages.join(", ")}" to "${destinationImages.join(", ")}" respectively`; if (username) { pushMsg += ` as "${username}"`; @@ -269,11 +283,24 @@ async function run(): Promise { args.push(`--creds=${creds}`); } + if (sigstorePrivateKey) { + args.push("--sign-by-sigstore-private-key"); + args.push(sigstorePrivateKeyFile); + } + await execute(await getPodmanPath(), args); core.info(`✅ Successfully pushed "${sourceImages[i]}" to "${destinationImages[i]}"`); registryPathList.push(destinationImages[i]); + try { + await fs.promises.unlink(sigstorePrivateKeyFile); + } + catch (err) { + core.warning(`Failed to remove temporary file used to store sigstore private key ` + + `"${sigstorePrivateKeyFile}": ${err}`); + } + try { const digest = (await fs.promises.readFile(digestFile)).toString(); core.info(digest);