Skip to content

Commit 23b2687

Browse files
committed
Add support for signing with Sigstore
Fixes: redhat-actions#89
1 parent 1d13b5a commit 23b2687

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Refer to the [`podman push`](http://docs.podman.io/en/latest/markdown/podman-man
3232
| password | Password, encrypted password, or access token to use to log in to the registry. Required unless already logged in to the registry. | None
3333
| tls-verify | Verify TLS certificates when contacting the registry. Set to `false` to skip certificate verification. | `true`
3434
| 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
35+
| sigstore-private-key | Sigstore private key to use to sign container images | None
36+
| sign-passphrase | Passphrase to unlock the Sigstore private key | None
3537
| extra-args | Extra args to be passed to podman push. Separate arguments by newline. Do not use quotes. | None
3638

3739
<a id="image-tag-inputs"></a>

action.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ inputs:
3333
By default, the filename will be determined from the image and tag.
3434
The contents of this file are the digest output.
3535
required: false
36+
sigstore-private-key:
37+
description: 'Sigstore private key to use to sign container images'
38+
required: false
39+
sign-passphrase:
40+
description: 'Passphrase to unlock the Sigstore private key'
41+
required: false
3642
extra-args:
3743
description: |
3844
Extra args to be passed to podman push.

src/generated/inputs-outputs.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,18 @@ export enum Inputs {
5252
* Default: None.
5353
*/
5454
USERNAME = "username",
55+
/**
56+
* Sigstore private key to use to sign container images
57+
* Required: false
58+
* Default: None.
59+
*/
60+
SIGSTORE_PRIVATE_KEY = "sigstore-private-key",
61+
/**
62+
* Passphrase to unlock the Sigstore private key
63+
* Required: false
64+
* Default: None.
65+
*/
66+
SIGN_PASSPHRASE = "sign-passphrase",
5567
}
5668

5769
export enum Outputs {

src/index.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,33 @@ async function run(): Promise<void> {
209209
}
210210
}
211211

212+
const sigstorePrivateKey = core.getInput(Inputs.SIGSTORE_PRIVATE_KEY);
213+
const sigstorePrivateKeyFile = path.join(process.env.RUNNER_TEMP || "", "sigstore_private_key");
214+
if (sigstorePrivateKey) {
215+
// Write sigstore private key to a temporary file in $RUNNER_TEMP that
216+
// will be removed after the image is pushed.
217+
try {
218+
await fs.promises.writeFile(sigstorePrivateKeyFile, sigstorePrivateKey);
219+
}
220+
catch (err) {
221+
throw new Error(`Could not write sigstore private key to temporary file `
222+
+ `"${sigstorePrivateKeyFile}": ${err}`);
223+
}
224+
}
225+
const signPassphrase = core.getInput(Inputs.SIGN_PASSPHRASE);
226+
const signPassphraseFile = path.join(process.env.RUNNER_TEMP || "", "sign_passphrase");
227+
if (signPassphrase || sigstorePrivateKey) {
228+
// Write passphrase (empty string if not provided) to a temporary file
229+
// in $RUNNER_TEMP that will be removed after the image is pushed.
230+
try {
231+
await fs.promises.writeFile(signPassphraseFile, signPassphrase || "");
232+
}
233+
catch (err) {
234+
throw new Error(`Could not write sign passphrase to temporary file `
235+
+ `"${signPassphraseFile}": ${err}`);
236+
}
237+
}
238+
212239
let pushMsg = `⏳ Pushing "${sourceImages.join(", ")}" to "${destinationImages.join(", ")}" respectively`;
213240
if (username) {
214241
pushMsg += ` as "${username}"`;
@@ -269,11 +296,36 @@ async function run(): Promise<void> {
269296
args.push(`--creds=${creds}`);
270297
}
271298

299+
if (sigstorePrivateKey) {
300+
args.push("--sign-by-sigstore-private-key");
301+
args.push(sigstorePrivateKeyFile);
302+
}
303+
304+
if (signPassphrase || sigstorePrivateKey) {
305+
args.push("--sign-passphrase-file");
306+
args.push(signPassphraseFile);
307+
}
308+
272309
await execute(await getPodmanPath(), args);
273310
core.info(`✅ Successfully pushed "${sourceImages[i]}" to "${destinationImages[i]}"`);
274311

275312
registryPathList.push(destinationImages[i]);
276313

314+
try {
315+
await fs.promises.unlink(sigstorePrivateKeyFile);
316+
}
317+
catch (err) {
318+
core.warning(`Failed to remove temporary file used to store sigstore private key `
319+
+ `"${sigstorePrivateKeyFile}": ${err}`);
320+
}
321+
try {
322+
await fs.promises.unlink(signPassphraseFile);
323+
}
324+
catch (err) {
325+
core.warning(`Failed to remove temporary file used to store sign passphrase `
326+
+ `"${signPassphraseFile}": ${err}`);
327+
}
328+
277329
try {
278330
const digest = (await fs.promises.readFile(digestFile)).toString();
279331
core.info(digest);

0 commit comments

Comments
 (0)