From c4a2f6d071a2d1b752efafcc1ad256baa5066226 Mon Sep 17 00:00:00 2001 From: Or Toren Date: Thu, 14 May 2026 10:17:59 +0300 Subject: [PATCH] signature validation --- buildscripts/getFrogbot.sh | 93 +++++++++++++++++++++++++++++++++++--- release/buildAndUpload.sh | 80 ++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 release/buildAndUpload.sh diff --git a/buildscripts/getFrogbot.sh b/buildscripts/getFrogbot.sh index aa55cab56..f89297fce 100644 --- a/buildscripts/getFrogbot.sh +++ b/buildscripts/getFrogbot.sh @@ -96,23 +96,104 @@ echoGreetings() { echo "Frogbot downloaded successfully!" } -getDownloadCommand() { +download_to() { + dl_url="$1" + dl_out="$2" if [ -n "${REMOTE_PATH}" ]; then if [ -n "${JF_ACCESS_TOKEN}" ]; then - curl -fLg -H "Authorization:Bearer ${JF_ACCESS_TOKEN}" -X GET "${URL}" -o "${FILE_NAME}" + curl -fLg -H "Authorization:Bearer ${JF_ACCESS_TOKEN}" -X GET "${dl_url}" -o "${dl_out}" else - curl -fLg -u "${JF_USER}:${JF_PASSWORD}" -X GET "${URL}" -o "${FILE_NAME}" + curl -fLg -u "${JF_USER}:${JF_PASSWORD}" -X GET "${dl_url}" -o "${dl_out}" fi else - curl -fLg -X GET "${URL}" -o "${FILE_NAME}" + curl -fLg -X GET "${dl_url}" -o "${dl_out}" fi } +download_optional() { + dl_url="$1" + dl_out="$2" + if [ -n "${REMOTE_PATH}" ]; then + if [ -n "${JF_ACCESS_TOKEN}" ]; then + curl -sfLg -H "Authorization:Bearer ${JF_ACCESS_TOKEN}" -X GET "${dl_url}" -o "${dl_out}" && return 0 + else + curl -sfLg -u "${JF_USER}:${JF_PASSWORD}" -X GET "${dl_url}" -o "${dl_out}" && return 0 + fi + else + curl -sfLg -X GET "${dl_url}" -o "${dl_out}" && return 0 + fi + return 1 +} + +verify_checksum() { + if command -v sha256sum >/dev/null 2>&1; then + sha256sum -c "${FILE_NAME}.sha256" + elif command -v shasum >/dev/null 2>&1; then + shasum -a 256 -c "${FILE_NAME}.sha256" + else + echo "Neither sha256sum nor shasum was found; cannot verify the binary checksum." >&2 + return 1 + fi +} + +verify_checksum_or_exit() { + if [ "${FROGBOT_INSECURE_SKIP_CHECKSUM_VERIFICATION:-}" = "1" ]; then + echo "WARNING: skipping checksum verification (FROGBOT_INSECURE_SKIP_CHECKSUM_VERIFICATION=1)." >&2 + return 0 + fi + checksum_url="${URL}.sha256" + if ! download_to "${checksum_url}" "${FILE_NAME}.sha256"; then + echo "Failed to download the checksum file for this Frogbot build." >&2 + echo "Releases that predate checksum publishing require FROGBOT_INSECURE_SKIP_CHECKSUM_VERIFICATION=1 (not recommended)." >&2 + rm -f "${FILE_NAME}" + exit 1 + fi + if ! verify_checksum; then + echo "Checksum verification failed." >&2 + rm -f "${FILE_NAME}" "${FILE_NAME}.sha256" + exit 1 + fi + rm -f "${FILE_NAME}.sha256" +} + +verify_gpg_if_signature_present() { + sig_url="${URL}.asc" + if ! download_optional "${sig_url}" "${FILE_NAME}.asc"; then + rm -f "${FILE_NAME}.asc" + return 0 + fi + key_url="${PLATFORM_URL}/artifactory/${REMOTE_PATH}frogbot/v3/${VERSION}/frogbot-signing-key.asc" + if ! download_optional "${key_url}" "frogbot-signing-key.asc"; then + echo "A detached signature was published but frogbot-signing-key.asc could not be downloaded for this release." >&2 + rm -f "${FILE_NAME}" "${FILE_NAME}.asc" + exit 1 + fi + if ! command -v gpg >/dev/null 2>&1; then + echo "gpg is required to verify the Frogbot release signature." >&2 + rm -f "${FILE_NAME}" "${FILE_NAME}.asc" "frogbot-signing-key.asc" + exit 1 + fi + GNUPGHOME=$(mktemp -d "${TMPDIR:-/tmp}/frogbot-gpg.XXXXXX") + export GNUPGHOME + gpg --batch --import "frogbot-signing-key.asc" >/dev/null 2>&1 + if ! gpg --batch --verify "${FILE_NAME}.asc" "${FILE_NAME}"; then + echo "GPG signature verification failed." >&2 + rm -rf "${GNUPGHOME}" + rm -f "${FILE_NAME}" "${FILE_NAME}.asc" "frogbot-signing-key.asc" + exit 1 + fi + rm -rf "${GNUPGHOME}" + rm -f "${FILE_NAME}.asc" "frogbot-signing-key.asc" +} + download() { - getDownloadCommand && setPermissions && echoGreetings + download_to "${URL}" "${FILE_NAME}" || { rm -f "${FILE_NAME}"; exit 1; } + verify_checksum_or_exit + verify_gpg_if_signature_present + setPermissions && echoGreetings } setFrogbotVersion "$@" setFrogbotRemoteRepositoryIfNeeded setFrogbotDownloadProperties -download \ No newline at end of file +download diff --git a/release/buildAndUpload.sh b/release/buildAndUpload.sh new file mode 100644 index 000000000..1964c6b4c --- /dev/null +++ b/release/buildAndUpload.sh @@ -0,0 +1,80 @@ +#!/bin/bash +set -eu + +build () { + pkg="$1" + export GOOS="$2" + export GOARCH="$3" + exeName="$4" + echo "Building $exeName for $GOOS-$GOARCH ..." + + CGO_ENABLED=0 jf go build -o "$exeName" -ldflags '-w -extldflags "-static" -X github.com/jfrog/frogbot/v3/utils.FrogbotVersion='"$version" + chmod +x "$exeName" + + if [[ "$pkg" = "frogbot-linux-386" ]]; then + verifyVersionMatching + fi +} + +buildAndUpload () { + pkg="$1" + goos="$2" + goarch="$3" + fileExtension="$4" + exeName="frogbot$fileExtension" + + build "$pkg" "$goos" "$goarch" "$exeName" + + destPath="$pkgPath/$version/$pkg/$exeName" + echo "Uploading $exeName to $destPath ..." + jf rt u "./$exeName" "$destPath" + sha256sum "$exeName" >"${exeName}.sha256" + jf rt u "./${exeName}.sha256" "$pkgPath/$version/$pkg/${exeName}.sha256" + rm -f "./${exeName}.sha256" + if [[ -n "${FROGBOT_GPG_KEY_ID:-}" ]] && command -v gpg >/dev/null 2>&1; then + gpg --batch --yes --local-user "$FROGBOT_GPG_KEY_ID" --detach-sign --armor -o "${exeName}.asc" "./$exeName" + jf rt u "./${exeName}.asc" "$pkgPath/$version/$pkg/${exeName}.asc" + rm -f "./${exeName}.asc" + fi +} + +upload_signing_public_key() { + if [[ -n "${FROGBOT_GPG_PUBLIC_KEY_FILE:-}" ]] && [[ -f "${FROGBOT_GPG_PUBLIC_KEY_FILE}" ]]; then + jf rt u "${FROGBOT_GPG_PUBLIC_KEY_FILE}" "$pkgPath/$version/frogbot-signing-key.asc" + fi +} + +verifyVersionMatching () { + echo "Verifying provided version matches built version..." + res=$(eval "./frogbot -v") + exitCode=$? + if [[ $exitCode -ne 0 ]]; then + echo "Error: Failed verifying version matches" + exit $exitCode + fi + + echo "Output: $res" + builtVersion="${res##* }" + if [[ "$builtVersion" != "$version" ]]; then + echo "Versions dont match. Provided: $version, Actual: $builtVersion" + exit 1 + fi + echo "Versions match." +} + +version="$1" +pkgPath="ecosys-frogbot/v3" + +buildAndUpload 'frogbot-linux-386' 'linux' '386' '' +buildAndUpload 'frogbot-linux-amd64' 'linux' 'amd64' '' +buildAndUpload 'frogbot-linux-s390x' 'linux' 's390x' '' +buildAndUpload 'frogbot-linux-arm64' 'linux' 'arm64' '' +buildAndUpload 'frogbot-linux-arm' 'linux' 'arm' '' +buildAndUpload 'frogbot-linux-ppc64' 'linux' 'ppc64' '' +buildAndUpload 'frogbot-linux-ppc64le' 'linux' 'ppc64le' '' +buildAndUpload 'frogbot-mac-386' 'darwin' 'amd64' '' +buildAndUpload 'frogbot-mac-arm64' 'darwin' 'arm64' '' +buildAndUpload 'frogbot-windows-amd64' 'windows' 'amd64' '.exe' + +upload_signing_public_key +jf rt u "./buildscripts/getFrogbot.sh" "$pkgPath/$version/" --flat