@docker/actions-toolkit 0.75.0 → 0.77.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/buildkit/buildkit.d.ts +3 -3
- package/lib/buildkit/buildkit.js +67 -117
- package/lib/buildkit/buildkit.js.map +1 -1
- package/lib/buildkit/config.js +7 -14
- package/lib/buildkit/config.js.map +1 -1
- package/lib/buildkit/git.d.ts +1 -1
- package/lib/buildkit/git.js +8 -12
- package/lib/buildkit/git.js.map +1 -1
- package/lib/buildx/bake.d.ts +4 -4
- package/lib/buildx/bake.js +76 -93
- package/lib/buildx/bake.js.map +1 -1
- package/lib/buildx/build.d.ts +5 -5
- package/lib/buildx/build.js +44 -78
- package/lib/buildx/build.js.map +1 -1
- package/lib/buildx/builder.d.ts +2 -2
- package/lib/buildx/builder.js +42 -91
- package/lib/buildx/builder.js.map +1 -1
- package/lib/buildx/buildx.d.ts +3 -3
- package/lib/buildx/buildx.js +212 -274
- package/lib/buildx/buildx.js.map +1 -1
- package/lib/buildx/history.d.ts +2 -2
- package/lib/buildx/history.js +226 -284
- package/lib/buildx/history.js.map +1 -1
- package/lib/buildx/imagetools.d.ts +5 -5
- package/lib/buildx/imagetools.js +67 -92
- package/lib/buildx/imagetools.js.map +1 -1
- package/lib/buildx/install.d.ts +14 -3
- package/lib/buildx/install.js +239 -276
- package/lib/buildx/install.js.map +1 -1
- package/lib/cache.js +88 -138
- package/lib/cache.js.map +1 -1
- package/lib/compose/compose.js +53 -107
- package/lib/compose/compose.js.map +1 -1
- package/lib/compose/install.d.ts +2 -2
- package/lib/compose/install.js +129 -191
- package/lib/compose/install.js.map +1 -1
- package/lib/context.js +10 -50
- package/lib/context.js.map +1 -1
- package/lib/cosign/cosign.js +55 -106
- package/lib/cosign/cosign.js.map +1 -1
- package/lib/cosign/dockerfile.js +1 -4
- package/lib/cosign/dockerfile.js.map +1 -1
- package/lib/cosign/install.d.ts +6 -3
- package/lib/cosign/install.js +183 -261
- package/lib/cosign/install.js.map +1 -1
- package/lib/docker/assets.js +15 -24
- package/lib/docker/assets.js.map +1 -1
- package/lib/docker/docker.d.ts +1 -1
- package/lib/docker/docker.js +112 -182
- package/lib/docker/docker.js.map +1 -1
- package/lib/docker/install.d.ts +3 -3
- package/lib/docker/install.js +543 -617
- package/lib/docker/install.js.map +1 -1
- package/lib/dockerhub.d.ts +1 -1
- package/lib/dockerhub.js +67 -125
- package/lib/dockerhub.js.map +1 -1
- package/lib/exec.js +9 -59
- package/lib/exec.js.map +1 -1
- package/lib/git.d.ts +2 -1
- package/lib/git.js +144 -220
- package/lib/git.js.map +1 -1
- package/lib/github/artifact.d.ts +19 -0
- package/lib/github/artifact.js +49 -0
- package/lib/github/artifact.js.map +1 -0
- package/lib/{github.d.ts → github/github.d.ts} +4 -8
- package/lib/github/github.js +135 -0
- package/lib/github/github.js.map +1 -0
- package/lib/github/summary.d.ts +20 -0
- package/lib/github/summary.js +166 -0
- package/lib/github/summary.js.map +1 -0
- package/lib/index.js +17 -64
- package/lib/index.js.map +1 -1
- package/lib/oci/oci.d.ts +2 -2
- package/lib/oci/oci.js +52 -104
- package/lib/oci/oci.js.map +1 -1
- package/lib/regclient/install.d.ts +2 -2
- package/lib/regclient/install.js +83 -141
- package/lib/regclient/install.js.map +1 -1
- package/lib/regclient/regctl.d.ts +1 -1
- package/lib/regclient/regctl.js +67 -123
- package/lib/regclient/regctl.js.map +1 -1
- package/lib/sigstore/sigstore.d.ts +5 -3
- package/lib/sigstore/sigstore.js +361 -344
- package/lib/sigstore/sigstore.js.map +1 -1
- package/lib/toolkit.d.ts +16 -16
- package/lib/toolkit.js +49 -37
- package/lib/toolkit.js.map +1 -1
- package/lib/types/buildkit/buildkit.js +1 -4
- package/lib/types/buildkit/buildkit.js.map +1 -1
- package/lib/types/buildkit/client.d.ts +2 -2
- package/lib/types/buildkit/client.js +1 -2
- package/lib/types/buildkit/client.js.map +1 -1
- package/lib/types/buildkit/control.d.ts +4 -4
- package/lib/types/buildkit/control.js +1 -2
- package/lib/types/buildkit/control.js.map +1 -1
- package/lib/types/buildkit/git.js +1 -2
- package/lib/types/buildkit/git.js.map +1 -1
- package/lib/types/buildkit/ops.js +1 -2
- package/lib/types/buildkit/ops.js.map +1 -1
- package/lib/types/buildkit/rpc.js +1 -2
- package/lib/types/buildkit/rpc.js.map +1 -1
- package/lib/types/buildx/bake.js +1 -2
- package/lib/types/buildx/bake.js.map +1 -1
- package/lib/types/buildx/build.js +1 -2
- package/lib/types/buildx/build.js.map +1 -1
- package/lib/types/buildx/builder.js +1 -2
- package/lib/types/buildx/builder.js.map +1 -1
- package/lib/types/buildx/buildx.d.ts +1 -1
- package/lib/types/buildx/buildx.js +1 -2
- package/lib/types/buildx/buildx.js.map +1 -1
- package/lib/types/buildx/history.js +1 -2
- package/lib/types/buildx/history.js.map +1 -1
- package/lib/types/buildx/imagetools.d.ts +3 -3
- package/lib/types/buildx/imagetools.js +1 -2
- package/lib/types/buildx/imagetools.js.map +1 -1
- package/lib/types/compose/compose.d.ts +1 -1
- package/lib/types/compose/compose.js +1 -2
- package/lib/types/compose/compose.js.map +1 -1
- package/lib/types/cosign/cosign.d.ts +1 -1
- package/lib/types/cosign/cosign.js +1 -2
- package/lib/types/cosign/cosign.js.map +1 -1
- package/lib/types/docker/docker.js +1 -2
- package/lib/types/docker/docker.js.map +1 -1
- package/lib/types/docker/mediatype.js +3 -6
- package/lib/types/docker/mediatype.js.map +1 -1
- package/lib/types/dockerhub.js +1 -2
- package/lib/types/dockerhub.js.map +1 -1
- package/lib/types/github/artifact.d.ts +26 -0
- package/lib/types/{git.d.ts → github/artifact.js} +3 -3
- package/lib/types/github/artifact.js.map +1 -0
- package/lib/types/{github.d.ts → github/github.d.ts} +4 -23
- package/lib/types/{git.js → github/github.js} +2 -3
- package/lib/types/github/github.js.map +1 -0
- package/lib/types/github/summary.d.ts +29 -0
- package/lib/types/{github.js → github/summary.js} +3 -4
- package/lib/types/github/summary.js.map +1 -0
- package/lib/types/intoto/intoto.js +2 -5
- package/lib/types/intoto/intoto.js.map +1 -1
- package/lib/types/intoto/slsa_provenance/v0.2/provenance.js +1 -4
- package/lib/types/intoto/slsa_provenance/v0.2/provenance.js.map +1 -1
- package/lib/types/oci/config.d.ts +2 -2
- package/lib/types/oci/config.js +1 -2
- package/lib/types/oci/config.js.map +1 -1
- package/lib/types/oci/descriptor.d.ts +1 -1
- package/lib/types/oci/descriptor.js +3 -6
- package/lib/types/oci/descriptor.js.map +1 -1
- package/lib/types/oci/digest.js +1 -2
- package/lib/types/oci/digest.js.map +1 -1
- package/lib/types/oci/index.d.ts +2 -2
- package/lib/types/oci/index.js +1 -2
- package/lib/types/oci/index.js.map +1 -1
- package/lib/types/oci/layout.js +4 -7
- package/lib/types/oci/layout.js.map +1 -1
- package/lib/types/oci/manifest.d.ts +2 -2
- package/lib/types/oci/manifest.js +1 -2
- package/lib/types/oci/manifest.js.map +1 -1
- package/lib/types/oci/mediatype.js +6 -9
- package/lib/types/oci/mediatype.js.map +1 -1
- package/lib/types/oci/oci.d.ts +4 -4
- package/lib/types/oci/oci.js +1 -2
- package/lib/types/oci/oci.js.map +1 -1
- package/lib/types/oci/versioned.js +1 -2
- package/lib/types/oci/versioned.js.map +1 -1
- package/lib/types/regclient/regclient.d.ts +1 -1
- package/lib/types/regclient/regclient.js +1 -2
- package/lib/types/regclient/regclient.js.map +1 -1
- package/lib/types/sigstore/sigstore.d.ts +11 -2
- package/lib/types/sigstore/sigstore.js +4 -7
- package/lib/types/sigstore/sigstore.js.map +1 -1
- package/lib/types/undock/undock.d.ts +1 -1
- package/lib/types/undock/undock.js +1 -2
- package/lib/types/undock/undock.js.map +1 -1
- package/lib/undock/install.d.ts +2 -2
- package/lib/undock/install.js +93 -151
- package/lib/undock/install.js.map +1 -1
- package/lib/undock/undock.js +88 -141
- package/lib/undock/undock.js.map +1 -1
- package/lib/util.js +36 -89
- package/lib/util.js.map +1 -1
- package/package.json +31 -42
- package/lib/github.js +0 -421
- package/lib/github.js.map +0 -1
- package/lib/types/git.js.map +0 -1
- package/lib/types/github.js.map +0 -1
package/lib/sigstore/sigstore.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Copyright 2025 actions-toolkit authors
|
|
4
3
|
*
|
|
@@ -14,359 +13,377 @@
|
|
|
14
13
|
* See the License for the specific language governing permissions and
|
|
15
14
|
* limitations under the License.
|
|
16
15
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
-
var ar = [];
|
|
37
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
-
return ar;
|
|
39
|
-
};
|
|
40
|
-
return ownKeys(o);
|
|
41
|
-
};
|
|
42
|
-
return function (mod) {
|
|
43
|
-
if (mod && mod.__esModule) return mod;
|
|
44
|
-
var result = {};
|
|
45
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
-
__setModuleDefault(result, mod);
|
|
47
|
-
return result;
|
|
48
|
-
};
|
|
49
|
-
})();
|
|
50
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
51
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
52
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
53
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
54
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
55
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
56
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
57
|
-
});
|
|
58
|
-
};
|
|
59
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
60
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
61
|
-
};
|
|
62
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
63
|
-
exports.Sigstore = void 0;
|
|
64
|
-
const crypto_1 = require("crypto");
|
|
65
|
-
const fs_1 = __importDefault(require("fs"));
|
|
66
|
-
const path_1 = __importDefault(require("path"));
|
|
67
|
-
const core = __importStar(require("@actions/core"));
|
|
68
|
-
const bundle_1 = require("@sigstore/bundle");
|
|
69
|
-
const sign_1 = require("@sigstore/sign");
|
|
70
|
-
const cosign_1 = require("../cosign/cosign");
|
|
71
|
-
const exec_1 = require("../exec");
|
|
72
|
-
const github_1 = require("../github");
|
|
73
|
-
const imagetools_1 = require("../buildx/imagetools");
|
|
74
|
-
const intoto_1 = require("../types/intoto/intoto");
|
|
75
|
-
const sigstore_1 = require("../types/sigstore/sigstore");
|
|
76
|
-
class Sigstore {
|
|
16
|
+
import { X509Certificate } from 'crypto';
|
|
17
|
+
import fs from 'fs';
|
|
18
|
+
import path from 'path';
|
|
19
|
+
import * as core from '@actions/core';
|
|
20
|
+
import { bundleFromJSON, bundleToJSON } from '@sigstore/bundle';
|
|
21
|
+
import { CIContextProvider, DSSEBundleBuilder, FulcioSigner, RekorWitness, TSAWitness } from '@sigstore/sign';
|
|
22
|
+
import * as tuf from '@sigstore/tuf';
|
|
23
|
+
import { toSignedEntity, toTrustMaterial, Verifier } from '@sigstore/verify';
|
|
24
|
+
import { Context } from '../context.js';
|
|
25
|
+
import { Cosign } from '../cosign/cosign.js';
|
|
26
|
+
import { Exec } from '../exec.js';
|
|
27
|
+
import { GitHub } from '../github/github.js';
|
|
28
|
+
import { ImageTools } from '../buildx/imagetools.js';
|
|
29
|
+
import { MEDIATYPE_PAYLOAD as INTOTO_MEDIATYPE_PAYLOAD } from '../types/intoto/intoto.js';
|
|
30
|
+
import { FULCIO_URL, REKOR_URL, SEARCH_URL, TSASERVER_URL } from '../types/sigstore/sigstore.js';
|
|
31
|
+
export class Sigstore {
|
|
32
|
+
cosign;
|
|
33
|
+
imageTools;
|
|
77
34
|
constructor(opts) {
|
|
78
|
-
this.cosign =
|
|
79
|
-
this.imageTools =
|
|
35
|
+
this.cosign = opts?.cosign || new Cosign();
|
|
36
|
+
this.imageTools = opts?.imageTools || new ImageTools();
|
|
80
37
|
}
|
|
81
|
-
signAttestationManifests(opts) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
38
|
+
async signAttestationManifests(opts) {
|
|
39
|
+
if (!(await this.cosign.isAvailable())) {
|
|
40
|
+
throw new Error('Cosign is required to sign attestation manifests');
|
|
41
|
+
}
|
|
42
|
+
const result = {};
|
|
43
|
+
try {
|
|
44
|
+
if (!process.env.ACTIONS_ID_TOKEN_REQUEST_URL) {
|
|
45
|
+
throw new Error('missing "id-token" permission. Please add "permissions: id-token: write" to your workflow.');
|
|
85
46
|
}
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
'--registry-referrers-mode', 'oci-1-1',
|
|
106
|
-
'--new-bundle-format',
|
|
107
|
-
'--use-signing-config'
|
|
108
|
-
];
|
|
109
|
-
if (noTransparencyLog) {
|
|
110
|
-
cosignArgs.push('--tlog-upload=false');
|
|
111
|
-
}
|
|
112
|
-
core.info(`[command]cosign ${[...cosignArgs, attestationRef].join(' ')}`);
|
|
113
|
-
const execRes = yield exec_1.Exec.getExecOutput('cosign', ['--verbose', ...cosignArgs, attestationRef], {
|
|
114
|
-
ignoreReturnCode: true,
|
|
115
|
-
silent: true,
|
|
116
|
-
env: Object.assign({}, process.env, {
|
|
117
|
-
COSIGN_EXPERIMENTAL: '1'
|
|
118
|
-
})
|
|
119
|
-
});
|
|
120
|
-
const signResult = cosign_1.Cosign.parseCommandOutput(execRes.stderr.trim());
|
|
121
|
-
if (execRes.exitCode != 0) {
|
|
122
|
-
if (signResult.errors && signResult.errors.length > 0) {
|
|
123
|
-
const errorMessages = signResult.errors.map(e => `- [${e.code}] ${e.message} : ${e.detail}`).join('\n');
|
|
124
|
-
throw new Error(`Cosign sign command failed with errors:\n${errorMessages}`);
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
// prettier-ignore
|
|
128
|
-
throw new Error(`Cosign sign command failed with: ${(_a = execRes.stderr.trim().split(/\r?\n/).filter(line => line.length > 0).pop()) !== null && _a !== void 0 ? _a : 'unknown error'}`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
const parsedBundle = Sigstore.parseBundle((0, bundle_1.bundleFromJSON)(signResult.bundle));
|
|
132
|
-
if (parsedBundle.tlogID) {
|
|
133
|
-
core.info(`Uploaded to Rekor transparency log: ${sigstore_1.SEARCH_URL}?logIndex=${parsedBundle.tlogID}`);
|
|
134
|
-
}
|
|
135
|
-
core.info(`Signature manifest pushed: https://oci.dag.dev/?referrers=${attestationRef}`);
|
|
136
|
-
result[attestationRef] = Object.assign(Object.assign({}, parsedBundle), { imageName: imageName });
|
|
137
|
-
}));
|
|
47
|
+
const endpoints = this.signingEndpoints(opts.noTransparencyLog);
|
|
48
|
+
core.info(`Using Sigstore signing endpoint: ${endpoints.fulcioURL}`);
|
|
49
|
+
const noTransparencyLog = Sigstore.noTransparencyLog(opts.noTransparencyLog);
|
|
50
|
+
const cosignExtraArgs = [];
|
|
51
|
+
if (await this.cosign.versionSatisfies('>=3.0.4')) {
|
|
52
|
+
await core.group(`Creating Sigstore protobuf signing config`, async () => {
|
|
53
|
+
const signingConfig = Context.tmpName({
|
|
54
|
+
template: 'signing-config-XXXXXX.json',
|
|
55
|
+
tmpdir: Context.tmpDir()
|
|
56
|
+
});
|
|
57
|
+
// prettier-ignore
|
|
58
|
+
const createConfigArgs = [
|
|
59
|
+
'signing-config',
|
|
60
|
+
'create',
|
|
61
|
+
'--with-default-services=true',
|
|
62
|
+
`--out=${signingConfig}`
|
|
63
|
+
];
|
|
64
|
+
if (noTransparencyLog) {
|
|
65
|
+
createConfigArgs.push('--no-default-rekor=true');
|
|
138
66
|
}
|
|
139
|
-
|
|
67
|
+
await Exec.exec('cosign', createConfigArgs, {
|
|
68
|
+
env: Object.assign({}, process.env, {
|
|
69
|
+
COSIGN_EXPERIMENTAL: '1'
|
|
70
|
+
})
|
|
71
|
+
});
|
|
72
|
+
core.info(JSON.stringify(JSON.parse(fs.readFileSync(signingConfig, { encoding: 'utf-8' })), null, 2));
|
|
73
|
+
cosignExtraArgs.push(`--signing-config=${signingConfig}`);
|
|
74
|
+
});
|
|
140
75
|
}
|
|
141
|
-
|
|
142
|
-
|
|
76
|
+
else {
|
|
77
|
+
cosignExtraArgs.push('--use-signing-config');
|
|
78
|
+
if (noTransparencyLog) {
|
|
79
|
+
cosignExtraArgs.push('--tlog-upload=false');
|
|
80
|
+
}
|
|
143
81
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
82
|
+
for (const imageName of opts.imageNames) {
|
|
83
|
+
const attestationDigests = await this.imageTools.attestationDigests(`${imageName}@${opts.imageDigest}`);
|
|
84
|
+
for (const attestationDigest of attestationDigests) {
|
|
85
|
+
const attestationRef = `${imageName}@${attestationDigest}`;
|
|
86
|
+
await core.group(`Signing attestation manifest ${attestationRef}`, async () => {
|
|
87
|
+
// prettier-ignore
|
|
88
|
+
const cosignArgs = [
|
|
89
|
+
'sign',
|
|
90
|
+
'--yes',
|
|
91
|
+
'--oidc-provider', 'github-actions',
|
|
92
|
+
'--registry-referrers-mode', 'oci-1-1',
|
|
93
|
+
'--new-bundle-format',
|
|
94
|
+
...cosignExtraArgs
|
|
95
|
+
];
|
|
96
|
+
core.info(`[command]cosign ${[...cosignArgs, attestationRef].join(' ')}`);
|
|
97
|
+
const execRes = await Exec.getExecOutput('cosign', ['--verbose', ...cosignArgs, attestationRef], {
|
|
98
|
+
ignoreReturnCode: true,
|
|
99
|
+
silent: true,
|
|
100
|
+
env: Object.assign({}, process.env, {
|
|
101
|
+
COSIGN_EXPERIMENTAL: '1'
|
|
102
|
+
})
|
|
103
|
+
});
|
|
104
|
+
const signResult = Cosign.parseCommandOutput(execRes.stderr.trim());
|
|
105
|
+
if (execRes.exitCode != 0) {
|
|
106
|
+
if (signResult.errors && signResult.errors.length > 0) {
|
|
107
|
+
const errorMessages = signResult.errors.map(e => `- [${e.code}] ${e.message} : ${e.detail}`).join('\n');
|
|
108
|
+
throw new Error(`Cosign sign command failed with errors:\n${errorMessages}`);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// prettier-ignore
|
|
112
|
+
throw new Error(`Cosign sign command failed with: ${execRes.stderr.trim().split(/\r?\n/).filter(line => line.length > 0).pop() ?? 'unknown error'}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const parsedBundle = Sigstore.parseBundle(bundleFromJSON(signResult.bundle));
|
|
116
|
+
if (parsedBundle.tlogID) {
|
|
117
|
+
core.info(`Uploaded to Rekor transparency log: ${SEARCH_URL}?logIndex=${parsedBundle.tlogID}`);
|
|
118
|
+
}
|
|
119
|
+
core.info(`Signature manifest pushed: https://oci.dag.dev/?referrers=${attestationRef}`);
|
|
120
|
+
result[attestationRef] = {
|
|
121
|
+
...parsedBundle,
|
|
122
|
+
imageName: imageName
|
|
123
|
+
};
|
|
156
124
|
});
|
|
157
|
-
|
|
158
|
-
result[attestationRef] = verifyResult;
|
|
159
|
-
}));
|
|
125
|
+
}
|
|
160
126
|
}
|
|
161
|
-
|
|
162
|
-
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
throw new Error(`Signing BuildKit attestation manifests failed: ${err.message}`);
|
|
130
|
+
}
|
|
131
|
+
return result;
|
|
163
132
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const verifyResult = yield this.verifyImageAttestation(attestationRef, opts);
|
|
175
|
-
core.info(`Signature manifest verified: https://oci.dag.dev/?image=${imageName}@${verifyResult.signatureManifestDigest}`);
|
|
133
|
+
async verifySignedManifests(signedManifestsResult, opts) {
|
|
134
|
+
const result = {};
|
|
135
|
+
for (const [attestationRef, signedRes] of Object.entries(signedManifestsResult)) {
|
|
136
|
+
await core.group(`Verifying signature of ${attestationRef}`, async () => {
|
|
137
|
+
const verifyResult = await this.verifyImageAttestation(attestationRef, {
|
|
138
|
+
certificateIdentityRegexp: opts.certificateIdentityRegexp,
|
|
139
|
+
noTransparencyLog: opts.noTransparencyLog || !signedRes.tlogID,
|
|
140
|
+
retryOnManifestUnknown: opts.retryOnManifestUnknown
|
|
141
|
+
});
|
|
142
|
+
core.info(`Signature manifest verified: https://oci.dag.dev/?image=${signedRes.imageName}@${verifyResult.signatureManifestDigest}`);
|
|
176
143
|
result[attestationRef] = verifyResult;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
180
147
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
148
|
+
async verifyImageAttestations(image, opts) {
|
|
149
|
+
const result = {};
|
|
150
|
+
const attestationDigests = await this.imageTools.attestationDigests(image, opts.platform);
|
|
151
|
+
if (attestationDigests.length === 0) {
|
|
152
|
+
throw new Error(`No attestation manifests found for ${image}`);
|
|
153
|
+
}
|
|
154
|
+
const imageName = image.split(':', 1)[0];
|
|
155
|
+
for (const attestationDigest of attestationDigests) {
|
|
156
|
+
const attestationRef = `${imageName}@${attestationDigest}`;
|
|
157
|
+
const verifyResult = await this.verifyImageAttestation(attestationRef, opts);
|
|
158
|
+
core.info(`Signature manifest verified: https://oci.dag.dev/?image=${imageName}@${verifyResult.signatureManifestDigest}`);
|
|
159
|
+
result[attestationRef] = verifyResult;
|
|
160
|
+
}
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
async verifyImageAttestation(attestationRef, opts) {
|
|
164
|
+
if (!(await this.cosign.isAvailable())) {
|
|
165
|
+
throw new Error('Cosign is required to verify signed manifests');
|
|
166
|
+
}
|
|
167
|
+
// prettier-ignore
|
|
168
|
+
const cosignArgs = [
|
|
169
|
+
'verify',
|
|
170
|
+
'--experimental-oci11',
|
|
171
|
+
'--new-bundle-format',
|
|
172
|
+
'--certificate-oidc-issuer', 'https://token.actions.githubusercontent.com',
|
|
173
|
+
'--certificate-identity-regexp', opts.certificateIdentityRegexp
|
|
174
|
+
];
|
|
175
|
+
if (opts.noTransparencyLog) {
|
|
176
|
+
// skip tlog verification but still verify the signed timestamp
|
|
177
|
+
cosignArgs.push('--use-signed-timestamps', '--insecure-ignore-tlog');
|
|
178
|
+
}
|
|
179
|
+
if (!opts.retryOnManifestUnknown) {
|
|
180
|
+
core.info(`[command]cosign ${[...cosignArgs, attestationRef].join(' ')}`);
|
|
181
|
+
const execRes = await Exec.getExecOutput('cosign', ['--verbose', ...cosignArgs, attestationRef], {
|
|
182
|
+
ignoreReturnCode: true,
|
|
183
|
+
silent: true,
|
|
184
|
+
env: Object.assign({}, process.env, {
|
|
185
|
+
COSIGN_EXPERIMENTAL: '1'
|
|
186
|
+
})
|
|
187
|
+
});
|
|
188
|
+
if (execRes.exitCode !== 0) {
|
|
189
|
+
// prettier-ignore
|
|
190
|
+
throw new Error(`Cosign verify command failed with: ${execRes.stderr.trim().split(/\r?\n/).filter(line => line.length > 0).pop() ?? 'unknown error'}`);
|
|
198
191
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
192
|
+
const verifyResult = Cosign.parseCommandOutput(execRes.stderr.trim());
|
|
193
|
+
return {
|
|
194
|
+
cosignArgs: cosignArgs,
|
|
195
|
+
signatureManifestDigest: verifyResult.signatureManifestDigest
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
const retries = 15;
|
|
199
|
+
let lastError;
|
|
200
|
+
core.info(`[command]cosign ${[...cosignArgs, attestationRef].join(' ')}`);
|
|
201
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
202
|
+
const execRes = await Exec.getExecOutput('cosign', ['--verbose', ...cosignArgs, attestationRef], {
|
|
203
|
+
ignoreReturnCode: true,
|
|
204
|
+
silent: true,
|
|
205
|
+
env: Object.assign({}, process.env, {
|
|
206
|
+
COSIGN_EXPERIMENTAL: '1'
|
|
207
|
+
})
|
|
208
|
+
});
|
|
209
|
+
const verifyResult = Cosign.parseCommandOutput(execRes.stderr.trim());
|
|
210
|
+
if (execRes.exitCode === 0) {
|
|
213
211
|
return {
|
|
214
212
|
cosignArgs: cosignArgs,
|
|
215
213
|
signatureManifestDigest: verifyResult.signatureManifestDigest
|
|
216
214
|
};
|
|
217
215
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
env: Object.assign({}, process.env, {
|
|
226
|
-
COSIGN_EXPERIMENTAL: '1'
|
|
227
|
-
})
|
|
228
|
-
});
|
|
229
|
-
const verifyResult = cosign_1.Cosign.parseCommandOutput(execRes.stderr.trim());
|
|
230
|
-
if (execRes.exitCode === 0) {
|
|
231
|
-
return {
|
|
232
|
-
cosignArgs: cosignArgs,
|
|
233
|
-
signatureManifestDigest: verifyResult.signatureManifestDigest
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
else {
|
|
237
|
-
if (verifyResult.errors && verifyResult.errors.length > 0) {
|
|
238
|
-
const errorMessages = verifyResult.errors.map(e => `- [${e.code}] ${e.message} : ${e.detail}`).join('\n');
|
|
239
|
-
lastError = new Error(`Cosign verify command failed with errors:\n${errorMessages}`);
|
|
240
|
-
if (verifyResult.errors.some(e => e.code === 'MANIFEST_UNKNOWN')) {
|
|
241
|
-
core.info(`Cosign verify command failed with MANIFEST_UNKNOWN, retrying attempt ${attempt + 1}/${retries}...\n${errorMessages}`);
|
|
242
|
-
yield new Promise(res => setTimeout(res, Math.pow(2, attempt) * 100));
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
throw lastError;
|
|
246
|
-
}
|
|
216
|
+
else {
|
|
217
|
+
if (verifyResult.errors && verifyResult.errors.length > 0) {
|
|
218
|
+
const errorMessages = verifyResult.errors.map(e => `- [${e.code}] ${e.message} : ${e.detail}`).join('\n');
|
|
219
|
+
lastError = new Error(`Cosign verify command failed with errors:\n${errorMessages}`);
|
|
220
|
+
if (verifyResult.errors.some(e => e.code === 'MANIFEST_UNKNOWN')) {
|
|
221
|
+
core.info(`Cosign verify command failed with MANIFEST_UNKNOWN, retrying attempt ${attempt + 1}/${retries}...\n${errorMessages}`);
|
|
222
|
+
await new Promise(res => setTimeout(res, Math.pow(2, attempt) * 100));
|
|
247
223
|
}
|
|
248
224
|
else {
|
|
249
|
-
|
|
250
|
-
throw new Error(`Cosign verify command failed with: ${(_b = execRes.stderr.trim().split(/\r?\n/).filter(line => line.length > 0).pop()) !== null && _b !== void 0 ? _b : 'unknown error'}`);
|
|
225
|
+
throw lastError;
|
|
251
226
|
}
|
|
252
227
|
}
|
|
228
|
+
else {
|
|
229
|
+
// prettier-ignore
|
|
230
|
+
throw new Error(`Cosign verify command failed with: ${execRes.stderr.trim().split(/\r?\n/).filter(line => line.length > 0).pop() ?? 'unknown error'}`);
|
|
231
|
+
}
|
|
253
232
|
}
|
|
254
|
-
|
|
255
|
-
|
|
233
|
+
}
|
|
234
|
+
throw lastError;
|
|
256
235
|
}
|
|
257
|
-
signProvenanceBlobs(opts) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
throw new Error('missing "id-token" permission. Please add "permissions: id-token: write" to your workflow.');
|
|
263
|
-
}
|
|
264
|
-
const endpoints = this.signingEndpoints(opts.noTransparencyLog);
|
|
265
|
-
core.info(`Using Sigstore signing endpoint: ${endpoints.fulcioURL}`);
|
|
266
|
-
const provenanceBlobs = Sigstore.getProvenanceBlobs(opts);
|
|
267
|
-
for (const p of Object.keys(provenanceBlobs)) {
|
|
268
|
-
yield core.group(`Signing ${p}`, () => __awaiter(this, void 0, void 0, function* () {
|
|
269
|
-
var _a;
|
|
270
|
-
const blob = provenanceBlobs[p];
|
|
271
|
-
const bundlePath = path_1.default.join(path_1.default.dirname(p), `${(_a = opts.name) !== null && _a !== void 0 ? _a : 'provenance'}.sigstore.json`);
|
|
272
|
-
const subjects = Sigstore.getProvenanceSubjects(blob);
|
|
273
|
-
if (subjects.length === 0) {
|
|
274
|
-
core.warning(`No subjects found in provenance ${p}, skip signing.`);
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
const bundle = yield Sigstore.signPayload({
|
|
278
|
-
data: blob,
|
|
279
|
-
type: intoto_1.MEDIATYPE_PAYLOAD
|
|
280
|
-
}, endpoints);
|
|
281
|
-
const parsedBundle = Sigstore.parseBundle(bundle);
|
|
282
|
-
core.info(`Provenance blob signed for:`);
|
|
283
|
-
for (const subject of subjects) {
|
|
284
|
-
const [digestAlg, digestValue] = Object.entries(subject.digest)[0] || [];
|
|
285
|
-
core.info(` - ${subject.name} (${digestAlg}:${digestValue})`);
|
|
286
|
-
}
|
|
287
|
-
if (parsedBundle.tlogID) {
|
|
288
|
-
core.info(`Attestation signature uploaded to Rekor transparency log: ${sigstore_1.SEARCH_URL}?logIndex=${parsedBundle.tlogID}`);
|
|
289
|
-
}
|
|
290
|
-
core.info(`Writing Sigstore bundle to: ${bundlePath}`);
|
|
291
|
-
fs_1.default.writeFileSync(bundlePath, JSON.stringify(parsedBundle.payload, null, 2), {
|
|
292
|
-
encoding: 'utf-8'
|
|
293
|
-
});
|
|
294
|
-
result[p] = Object.assign(Object.assign({}, parsedBundle), { bundlePath: bundlePath, subjects: subjects });
|
|
295
|
-
}));
|
|
296
|
-
}
|
|
236
|
+
async signProvenanceBlobs(opts) {
|
|
237
|
+
const result = {};
|
|
238
|
+
try {
|
|
239
|
+
if (!process.env.ACTIONS_ID_TOKEN_REQUEST_URL) {
|
|
240
|
+
throw new Error('missing "id-token" permission. Please add "permissions: id-token: write" to your workflow.');
|
|
297
241
|
}
|
|
298
|
-
|
|
299
|
-
|
|
242
|
+
const endpoints = this.signingEndpoints(opts.noTransparencyLog);
|
|
243
|
+
core.info(`Using Sigstore signing endpoint: ${endpoints.fulcioURL}`);
|
|
244
|
+
const provenanceBlobs = Sigstore.getProvenanceBlobs(opts);
|
|
245
|
+
for (const p of Object.keys(provenanceBlobs)) {
|
|
246
|
+
await core.group(`Signing ${p}`, async () => {
|
|
247
|
+
const blob = provenanceBlobs[p];
|
|
248
|
+
const bundlePath = path.join(path.dirname(p), `${opts.name ?? 'provenance'}.sigstore.json`);
|
|
249
|
+
const subjects = Sigstore.getProvenanceSubjects(blob);
|
|
250
|
+
if (subjects.length === 0) {
|
|
251
|
+
core.warning(`No subjects found in provenance ${p}, skip signing.`);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const bundle = await Sigstore.signPayload({
|
|
255
|
+
data: blob,
|
|
256
|
+
type: INTOTO_MEDIATYPE_PAYLOAD
|
|
257
|
+
}, endpoints);
|
|
258
|
+
const parsedBundle = Sigstore.parseBundle(bundle);
|
|
259
|
+
core.info(`Provenance blob signed for:`);
|
|
260
|
+
for (const subject of subjects) {
|
|
261
|
+
const [digestAlg, digestValue] = Object.entries(subject.digest)[0] || [];
|
|
262
|
+
core.info(` - ${subject.name} (${digestAlg}:${digestValue})`);
|
|
263
|
+
}
|
|
264
|
+
if (parsedBundle.tlogID) {
|
|
265
|
+
core.info(`Attestation signature uploaded to Rekor transparency log: ${SEARCH_URL}?logIndex=${parsedBundle.tlogID}`);
|
|
266
|
+
}
|
|
267
|
+
core.info(`Writing Sigstore bundle to: ${bundlePath}`);
|
|
268
|
+
fs.writeFileSync(bundlePath, JSON.stringify(parsedBundle.payload, null, 2), {
|
|
269
|
+
encoding: 'utf-8'
|
|
270
|
+
});
|
|
271
|
+
result[p] = {
|
|
272
|
+
...parsedBundle,
|
|
273
|
+
bundlePath: bundlePath,
|
|
274
|
+
subjects: subjects
|
|
275
|
+
};
|
|
276
|
+
});
|
|
300
277
|
}
|
|
301
|
-
|
|
302
|
-
|
|
278
|
+
}
|
|
279
|
+
catch (err) {
|
|
280
|
+
throw new Error(`Signing BuildKit provenance blobs failed: ${err.message}`);
|
|
281
|
+
}
|
|
282
|
+
return result;
|
|
303
283
|
}
|
|
304
|
-
verifySignedArtifacts(signedArtifactsResult, opts) {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
if
|
|
324
|
-
|
|
325
|
-
cosignArgs.push('--use-signed-timestamps', '--insecure-ignore-tlog');
|
|
326
|
-
}
|
|
327
|
-
const execRes = yield exec_1.Exec.getExecOutput('cosign', [...cosignArgs, '--bundle', signedRes.bundlePath, artifactPath], {
|
|
328
|
-
ignoreReturnCode: true
|
|
329
|
-
});
|
|
330
|
-
if (execRes.stderr.length > 0 && execRes.exitCode != 0) {
|
|
331
|
-
throw new Error(execRes.stderr);
|
|
332
|
-
}
|
|
333
|
-
result[artifactPath] = {
|
|
334
|
-
bundlePath: signedRes.bundlePath,
|
|
335
|
-
cosignArgs: cosignArgs
|
|
336
|
-
};
|
|
284
|
+
async verifySignedArtifacts(signedArtifactsResult, opts) {
|
|
285
|
+
const result = {};
|
|
286
|
+
if (!(await this.cosign.isAvailable())) {
|
|
287
|
+
throw new Error('Cosign is required to verify signed artifacts');
|
|
288
|
+
}
|
|
289
|
+
for (const [provenancePath, signedRes] of Object.entries(signedArtifactsResult)) {
|
|
290
|
+
const baseDir = path.dirname(provenancePath);
|
|
291
|
+
await core.group(`Verifying signature bundle ${signedRes.bundlePath}`, async () => {
|
|
292
|
+
for (const subject of signedRes.subjects) {
|
|
293
|
+
const artifactPath = path.join(baseDir, subject.name);
|
|
294
|
+
core.info(`Verifying signed artifact ${artifactPath}`);
|
|
295
|
+
// prettier-ignore
|
|
296
|
+
const cosignArgs = [
|
|
297
|
+
'verify-blob-attestation',
|
|
298
|
+
'--new-bundle-format',
|
|
299
|
+
'--certificate-oidc-issuer', 'https://token.actions.githubusercontent.com',
|
|
300
|
+
'--certificate-identity-regexp', opts.certificateIdentityRegexp
|
|
301
|
+
];
|
|
302
|
+
if (opts.noTransparencyLog || !signedRes.tlogID) {
|
|
303
|
+
// if there is no tlog entry, we skip tlog verification but still verify the signed timestamp
|
|
304
|
+
cosignArgs.push('--use-signed-timestamps', '--insecure-ignore-tlog');
|
|
337
305
|
}
|
|
338
|
-
|
|
306
|
+
const execRes = await Exec.getExecOutput('cosign', [...cosignArgs, '--bundle', signedRes.bundlePath, artifactPath], {
|
|
307
|
+
ignoreReturnCode: true
|
|
308
|
+
});
|
|
309
|
+
if (execRes.stderr.length > 0 && execRes.exitCode != 0) {
|
|
310
|
+
throw new Error(execRes.stderr);
|
|
311
|
+
}
|
|
312
|
+
result[artifactPath] = {
|
|
313
|
+
bundlePath: signedRes.bundlePath,
|
|
314
|
+
cosignArgs: cosignArgs
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
return result;
|
|
320
|
+
}
|
|
321
|
+
async verifyArtifact(artifactPath, bundlePath, opts) {
|
|
322
|
+
core.info(`Verifying keyless verification bundle signature`);
|
|
323
|
+
const parsedBundle = JSON.parse(fs.readFileSync(bundlePath, 'utf-8'));
|
|
324
|
+
const bundle = bundleFromJSON(parsedBundle);
|
|
325
|
+
core.info(`Fetching Sigstore TUF trusted root metadata`);
|
|
326
|
+
const trustedRoot = await tuf.getTrustedRoot();
|
|
327
|
+
const trustMaterial = toTrustMaterial(trustedRoot);
|
|
328
|
+
try {
|
|
329
|
+
core.info(`Verifying artifact signature`);
|
|
330
|
+
const signedEntity = toSignedEntity(bundle, fs.readFileSync(artifactPath));
|
|
331
|
+
const signingCert = Sigstore.parseCertificate(bundle);
|
|
332
|
+
// collect transparency log ID if available
|
|
333
|
+
const tlogEntries = bundle.verificationMaterial.tlogEntries;
|
|
334
|
+
const tlogID = tlogEntries.length > 0 ? tlogEntries[0].logIndex : undefined;
|
|
335
|
+
// TODO: remove when subjectAlternativeName check with regex is supported: https://github.com/sigstore/sigstore-js/pull/1556
|
|
336
|
+
if (opts?.subjectAlternativeName && opts?.subjectAlternativeName instanceof RegExp) {
|
|
337
|
+
const subjectAltName = signingCert.subjectAltName?.replace(/^uri:/i, '');
|
|
338
|
+
if (!subjectAltName) {
|
|
339
|
+
throw new Error('Signing certificate does not contain subjectAltName');
|
|
340
|
+
}
|
|
341
|
+
else if (!subjectAltName.match(opts.subjectAlternativeName)) {
|
|
342
|
+
throw new Error(`Signing certificate subjectAlternativeName "${subjectAltName}" does not match expected pattern`);
|
|
343
|
+
}
|
|
339
344
|
}
|
|
340
|
-
|
|
341
|
-
|
|
345
|
+
const verifier = new Verifier(trustMaterial);
|
|
346
|
+
const signer = verifier.verify(signedEntity, {
|
|
347
|
+
subjectAlternativeName: opts?.subjectAlternativeName && typeof opts.subjectAlternativeName === 'string' ? opts.subjectAlternativeName : undefined,
|
|
348
|
+
extensions: opts?.issuer ? { issuer: opts.issuer } : undefined
|
|
349
|
+
});
|
|
350
|
+
core.debug(`Sigstore.verifyArtifact signer: ${JSON.stringify(signer)}`);
|
|
351
|
+
return {
|
|
352
|
+
payload: parsedBundle,
|
|
353
|
+
certificate: signingCert.toString(),
|
|
354
|
+
tlogID: tlogID
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
catch (err) {
|
|
358
|
+
throw new Error(`Failed to verify artifact signature: ${err}`);
|
|
359
|
+
}
|
|
342
360
|
}
|
|
343
361
|
signingEndpoints(noTransparencyLog) {
|
|
344
362
|
noTransparencyLog = Sigstore.noTransparencyLog(noTransparencyLog);
|
|
345
363
|
core.info(`Upload to transparency log: ${noTransparencyLog ? 'disabled' : 'enabled'}`);
|
|
346
364
|
return {
|
|
347
|
-
fulcioURL:
|
|
348
|
-
rekorURL: noTransparencyLog ? undefined :
|
|
349
|
-
tsaServerURL:
|
|
365
|
+
fulcioURL: FULCIO_URL,
|
|
366
|
+
rekorURL: noTransparencyLog ? undefined : REKOR_URL,
|
|
367
|
+
tsaServerURL: TSASERVER_URL
|
|
350
368
|
};
|
|
351
369
|
}
|
|
352
370
|
static noTransparencyLog(noTransparencyLog) {
|
|
353
|
-
|
|
354
|
-
return noTransparencyLog !== null && noTransparencyLog !== void 0 ? noTransparencyLog : (_a = github_1.GitHub.context.payload.repository) === null || _a === void 0 ? void 0 : _a.private;
|
|
371
|
+
return noTransparencyLog ?? GitHub.context.payload.repository?.private;
|
|
355
372
|
}
|
|
356
373
|
static getProvenanceBlobs(opts) {
|
|
357
374
|
// For single platform build
|
|
358
|
-
const singleProvenance =
|
|
359
|
-
if (
|
|
360
|
-
return { [singleProvenance]:
|
|
375
|
+
const singleProvenance = path.join(opts.localExportDir, 'provenance.json');
|
|
376
|
+
if (fs.existsSync(singleProvenance)) {
|
|
377
|
+
return { [singleProvenance]: fs.readFileSync(singleProvenance) };
|
|
361
378
|
}
|
|
362
379
|
// For multi-platform build
|
|
363
|
-
const dirents =
|
|
380
|
+
const dirents = fs.readdirSync(opts.localExportDir, { withFileTypes: true });
|
|
364
381
|
const platformFolders = dirents.filter(dirent => dirent.isDirectory());
|
|
365
|
-
if (platformFolders.length > 0 && platformFolders.length === dirents.length && platformFolders.every(platformFolder =>
|
|
382
|
+
if (platformFolders.length > 0 && platformFolders.length === dirents.length && platformFolders.every(platformFolder => fs.existsSync(path.join(opts.localExportDir, platformFolder.name, 'provenance.json')))) {
|
|
366
383
|
const result = {};
|
|
367
384
|
for (const platformFolder of platformFolders) {
|
|
368
|
-
const p =
|
|
369
|
-
result[p] =
|
|
385
|
+
const p = path.join(opts.localExportDir, platformFolder.name, 'provenance.json');
|
|
386
|
+
result[p] = fs.readFileSync(p);
|
|
370
387
|
}
|
|
371
388
|
return result;
|
|
372
389
|
}
|
|
@@ -379,34 +396,43 @@ class Sigstore {
|
|
|
379
396
|
digest: s.digest
|
|
380
397
|
}));
|
|
381
398
|
}
|
|
382
|
-
static signPayload(artifact, endpoints, timeout, retries) {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
399
|
+
static async signPayload(artifact, endpoints, timeout, retries) {
|
|
400
|
+
const witnesses = [];
|
|
401
|
+
const signer = new FulcioSigner({
|
|
402
|
+
identityProvider: new CIContextProvider('sigstore'),
|
|
403
|
+
fulcioBaseURL: endpoints.fulcioURL,
|
|
404
|
+
timeout: timeout,
|
|
405
|
+
retry: retries
|
|
406
|
+
});
|
|
407
|
+
if (endpoints.rekorURL) {
|
|
408
|
+
witnesses.push(new RekorWitness({
|
|
409
|
+
rekorBaseURL: endpoints.rekorURL,
|
|
410
|
+
fetchOnConflict: true,
|
|
388
411
|
timeout: timeout,
|
|
389
412
|
retry: retries
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
witnesses.push(new sign_1.TSAWitness({
|
|
401
|
-
tsaBaseURL: endpoints.tsaServerURL,
|
|
402
|
-
timeout: timeout,
|
|
403
|
-
retry: retries
|
|
404
|
-
}));
|
|
405
|
-
}
|
|
406
|
-
return new sign_1.DSSEBundleBuilder({ signer, witnesses }).create(artifact);
|
|
407
|
-
});
|
|
413
|
+
}));
|
|
414
|
+
}
|
|
415
|
+
if (endpoints.tsaServerURL) {
|
|
416
|
+
witnesses.push(new TSAWitness({
|
|
417
|
+
tsaBaseURL: endpoints.tsaServerURL,
|
|
418
|
+
timeout: timeout,
|
|
419
|
+
retry: retries
|
|
420
|
+
}));
|
|
421
|
+
}
|
|
422
|
+
return new DSSEBundleBuilder({ signer, witnesses }).create(artifact);
|
|
408
423
|
}
|
|
409
424
|
static parseBundle(bundle) {
|
|
425
|
+
const signingCert = Sigstore.parseCertificate(bundle);
|
|
426
|
+
// collect transparency log ID if available
|
|
427
|
+
const tlogEntries = bundle.verificationMaterial.tlogEntries;
|
|
428
|
+
const tlogID = tlogEntries.length > 0 ? tlogEntries[0].logIndex : undefined;
|
|
429
|
+
return {
|
|
430
|
+
payload: bundleToJSON(bundle),
|
|
431
|
+
certificate: signingCert.toString(),
|
|
432
|
+
tlogID: tlogID
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
static parseCertificate(bundle) {
|
|
410
436
|
let certBytes;
|
|
411
437
|
switch (bundle.verificationMaterial.content.$case) {
|
|
412
438
|
case 'x509CertificateChain':
|
|
@@ -418,16 +444,7 @@ class Sigstore {
|
|
|
418
444
|
default:
|
|
419
445
|
throw new Error('Bundle must contain an x509 certificate');
|
|
420
446
|
}
|
|
421
|
-
|
|
422
|
-
// collect transparency log ID if available
|
|
423
|
-
const tlogEntries = bundle.verificationMaterial.tlogEntries;
|
|
424
|
-
const tlogID = tlogEntries.length > 0 ? tlogEntries[0].logIndex : undefined;
|
|
425
|
-
return {
|
|
426
|
-
payload: (0, bundle_1.bundleToJSON)(bundle),
|
|
427
|
-
certificate: signingCert.toString(),
|
|
428
|
-
tlogID: tlogID
|
|
429
|
-
};
|
|
447
|
+
return new X509Certificate(certBytes);
|
|
430
448
|
}
|
|
431
449
|
}
|
|
432
|
-
exports.Sigstore = Sigstore;
|
|
433
450
|
//# sourceMappingURL=sigstore.js.map
|