Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v16.x] tools: automate update openssl v16 #48500

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions test/abort/test-signal-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ if (process.argv[2] === 'child') {
const child = spawnSync(process.execPath,
['--expose-internals', __filename, 'child'],
{ stdio: 'inherit' });
// FreeBSD uses SIGILL for this kind of crash.
// FreeBSD uses SIGILL (v12.2) or SIGBUS (v12.4 and greater) for this kind of crash.
// macOS uses SIGILL or SIGTRAP (arm64) for this kind of crash.
assert(child.signal === 'SIGSEGV' || child.signal === 'SIGILL' ||
child.signal === 'SIGTRAP', `child.signal = ${child.signal}`);
const allowedSignals = ['SIGSEGV', 'SIGILL', 'SIGTRAP', 'SIGBUS'];
assert(
allowedSignals.includes(child.signal),
`child.signal = ${child.signal}`,
);
}
185 changes: 185 additions & 0 deletions tools/dep_updaters/update-openssl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
#!/bin/sh
set -e
# Shell script to update OpenSSL in the source tree to a specific version
# Based on https://github.com/nodejs/node/blob/main/doc/contributing/maintaining/maintaining-openssl.md

cleanup() {
EXIT_CODE=$?
[ -d "$WORKSPACE" ] && rm -rf "$WORKSPACE"
exit $EXIT_CODE
}

download_v1() {
LATEST_V1_TAG_NAME="$("$NODE" --input-type=module --experimental-fetch <<'EOF'
const res = await fetch('https://api.github.com/repos/quictls/openssl/git/matching-refs/tags/OpenSSL_1');
if (!res.ok) throw new Error(`FetchError: ${res.status} ${res.statusText}`);
const releases = await res.json()
const latest = releases.reverse().find(({ ref }) => ref.includes('quic'));
if(!latest) throw new Error(`Could not find latest release for v1`);
console.log(latest.ref.replace('refs/tags/',''));
EOF
)"

NEW_VERSION_V1=$(echo "$LATEST_V1_TAG_NAME" | sed 's/OpenSSL_//;s/_/./g;s/-/+/g')

case "$NEW_VERSION_V1" in
*quic1) NEW_VERSION_V1_NO_RELEASE="${NEW_VERSION_V1%1}" ;;
*) NEW_VERSION_V1_NO_RELEASE="$NEW_VERSION_V1" ;;
esac

VERSION_H="$DEPS_DIR/openssl/openssl/include/openssl/opensslv.h"
CURRENT_VERSION=$(grep "OPENSSL_VERSION_TEXT" "$VERSION_H" | sed -n "s/.*OpenSSL \([^\"]*\).*/\1/p" | cut -d ' ' -f 1)

# This function exit with 0 if new version and current version are the same
compare_dependency_version "openssl" "$NEW_VERSION_V1_NO_RELEASE" "$CURRENT_VERSION"

echo "Making temporary workspace..."
WORKSPACE=$(mktemp -d 2> /dev/null || mktemp -d -t 'tmp')
cd "$WORKSPACE"

echo "Fetching OpenSSL source archive..."
OPENSSL_TARBALL="openssl.tar.gz"
curl -sL -o "$OPENSSL_TARBALL" "https://api.github.com/repos/quictls/openssl/tarball/$LATEST_V1_TAG_NAME"
log_and_verify_sha256sum "openssl" "$OPENSSL_TARBALL"
gzip -dc "$OPENSSL_TARBALL" | tar xf -
rm "$OPENSSL_TARBALL"

mv quictls-openssl-* openssl

echo "Replacing existing OpenSSL..."
rm -rf "$DEPS_DIR/openssl/openssl"
mv "$WORKSPACE/openssl" "$DEPS_DIR/openssl/"

echo "All done!"
echo ""
echo "Please git add openssl, and commit the new version:"
echo ""
echo "$ git add -A deps/openssl/openssl"
echo "$ git add doc/contributing/maintaining/maintaining-dependencies.md"
echo "$ git commit -m \"deps: upgrade openssl sources to quictls/openssl-$NEW_VERSION_V1\""
echo ""
# The last line of the script should always print the new version,
# as we need to add it to $GITHUB_ENV variable.
echo "NEW_VERSION=$NEW_VERSION_V1"
}

