Files
attest/src/attest.ts
Brian DeHamer faa6467995 refactor core attestation logic (#73)
Signed-off-by: Brian DeHamer <bdehamer@github.com>
2024-05-28 11:00:03 -07:00

68 lines
1.9 KiB
TypeScript

import { Attestation, Predicate, Subject, attest } from '@actions/attest'
import { attachArtifactToImage, getRegistryCredentials } from '@sigstore/oci'
const OCI_TIMEOUT = 2000
const OCI_RETRY = 3
export type SigstoreInstance = 'public-good' | 'github'
export type AttestResult = Attestation & {
subjectName: string
subjectDigest: string
attestationDigest?: string
}
export const createAttestation = async (
subject: Subject,
predicate: Predicate,
opts: {
sigstoreInstance: SigstoreInstance
pushToRegistry: boolean
githubToken: string
}
): Promise<AttestResult> => {
// Sign provenance w/ Sigstore
const attestation = await attest({
subjectName: subject.name,
subjectDigest: subject.digest,
predicateType: predicate.type,
predicate: predicate.params,
sigstore: opts.sigstoreInstance,
token: opts.githubToken
})
const subDigest = subjectDigest(subject)
const result: AttestResult = {
...attestation,
subjectName: subject.name,
subjectDigest: subDigest
}
if (opts.pushToRegistry) {
const credentials = getRegistryCredentials(subject.name)
const artifact = await attachArtifactToImage({
credentials,
imageName: subject.name,
imageDigest: subDigest,
artifact: Buffer.from(JSON.stringify(attestation.bundle)),
mediaType: attestation.bundle.mediaType,
annotations: {
'dev.sigstore.bundle.content': 'dsse-envelope',
'dev.sigstore.bundle.predicateType': predicate.type
},
fetchOpts: { timeout: OCI_TIMEOUT, retry: OCI_RETRY }
})
// Add the attestation's digest to the result
result.attestationDigest = artifact.digest
}
return result
}
// Returns the subject's digest as a formatted string of the form
// "<algorithm>:<digest>".
const subjectDigest = (subject: Subject): string => {
const alg = Object.keys(subject.digest).sort()[0]
return `${alg}:${subject.digest[alg]}`
}