diff --git a/common-npm-packages/docker-common/containerimageutils.ts b/common-npm-packages/docker-common/containerimageutils.ts index bdad3fef..fa0f07af 100644 --- a/common-npm-packages/docker-common/containerimageutils.ts +++ b/common-npm-packages/docker-common/containerimageutils.ts @@ -253,3 +253,60 @@ export function getImageIdFromBuildOutput(output: string): string { return ""; } +export function getBaseImageDigestDockerFile(dockerFileContentPath: string): string { + // This method checks if there is FROM image@sha256:digest present in Dockerfile + // if matched it returns digest + // if not, it returns null + + try { + var dockerFileContent=fs.readFileSync(dockerFileContentPath).toString(); + if (!dockerFileContent || dockerFileContent == "") { + return null; + } + var lines = dockerFileContent.split(/[\r?\n]/); + var aliasToImageNameMapping: Map = new Map(); + var baseImage = ""; + + // Added regex pattern to check line starts with FROM IMAGE + const matchPatternForDockerImage = new RegExp(/^FROM\s+IMAGE/); + + for (var i = 0; i < lines.length; i++) { + const currentLine = lines[i].trim(); + + if (!currentLine.toUpperCase().match(matchPatternForDockerImage)) { + continue; + } + var nameComponents = currentLine.substring(4).toLowerCase().split(" as "); + var prospectImageName = nameComponents[0].trim(); + + if (nameComponents.length > 1) { + var alias = nameComponents[1].trim(); + + if (aliasToImageNameMapping.has(prospectImageName)) { + aliasToImageNameMapping.set(alias, aliasToImageNameMapping.get(prospectImageName)); + } else { + aliasToImageNameMapping.set(alias, prospectImageName); + } + + baseImage = aliasToImageNameMapping.get(alias); + } else { + baseImage = aliasToImageNameMapping.has(prospectImageName) + ? aliasToImageNameMapping.get(prospectImageName) + : prospectImageName; + } + } + + let baseImageData = baseImage.split('@'); + if (baseImageData.length > 1) { + let digest = baseImageData[1].split(':'); + if (digest.length > 1){ + return digest[1]; + } + } + + return null; + } catch (error) { + tl.debug(`An error ocurred getting the base image digest. ${error.message}`); + return null; + } +} \ No newline at end of file diff --git a/common-npm-packages/docker-common/package-lock.json b/common-npm-packages/docker-common/package-lock.json index 2dbd9884..01020584 100644 --- a/common-npm-packages/docker-common/package-lock.json +++ b/common-npm-packages/docker-common/package-lock.json @@ -1,12 +1,12 @@ { "name": "azure-pipelines-tasks-docker-common", - "version": "2.247.0", + "version": "2.254.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "azure-pipelines-tasks-docker-common", - "version": "2.247.0", + "version": "2.254.0", "license": "MIT", "dependencies": { "@types/mocha": "^5.2.7", diff --git a/common-npm-packages/docker-common/package.json b/common-npm-packages/docker-common/package.json index bea866a5..ed7c41c4 100644 --- a/common-npm-packages/docker-common/package.json +++ b/common-npm-packages/docker-common/package.json @@ -1,6 +1,6 @@ { "name": "azure-pipelines-tasks-docker-common", - "version": "2.247.0", + "version": "2.254.0", "description": "Common Library for Azure Rest Calls", "repository": { "type": "git", diff --git a/common-npm-packages/docker-common/pipelineutils.ts b/common-npm-packages/docker-common/pipelineutils.ts index c9e8132b..5319babd 100644 --- a/common-npm-packages/docker-common/pipelineutils.ts +++ b/common-npm-packages/docker-common/pipelineutils.ts @@ -65,11 +65,20 @@ function addBaseImageLabels(connection: ContainerConnection, labels: string[], d tl.debug("Image digest couldn't be extracted because no connection was found."); return; } + let digestImageFromFileEnabled = tl.getPipelineFeature('UseDigestImageFromFile'); + var baseImageDigest = ""; + if (digestImageFromFileEnabled) { + baseImageDigest = containerUtils.getBaseImageDigestDockerFile(dockerFilePath); + } + //first check if there is digest passed in Dockerfile + if (!baseImageDigest) { + baseImageDigest = containerUtils.getImageDigest(connection, baseImageName); + } - const baseImageDigest = containerUtils.getImageDigest(connection, baseImageName); + //if there is no digest in Dockerfile, get digest using ImageName:tag if (baseImageDigest) { addLabelWithValue("image.base.digest", baseImageDigest, labels); - } + } } function getReverseDNSName(): string { diff --git a/package-lock.json b/package-lock.json index 0366b720..24fcd0b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6475,4 +6475,4 @@ "dev": true } } -} \ No newline at end of file +}