download_v3() {
LATEST_V3_TAG_NAME="$("$NODE" --input-type=module <<'EOF'
const res = await fetch('https://api.github.com/repos/quictls/openssl/git/matching-refs/tags/openssl-3.0');
if (!res.ok) throw new Error(`FetchError: ${res.status} ${res.statusText}`, { cause: res });
const releases = await res.json()
const latest = releases.findLast(({ ref }) => ref.includes('quic'));
if(!latest) throw new Error(`Could not find latest release for v3.0`);
console.log(latest.ref.replace('refs/tags/',''));
EOF
)"
NEW_VERSION_V3=$(echo "$LATEST_V3_TAG_NAME" | sed 's/openssl-//;s/-/+/g')

case "$NEW_VERSION_V3" in
*quic1) NEW_VERSION_V3_NO_RELEASE="${NEW_VERSION_V3%1}" ;;
*) NEW_VERSION_V3_NO_RELEASE="$NEW_VERSION_V3" ;;
esac
VERSION_H="./deps/openssl/config/archs/linux-x86_64/asm/include/openssl/opensslv.h"
CURRENT_VERSION=$(grep "OPENSSL_FULL_VERSION_STR" $VERSION_H | sed -n "s/^.*VERSION_STR \"\(.*\)\"/\1/p")
# This function exit with 0 if new version and current version are the same
compare_dependency_version "openssl" "$NEW_VERSION_V3_NO_RELEASE" "$CURRENT_VERSION"

echo "Making temporary workspace..."

WORKSPACE=$(mktemp -d 2> /dev/null || mktemp -d -t 'tmp')

cd "$WORKSPACE"
echo "Fetching OpenSSL source archive..."

OPENSSL_TARBALL="openssl.tar.gz"

curl -sL -o "$OPENSSL_TARBALL" "https://api.github.com/repos/quictls/openssl/tarball/$LATEST_V3_TAG_NAME"

log_and_verify_sha256sum "openssl" "$OPENSSL_TARBALL"

gzip -dc "$OPENSSL_TARBALL" | tar xf -

rm "$OPENSSL_TARBALL"
mv quictls-openssl-* openssl
echo "Replacing existing OpenSSL..."
rm -rf "$DEPS_DIR/openssl/openssl"
mv "$WORKSPACE/openssl" "$DEPS_DIR/openssl/"

# Update the version number
update_dependency_version "openssl" "$NEW_VERSION_V3"
echo "All done!"
echo ""
echo "Please git add openssl, and commit the new version:"
echo ""
echo "$ git add -A deps/openssl/openssl"
echo "$ git add doc/contributing/maintaining/maintaining-dependencies.md"
echo "$ git commit -m \"deps: upgrade openssl sources to quictls/openssl-$NEW_VERSION_V3\""
echo ""
# The last line of the script should always print the new version,
# as we need to add it to $GITHUB_ENV variable.
echo "NEW_VERSION=$NEW_VERSION_V3"
}

regenerate() {
command -v perl >/dev/null 2>&1 || { echo >&2 "Error: 'Perl' required but not installed."; exit 1; }
command -v nasm >/dev/null 2>&1 || { echo >&2 "Error: 'nasm' required but not installed."; exit 1; }
command -v as >/dev/null 2>&1 || { echo >&2 "Error: 'GNU as' required but not installed."; exit 1; }
perl -e "use Text::Template">/dev/null 2>&1 || { echo >&2 "Error: 'Text::Template' Perl module required but not installed."; exit 1; }

echo "Regenerating platform-dependent files..."

make -C "$DEPS_DIR/openssl/config" clean
# Needed for compatibility with nasm on 32-bit Windows
# See https://github.com/nodejs/node/blob/main/doc/contributing/maintaining/maintaining-openssl.md#2-execute-make-in-depsopensslconfig-directory
sed -i 's/#ifdef/%ifdef/g' "$DEPS_DIR/openssl/openssl/crypto/perlasm/x86asm.pl"
sed -i 's/#endif/%endif/g' "$DEPS_DIR/openssl/openssl/crypto/perlasm/x86asm.pl"
make -C "$DEPS_DIR/openssl/config"

echo "All done!"
echo ""
echo "Please commit the regenerated files:"
echo ""
echo "$ git add -A deps/openssl/config/archs deps/openssl/openssl"
echo "$ git commit -m \"deps: update archs files for openssl\""
echo ""
}

help() {
echo "Shell script to update OpenSSL in the source tree to a specific version"
echo "Sub-commands:"
printf "%-23s %s\n" "help" "show help menu and commands"
printf "%-23s %s\n" "download" "download and replace OpenSSL source code with new version"
printf "%-23s %s\n" "regenerate" "regenerate platform-specific files"
echo ""
exit "${1:-0}"
}

