This commit is contained in:
ejahnGithub
2024-02-23 08:47:57 -08:00
parent d83c83490f
commit 4eddc006f0
16 changed files with 180 additions and 514 deletions
+1
View File
@@ -103,3 +103,4 @@ __tests__/runner/*
*.code-workspace
packages/**/dist
packages/attest/dist
Generated Vendored
+179 -179
View File
@@ -64798,7 +64798,7 @@ exports.writeAttestation = writeAttestation;
/***/ }),
/***/ 5144:
/***/ 9112:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
@@ -64812,181 +64812,6 @@ exports.FULCIO_INTERNAL_URL = 'https://fulcio.githubapp.com';
exports.TSA_INTERNAL_URL = 'https://timestamp.githubapp.com';
/***/ }),
/***/ 7391:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"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.storePredicate = exports.predicateFromInputs = void 0;
const core = __importStar(__nccwpck_require__(2186));
const fs_1 = __importDefault(__nccwpck_require__(7147));
const path = __importStar(__nccwpck_require__(1017));
// Returns the predicate specified by the action's inputs. The predicate value
// may be specified as a path to a file or as a string.
const predicateFromInputs = () => {
const predicateType = core.getInput('predicate-type', { required: true });
const predicateStr = core.getInput('predicate', { required: false });
const predicatePath = core.getInput('predicate-path', { required: false });
if (!predicatePath && !predicateStr) {
throw new Error('One of predicate-path or predicate must be provided');
}
const params = predicatePath
? fs_1.default.readFileSync(predicatePath, 'utf-8')
: predicateStr;
return { type: predicateType, params: JSON.parse(params) };
};
exports.predicateFromInputs = predicateFromInputs;
const storePredicate = (predicate) => {
// random tempfile
const basePath = process.env['RUNNER_TEMP'];
if (!basePath) {
throw new Error('Missing RUNNER_TEMP environment variable');
}
const tmpDir = fs_1.default.mkdtempSync(path.join(basePath, path.sep));
const tempFile = path.join(tmpDir, 'predicate.json');
// write predicate to file
fs_1.default.writeFileSync(tempFile, JSON.stringify(predicate.params));
return tempFile;
};
exports.storePredicate = storePredicate;
/***/ }),
/***/ 7552:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"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.subjectFromInputs = void 0;
const core = __importStar(__nccwpck_require__(2186));
const glob = __importStar(__nccwpck_require__(8090));
const crypto_1 = __importDefault(__nccwpck_require__(6113));
const fs_1 = __importDefault(__nccwpck_require__(7147));
const path_1 = __importDefault(__nccwpck_require__(1017));
const DIGEST_ALGORITHM = 'sha256';
// Returns the subject specified by the action's inputs. The subject may be
// specified as a path to a file or as a digest. If a path is provided, the
// file's digest is calculated and returned along with the subject's name. If a
// digest is provided, the name must also be provided.
const subjectFromInputs = async () => {
const subjectPath = core.getInput('subject-path', { required: false });
const subjectDigest = core.getInput('subject-digest', { required: false });
const subjectName = core.getInput('subject-name', { required: false });
if (!subjectPath && !subjectDigest) {
throw new Error('One of subject-path or subject-digest must be provided');
}
if (subjectPath && subjectDigest) {
throw new Error('Only one of subject-path or subject-digest may be provided');
}
if (subjectDigest && !subjectName) {
throw new Error('subject-name must be provided when using subject-digest');
}
if (subjectPath) {
return await getSubjectFromPath(subjectPath, subjectName);
}
else {
return [getSubjectFromDigest(subjectDigest, subjectName)];
}
};
exports.subjectFromInputs = subjectFromInputs;
// Returns the subject specified by the path to a file. The file's digest is
// calculated and returned along with the subject's name.
const getSubjectFromPath = async (subjectPath, subjectName) => {
/* eslint-disable-next-line github/no-then */
const files = await glob.create(subjectPath).then(async (g) => g.glob());
const subjects = files.map(async (file) => {
const name = subjectName || path_1.default.parse(file).base;
const digest = await digestFile(DIGEST_ALGORITHM, file);
return { name, digest: { [DIGEST_ALGORITHM]: digest } };
});
if (subjects.length === 0) {
throw new Error(`Could not find subject at path ${subjectPath}`);
}
return Promise.all(subjects);
};
// Returns the subject specified by the digest of a file. The digest is returned
// along with the subject's name.
const getSubjectFromDigest = (subjectDigest, subjectName) => {
if (!subjectDigest.match(/^sha256:[A-Za-z0-9]{64}$/)) {
throw new Error('subject-digest must be in the format "sha256:<hex-digest>"');
}
const [alg, digest] = subjectDigest.split(':');
return {
name: subjectName,
digest: { [alg]: digest }
};
};
// Calculates the digest of a file using the specified algorithm. The file is
// streamed into the digest function to avoid loading the entire file into
// memory. The returned digest is a hex string.
const digestFile = async (algorithm, filePath) => {
return new Promise((resolve, reject) => {
const hash = crypto_1.default.createHash(algorithm).setEncoding('hex');
fs_1.default.createReadStream(filePath)
.once('error', reject)
.pipe(hash)
.once('finish', () => resolve(hash.read()));
});
};
/***/ }),
/***/ 399:
@@ -65030,9 +64855,9 @@ const oci_1 = __nccwpck_require__(7353);
const fs_1 = __importDefault(__nccwpck_require__(7147));
const os_1 = __importDefault(__nccwpck_require__(2037));
const path_1 = __importDefault(__nccwpck_require__(1017));
const endpoints_1 = __nccwpck_require__(5144);
const predicate_1 = __nccwpck_require__(7391);
const subject_1 = __nccwpck_require__(7552);
const endpoints_1 = __nccwpck_require__(9112);
const predicate_1 = __nccwpck_require__(2103);
const subject_1 = __nccwpck_require__(5206);
const COLOR_CYAN = '\x1B[36m';
const COLOR_DEFAULT = '\x1B[39m';
const ATTESTATION_FILE_NAME = 'attestation.jsonl';
@@ -65145,6 +64970,181 @@ const subjectDigest = (subject) => {
const attestationURL = (id) => `${github.context.serverUrl}/${github.context.repo.owner}/${github.context.repo.repo}/attestations/${id}`;
/***/ }),
/***/ 2103:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"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.storePredicate = exports.predicateFromInputs = void 0;
const core = __importStar(__nccwpck_require__(2186));
const fs_1 = __importDefault(__nccwpck_require__(7147));
const path = __importStar(__nccwpck_require__(1017));
// Returns the predicate specified by the action's inputs. The predicate value
// may be specified as a path to a file or as a string.
const predicateFromInputs = () => {
const predicateType = core.getInput('predicate-type', { required: true });
const predicateStr = core.getInput('predicate', { required: false });
const predicatePath = core.getInput('predicate-path', { required: false });
if (!predicatePath && !predicateStr) {
throw new Error('One of predicate-path or predicate must be provided');
}
const params = predicatePath
? fs_1.default.readFileSync(predicatePath, 'utf-8')
: predicateStr;
return { type: predicateType, params: JSON.parse(params) };
};
exports.predicateFromInputs = predicateFromInputs;
const storePredicate = (predicate) => {
// random tempfile
const basePath = process.env['RUNNER_TEMP'];
if (!basePath) {
throw new Error('Missing RUNNER_TEMP environment variable');
}
const tmpDir = fs_1.default.mkdtempSync(path.join(basePath, path.sep));
const tempFile = path.join(tmpDir, 'predicate.json');
// write predicate to file
fs_1.default.writeFileSync(tempFile, JSON.stringify(predicate.params));
return tempFile;
};
exports.storePredicate = storePredicate;
/***/ }),
/***/ 5206:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"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.subjectFromInputs = void 0;
const core = __importStar(__nccwpck_require__(2186));
const glob = __importStar(__nccwpck_require__(8090));
const crypto_1 = __importDefault(__nccwpck_require__(6113));
const fs_1 = __importDefault(__nccwpck_require__(7147));
const path_1 = __importDefault(__nccwpck_require__(1017));
const DIGEST_ALGORITHM = 'sha256';
// Returns the subject specified by the action's inputs. The subject may be
// specified as a path to a file or as a digest. If a path is provided, the
// file's digest is calculated and returned along with the subject's name. If a
// digest is provided, the name must also be provided.
const subjectFromInputs = async () => {
const subjectPath = core.getInput('subject-path', { required: false });
const subjectDigest = core.getInput('subject-digest', { required: false });
const subjectName = core.getInput('subject-name', { required: false });
if (!subjectPath && !subjectDigest) {
throw new Error('One of subject-path or subject-digest must be provided');
}
if (subjectPath && subjectDigest) {
throw new Error('Only one of subject-path or subject-digest may be provided');
}
if (subjectDigest && !subjectName) {
throw new Error('subject-name must be provided when using subject-digest');
}
if (subjectPath) {
return await getSubjectFromPath(subjectPath, subjectName);
}
else {
return [getSubjectFromDigest(subjectDigest, subjectName)];
}
};
exports.subjectFromInputs = subjectFromInputs;
// Returns the subject specified by the path to a file. The file's digest is
// calculated and returned along with the subject's name.
const getSubjectFromPath = async (subjectPath, subjectName) => {
/* eslint-disable-next-line github/no-then */
const files = await glob.create(subjectPath).then(async (g) => g.glob());
const subjects = files.map(async (file) => {
const name = subjectName || path_1.default.parse(file).base;
const digest = await digestFile(DIGEST_ALGORITHM, file);
return { name, digest: { [DIGEST_ALGORITHM]: digest } };
});
if (subjects.length === 0) {
throw new Error(`Could not find subject at path ${subjectPath}`);
}
return Promise.all(subjects);
};
// Returns the subject specified by the digest of a file. The digest is returned
// along with the subject's name.
const getSubjectFromDigest = (subjectDigest, subjectName) => {
if (!subjectDigest.match(/^sha256:[A-Za-z0-9]{64}$/)) {
throw new Error('subject-digest must be in the format "sha256:<hex-digest>"');
}
const [alg, digest] = subjectDigest.split(':');
return {
name: subjectName,
digest: { [alg]: digest }
};
};
// Calculates the digest of a file using the specified algorithm. The file is
// streamed into the digest function to avoid loading the entire file into
// memory. The returned digest is a hex string.
const digestFile = async (algorithm, filePath) => {
return new Promise((resolve, reject) => {
const hash = crypto_1.default.createHash(algorithm).setEncoding('hex');
fs_1.default.createReadStream(filePath)
.once('error', reject)
.pipe(hash)
.once('finish', () => resolve(hash.read()));
});
};
/***/ }),
/***/ 9491:
-16
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,2 +0,0 @@
import type { SBOM, Predicate } from './shared.types';
export declare const generateSBOMPredicate: (sbom: SBOM) => Predicate;
-32
View File
@@ -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
View File
@@ -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
View File
@@ -1,2 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-16
View File
@@ -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
View File
@@ -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
View File
@@ -1 +0,0 @@
export declare const writeAttestation: (attestation: unknown, token: string) => Promise<string>;
-51
View File
@@ -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;