snyk-docker-plugin
Version:
Snyk CLI docker plugin
92 lines • 3.71 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.parsePlatform = exports.fetchAttestationsFromRegistry = void 0;
const docker_registry_v2_client_1 = require("@snyk/docker-registry-v2-client");
const Debug = require("debug");
const error_utils_1 = require("../error-utils");
const layer_1 = require("./oci-archive/layer");
const debug = Debug("snyk");
const MEDIATYPE_IN_TOTO = "application/vnd.in-toto+json";
const PREDICATE_TYPE_ANNOTATION = "in-toto.io/predicate-type";
const SLSA_PROVENANCE_PREFIX = "https://slsa.dev/provenance/";
// Fetches provenance attestations for an image directly from its source registry.
async function fetchAttestationsFromRegistry(ref) {
var _a;
const { registryBase, repo, imageReference, username, password, platform } = ref;
let manifest;
try {
manifest = await (0, docker_registry_v2_client_1.getAttestationManifest)(registryBase, repo, imageReference, username, password, undefined, platform);
}
catch (error) {
debug(`[provenance] failed to fetch attestation manifest for ${repo}@${imageReference}: ${(0, error_utils_1.getErrorMessage)(error)}`);
return [];
}
if (!manifest ||
!Array.isArray(manifest.layers) ||
manifest.layers.length === 0) {
return [];
}
const inTotoStatements = {};
for (const layer of manifest.layers) {
if (layer.mediaType !== MEDIATYPE_IN_TOTO) {
continue;
}
const predicateType = (_a = layer.annotations) === null || _a === void 0 ? void 0 : _a[PREDICATE_TYPE_ANNOTATION];
if (predicateType && !predicateType.startsWith(SLSA_PROVENANCE_PREFIX)) {
continue;
}
if (typeof layer.size === "number" && layer.size > layer_1.MAX_JSON_SIZE_BYTES) {
debug(`[provenance] skipping oversized attestation layer ${layer.digest} (${layer.size} bytes > ${layer_1.MAX_JSON_SIZE_BYTES})`);
continue;
}
try {
const blob = await (0, docker_registry_v2_client_1.getLayer)(registryBase, repo, layer.digest, username, password);
inTotoStatements[layer.digest] = JSON.parse(blob.toString("utf-8"));
}
catch (error) {
debug(`[provenance] skipping layer ${layer.digest}: ${(0, error_utils_1.getErrorMessage)(error)}`);
}
}
if (Object.keys(inTotoStatements).length === 0) {
return [];
}
if (!manifest.manifestDigest) {
debug(`[provenance] no descriptor digest for attestation manifest ${repo}@${imageReference}; skipping`);
return [];
}
const resolvedManifest = {
schemaVersion: String(manifest.schemaVersion),
mediaType: manifest.mediaType,
config: { digest: manifest.config.digest },
layers: manifest.layers.map((layer) => ({
digest: layer.digest,
mediaType: layer.mediaType,
size: layer.size,
annotations: layer.annotations,
})),
};
return [
{
manifestDigest: manifest.manifestDigest,
manifest: resolvedManifest,
inTotoStatements,
},
];
}
exports.fetchAttestationsFromRegistry = fetchAttestationsFromRegistry;
function parsePlatform(platform) {
if (!platform) {
return undefined;
}
const info = (0, layer_1.getOciPlatformInfoFromOptionString)(platform);
if (!info.os || !info.architecture) {
return undefined;
}
return {
os: info.os,
architecture: info.architecture,
variant: info.variant,
};
}
exports.parsePlatform = parsePlatform;
//# sourceMappingURL=fetch-registry-provenance-attestations.js.map