Verify JDK downloads with vendor checksums (#1167)

* Verify JDK downloads with vendor checksums

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d

* Handle missing vendor checksum values

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d

* Preserve checksum error during cleanup failure

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d

* Validate checksum metadata value types

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d

* Clarify checksum documentation

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d

* Expand vendor checksum verification

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d

* Accept SHA-256 or SHA-512 for JetBrains checksum sibling

JetBrains publishes a single, generically-named ".checksum" sibling
whose digest algorithm isn't disclosed by the filename. Older JBR 11
builds (e.g. jbrsdk_nomod-11_0_16-*-b2043.64.tar.gz) publish a SHA-256
digest there, while newer builds publish SHA-512. The JetBrains
installer previously assumed SHA-512 unconditionally, so verification
failed with "Malformed sha512 checksum metadata ... expected a
128-character hexadecimal digest" for those older builds, breaking the
jetbrains 11 e2e job on macOS and Windows.

fetchChecksum now accepts a list of candidate algorithms and infers
the actual algorithm from the returned digest's length, preferring the
strongest match. The JetBrains installer passes ['sha512', 'sha256'];
all other callers are unaffected since they already pass a single,
vendor-disclosed algorithm.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d

* Use SapMachine archive checksum files

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a800a031-600e-4d28-b23e-be309555d38d
This commit is contained in:
Bruno Borges
2026-07-29 04:43:56 -04:00
committed by GitHub
parent 19c23b379e
commit 27f2c62824
39 changed files with 1629 additions and 103 deletions
+41 -10
View File
@@ -6,7 +6,7 @@ import fs from 'fs';
import semver from 'semver';
import {JavaBase} from '../base-installer.js';
import {IZuluVersions} from './models.js';
import {IZuluPackageDetails, IZuluVersions} from './models.js';
import {
extractJdkFile,
getDownloadArchiveExtension,
@@ -20,6 +20,15 @@ import {
JavaInstallerResults
} from '../base-models.js';
// The Azul Metadata API only reports the sha256 checksum on the
// package-details endpoint, keyed by package_uuid, so the resolved candidate
// must retain its UUID after sorting until the single follow-up request is made.
interface ZuluResolvedRelease {
version: string;
url: string;
packageUuid: string;
}
export class ZuluDistribution extends JavaBase {
constructor(installerOptions: JavaInstallerOptions) {
super('Zulu', installerOptions);
@@ -40,7 +49,8 @@ export class ZuluDistribution extends JavaBase {
return {
version: convertVersionToSemver(javaVersion),
url: item.download_url,
zuluVersion: convertVersionToSemver(item.distro_version)
zuluVersion: convertVersionToSemver(item.distro_version),
packageUuid: item.package_uuid
};
});
@@ -54,12 +64,11 @@ export class ZuluDistribution extends JavaBase {
-semver.compareBuild(a.zuluVersion, b.zuluVersion)
);
})
.map(item => {
return {
version: item.version,
url: item.url
} as JavaDownloadRelease;
});
.map((item): ZuluResolvedRelease => ({
version: item.version,
url: item.url,
packageUuid: item.packageUuid
}));
const resolvedFullVersion =
satisfiedVersions.length > 0 ? satisfiedVersions[0] : null;
@@ -70,7 +79,29 @@ export class ZuluDistribution extends JavaBase {
throw this.createVersionNotFoundError(version, availableVersionStrings);
}
return resolvedFullVersion;
const packageDetailsUrl = `https://api.azul.com/metadata/v1/zulu/packages/${resolvedFullVersion.packageUuid}`;
const packageDetails = (
await this.http.getJson<IZuluPackageDetails>(packageDetailsUrl)
).result;
const digest = packageDetails?.sha256_hash?.match(/^[a-f0-9]{64}$/i)?.[0];
if (!digest) {
core.debug(
`No authoritative sha256 checksum is available for Zulu version ${resolvedFullVersion.version} from ${packageDetailsUrl}; skipping checksum verification.`
);
}
return {
version: resolvedFullVersion.version,
url: resolvedFullVersion.url,
checksum: digest
? {
algorithm: 'sha256',
value: digest,
source: packageDetailsUrl
}
: undefined
};
}
protected async downloadTool(
@@ -79,7 +110,7 @@ export class ZuluDistribution extends JavaBase {
core.info(
`Downloading Java ${javaRelease.version} (${this.distribution}) from ${javaRelease.url} ...`
);
let javaArchivePath = await tc.downloadTool(javaRelease.url);
let javaArchivePath = await this.downloadAndVerify(javaRelease);
core.info(`Extracting Java archive...`);
const extension = getDownloadArchiveExtension();