main() {
if [ ${#} -eq 0 ]; then
help 0
fi

trap cleanup INT TERM EXIT

BASE_DIR=$(cd "$(dirname "$0")/../.." && pwd)
DEPS_DIR="$BASE_DIR/deps"

[ -z "$NODE" ] && NODE="$BASE_DIR/out/Release/node"
[ -x "$NODE" ] || NODE=$(command -v node)

# shellcheck disable=SC1091
. "$BASE_DIR/tools/dep_updaters/utils.sh"

case ${1} in
help | regenerate | download_v1 | download_v3 )
$1 "${2}"
;;
* )
echo "unknown command: $1"
help 1
exit 1
;;
esac
}

main "$@"
99 changes: 99 additions & 0 deletions tools/dep_updaters/utils.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/bin/sh

ROOT=$(cd "$(dirname "$0")/../.." && pwd)

# This function compare new version with current version of a depdendency and
# exit the script if the versions are the same
#
# $1 is the package name e.g. 'acorn', 'ada', 'base64' etc. See the file
# https://github.com/nodejs/node/blob/main/doc/contributing/maintaining/maintaining-dependencies.md
# for a complete list of package name
# $2 is the new version.
compare_dependency_version() {
package_name="$1"
new_version="$2"
current_version="$3"
echo "Comparing $new_version with $current_version"
if [ "$new_version" = "$current_version" ]; then
echo "Skipped because $package_name is on the latest version."
exit 0
fi
}

# This function inform to commit the new version of a maintained dependency
# and print the last line of the script "NEW_VERSION=$NEW_VERSION" as we need
# to add it to $GITHUB_ENV variable.
#
# $1 is the package name e.g. 'acorn', 'ada', 'base64' etc. See the file
# https://github.com/nodejs/node/blob/main/doc/contributing/maintaining/maintaining-dependencies.md
# for a complete list of package name
# $2 is the new version.
# $3 (optional) other files to be git added apart from the deps/package_name
finalize_version_update() {
package_name="$1"
new_version="$2"
extra_files="$3"

# Update the version number on maintaining-dependencies.md
update_dependency_version "$package_name" "$new_version"

echo "All done!"
echo ""
echo "Please git add $package_name and commit the new version:"
echo ""
echo "$ git add -A deps/$package_name $extra_files"
echo "$ git add doc/contributing/maintaining/maintaining-dependencies.md"
echo "$ git commit -m \"deps: update $package_name to $new_version\""
echo ""

# The last line of the script should always print the new version,
# as we need to add it to $GITHUB_ENV variable.
echo "NEW_VERSION=$new_version"
}

# This function logs the archive checksum and, if provided, compares it with
# the deposited checksum
#
# $1 is the package name e.g. 'acorn', 'ada', 'base64' etc. See the file
# https://github.com/nodejs/node/blob/main/doc/contributing/maintaining/maintaining-dependencies.md
# for a complete list of package name
# $2 is the downloaded archive
# $3 (optional) is the deposited sha256 cheksum. When provided, it is checked
# against the checksum generated from the archive
log_and_verify_sha256sum() {
package_name="$1"
archive="$2"
checksum="$3"
bsd_formatted_checksum=$(shasum -a 256 --tag "$archive")
if [ -z "$3" ]; then
echo "$bsd_formatted_checksum"
else
archive_checksum=$(shasum -a 256 "$archive")
if [ "$checksum" = "$archive_checksum" ]; then
echo "Valid $package_name checksum"
echo "$bsd_formatted_checksum"
else
echo "ERROR - Invalid $package_name checksum:"
echo "deposited: $checksum"
echo "generated: $archive_checksum"
exit 1
fi
fi
}

# This function update the version of a maintained dependency in
# https://github.com/nodejs/node/blob/main/doc/contributing/maintaining/maintaining-dependencies.md
#
# $1 is the package name e.g. 'acorn', 'ada', 'base64' etc. See that file
# for a complete list of package name
# $2 is the new version.
update_dependency_version() {
package_name="$1"
new_version="$2"
deps_file_path="$ROOT/doc/contributing/maintaining/maintaining-dependencies.md"
# Remove version dots for anchor markdown
version_no_dots=$(echo "$new_version" | sed -e 's/\.//g')
perl -i -pe 's|^\* \['"$package_name"'.*|* ['"$package_name"' '"$new_version"'][]|' "$deps_file_path"
perl -i -pe 's|^\['"$package_name"'.*\]: #'"$package_name"'.*|['"$package_name"' '"$new_version"']: #'"$package_name"'-'"$version_no_dots"'|' "$deps_file_path"
perl -i -pe 's|^### '"$package_name"'.*|### '"$package_name"' '"$new_version"'|' "$deps_file_path"
}