@@ -18,60 +18,32 @@ import {X509Certificate} from 'crypto';
1818import fs from 'fs' ;
1919import path from 'path' ;
2020
21- import { Endpoints } from '@actions/attest/lib/endpoints' ;
2221import * as core from '@actions/core' ;
23- import { signPayload } from '@actions/attest/lib/sign' ;
2422import { bundleFromJSON , bundleToJSON } from '@sigstore/bundle' ;
25- import { Attestation } from '@actions/attest' ;
26- import { Bundle } from '@sigstore/sign' ;
23+ import { Artifact , Bundle , CIContextProvider , DSSEBundleBuilder , FulcioSigner , RekorWitness , TSAWitness , Witness } from '@sigstore/sign' ;
2724
2825import { Cosign } from '../cosign/cosign' ;
2926import { Exec } from '../exec' ;
3027import { GitHub } from '../github' ;
3128import { ImageTools } from '../buildx/imagetools' ;
3229
3330import { MEDIATYPE_PAYLOAD as INTOTO_MEDIATYPE_PAYLOAD , Subject } from '../types/intoto/intoto' ;
34- import { FULCIO_URL , REKOR_URL , SEARCH_URL , TSASERVER_URL } from '../types/sigstore/sigstore' ;
35-
36- export interface SignAttestationManifestsOpts {
37- imageNames : Array < string > ;
38- imageDigest : string ;
39- noTransparencyLog ?: boolean ;
40- }
41-
42- export interface SignAttestationManifestsResult extends Attestation {
43- imageName : string ;
44- }
45-
46- export interface VerifySignedManifestsOpts {
47- certificateIdentityRegexp : string ;
48- retries ?: number ;
49- }
50-
51- export interface VerifySignedManifestsResult {
52- cosignArgs : Array < string > ;
53- signatureManifestDigest : string ;
54- }
55-
56- export interface SignProvenanceBlobsOpts {
57- localExportDir : string ;
58- name ?: string ;
59- noTransparencyLog ?: boolean ;
60- }
61-
62- export interface SignProvenanceBlobsResult extends Attestation {
63- bundlePath : string ;
64- subjects : Array < Subject > ;
65- }
66-
67- export interface VerifySignedArtifactsOpts {
68- certificateIdentityRegexp : string ;
69- }
70-
71- export interface VerifySignedArtifactsResult {
72- bundlePath : string ;
73- cosignArgs : Array < string > ;
74- }
31+ import {
32+ Endpoints ,
33+ FULCIO_URL ,
34+ ParsedBundle ,
35+ REKOR_URL ,
36+ SEARCH_URL ,
37+ SignAttestationManifestsOpts ,
38+ SignAttestationManifestsResult ,
39+ SignProvenanceBlobsOpts ,
40+ SignProvenanceBlobsResult ,
41+ TSASERVER_URL ,
42+ VerifySignedArtifactsOpts ,
43+ VerifySignedArtifactsResult ,
44+ VerifySignedManifestsOpts ,
45+ VerifySignedManifestsResult
46+ } from '../types/sigstore/sigstore' ;
7547
7648export interface SigstoreOpts {
7749 cosign ?: Cosign ;
@@ -138,13 +110,13 @@ export class Sigstore {
138110 throw new Error ( `Cosign sign command failed with exit code ${ execRes . exitCode } ` ) ;
139111 }
140112 }
141- const attest = Sigstore . toAttestation ( bundleFromJSON ( signResult . bundle ) ) ;
142- if ( attest . tlogID ) {
143- core . info ( `Uploaded to Rekor transparency log: ${ SEARCH_URL } ?logIndex=${ attest . tlogID } ` ) ;
113+ const parsedBundle = Sigstore . parseBundle ( bundleFromJSON ( signResult . bundle ) ) ;
114+ if ( parsedBundle . tlogID ) {
115+ core . info ( `Uploaded to Rekor transparency log: ${ SEARCH_URL } ?logIndex=${ parsedBundle . tlogID } ` ) ;
144116 }
145117 core . info ( `Signature manifest pushed: https://oci.dag.dev/?referrers=${ attestationRef } ` ) ;
146118 result [ attestationRef ] = {
147- ...attest ,
119+ ...parsedBundle ,
148120 imageName : imageName
149121 } ;
150122 } ) ;
@@ -242,28 +214,28 @@ export class Sigstore {
242214 core . warning ( `No subjects found in provenance ${ p } , skip signing.` ) ;
243215 return ;
244216 }
245- const bundle = await signPayload (
217+ const bundle = await Sigstore . signPayload (
246218 {
247- body : blob ,
219+ data : blob ,
248220 type : INTOTO_MEDIATYPE_PAYLOAD
249221 } ,
250222 endpoints
251223 ) ;
252- const attest = Sigstore . toAttestation ( bundle ) ;
224+ const parsedBundle = Sigstore . parseBundle ( bundle ) ;
253225 core . info ( `Provenance blob signed for:` ) ;
254226 for ( const subject of subjects ) {
255227 const [ digestAlg , digestValue ] = Object . entries ( subject . digest ) [ 0 ] || [ ] ;
256228 core . info ( ` - ${ subject . name } (${ digestAlg } :${ digestValue } )` ) ;
257229 }
258- if ( attest . tlogID ) {
259- core . info ( `Attestation signature uploaded to Rekor transparency log: ${ SEARCH_URL } ?logIndex=${ attest . tlogID } ` ) ;
230+ if ( parsedBundle . tlogID ) {
231+ core . info ( `Attestation signature uploaded to Rekor transparency log: ${ SEARCH_URL } ?logIndex=${ parsedBundle . tlogID } ` ) ;
260232 }
261233 core . info ( `Writing Sigstore bundle to: ${ bundlePath } ` ) ;
262- fs . writeFileSync ( bundlePath , JSON . stringify ( attest . bundle , null , 2 ) , {
234+ fs . writeFileSync ( bundlePath , JSON . stringify ( parsedBundle . payload , null , 2 ) , {
263235 encoding : 'utf-8'
264236 } ) ;
265237 result [ p ] = {
266- ...attest ,
238+ ...parsedBundle ,
267239 bundlePath : bundlePath ,
268240 subjects : subjects
269241 } ;
@@ -359,8 +331,41 @@ export class Sigstore {
359331 } ) ) ;
360332 }
361333
362- // https://github.com/actions/toolkit/blob/d3ab50471b4ff1d1274dffb90ef9c5d9949b4886/packages/attest/src/attest.ts#L90
363- private static toAttestation ( bundle : Bundle ) : Attestation {
334+ private static async signPayload ( artifact : Artifact , endpoints : Endpoints , timeout ?: number , retries ?: number ) : Promise < Bundle > {
335+ const witnesses : Witness [ ] = [ ] ;
336+
337+ const signer = new FulcioSigner ( {
338+ identityProvider : new CIContextProvider ( 'sigstore' ) ,
339+ fulcioBaseURL : endpoints . fulcioURL ,
340+ timeout : timeout ,
341+ retry : retries
342+ } ) ;
343+
344+ if ( endpoints . rekorURL ) {
345+ witnesses . push (
346+ new RekorWitness ( {
347+ rekorBaseURL : endpoints . rekorURL ,
348+ fetchOnConflict : true ,
349+ timeout : timeout ,
350+ retry : retries
351+ } )
352+ ) ;
353+ }
354+
355+ if ( endpoints . tsaServerURL ) {
356+ witnesses . push (
357+ new TSAWitness ( {
358+ tsaBaseURL : endpoints . tsaServerURL ,
359+ timeout : timeout ,
360+ retry : retries
361+ } )
362+ ) ;
363+ }
364+
365+ return new DSSEBundleBuilder ( { signer, witnesses} ) . create ( artifact ) ;
366+ }
367+
368+ private static parseBundle ( bundle : Bundle ) : ParsedBundle {
364369 let certBytes : Buffer ;
365370 switch ( bundle . verificationMaterial . content . $case ) {
366371 case 'x509CertificateChain' :
@@ -375,12 +380,12 @@ export class Sigstore {
375380
376381 const signingCert = new X509Certificate ( certBytes ) ;
377382
378- // Collect transparency log ID if available
383+ // collect transparency log ID if available
379384 const tlogEntries = bundle . verificationMaterial . tlogEntries ;
380385 const tlogID = tlogEntries . length > 0 ? tlogEntries [ 0 ] . logIndex : undefined ;
381386
382387 return {
383- bundle : bundleToJSON ( bundle ) ,
388+ payload : bundleToJSON ( bundle ) ,
384389 certificate : signingCert . toString ( ) ,
385390 tlogID : tlogID
386391 } ;
0 commit comments