snyk-docker-plugin
Version:
Snyk CLI docker plugin
122 lines • 5.05 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getManifestLayers = exports.createGetImageIdFromManifest = exports.createExtractArchive = exports.kanikoArchiveConfig = exports.dockerArchiveConfig = exports.InvalidArchiveError = void 0;
const Debug = require("debug");
const fs_1 = require("fs");
const gunzip = require("gunzip-maybe");
const path_1 = require("path");
const tar_stream_1 = require("tar-stream");
const error_utils_1 = require("../error-utils");
const stream_utils_1 = require("../stream-utils");
class InvalidArchiveError extends Error {
constructor(message) {
super();
this.name = "InvalidArchiveError";
this.message = message;
}
}
exports.InvalidArchiveError = InvalidArchiveError;
const types_1 = require("../types");
const layer_1 = require("./layer");
const debug = Debug("snyk");
exports.dockerArchiveConfig = {
isLayerFile: (name) => (0, path_1.basename)(name).endsWith(".tar"),
isImageConfigFile: (name) => new RegExp("[A-Fa-f0-9]{64}\\.json").test(name),
formatLabel: "Docker",
layerErrorType: "tar",
extractImageId: (configValue) => configValue.split(".")[0],
};
exports.kanikoArchiveConfig = {
isLayerFile: (name) => (0, path_1.basename)(name).endsWith(".tar.gz"),
isImageConfigFile: (name) => new RegExp("sha256:[A-Fa-f0-9]{64}").test(name),
formatLabel: "Kaniko",
layerErrorType: "tar.gz",
extractImageId: (configValue) => configValue,
};
function createExtractArchive(config) {
return (archiveFilesystemPath, extractActions, _options) => new Promise((resolve, reject) => {
const tarExtractor = (0, tar_stream_1.extract)();
const layers = {};
let manifest;
let imageConfig;
tarExtractor.on("entry", async (header, stream, next) => {
if (header.type === "file") {
const normalizedName = (0, path_1.normalize)(header.name);
if (config.isLayerFile(normalizedName)) {
try {
layers[normalizedName] = await (0, layer_1.extractImageLayer)(stream, extractActions);
}
catch (error) {
debug(`Error extracting layer content from: '${(0, error_utils_1.getErrorMessage)(error)}'`);
reject(new Error(`Error reading ${config.layerErrorType} archive`));
}
}
else if (isManifestFile(normalizedName)) {
const manifestArray = await getManifestFile(stream);
manifest = manifestArray[0];
}
else if (config.isImageConfigFile(normalizedName)) {
imageConfig = await getManifestFile(stream);
}
}
stream.resume();
next();
});
tarExtractor.on("finish", () => {
try {
resolve(assembleLayersAndManifest(manifest, imageConfig, layers));
}
catch (error) {
debug(`Error getting layers and manifest content from ${config.formatLabel} archive: ${(0, error_utils_1.getErrorMessage)(error)}`);
reject(new InvalidArchiveError(`Invalid ${config.formatLabel} archive`));
}
});
tarExtractor.on("error", (error) => reject(error));
(0, fs_1.createReadStream)(archiveFilesystemPath)
.on("error", (error) => reject(error))
.pipe(gunzip())
.pipe(tarExtractor);
});
}
exports.createExtractArchive = createExtractArchive;
function assembleLayersAndManifest(manifest, imageConfig, layers) {
const layersWithNormalizedNames = manifest.Layers.map((layerName) => (0, path_1.normalize)(layerName));
const filteredLayers = layersWithNormalizedNames
.filter((layerName) => layers[layerName])
.map((layerName) => layers[layerName])
.reverse();
if (filteredLayers.length === 0) {
throw new Error("We found no layers in the provided image");
}
return {
layers: filteredLayers,
manifest,
imageConfig,
};
}
async function getManifestFile(stream) {
return (0, stream_utils_1.streamToJson)(stream);
}
function isManifestFile(name) {
return name === "manifest.json";
}
function createGetImageIdFromManifest(config) {
return (manifest) => {
try {
const imageId = config.extractImageId(manifest.Config);
if (imageId.includes(":")) {
return imageId;
}
return `${types_1.HashAlgorithm.Sha256}:${imageId}`;
}
catch (err) {
throw new Error("Failed to extract image ID from archive manifest");
}
};
}
exports.createGetImageIdFromManifest = createGetImageIdFromManifest;
function getManifestLayers(manifest) {
return manifest.Layers.map((layer) => (0, path_1.normalize)(layer));
}
exports.getManifestLayers = getManifestLayers;
//# sourceMappingURL=generic-archive-extractor.js.map