11cb0ef41Sopenharmony_ciconst sigstore = require('sigstore') 21cb0ef41Sopenharmony_ciconst { readFile } = require('fs/promises') 31cb0ef41Sopenharmony_ciconst ci = require('ci-info') 41cb0ef41Sopenharmony_ciconst { env } = process 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ciconst INTOTO_PAYLOAD_TYPE = 'application/vnd.in-toto+json' 71cb0ef41Sopenharmony_ciconst INTOTO_STATEMENT_V01_TYPE = 'https://in-toto.io/Statement/v0.1' 81cb0ef41Sopenharmony_ciconst INTOTO_STATEMENT_V1_TYPE = 'https://in-toto.io/Statement/v1' 91cb0ef41Sopenharmony_ciconst SLSA_PREDICATE_V02_TYPE = 'https://slsa.dev/provenance/v0.2' 101cb0ef41Sopenharmony_ciconst SLSA_PREDICATE_V1_TYPE = 'https://slsa.dev/provenance/v1' 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ciconst GITHUB_BUILDER_ID_PREFIX = 'https://github.com/actions/runner' 131cb0ef41Sopenharmony_ciconst GITHUB_BUILD_TYPE = 'https://slsa-framework.github.io/github-actions-buildtypes/workflow/v1' 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ciconst GITLAB_BUILD_TYPE_PREFIX = 'https://github.com/npm/cli/gitlab' 161cb0ef41Sopenharmony_ciconst GITLAB_BUILD_TYPE_VERSION = 'v0alpha1' 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ciconst generateProvenance = async (subject, opts) => { 191cb0ef41Sopenharmony_ci let payload 201cb0ef41Sopenharmony_ci if (ci.GITHUB_ACTIONS) { 211cb0ef41Sopenharmony_ci /* istanbul ignore next - not covering missing env var case */ 221cb0ef41Sopenharmony_ci const relativeRef = (env.GITHUB_WORKFLOW_REF || '').replace(env.GITHUB_REPOSITORY + '/', '') 231cb0ef41Sopenharmony_ci const delimiterIndex = relativeRef.indexOf('@') 241cb0ef41Sopenharmony_ci const workflowPath = relativeRef.slice(0, delimiterIndex) 251cb0ef41Sopenharmony_ci const workflowRef = relativeRef.slice(delimiterIndex + 1) 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci payload = { 281cb0ef41Sopenharmony_ci _type: INTOTO_STATEMENT_V1_TYPE, 291cb0ef41Sopenharmony_ci subject, 301cb0ef41Sopenharmony_ci predicateType: SLSA_PREDICATE_V1_TYPE, 311cb0ef41Sopenharmony_ci predicate: { 321cb0ef41Sopenharmony_ci buildDefinition: { 331cb0ef41Sopenharmony_ci buildType: GITHUB_BUILD_TYPE, 341cb0ef41Sopenharmony_ci externalParameters: { 351cb0ef41Sopenharmony_ci workflow: { 361cb0ef41Sopenharmony_ci ref: workflowRef, 371cb0ef41Sopenharmony_ci repository: `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}`, 381cb0ef41Sopenharmony_ci path: workflowPath, 391cb0ef41Sopenharmony_ci }, 401cb0ef41Sopenharmony_ci }, 411cb0ef41Sopenharmony_ci internalParameters: { 421cb0ef41Sopenharmony_ci github: { 431cb0ef41Sopenharmony_ci event_name: env.GITHUB_EVENT_NAME, 441cb0ef41Sopenharmony_ci repository_id: env.GITHUB_REPOSITORY_ID, 451cb0ef41Sopenharmony_ci repository_owner_id: env.GITHUB_REPOSITORY_OWNER_ID, 461cb0ef41Sopenharmony_ci }, 471cb0ef41Sopenharmony_ci }, 481cb0ef41Sopenharmony_ci resolvedDependencies: [ 491cb0ef41Sopenharmony_ci { 501cb0ef41Sopenharmony_ci uri: `git+${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}@${env.GITHUB_REF}`, 511cb0ef41Sopenharmony_ci digest: { 521cb0ef41Sopenharmony_ci gitCommit: env.GITHUB_SHA, 531cb0ef41Sopenharmony_ci }, 541cb0ef41Sopenharmony_ci }, 551cb0ef41Sopenharmony_ci ], 561cb0ef41Sopenharmony_ci }, 571cb0ef41Sopenharmony_ci runDetails: { 581cb0ef41Sopenharmony_ci builder: { id: `${GITHUB_BUILDER_ID_PREFIX}/${env.RUNNER_ENVIRONMENT}` }, 591cb0ef41Sopenharmony_ci metadata: { 601cb0ef41Sopenharmony_ci /* eslint-disable-next-line max-len */ 611cb0ef41Sopenharmony_ci invocationId: `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}/actions/runs/${env.GITHUB_RUN_ID}/attempts/${env.GITHUB_RUN_ATTEMPT}`, 621cb0ef41Sopenharmony_ci }, 631cb0ef41Sopenharmony_ci }, 641cb0ef41Sopenharmony_ci }, 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci if (ci.GITLAB) { 681cb0ef41Sopenharmony_ci payload = { 691cb0ef41Sopenharmony_ci _type: INTOTO_STATEMENT_V01_TYPE, 701cb0ef41Sopenharmony_ci subject, 711cb0ef41Sopenharmony_ci predicateType: SLSA_PREDICATE_V02_TYPE, 721cb0ef41Sopenharmony_ci predicate: { 731cb0ef41Sopenharmony_ci buildType: `${GITLAB_BUILD_TYPE_PREFIX}/${GITLAB_BUILD_TYPE_VERSION}`, 741cb0ef41Sopenharmony_ci builder: { id: `${env.CI_PROJECT_URL}/-/runners/${env.CI_RUNNER_ID}` }, 751cb0ef41Sopenharmony_ci invocation: { 761cb0ef41Sopenharmony_ci configSource: { 771cb0ef41Sopenharmony_ci uri: `git+${env.CI_PROJECT_URL}`, 781cb0ef41Sopenharmony_ci digest: { 791cb0ef41Sopenharmony_ci sha1: env.CI_COMMIT_SHA, 801cb0ef41Sopenharmony_ci }, 811cb0ef41Sopenharmony_ci entryPoint: env.CI_JOB_NAME, 821cb0ef41Sopenharmony_ci }, 831cb0ef41Sopenharmony_ci parameters: { 841cb0ef41Sopenharmony_ci CI: env.CI, 851cb0ef41Sopenharmony_ci CI_API_GRAPHQL_URL: env.CI_API_GRAPHQL_URL, 861cb0ef41Sopenharmony_ci CI_API_V4_URL: env.CI_API_V4_URL, 871cb0ef41Sopenharmony_ci CI_BUILD_BEFORE_SHA: env.CI_BUILD_BEFORE_SHA, 881cb0ef41Sopenharmony_ci CI_BUILD_ID: env.CI_BUILD_ID, 891cb0ef41Sopenharmony_ci CI_BUILD_NAME: env.CI_BUILD_NAME, 901cb0ef41Sopenharmony_ci CI_BUILD_REF: env.CI_BUILD_REF, 911cb0ef41Sopenharmony_ci CI_BUILD_REF_NAME: env.CI_BUILD_REF_NAME, 921cb0ef41Sopenharmony_ci CI_BUILD_REF_SLUG: env.CI_BUILD_REF_SLUG, 931cb0ef41Sopenharmony_ci CI_BUILD_STAGE: env.CI_BUILD_STAGE, 941cb0ef41Sopenharmony_ci CI_COMMIT_BEFORE_SHA: env.CI_COMMIT_BEFORE_SHA, 951cb0ef41Sopenharmony_ci CI_COMMIT_BRANCH: env.CI_COMMIT_BRANCH, 961cb0ef41Sopenharmony_ci CI_COMMIT_REF_NAME: env.CI_COMMIT_REF_NAME, 971cb0ef41Sopenharmony_ci CI_COMMIT_REF_PROTECTED: env.CI_COMMIT_REF_PROTECTED, 981cb0ef41Sopenharmony_ci CI_COMMIT_REF_SLUG: env.CI_COMMIT_REF_SLUG, 991cb0ef41Sopenharmony_ci CI_COMMIT_SHA: env.CI_COMMIT_SHA, 1001cb0ef41Sopenharmony_ci CI_COMMIT_SHORT_SHA: env.CI_COMMIT_SHORT_SHA, 1011cb0ef41Sopenharmony_ci CI_COMMIT_TIMESTAMP: env.CI_COMMIT_TIMESTAMP, 1021cb0ef41Sopenharmony_ci CI_COMMIT_TITLE: env.CI_COMMIT_TITLE, 1031cb0ef41Sopenharmony_ci CI_CONFIG_PATH: env.CI_CONFIG_PATH, 1041cb0ef41Sopenharmony_ci CI_DEFAULT_BRANCH: env.CI_DEFAULT_BRANCH, 1051cb0ef41Sopenharmony_ci CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX: 1061cb0ef41Sopenharmony_ci env.CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX, 1071cb0ef41Sopenharmony_ci CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX: env.CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX, 1081cb0ef41Sopenharmony_ci CI_DEPENDENCY_PROXY_SERVER: env.CI_DEPENDENCY_PROXY_SERVER, 1091cb0ef41Sopenharmony_ci CI_DEPENDENCY_PROXY_USER: env.CI_DEPENDENCY_PROXY_USER, 1101cb0ef41Sopenharmony_ci CI_JOB_ID: env.CI_JOB_ID, 1111cb0ef41Sopenharmony_ci CI_JOB_NAME: env.CI_JOB_NAME, 1121cb0ef41Sopenharmony_ci CI_JOB_NAME_SLUG: env.CI_JOB_NAME_SLUG, 1131cb0ef41Sopenharmony_ci CI_JOB_STAGE: env.CI_JOB_STAGE, 1141cb0ef41Sopenharmony_ci CI_JOB_STARTED_AT: env.CI_JOB_STARTED_AT, 1151cb0ef41Sopenharmony_ci CI_JOB_URL: env.CI_JOB_URL, 1161cb0ef41Sopenharmony_ci CI_NODE_TOTAL: env.CI_NODE_TOTAL, 1171cb0ef41Sopenharmony_ci CI_PAGES_DOMAIN: env.CI_PAGES_DOMAIN, 1181cb0ef41Sopenharmony_ci CI_PAGES_URL: env.CI_PAGES_URL, 1191cb0ef41Sopenharmony_ci CI_PIPELINE_CREATED_AT: env.CI_PIPELINE_CREATED_AT, 1201cb0ef41Sopenharmony_ci CI_PIPELINE_ID: env.CI_PIPELINE_ID, 1211cb0ef41Sopenharmony_ci CI_PIPELINE_IID: env.CI_PIPELINE_IID, 1221cb0ef41Sopenharmony_ci CI_PIPELINE_SOURCE: env.CI_PIPELINE_SOURCE, 1231cb0ef41Sopenharmony_ci CI_PIPELINE_URL: env.CI_PIPELINE_URL, 1241cb0ef41Sopenharmony_ci CI_PROJECT_CLASSIFICATION_LABEL: env.CI_PROJECT_CLASSIFICATION_LABEL, 1251cb0ef41Sopenharmony_ci CI_PROJECT_DESCRIPTION: env.CI_PROJECT_DESCRIPTION, 1261cb0ef41Sopenharmony_ci CI_PROJECT_ID: env.CI_PROJECT_ID, 1271cb0ef41Sopenharmony_ci CI_PROJECT_NAME: env.CI_PROJECT_NAME, 1281cb0ef41Sopenharmony_ci CI_PROJECT_NAMESPACE: env.CI_PROJECT_NAMESPACE, 1291cb0ef41Sopenharmony_ci CI_PROJECT_NAMESPACE_ID: env.CI_PROJECT_NAMESPACE_ID, 1301cb0ef41Sopenharmony_ci CI_PROJECT_PATH: env.CI_PROJECT_PATH, 1311cb0ef41Sopenharmony_ci CI_PROJECT_PATH_SLUG: env.CI_PROJECT_PATH_SLUG, 1321cb0ef41Sopenharmony_ci CI_PROJECT_REPOSITORY_LANGUAGES: env.CI_PROJECT_REPOSITORY_LANGUAGES, 1331cb0ef41Sopenharmony_ci CI_PROJECT_ROOT_NAMESPACE: env.CI_PROJECT_ROOT_NAMESPACE, 1341cb0ef41Sopenharmony_ci CI_PROJECT_TITLE: env.CI_PROJECT_TITLE, 1351cb0ef41Sopenharmony_ci CI_PROJECT_URL: env.CI_PROJECT_URL, 1361cb0ef41Sopenharmony_ci CI_PROJECT_VISIBILITY: env.CI_PROJECT_VISIBILITY, 1371cb0ef41Sopenharmony_ci CI_REGISTRY: env.CI_REGISTRY, 1381cb0ef41Sopenharmony_ci CI_REGISTRY_IMAGE: env.CI_REGISTRY_IMAGE, 1391cb0ef41Sopenharmony_ci CI_REGISTRY_USER: env.CI_REGISTRY_USER, 1401cb0ef41Sopenharmony_ci CI_RUNNER_DESCRIPTION: env.CI_RUNNER_DESCRIPTION, 1411cb0ef41Sopenharmony_ci CI_RUNNER_ID: env.CI_RUNNER_ID, 1421cb0ef41Sopenharmony_ci CI_RUNNER_TAGS: env.CI_RUNNER_TAGS, 1431cb0ef41Sopenharmony_ci CI_SERVER_HOST: env.CI_SERVER_HOST, 1441cb0ef41Sopenharmony_ci CI_SERVER_NAME: env.CI_SERVER_NAME, 1451cb0ef41Sopenharmony_ci CI_SERVER_PORT: env.CI_SERVER_PORT, 1461cb0ef41Sopenharmony_ci CI_SERVER_PROTOCOL: env.CI_SERVER_PROTOCOL, 1471cb0ef41Sopenharmony_ci CI_SERVER_REVISION: env.CI_SERVER_REVISION, 1481cb0ef41Sopenharmony_ci CI_SERVER_SHELL_SSH_HOST: env.CI_SERVER_SHELL_SSH_HOST, 1491cb0ef41Sopenharmony_ci CI_SERVER_SHELL_SSH_PORT: env.CI_SERVER_SHELL_SSH_PORT, 1501cb0ef41Sopenharmony_ci CI_SERVER_URL: env.CI_SERVER_URL, 1511cb0ef41Sopenharmony_ci CI_SERVER_VERSION: env.CI_SERVER_VERSION, 1521cb0ef41Sopenharmony_ci CI_SERVER_VERSION_MAJOR: env.CI_SERVER_VERSION_MAJOR, 1531cb0ef41Sopenharmony_ci CI_SERVER_VERSION_MINOR: env.CI_SERVER_VERSION_MINOR, 1541cb0ef41Sopenharmony_ci CI_SERVER_VERSION_PATCH: env.CI_SERVER_VERSION_PATCH, 1551cb0ef41Sopenharmony_ci CI_TEMPLATE_REGISTRY_HOST: env.CI_TEMPLATE_REGISTRY_HOST, 1561cb0ef41Sopenharmony_ci GITLAB_CI: env.GITLAB_CI, 1571cb0ef41Sopenharmony_ci GITLAB_FEATURES: env.GITLAB_FEATURES, 1581cb0ef41Sopenharmony_ci GITLAB_USER_ID: env.GITLAB_USER_ID, 1591cb0ef41Sopenharmony_ci GITLAB_USER_LOGIN: env.GITLAB_USER_LOGIN, 1601cb0ef41Sopenharmony_ci RUNNER_GENERATE_ARTIFACTS_METADATA: env.RUNNER_GENERATE_ARTIFACTS_METADATA, 1611cb0ef41Sopenharmony_ci }, 1621cb0ef41Sopenharmony_ci environment: { 1631cb0ef41Sopenharmony_ci name: env.CI_RUNNER_DESCRIPTION, 1641cb0ef41Sopenharmony_ci architecture: env.CI_RUNNER_EXECUTABLE_ARCH, 1651cb0ef41Sopenharmony_ci server: env.CI_SERVER_URL, 1661cb0ef41Sopenharmony_ci project: env.CI_PROJECT_PATH, 1671cb0ef41Sopenharmony_ci job: { 1681cb0ef41Sopenharmony_ci id: env.CI_JOB_ID, 1691cb0ef41Sopenharmony_ci }, 1701cb0ef41Sopenharmony_ci pipeline: { 1711cb0ef41Sopenharmony_ci id: env.CI_PIPELINE_ID, 1721cb0ef41Sopenharmony_ci ref: env.CI_CONFIG_PATH, 1731cb0ef41Sopenharmony_ci }, 1741cb0ef41Sopenharmony_ci }, 1751cb0ef41Sopenharmony_ci }, 1761cb0ef41Sopenharmony_ci metadata: { 1771cb0ef41Sopenharmony_ci buildInvocationId: `${env.CI_JOB_URL}`, 1781cb0ef41Sopenharmony_ci completeness: { 1791cb0ef41Sopenharmony_ci parameters: true, 1801cb0ef41Sopenharmony_ci environment: true, 1811cb0ef41Sopenharmony_ci materials: false, 1821cb0ef41Sopenharmony_ci }, 1831cb0ef41Sopenharmony_ci reproducible: false, 1841cb0ef41Sopenharmony_ci }, 1851cb0ef41Sopenharmony_ci materials: [ 1861cb0ef41Sopenharmony_ci { 1871cb0ef41Sopenharmony_ci uri: `git+${env.CI_PROJECT_URL}`, 1881cb0ef41Sopenharmony_ci digest: { 1891cb0ef41Sopenharmony_ci sha1: env.CI_COMMIT_SHA, 1901cb0ef41Sopenharmony_ci }, 1911cb0ef41Sopenharmony_ci }, 1921cb0ef41Sopenharmony_ci ], 1931cb0ef41Sopenharmony_ci }, 1941cb0ef41Sopenharmony_ci } 1951cb0ef41Sopenharmony_ci } 1961cb0ef41Sopenharmony_ci return sigstore.attest(Buffer.from(JSON.stringify(payload)), INTOTO_PAYLOAD_TYPE, opts) 1971cb0ef41Sopenharmony_ci} 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ciconst verifyProvenance = async (subject, provenancePath) => { 2001cb0ef41Sopenharmony_ci let provenanceBundle 2011cb0ef41Sopenharmony_ci try { 2021cb0ef41Sopenharmony_ci provenanceBundle = JSON.parse(await readFile(provenancePath)) 2031cb0ef41Sopenharmony_ci } catch (err) { 2041cb0ef41Sopenharmony_ci err.message = `Invalid provenance provided: ${err.message}` 2051cb0ef41Sopenharmony_ci throw err 2061cb0ef41Sopenharmony_ci } 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci const payload = extractProvenance(provenanceBundle) 2091cb0ef41Sopenharmony_ci if (!payload.subject || !payload.subject.length) { 2101cb0ef41Sopenharmony_ci throw new Error('No subject found in sigstore bundle payload') 2111cb0ef41Sopenharmony_ci } 2121cb0ef41Sopenharmony_ci if (payload.subject.length > 1) { 2131cb0ef41Sopenharmony_ci throw new Error('Found more than one subject in the sigstore bundle payload') 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ci const bundleSubject = payload.subject[0] 2171cb0ef41Sopenharmony_ci if (subject.name !== bundleSubject.name) { 2181cb0ef41Sopenharmony_ci throw new Error( 2191cb0ef41Sopenharmony_ci `Provenance subject ${bundleSubject.name} does not match the package: ${subject.name}` 2201cb0ef41Sopenharmony_ci ) 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci if (subject.digest.sha512 !== bundleSubject.digest.sha512) { 2231cb0ef41Sopenharmony_ci throw new Error('Provenance subject digest does not match the package') 2241cb0ef41Sopenharmony_ci } 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci await sigstore.verify(provenanceBundle) 2271cb0ef41Sopenharmony_ci return provenanceBundle 2281cb0ef41Sopenharmony_ci} 2291cb0ef41Sopenharmony_ci 2301cb0ef41Sopenharmony_ciconst extractProvenance = (bundle) => { 2311cb0ef41Sopenharmony_ci if (!bundle?.dsseEnvelope?.payload) { 2321cb0ef41Sopenharmony_ci throw new Error('No dsseEnvelope with payload found in sigstore bundle') 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci try { 2351cb0ef41Sopenharmony_ci return JSON.parse(Buffer.from(bundle.dsseEnvelope.payload, 'base64').toString('utf8')) 2361cb0ef41Sopenharmony_ci } catch (err) { 2371cb0ef41Sopenharmony_ci err.message = `Failed to parse payload from dsseEnvelope: ${err.message}` 2381cb0ef41Sopenharmony_ci throw err 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci} 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_cimodule.exports = { 2431cb0ef41Sopenharmony_ci generateProvenance, 2441cb0ef41Sopenharmony_ci verifyProvenance, 2451cb0ef41Sopenharmony_ci} 246