mirror of
https://github.com/stablyai/orca.git
synced 2026-10-18 08:03:22 +00:00
171 lines
6.0 KiB
JavaScript
171 lines
6.0 KiB
JavaScript
import { createHash } from 'node:crypto'
|
|
import { readFile, stat, writeFile } from 'node:fs/promises'
|
|
import { createRequire } from 'node:module'
|
|
import { join } from 'node:path'
|
|
|
|
const require = createRequire(import.meta.url)
|
|
|
|
function sha256(bytes) {
|
|
return `sha256:${createHash('sha256').update(bytes).digest('hex')}`
|
|
}
|
|
|
|
function spdxId(value) {
|
|
return `SPDXRef-${value.replace(/[^A-Za-z0-9.-]/g, '-')}`
|
|
}
|
|
|
|
function packageRecord(name, version, license) {
|
|
return {
|
|
name,
|
|
SPDXID: spdxId(`Package-${name}`),
|
|
versionInfo: version,
|
|
downloadLocation: 'NOASSERTION',
|
|
filesAnalyzed: false,
|
|
licenseConcluded: license,
|
|
licenseDeclared: license,
|
|
copyrightText: 'NOASSERTION'
|
|
}
|
|
}
|
|
|
|
function installedPackage(name) {
|
|
const parsed = require(`${name}/package.json`)
|
|
return packageRecord(parsed.name, parsed.version, parsed.license ?? 'NOASSERTION')
|
|
}
|
|
|
|
function watcherNativePackage(tuple) {
|
|
if (tuple.startsWith('linux-')) {
|
|
return `@parcel/watcher-linux-${tuple.slice('linux-'.length)}`
|
|
}
|
|
return `@parcel/watcher-${tuple}`
|
|
}
|
|
|
|
async function writeJson(path, value) {
|
|
const bytes = Buffer.from(`${JSON.stringify(value, null, 2)}\n`, 'utf8')
|
|
await writeFile(path, bytes, { flag: 'wx', mode: 0o600 })
|
|
return { name: path.split(/[\\/]/).at(-1), size: bytes.length, sha256: sha256(bytes) }
|
|
}
|
|
|
|
export async function writeSshRelayRuntimeMetadata({
|
|
outputDirectory,
|
|
identity,
|
|
archive,
|
|
nodeRelease,
|
|
sourceDateEpoch,
|
|
gitCommit,
|
|
builder,
|
|
toolchain
|
|
}) {
|
|
const createdAt = new Date(sourceDateEpoch * 1000).toISOString()
|
|
const sbomName = `orca-ssh-relay-runtime-${identity.tupleId}.spdx.json`
|
|
const provenanceName = `orca-ssh-relay-runtime-${identity.tupleId}.provenance.json`
|
|
const identityName = `orca-ssh-relay-runtime-${identity.tupleId}.identity.json`
|
|
const files = identity.entries
|
|
.filter((entry) => entry.type === 'file')
|
|
.map((entry, index) => ({
|
|
fileName: entry.path,
|
|
SPDXID: `SPDXRef-File-${index + 1}`,
|
|
checksums: [{ algorithm: 'SHA256', checksumValue: entry.sha256.slice('sha256:'.length) }],
|
|
licenseConcluded: 'NOASSERTION',
|
|
copyrightText: 'NOASSERTION'
|
|
}))
|
|
const packages = [
|
|
packageRecord('node', identity.nodeVersion, 'NOASSERTION'),
|
|
packageRecord('orca-ssh-relay', '0.1.0', 'NOASSERTION'),
|
|
installedPackage('node-pty'),
|
|
installedPackage('@parcel/watcher'),
|
|
installedPackage(watcherNativePackage(identity.tupleId)),
|
|
installedPackage('detect-libc'),
|
|
installedPackage('is-glob'),
|
|
installedPackage('is-extglob'),
|
|
installedPackage('picomatch')
|
|
]
|
|
const documentId = identity.contentId.slice('sha256:'.length)
|
|
const sbom = {
|
|
spdxVersion: 'SPDX-2.3',
|
|
dataLicense: 'CC0-1.0',
|
|
SPDXID: 'SPDXRef-DOCUMENT',
|
|
name: `Orca SSH relay runtime ${identity.tupleId}`,
|
|
documentNamespace: `https://github.com/stablyai/orca/ssh-relay-runtime/${documentId}`,
|
|
creationInfo: { created: createdAt, creators: ['Organization: Stably AI'] },
|
|
packages,
|
|
files,
|
|
relationships: packages.map((component) => ({
|
|
spdxElementId: 'SPDXRef-DOCUMENT',
|
|
relationshipType: 'DESCRIBES',
|
|
relatedSpdxElement: component.SPDXID
|
|
}))
|
|
}
|
|
const nativeFiles = identity.entries
|
|
.filter(
|
|
(entry) =>
|
|
entry.type === 'file' &&
|
|
['node', 'node-pty-native', 'parcel-watcher-native', 'native-runtime'].includes(entry.role)
|
|
)
|
|
.map((entry) => ({ path: entry.path, sha256: entry.sha256 }))
|
|
const resolvedDependencies = [
|
|
{
|
|
uri: `${nodeRelease.baseUrl}/${nodeRelease.archives[identity.tupleId].name}`,
|
|
digest: { sha256: nodeRelease.archives[identity.tupleId].sha256 }
|
|
},
|
|
{
|
|
uri: nodeRelease.signature.key.sourceUrl,
|
|
digest: { sha256: nodeRelease.signature.key.sha256 }
|
|
},
|
|
{ uri: `git+https://github.com/stablyai/orca@${gitCommit}`, digest: { gitCommit } }
|
|
]
|
|
if (identity.tupleId.startsWith('win32-')) {
|
|
const headers = nodeRelease.windowsBuildInputs.headersArchive
|
|
const library = nodeRelease.windowsBuildInputs.importLibraries[identity.tupleId]
|
|
resolvedDependencies.splice(
|
|
1,
|
|
0,
|
|
{ uri: `${nodeRelease.baseUrl}/${headers.name}`, digest: { sha256: headers.sha256 } },
|
|
{ uri: `${nodeRelease.baseUrl}/${library.name}`, digest: { sha256: library.sha256 } }
|
|
)
|
|
}
|
|
const provenance = {
|
|
_type: 'https://in-toto.io/Statement/v1',
|
|
subject: [{ name: archive.name, digest: { sha256: archive.sha256.slice('sha256:'.length) } }],
|
|
predicateType: 'https://slsa.dev/provenance/v1',
|
|
predicate: {
|
|
buildDefinition: {
|
|
buildType: 'https://github.com/stablyai/orca/ssh-relay-runtime-build/v1',
|
|
externalParameters: {
|
|
tuple: identity.tupleId,
|
|
nodeVersion: identity.nodeVersion,
|
|
sourceDateEpoch
|
|
},
|
|
internalParameters: { toolchain },
|
|
resolvedDependencies
|
|
},
|
|
runDetails: {
|
|
builder: { id: builder },
|
|
metadata: { invocationId: process.env.GITHUB_RUN_ID ?? 'local-unpublished-build' },
|
|
byproducts: [{ name: 'native-files', content: nativeFiles }]
|
|
}
|
|
}
|
|
}
|
|
const identityDocument = {
|
|
...identity,
|
|
archive: {
|
|
name: archive.name,
|
|
size: archive.size,
|
|
expandedSize: identity.expandedSize,
|
|
fileCount: identity.fileCount,
|
|
sha256: archive.sha256
|
|
}
|
|
}
|
|
const [sbomAsset, provenanceAsset, identityAsset] = await Promise.all([
|
|
writeJson(join(outputDirectory, sbomName), sbom),
|
|
writeJson(join(outputDirectory, provenanceName), provenance),
|
|
writeJson(join(outputDirectory, identityName), identityDocument)
|
|
])
|
|
for (const asset of [sbomAsset, provenanceAsset, identityAsset]) {
|
|
const metadata = await stat(join(outputDirectory, asset.name))
|
|
const bytes = await readFile(join(outputDirectory, asset.name))
|
|
if (metadata.size !== asset.size || sha256(bytes) !== asset.sha256) {
|
|
throw new Error(`Runtime metadata changed while being finalized: ${asset.name}`)
|
|
}
|
|
}
|
|
return { sbom: sbomAsset, provenance: provenanceAsset, identity: identityAsset }
|
|
}
|