codekingpro/portable-devtools
114k
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.bundleBuilderFromSigningConfig = bundleBuilderFromSigningConfig;
4/*
5Copyright 2025 The Sigstore Authors.
6
7Licensed under the Apache License, Version 2.0 (the "License");
8you may not use this file except in compliance with the License.
9You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13Unless required by applicable law or agreed to in writing, software
14distributed under the License is distributed on an "AS IS" BASIS,
15WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16See the License for the specific language governing permissions and
17limitations under the License.
18*/
19const protobuf_specs_1 = require("@sigstore/protobuf-specs");
20const dsse_1 = require("./bundler/dsse");
21const message_1 = require("./bundler/message");
22const signer_1 = require("./signer");
23const witness_1 = require("./witness");
24const MAX_CA_API_VERSION = 1;
25const MAX_TLOG_API_VERSION = 2;
26const MAX_TSA_API_VERSION = 1;
27const DEFAULT_TIMEOUT = 5000;
28const DEFAULT_REKORV2_TIMEOUT = 20000;
29const DEFAULT_RETRY = { retries: 2 };
30// Creates a BundleBuilder based on the provided SigningConfig
31function bundleBuilderFromSigningConfig(options) {
32 const { signingConfig, identityProvider, bundleType } = options;
33 const fetchOptions = options.fetchOptions || {
34 timeout: DEFAULT_TIMEOUT,
35 retry: DEFAULT_RETRY,
36 };
37 const signer = fulcioSignerFromConfig(signingConfig, identityProvider, fetchOptions);
38 const witnesses = witnessesFromConfig(signingConfig, fetchOptions);
39 switch (bundleType) {
40 case 'messageSignature':
41 return new message_1.MessageSignatureBundleBuilder({ signer, witnesses });
42 case 'dsseEnvelope':
43 return new dsse_1.DSSEBundleBuilder({ signer, witnesses });
44 }
45}
46function fulcioSignerFromConfig(signingConfig, identityProvider, fetchOptions) {
47 const service = certAuthorityService(signingConfig);
48 return new signer_1.FulcioSigner({
49 fulcioBaseURL: service.url,
50 identityProvider: identityProvider,
51 timeout: fetchOptions.timeout,
52 retry: fetchOptions.retry,
53 });
54}
55function witnessesFromConfig(signingConfig, fetchOptions) {
56 const witnesses = [];
57 if (signingConfig.rekorTlogConfig) {
58 if (signingConfig.rekorTlogConfig.selector !== protobuf_specs_1.ServiceSelector.ANY) {
59 throw new Error('Unsupported Rekor TLog selector in signing configuration');
60 }
61 const tlog = tlogService(signingConfig);
62 witnesses.push(new witness_1.RekorWitness({
63 rekorBaseURL: tlog.url,
64 majorApiVersion: tlog.majorApiVersion,
65 retry: fetchOptions.retry,
66 timeout:
67 // Ensure Rekor V2 has at least a 20 second timeout
68 tlog.majorApiVersion === 1
69 ? fetchOptions.timeout
70 : Math.min(fetchOptions.timeout ||
71 /* istanbul ignore next */ DEFAULT_TIMEOUT, DEFAULT_REKORV2_TIMEOUT),
72 }));
73 }
74 if (signingConfig.tsaConfig) {
75 if (signingConfig.tsaConfig.selector !== protobuf_specs_1.ServiceSelector.ANY) {
76 throw new Error('Unsupported TSA selector in signing configuration');
77 }
78 const tsa = tsaService(signingConfig);
79 witnesses.push(new witness_1.TSAWitness({
80 tsaBaseURL: tsa.url,
81 retry: fetchOptions.retry,
82 timeout: fetchOptions.timeout,
83 }));
84 }
85 return witnesses;
86}
87// Returns the first valid CA service from the signing configuration
88function certAuthorityService(signingConfig) {
89 const compatibleCAs = filterServicesByMaxAPIVersion(signingConfig.caUrls, MAX_CA_API_VERSION);
90 const sortedCAs = sortServicesByStartDate(compatibleCAs);
91 if (sortedCAs.length === 0) {
92 throw new Error('No valid CA services found in signing configuration');
93 }
94 return sortedCAs[0];
95}
96// Returns the first valid TLog service from the signing configuration
97function tlogService(signingConfig) {
98 const compatibleTLogs = filterServicesByMaxAPIVersion(signingConfig.rekorTlogUrls, MAX_TLOG_API_VERSION);
99 const sortedTLogs = sortServicesByStartDate(compatibleTLogs);
100 if (sortedTLogs.length === 0) {
101 throw new Error('No valid TLogs found in signing configuration');
102 }
103 return sortedTLogs[0];
104}
105// Returns the first valid TSA service from the signing configuration
106function tsaService(signingConfig) {
107 const compatibleTSAs = filterServicesByMaxAPIVersion(signingConfig.tsaUrls, MAX_TSA_API_VERSION);
108 const sortedTSAs = sortServicesByStartDate(compatibleTSAs);
109 if (sortedTSAs.length === 0) {
110 throw new Error('No valid TSAs found in signing configuration');
111 }
112 return sortedTSAs[0];
113}
114// Returns the services sorted by start date (most recent first), filtering out
115// any services that have an end date in the past
116function sortServicesByStartDate(services) {
117 const now = new Date();
118 // Filter out any services that have an end date in the past
119 const validServices = services.filter((service) => {
120 // If there's no end date, the service is still valid
121 if (!service.validFor?.end) {
122 return true;
123 }
124 // Keep services whose end date is in the future or present
125 return service.validFor.end >= now;
126 });
127 return validServices.sort((a, b) => {
128 /* istanbul ignore next */
129 const aStart = a.validFor?.start?.getTime() ?? 0;
130 /* istanbul ignore next */
131 const bStart = b.validFor?.start?.getTime() ?? 0;
132 // Sort descending (most recent first)
133 return bStart - aStart;
134 });
135}
136// Returns a filtered list of services whose major API version is less than or
137// equal to the specified version
138function filterServicesByMaxAPIVersion(services, apiVersion) {
139 // Filter out any services with a major API version greater than the specified version
140 return services.filter((service) => {
141 return service.majorApiVersion <= apiVersion;
142 });
143}
144 