mirror of
https://github.com/actions/attest-build-provenance.git
synced 2025-12-14 03:12:20 +00:00
removed dist
This commit is contained in:
parent
381fca5703
commit
ac3b5bcd98
2
.gitignore
vendored
2
.gitignore
vendored
@ -101,3 +101,5 @@ __tests__/runner/*
|
|||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
|
|
||||||
|
packages/attest/dist
|
||||||
|
|||||||
16
packages/attest/dist/attest.d.ts
vendored
16
packages/attest/dist/attest.d.ts
vendored
@ -1,16 +0,0 @@
|
|||||||
import { SignOptions } from './sign';
|
|
||||||
import type { Attestation } from './shared.types';
|
|
||||||
type AttestBaseOptions = SignOptions & {
|
|
||||||
subjectName: string;
|
|
||||||
subjectDigest: Record<string, string>;
|
|
||||||
token: string;
|
|
||||||
skipWrite?: boolean;
|
|
||||||
};
|
|
||||||
export type AttestOptions = AttestBaseOptions & {
|
|
||||||
predicateType: string;
|
|
||||||
predicate: object;
|
|
||||||
};
|
|
||||||
export type AttestProvenanceOptions = AttestBaseOptions;
|
|
||||||
export declare function attest(options: AttestOptions): Promise<Attestation>;
|
|
||||||
export declare function attestProvenance(options: AttestProvenanceOptions): Promise<Attestation>;
|
|
||||||
export {};
|
|
||||||
62
packages/attest/dist/attest.js
vendored
62
packages/attest/dist/attest.js
vendored
@ -1,62 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.attestProvenance = exports.attest = void 0;
|
|
||||||
const bundle_1 = require("@sigstore/bundle");
|
|
||||||
const provenance_1 = require("./provenance");
|
|
||||||
const sign_1 = require("./sign");
|
|
||||||
const store_1 = require("./store");
|
|
||||||
const assert_1 = __importDefault(require("assert"));
|
|
||||||
const crypto_1 = require("crypto");
|
|
||||||
const INTOTO_PAYLOAD_TYPE = 'application/vnd.in-toto+json';
|
|
||||||
const INTOTO_STATEMENT_V1_TYPE = 'https://in-toto.io/Statement/v1';
|
|
||||||
async function attest(options) {
|
|
||||||
const subject = {
|
|
||||||
name: options.subjectName,
|
|
||||||
digest: options.subjectDigest
|
|
||||||
};
|
|
||||||
const statement = {
|
|
||||||
_type: INTOTO_STATEMENT_V1_TYPE,
|
|
||||||
subject: [subject],
|
|
||||||
predicateType: options.predicateType,
|
|
||||||
predicate: options.predicate
|
|
||||||
};
|
|
||||||
// Sign the provenance statement
|
|
||||||
const payload = {
|
|
||||||
body: Buffer.from(JSON.stringify(statement)),
|
|
||||||
type: INTOTO_PAYLOAD_TYPE
|
|
||||||
};
|
|
||||||
const bundle = await (0, sign_1.signPayload)(payload, options);
|
|
||||||
// Store the attestation
|
|
||||||
let attestationID;
|
|
||||||
if (options.skipWrite !== true) {
|
|
||||||
attestationID = await (0, store_1.writeAttestation)((0, bundle_1.bundleToJSON)(bundle), options.token);
|
|
||||||
}
|
|
||||||
return toAttestation(bundle, attestationID);
|
|
||||||
}
|
|
||||||
exports.attest = attest;
|
|
||||||
async function attestProvenance(options) {
|
|
||||||
const predicate = (0, provenance_1.generateProvenancePredicate)(process.env);
|
|
||||||
return attest({
|
|
||||||
...options,
|
|
||||||
predicateType: predicate.type,
|
|
||||||
predicate: predicate.params
|
|
||||||
});
|
|
||||||
}
|
|
||||||
exports.attestProvenance = attestProvenance;
|
|
||||||
function toAttestation(bundle, attestationID) {
|
|
||||||
// Extract the signing certificate from the bundle
|
|
||||||
(0, assert_1.default)(bundle.verificationMaterial.content.$case === 'x509CertificateChain', 'Bundle must contain an x509 certificate chain');
|
|
||||||
const signingCert = new crypto_1.X509Certificate(bundle.verificationMaterial.content.x509CertificateChain.certificates[0].rawBytes);
|
|
||||||
// Determine if we can provide a link to the transparency log
|
|
||||||
const tlogEntries = bundle.verificationMaterial.tlogEntries;
|
|
||||||
const tlogID = tlogEntries.length > 0 ? tlogEntries[0].logIndex : undefined;
|
|
||||||
return {
|
|
||||||
bundle: (0, bundle_1.bundleToJSON)(bundle),
|
|
||||||
certificate: signingCert.toString(),
|
|
||||||
tlogID,
|
|
||||||
attestationID
|
|
||||||
};
|
|
||||||
}
|
|
||||||
4
packages/attest/dist/index.d.ts
vendored
4
packages/attest/dist/index.d.ts
vendored
@ -1,4 +0,0 @@
|
|||||||
export { AttestOptions, AttestProvenanceOptions, attest, attestProvenance } from './attest';
|
|
||||||
export { generateProvenancePredicate } from './provenance';
|
|
||||||
export { generateSBOMPredicate } from './sbom';
|
|
||||||
export type { Attestation, Predicate, Subject, SBOM } from './shared.types';
|
|
||||||
10
packages/attest/dist/index.js
vendored
10
packages/attest/dist/index.js
vendored
@ -1,10 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.generateSBOMPredicate = exports.generateProvenancePredicate = exports.attestProvenance = exports.attest = void 0;
|
|
||||||
var attest_1 = require("./attest");
|
|
||||||
Object.defineProperty(exports, "attest", { enumerable: true, get: function () { return attest_1.attest; } });
|
|
||||||
Object.defineProperty(exports, "attestProvenance", { enumerable: true, get: function () { return attest_1.attestProvenance; } });
|
|
||||||
var provenance_1 = require("./provenance");
|
|
||||||
Object.defineProperty(exports, "generateProvenancePredicate", { enumerable: true, get: function () { return provenance_1.generateProvenancePredicate; } });
|
|
||||||
var sbom_1 = require("./sbom");
|
|
||||||
Object.defineProperty(exports, "generateSBOMPredicate", { enumerable: true, get: function () { return sbom_1.generateSBOMPredicate; } });
|
|
||||||
9
packages/attest/dist/provenance.d.ts
vendored
9
packages/attest/dist/provenance.d.ts
vendored
@ -1,9 +0,0 @@
|
|||||||
/// <reference types="node" />
|
|
||||||
/// <reference types="node" />
|
|
||||||
/// <reference types="node" />
|
|
||||||
/// <reference types="node" />
|
|
||||||
/// <reference types="node" />
|
|
||||||
import type { Predicate, Subject } from './shared.types';
|
|
||||||
export declare const SLSA_PREDICATE_V1_TYPE = "https://slsa.dev/provenance/v1";
|
|
||||||
export declare const generateProvenancePredicate: (env: NodeJS.ProcessEnv) => Predicate;
|
|
||||||
export declare const generateProvenance: (subject: Subject, env: NodeJS.ProcessEnv) => object;
|
|
||||||
65
packages/attest/dist/provenance.js
vendored
65
packages/attest/dist/provenance.js
vendored
@ -1,65 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.generateProvenance = exports.generateProvenancePredicate = exports.SLSA_PREDICATE_V1_TYPE = void 0;
|
|
||||||
const INTOTO_STATEMENT_V1_TYPE = 'https://in-toto.io/Statement/v1';
|
|
||||||
exports.SLSA_PREDICATE_V1_TYPE = 'https://slsa.dev/provenance/v1';
|
|
||||||
const GITHUB_BUILDER_ID_PREFIX = 'https://github.com/actions/runner';
|
|
||||||
const GITHUB_BUILD_TYPE = 'https://slsa-framework.github.io/github-actions-buildtypes/workflow/v1';
|
|
||||||
const generateProvenancePredicate = (env) => {
|
|
||||||
const workflow = env.GITHUB_WORKFLOW_REF || /* istanbul ignore next */ '';
|
|
||||||
// Split just the path and ref from the workflow string.
|
|
||||||
// owner/repo/.github/workflows/main.yml@main =>
|
|
||||||
// .github/workflows/main.yml, main
|
|
||||||
const [workflowPath, workflowRef] = workflow
|
|
||||||
.replace(`${env.GITHUB_REPOSITORY}/`, '')
|
|
||||||
.split('@');
|
|
||||||
return {
|
|
||||||
type: exports.SLSA_PREDICATE_V1_TYPE,
|
|
||||||
params: {
|
|
||||||
buildDefinition: {
|
|
||||||
buildType: GITHUB_BUILD_TYPE,
|
|
||||||
externalParameters: {
|
|
||||||
workflow: {
|
|
||||||
ref: workflowRef,
|
|
||||||
repository: `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}`,
|
|
||||||
path: workflowPath
|
|
||||||
}
|
|
||||||
},
|
|
||||||
internalParameters: {
|
|
||||||
github: {
|
|
||||||
event_name: env.GITHUB_EVENT_NAME,
|
|
||||||
repository_id: env.GITHUB_REPOSITORY_ID,
|
|
||||||
repository_owner_id: env.GITHUB_REPOSITORY_OWNER_ID
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolvedDependencies: [
|
|
||||||
{
|
|
||||||
uri: `git+${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}@${env.GITHUB_REF}`,
|
|
||||||
digest: {
|
|
||||||
gitCommit: env.GITHUB_SHA
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
runDetails: {
|
|
||||||
builder: {
|
|
||||||
id: `${GITHUB_BUILDER_ID_PREFIX}/${env.RUNNER_ENVIRONMENT}`
|
|
||||||
},
|
|
||||||
metadata: {
|
|
||||||
invocationId: `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}/actions/runs/${env.GITHUB_RUN_ID}/attempts/${env.GITHUB_RUN_ATTEMPT}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
exports.generateProvenancePredicate = generateProvenancePredicate;
|
|
||||||
const generateProvenance = (subject, env) => {
|
|
||||||
const predicate = (0, exports.generateProvenancePredicate)(env);
|
|
||||||
return {
|
|
||||||
_type: INTOTO_STATEMENT_V1_TYPE,
|
|
||||||
subject: [subject],
|
|
||||||
predicateType: predicate.type,
|
|
||||||
predicate: predicate.params
|
|
||||||
};
|
|
||||||
};
|
|
||||||
exports.generateProvenance = generateProvenance;
|
|
||||||
2
packages/attest/dist/sbom.d.ts
vendored
2
packages/attest/dist/sbom.d.ts
vendored
@ -1,2 +0,0 @@
|
|||||||
import type { SBOM, Predicate } from './shared.types';
|
|
||||||
export declare const generateSBOMPredicate: (sbom: SBOM) => Predicate;
|
|
||||||
32
packages/attest/dist/sbom.js
vendored
32
packages/attest/dist/sbom.js
vendored
@ -1,32 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.generateSBOMPredicate = void 0;
|
|
||||||
const generateSBOMPredicate = (sbom) => {
|
|
||||||
if (sbom.type === 'spdx') {
|
|
||||||
return generateSPDXIntoto(sbom.object);
|
|
||||||
}
|
|
||||||
if (sbom.type === 'cyclonedx') {
|
|
||||||
return generateCycloneDXIntoto(sbom.object);
|
|
||||||
}
|
|
||||||
throw new Error('Unsupported SBOM format');
|
|
||||||
};
|
|
||||||
exports.generateSBOMPredicate = generateSBOMPredicate;
|
|
||||||
// ref: https://github.com/in-toto/attestation/blob/main/spec/predicates/spdx.md
|
|
||||||
const generateSPDXIntoto = (sbom) => {
|
|
||||||
const spdxVersion = sbom?.['spdxVersion'];
|
|
||||||
if (!spdxVersion) {
|
|
||||||
throw new Error('Cannot find spdxVersion in the SBOM');
|
|
||||||
}
|
|
||||||
const version = spdxVersion.split('-')[1];
|
|
||||||
return {
|
|
||||||
type: `https://spdx.dev/Document/v${version}`,
|
|
||||||
params: sbom
|
|
||||||
};
|
|
||||||
};
|
|
||||||
// ref: https://github.com/in-toto/attestation/blob/main/spec/predicates/cyclonedx.md
|
|
||||||
const generateCycloneDXIntoto = (sbom) => {
|
|
||||||
return {
|
|
||||||
type: 'https://cyclonedx.org/bom',
|
|
||||||
params: sbom
|
|
||||||
};
|
|
||||||
};
|
|
||||||
19
packages/attest/dist/shared.types.d.ts
vendored
19
packages/attest/dist/shared.types.d.ts
vendored
@ -1,19 +0,0 @@
|
|||||||
import type { SerializedBundle } from '@sigstore/bundle';
|
|
||||||
export type Subject = {
|
|
||||||
name: string;
|
|
||||||
digest: Record<string, string>;
|
|
||||||
};
|
|
||||||
export type Predicate = {
|
|
||||||
type: string;
|
|
||||||
params: object;
|
|
||||||
};
|
|
||||||
export type Attestation = {
|
|
||||||
bundle: SerializedBundle;
|
|
||||||
certificate: string;
|
|
||||||
tlogID?: string;
|
|
||||||
attestationID?: string;
|
|
||||||
};
|
|
||||||
export type SBOM = {
|
|
||||||
type: 'spdx' | 'cyclonedx';
|
|
||||||
object: object;
|
|
||||||
};
|
|
||||||
2
packages/attest/dist/shared.types.js
vendored
2
packages/attest/dist/shared.types.js
vendored
@ -1,2 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
16
packages/attest/dist/sign.d.ts
vendored
16
packages/attest/dist/sign.d.ts
vendored
@ -1,16 +0,0 @@
|
|||||||
/// <reference types="node" />
|
|
||||||
import { Bundle } from '@sigstore/bundle';
|
|
||||||
import { IdentityProvider } from '@sigstore/sign';
|
|
||||||
export type Payload = {
|
|
||||||
body: Buffer;
|
|
||||||
type: string;
|
|
||||||
};
|
|
||||||
export type SignOptions = {
|
|
||||||
fulcioURL: string;
|
|
||||||
rekorURL?: string;
|
|
||||||
tsaServerURL?: string;
|
|
||||||
identityProvider?: IdentityProvider;
|
|
||||||
timeout?: number;
|
|
||||||
retry?: number;
|
|
||||||
};
|
|
||||||
export declare const signPayload: (payload: Payload, options: SignOptions) => Promise<Bundle>;
|
|
||||||
46
packages/attest/dist/sign.js
vendored
46
packages/attest/dist/sign.js
vendored
@ -1,46 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.signPayload = void 0;
|
|
||||||
const sign_1 = require("@sigstore/sign");
|
|
||||||
const OIDC_AUDIENCE = 'sigstore';
|
|
||||||
const DEFAULT_TIMEOUT = 10000;
|
|
||||||
const DEFAULT_RETRIES = 3;
|
|
||||||
// Signs the provided payload with Sigstore.
|
|
||||||
const signPayload = async (payload, options) => {
|
|
||||||
const artifact = {
|
|
||||||
data: payload.body,
|
|
||||||
type: payload.type
|
|
||||||
};
|
|
||||||
// Sign the artifact and build the bundle
|
|
||||||
return initBundleBuilder(options).create(artifact);
|
|
||||||
};
|
|
||||||
exports.signPayload = signPayload;
|
|
||||||
// Assembles the Sigstore bundle builder with the appropriate options
|
|
||||||
const initBundleBuilder = (opts) => {
|
|
||||||
const identityProvider = opts.identityProvider || new sign_1.CIContextProvider(OIDC_AUDIENCE);
|
|
||||||
const timeout = opts.timeout || DEFAULT_TIMEOUT;
|
|
||||||
const retry = opts.retry || DEFAULT_RETRIES;
|
|
||||||
const witnesses = [];
|
|
||||||
const signer = new sign_1.FulcioSigner({
|
|
||||||
identityProvider: identityProvider,
|
|
||||||
fulcioBaseURL: opts.fulcioURL,
|
|
||||||
timeout: timeout,
|
|
||||||
retry: retry
|
|
||||||
});
|
|
||||||
if (opts.rekorURL) {
|
|
||||||
witnesses.push(new sign_1.RekorWitness({
|
|
||||||
rekorBaseURL: opts.rekorURL,
|
|
||||||
entryType: 'dsse',
|
|
||||||
timeout: timeout,
|
|
||||||
retry: retry
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
if (opts.tsaServerURL) {
|
|
||||||
witnesses.push(new sign_1.TSAWitness({
|
|
||||||
tsaBaseURL: opts.tsaServerURL,
|
|
||||||
timeout: timeout,
|
|
||||||
retry: retry
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
return new sign_1.DSSEBundleBuilder({ signer, witnesses });
|
|
||||||
};
|
|
||||||
1
packages/attest/dist/store.d.ts
vendored
1
packages/attest/dist/store.d.ts
vendored
@ -1 +0,0 @@
|
|||||||
export declare const writeAttestation: (attestation: unknown, token: string) => Promise<string>;
|
|
||||||
51
packages/attest/dist/store.js
vendored
51
packages/attest/dist/store.js
vendored
@ -1,51 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
||||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
||||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
||||||
}
|
|
||||||
Object.defineProperty(o, k2, desc);
|
|
||||||
}) : (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
o[k2] = m[k];
|
|
||||||
}));
|
|
||||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
||||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
||||||
}) : function(o, v) {
|
|
||||||
o["default"] = v;
|
|
||||||
});
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
||||||
__setModuleDefault(result, mod);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.writeAttestation = void 0;
|
|
||||||
const github = __importStar(require("@actions/github"));
|
|
||||||
const make_fetch_happen_1 = __importDefault(require("make-fetch-happen"));
|
|
||||||
const CREATE_ATTESTATION_REQUEST = 'POST /repos/{owner}/{repo}/attestations';
|
|
||||||
// Upload the attestation to the repository's attestations endpoint. Returns the
|
|
||||||
// ID of the uploaded attestation.
|
|
||||||
const writeAttestation = async (attestation, token) => {
|
|
||||||
const octokit = github.getOctokit(token, { request: { fetch: make_fetch_happen_1.default } });
|
|
||||||
try {
|
|
||||||
const response = await octokit.request(CREATE_ATTESTATION_REQUEST, {
|
|
||||||
owner: github.context.repo.owner,
|
|
||||||
repo: github.context.repo.repo,
|
|
||||||
data: { bundle: attestation }
|
|
||||||
});
|
|
||||||
return response.data?.id;
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
/* istanbul ignore next */
|
|
||||||
const message = err instanceof Error ? err.message : err;
|
|
||||||
throw new Error(`Failed to persist attestation: ${message}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.writeAttestation = writeAttestation;
|
|
||||||
Loading…
Reference in New Issue
Block a user