cosign(install): use sigstore module to verify signature

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax
2025-12-16 19:44:35 +01:00
parent 44e7279490
commit eb8ed6b687
3 changed files with 149 additions and 14 deletions

View File

@@ -58,6 +58,8 @@
"@octokit/plugin-rest-endpoint-methods": "^10.4.1",
"@sigstore/bundle": "^4.0.0",
"@sigstore/sign": "^4.0.1",
"@sigstore/tuf": "^4.0.0",
"@sigstore/verify": "^3.0.0",
"async-retry": "^1.3.3",
"csv-parse": "^6.1.0",
"gunzip-maybe": "^1.4.2",

View File

@@ -19,6 +19,9 @@ import os from 'os';
import path from 'path';
import * as core from '@actions/core';
import * as tc from '@actions/tool-cache';
import {bundleFromJSON, SerializedBundle} from '@sigstore/bundle';
import * as tuf from '@sigstore/tuf';
import {toSignedEntity, toTrustMaterial, Verifier} from '@sigstore/verify';
import * as semver from 'semver';
import * as util from 'util';
@@ -188,24 +191,32 @@ export class Install {
}
private async verifySignature(cosignBinPath: string, downloadURL: string): Promise<void> {
const cosignBootstrapPath = path.join(Context.tmpDir(), `cosign-bootstrap${os.platform() == 'win32' ? '.exe' : ''}`);
fs.copyFileSync(cosignBinPath, cosignBootstrapPath);
fs.chmodSync(cosignBootstrapPath, '0755');
const bundleURL = `${downloadURL}.sigstore.json`;
core.info(`Downloading keyless verification bundle at ${bundleURL}`);
const bundlePath = await tc.downloadTool(bundleURL, undefined, this.githubToken);
core.debug(`Install.verifySignature bundlePath: ${bundlePath}`);
core.info(`Verifying cosign binary signature with keyless verification bundle`);
// prettier-ignore
await Exec.exec(cosignBootstrapPath, [
'verify-blob',
'--certificate-identity', 'keyless@projectsigstore.iam.gserviceaccount.com',
'--certificate-oidc-issuer', 'https://accounts.google.com',
'--bundle', bundlePath,
cosignBinPath
]);
core.info(`Verifying keyless verification bundle signature`);
const parsedBundle = JSON.parse(fs.readFileSync(bundlePath, 'utf-8')) as SerializedBundle;
const bundle = bundleFromJSON(parsedBundle);
core.info(`Fetching Sigstore TUF trusted root metadata`);
const trustedRoot = await tuf.getTrustedRoot();
const trustMaterial = toTrustMaterial(trustedRoot);
try {
core.info(`Verifying cosign binary signature`);
const signedEntity = toSignedEntity(bundle, fs.readFileSync(cosignBinPath));
const verifier = new Verifier(trustMaterial);
const signer = verifier.verify(signedEntity, {
subjectAlternativeName: 'keyless@projectsigstore.iam.gserviceaccount.com',
extensions: {issuer: 'https://accounts.google.com'}
});
core.debug(`Install.verifySignature signer: ${JSON.stringify(signer)}`);
core.info(`Cosign binary signature verified!`);
} catch (err) {
throw new Error(`Failed to verify cosign binary signature: ${err}`);
}
}
private filename(): string {

124
yarn.lock
View File

@@ -1185,6 +1185,8 @@ __metadata:
"@sigstore/bundle": "npm:^4.0.0"
"@sigstore/rekor-types": "npm:^3.0.0"
"@sigstore/sign": "npm:^4.0.1"
"@sigstore/tuf": "npm:^4.0.0"
"@sigstore/verify": "npm:^3.0.0"
"@types/gunzip-maybe": "npm:^1.4.3"
"@types/he": "npm:^1.2.3"
"@types/js-yaml": "npm:^4.0.9"
@@ -2273,6 +2275,27 @@ __metadata:
languageName: node
linkType: hard
"@sigstore/tuf@npm:^4.0.0":
version: 4.0.0
resolution: "@sigstore/tuf@npm:4.0.0"
dependencies:
"@sigstore/protobuf-specs": "npm:^0.5.0"
tuf-js: "npm:^4.0.0"
checksum: 10/8f47a0bc814a8ee1ef59bc90eb7954e0bb33734a913c77c04bdbf08fce2622d406feb0b243191154453a046224fcc512e916c1c919563fab902070b66837ad5e
languageName: node
linkType: hard
"@sigstore/verify@npm:^3.0.0":
version: 3.0.0
resolution: "@sigstore/verify@npm:3.0.0"
dependencies:
"@sigstore/bundle": "npm:^4.0.0"
"@sigstore/core": "npm:^3.0.0"
"@sigstore/protobuf-specs": "npm:^0.5.0"
checksum: 10/c5b4891f42586a4c68fb22f127f19dd16b0bda0388ae8a40727cedd2443919006df3ec1ac4d6c3bd2786cff4c3f8d987135e87979262790e718bcc53e8a3a6c1
languageName: node
linkType: hard
"@sinclair/typebox@npm:^0.34.0":
version: 0.34.41
resolution: "@sinclair/typebox@npm:0.34.41"
@@ -2333,6 +2356,23 @@ __metadata:
languageName: node
linkType: hard
"@tufjs/canonical-json@npm:2.0.0":
version: 2.0.0
resolution: "@tufjs/canonical-json@npm:2.0.0"
checksum: 10/cc719a1d0d0ae1aa1ba551a82c87dcbefac088e433c03a3d8a1d547ea721350e47dab4ab5b0fca40d5c7ab1f4882e72edc39c9eae15bf47c45c43bcb6ee39f4f
languageName: node
linkType: hard
"@tufjs/models@npm:4.0.0":
version: 4.0.0
resolution: "@tufjs/models@npm:4.0.0"
dependencies:
"@tufjs/canonical-json": "npm:2.0.0"
minimatch: "npm:^9.0.5"
checksum: 10/1b8d119b4144018d92237aa0dfcf4ac85ee609dd0062d15817736cfd0d0d594761e9179dd7b580894a6e7f67dd06d4421f16534756b66441c8838e8644e77632
languageName: node
linkType: hard
"@tybys/wasm-util@npm:^0.10.0":
version: 0.10.1
resolution: "@tybys/wasm-util@npm:0.10.1"
@@ -3947,6 +3987,18 @@ __metadata:
languageName: node
linkType: hard
"debug@npm:^4.4.1":
version: 4.4.3
resolution: "debug@npm:4.4.3"
dependencies:
ms: "npm:^2.1.3"
peerDependenciesMeta:
supports-color:
optional: true
checksum: 10/9ada3434ea2993800bd9a1e320bd4aa7af69659fb51cca685d390949434bc0a8873c21ed7c9b852af6f2455a55c6d050aa3937d52b3c69f796dab666f762acad
languageName: node
linkType: hard
"dedent@npm:^1.6.0":
version: 1.7.0
resolution: "dedent@npm:1.7.0"
@@ -7062,6 +7114,25 @@ __metadata:
languageName: node
linkType: hard
"make-fetch-happen@npm:^15.0.0":
version: 15.0.3
resolution: "make-fetch-happen@npm:15.0.3"
dependencies:
"@npmcli/agent": "npm:^4.0.0"
cacache: "npm:^20.0.1"
http-cache-semantics: "npm:^4.1.1"
minipass: "npm:^7.0.2"
minipass-fetch: "npm:^5.0.0"
minipass-flush: "npm:^1.0.5"
minipass-pipeline: "npm:^1.2.4"
negotiator: "npm:^1.0.0"
proc-log: "npm:^6.0.0"
promise-retry: "npm:^2.0.1"
ssri: "npm:^13.0.0"
checksum: 10/78da4fc1df83cb596e2bae25aa0653b8a9c6cbdd6674a104894e03be3acfcd08c70b78f06ef6407fbd6b173f6a60672480d78641e693d05eb71c09c13ee35278
languageName: node
linkType: hard
"make-fetch-happen@npm:^15.0.2":
version: 15.0.2
resolution: "make-fetch-happen@npm:15.0.2"
@@ -7175,6 +7246,15 @@ __metadata:
languageName: node
linkType: hard
"minimatch@npm:^9.0.5":
version: 9.0.5
resolution: "minimatch@npm:9.0.5"
dependencies:
brace-expansion: "npm:^2.0.1"
checksum: 10/dd6a8927b063aca6d910b119e1f2df6d2ce7d36eab91de83167dd136bb85e1ebff97b0d3de1cb08bd1f7e018ca170b4962479fefab5b2a69e2ae12cb2edc8348
languageName: node
linkType: hard
"minimist@npm:^1.2.0, minimist@npm:^1.2.6":
version: 1.2.7
resolution: "minimist@npm:1.2.7"
@@ -7237,6 +7317,21 @@ __metadata:
languageName: node
linkType: hard
"minipass-fetch@npm:^5.0.0":
version: 5.0.0
resolution: "minipass-fetch@npm:5.0.0"
dependencies:
encoding: "npm:^0.1.13"
minipass: "npm:^7.0.3"
minipass-sized: "npm:^1.0.3"
minizlib: "npm:^3.0.1"
dependenciesMeta:
encoding:
optional: true
checksum: 10/4fb7dca630a64e6970a8211dade505bfe260d0b8d60beb348dcdfb95fe35ef91d977b29963929c9017ae0805686aa3f413107dc6bc5deac9b9e26b0b41c3b86c
languageName: node
linkType: hard
"minipass-flush@npm:^1.0.5":
version: 1.0.5
resolution: "minipass-flush@npm:1.0.5"
@@ -7347,7 +7442,7 @@ __metadata:
languageName: node
linkType: hard
"ms@npm:^2.0.0, ms@npm:^2.1.1":
"ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3":
version: 2.1.3
resolution: "ms@npm:2.1.3"
checksum: 10/aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d
@@ -7879,6 +7974,13 @@ __metadata:
languageName: node
linkType: hard
"proc-log@npm:^6.0.0":
version: 6.1.0
resolution: "proc-log@npm:6.1.0"
checksum: 10/9033f30f168ed5a0991b773d0c50ff88384c4738e9a0a67d341de36bf7293771eed648ab6a0562f62276da12fde91f3bbfc75ffff6e71ad49aafd74fc646be66
languageName: node
linkType: hard
"process-nextick-args@npm:~2.0.0":
version: 2.0.1
resolution: "process-nextick-args@npm:2.0.1"
@@ -8552,6 +8654,15 @@ __metadata:
languageName: node
linkType: hard
"ssri@npm:^13.0.0":
version: 13.0.0
resolution: "ssri@npm:13.0.0"
dependencies:
minipass: "npm:^7.0.3"
checksum: 10/fd59bfedf0659c1b83f6e15459162da021f08ec0f5834dd9163296f8b77ee82f9656aa1d415c3d3848484293e0e6aefdd482e863e52ddb53d520bb73da1eeec1
languageName: node
linkType: hard
"ssri@npm:^9.0.0":
version: 9.0.1
resolution: "ssri@npm:9.0.1"
@@ -9067,6 +9178,17 @@ __metadata:
languageName: node
linkType: hard
"tuf-js@npm:^4.0.0":
version: 4.0.0
resolution: "tuf-js@npm:4.0.0"
dependencies:
"@tufjs/models": "npm:4.0.0"
debug: "npm:^4.4.1"
make-fetch-happen: "npm:^15.0.0"
checksum: 10/7de216e39578f7abd449b2eaed7977b9e99f3b66bcc7ff24f4f4a4a4bcca032a1c180e2a3fd20019ed820d898010fcd9f2654446c87dbf93a9b13f163bb99422
languageName: node
linkType: hard
"tunnel@npm:^0.0.6":
version: 0.0.6
resolution: "tunnel@npm:0.0.6"