Skip to content

Commit 1c0dc52

Browse files
committed
sigstore: always set TSA server endpoint to provide trusted timestamping
Signed-off-by: CrazyMax <[email protected]>
1 parent 36cc951 commit 1c0dc52

3 files changed

Lines changed: 43 additions & 10 deletions

File tree

__tests__/sigstore/sigstore.test.itg.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import {describe, expect, it} from '@jest/globals';
17+
import {describe, expect, jest, it} from '@jest/globals';
1818
import fs from 'fs';
1919
import * as path from 'path';
2020

@@ -24,6 +24,9 @@ const fixturesDir = path.join(__dirname, '..', '.fixtures');
2424

2525
const maybe = process.env.GITHUB_ACTIONS && process.env.GITHUB_ACTIONS === 'true' && process.env.ACTIONS_ID_TOKEN_REQUEST_URL && process.env.ImageOS && process.env.ImageOS.startsWith('ubuntu') ? describe : describe.skip;
2626

27+
// needs current GitHub repo info
28+
jest.unmock('@actions/github');
29+
2730
maybe('signProvenanceBlobs', () => {
2831
it('single platform', async () => {
2932
const sigstore = new Sigstore();

src/sigstore/sigstore.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,22 @@ import {X509Certificate} from 'crypto';
1818
import fs from 'fs';
1919
import path from 'path';
2020

21-
import {signingEndpoints, SigstoreInstance} from '@actions/attest/lib/endpoints';
21+
import {Endpoints} from '@actions/attest/lib/endpoints';
2222
import * as core from '@actions/core';
2323
import {signPayload} from '@actions/attest/lib/sign';
2424
import {bundleToJSON} from '@sigstore/bundle';
2525
import {Attestation} from '@actions/attest';
2626
import {Bundle} from '@sigstore/sign';
2727

28-
import {Subject} from '../types/intoto/intoto';
28+
import {GitHub} from '../github';
29+
30+
import {MEDIATYPE_PAYLOAD as intotoMediatypePayload, Subject} from '../types/intoto/intoto';
31+
import {FULCIO_URL, REKOR_URL, SEARCH_URL, TSASERVER_URL} from '../types/sigstore/sigstore';
2932

3033
export interface SignProvenanceBlobsOpts {
3134
localExportDir: string;
3235
name?: string;
36+
noTransparencyLog?: boolean;
3337
}
3438

3539
export interface SignProvenanceBlobsResult extends Attestation {
@@ -38,18 +42,14 @@ export interface SignProvenanceBlobsResult extends Attestation {
3842
}
3943

4044
export class Sigstore {
41-
private intotoPayloadType = 'application/vnd.in-toto+json';
42-
private searchSigstoreURL = 'https://search.sigstore.dev';
43-
4445
public async signProvenanceBlobs(opts: SignProvenanceBlobsOpts): Promise<Record<string, SignProvenanceBlobsResult>> {
4546
const result: Record<string, SignProvenanceBlobsResult> = {};
4647
try {
4748
if (!process.env.ACTIONS_ID_TOKEN_REQUEST_URL) {
4849
throw new Error('missing "id-token" permission. Please add "permissions: id-token: write" to your workflow.');
4950
}
5051

51-
const sigstoreInstance: SigstoreInstance = 'public-good';
52-
const endpoints = signingEndpoints(sigstoreInstance);
52+
const endpoints = this.signingEndpoints(opts);
5353
core.info(`Using Sigstore signing endpoint: ${endpoints.fulcioURL}`);
5454

5555
const provenanceBlobs = Sigstore.getProvenanceBlobs(opts);
@@ -65,7 +65,7 @@ export class Sigstore {
6565
const bundle = await signPayload(
6666
{
6767
body: blob,
68-
type: this.intotoPayloadType
68+
type: intotoMediatypePayload
6969
},
7070
endpoints
7171
);
@@ -76,7 +76,7 @@ export class Sigstore {
7676
core.info(` - ${subject.name} (${digestAlg}:${digestValue})`);
7777
}
7878
if (attest.tlogID) {
79-
core.info(`Attestation signature uploaded to Rekor transparency log: ${this.searchSigstoreURL}?logIndex=${attest.tlogID}`);
79+
core.info(`Attestation signature uploaded to Rekor transparency log: ${SEARCH_URL}?logIndex=${attest.tlogID}`);
8080
}
8181
core.info(`Writing Sigstore bundle to: ${bundlePath}`);
8282
fs.writeFileSync(bundlePath, JSON.stringify(attest.bundle, null, 2), {
@@ -95,6 +95,16 @@ export class Sigstore {
9595
return result;
9696
}
9797

98+
private signingEndpoints(opts: SignProvenanceBlobsOpts): Endpoints {
99+
const noTransparencyLog = opts.noTransparencyLog ?? GitHub.context.payload.repository?.private;
100+
core.info(`Upload to transparency log: ${noTransparencyLog ? 'disabled' : 'enabled'}`);
101+
return {
102+
fulcioURL: FULCIO_URL,
103+
rekorURL: noTransparencyLog ? undefined : REKOR_URL,
104+
tsaServerURL: TSASERVER_URL
105+
};
106+
}
107+
98108
private static getProvenanceBlobs(opts: SignProvenanceBlobsOpts): Record<string, Buffer> {
99109
// For single platform build
100110
const singleProvenance = path.join(opts.localExportDir, 'provenance.json');

src/types/sigstore/sigstore.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Copyright 2025 actions-toolkit authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
export const FULCIO_URL = 'https://fulcio.sigstore.dev';
18+
export const REKOR_URL = 'https://rekor.sigstore.dev';
19+
export const TSASERVER_URL = 'https://timestamp.sigstore.dev';
20+
export const SEARCH_URL = 'https://search.sigstore.dev';

0 commit comments

Comments
 (0)