Skip to content

Commit f4a59b7

Browse files
facutuescatargos
authored andcommitted
tools: add automation for updating OpenSSL dependency
Add a Github Action that checks for new versions of the `OpenSSL` library, and creates a PR to update it if a newer version than the one present in the repo is found. Refs: nodejs/security-wg#828 PR-URL: #45605 Reviewed-By: Michael Dawson <midawson@redhat.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
1 parent 6740679 commit f4a59b7

File tree

3 files changed

+210
-0
lines changed

3 files changed

+210
-0
lines changed

.github/workflows/update-openssl.yml

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: OpenSSL update
2+
on:
3+
schedule:
4+
# Run once a week at 00:05 AM UTC on Sunday.
5+
- cron: 5 0 * * 0
6+
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
openssl-update:
14+
if: github.repository == 'nodejs/node'
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v3
18+
with:
19+
persist-credentials: false
20+
- name: Check if update branch already exists
21+
run: |
22+
BRANCH_EXISTS=$(git ls-remote --heads origin actions/tools-update-openssl)
23+
echo "BRANCH_EXISTS=$BRANCH_EXISTS" >> $GITHUB_ENV
24+
- name: Check and download new OpenSSL version
25+
# Only run rest of the workflow if the update branch does not yet exist
26+
if: ${{ env.BRANCH_EXISTS == '' }}
27+
run: |
28+
NEW_VERSION=$(gh api repos/quictls/openssl/releases -q '.[].tag_name|select(contains("openssl-3"))|ltrimstr("openssl-")' | head -n1)
29+
NEW_VERSION_NO_RELEASE_1=$(case $NEW_VERSION in *quic1) echo ${NEW_VERSION%1};; *) echo $NEW_VERSION;; esac)
30+
VERSION_H="./deps/openssl/config/archs/linux-x86_64/asm/include/openssl/opensslv.h"
31+
CURRENT_VERSION=$(grep "OPENSSL_FULL_VERSION_STR" $VERSION_H | sed -n "s/^.*VERSION_STR \"\(.*\)\"/\1/p")
32+
if [ "$NEW_VERSION_NO_RELEASE_1" != "$CURRENT_VERSION" ]; then
33+
echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
34+
echo "HAS_UPDATE=true" >> $GITHUB_ENV
35+
./tools/dep_updaters/update-openssl.sh download "$NEW_VERSION"
36+
fi
37+
env:
38+
GITHUB_TOKEN: ${{ secrets.GH_USER_TOKEN }}
39+
- name: Create PR with first commit
40+
if: env.HAS_UPDATE
41+
uses: gr2m/create-or-update-pull-request-action@v1
42+
# Creates a PR with the new OpenSSL source code committed
43+
env:
44+
GITHUB_TOKEN: ${{ secrets.GH_USER_TOKEN }}
45+
with:
46+
author: Node.js GitHub Bot <github-bot@iojs.org>
47+
body: This is an automated update of OpenSSL to ${{ env.NEW_VERSION }}.
48+
branch: actions/tools-update-openssl # Custom branch *just* for this Action.
49+
commit-message: 'deps: upgrade openssl sources to quictls/openssl-${{ env.NEW_VERSION }}'
50+
labels: dependencies
51+
title: 'deps: update OpenSSL to ${{ env.NEW_VERSION }}'
52+
path: deps/openssl
53+
- name: Regenerate platform specific files
54+
if: env.HAS_UPDATE
55+
run: |
56+
sudo apt install -y nasm libtext-template-perl
57+
./tools/dep_updaters/update-openssl.sh regenerate
58+
env:
59+
GITHUB_TOKEN: ${{ secrets.GH_USER_TOKEN }}
60+
- name: Add second commit
61+
# Adds a second commit to the PR with the generated platform-dependent files
62+
if: env.HAS_UPDATE
63+
uses: gr2m/create-or-update-pull-request-action@v1
64+
env:
65+
GITHUB_TOKEN: ${{ secrets.GH_USER_TOKEN }}
66+
with:
67+
author: Node.js GitHub Bot <github-bot@iojs.org>
68+
branch: actions/tools-update-openssl # Custom branch *just* for this Action.
69+
commit-message: 'deps: update archs files for openssl-${{ env.NEW_VERSION }}'
70+
path: deps/openssl

tools/dep_updaters/README.md

+41
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,45 @@ been created with the changes), do the following:
6161
4. Create a commit for the update and in the commit message include the
6262
important/relevant items from the changelog.
6363

64+
## OpenSSL
65+
66+
The `update-openssl.sh` script automates the steps described in
67+
[`maintaining-openssl.md`][]. The main difference is that the script downloads
68+
the release tarball from GitHub, instead of cloning the repo and using that as
69+
the source code. This is useful since the release tarball does not include
70+
development-specific files and directories (e.g the `.github` folder).
71+
72+
The script has to be run in two steps. The first one (using the `download`
73+
sub-command) replaces the OpenSSL source code with the new version. The second
74+
one (using the `regenerate` sub-command) regenerates the platform-specific
75+
files. This makes it easier to create two separate git commits, making the git
76+
history more descriptive.
77+
78+
For example, in order to update to version `3.0.7+quic1`, the following commands
79+
should be run:
80+
81+
```bash
82+
./tools/dep_updaters/update-openssl.sh download 3.0.7+quic1
83+
git add -A deps/openssl/openssl
84+
git commit -m "deps: upgrade openssl sources to quictls/openssl-3.0.7+quic1"
85+
86+
./tools/dep_updaters/update-openssl.sh regenerate 3.0.7+quic1
87+
git add -A deps/openssl/config/archs deps/openssl/openssl
88+
git commit -m "deps: update archs files for openssl"
89+
```
90+
91+
Once the script has run (either manually, or by CI in which case a PR will have
92+
been created with the changes), do the following:
93+
94+
1. Check the `CHANGES.md` file in the [repo](https://github.com/quictls/openssl)
95+
for things that might require changes in Node.js.
96+
2. Check the diffs to ensure the changes are right. Even if there are no changes
97+
in the source, `buildinf.h` files will be updated because they have timestamp
98+
data in them.
99+
3. Check that Node.js compiles without errors and the tests pass.
100+
4. Create a commit for the update and in the commit message include the
101+
important/relevant items from the changelog.
102+
64103
## postject
65104

66105
The `update-postject.sh` script downloads postject from the [npm package](http://npmjs.com/package/postject)
@@ -80,3 +119,5 @@ been created with the changes), do the following:
80119
2. Check that Node.js compiles without errors and the tests pass.
81120
3. Create a commit for the update and in the commit message include the
82121
important/relevant items from the changelog.
122+
123+
[`maintaining-openssl.md`]: https://github.com/nodejs/node/blob/main/doc/contributing/maintaining-openssl.md

tools/dep_updaters/update-openssl.sh

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#!/bin/sh
2+
set -e
3+
# Shell script to update OpenSSL in the source tree to a specific version
4+
# Based on https://github.com/nodejs/node/blob/main/doc/contributing/maintaining-openssl.md
5+
6+
cleanup() {
7+
EXIT_CODE=$?
8+
[ -d "$WORKSPACE" ] && rm -rf "$WORKSPACE"
9+
exit $EXIT_CODE
10+
}
11+
12+
download() {
13+
if [ -z "$1" ]; then
14+
echo "Error: please provide an OpenSSL version to update to"
15+
echo " e.g. ./$0 download 3.0.7+quic1"
16+
exit 1
17+
fi
18+
19+
OPENSSL_VERSION=$1
20+
echo "Making temporary workspace..."
21+
WORKSPACE=$(mktemp -d 2> /dev/null || mktemp -d -t 'tmp')
22+
23+
24+
cd "$WORKSPACE"
25+
26+
echo "Fetching OpenSSL source archive..."
27+
curl -sL "https://api.github.com/repos/quictls/openssl/tarball/openssl-$OPENSSL_VERSION" | tar xzf -
28+
mv quictls-openssl-* openssl
29+
30+
echo "Replacing existing OpenSSL..."
31+
rm -rf "$DEPS_DIR/openssl/openssl"
32+
mv "$WORKSPACE/openssl" "$DEPS_DIR/openssl/"
33+
34+
echo "All done!"
35+
echo ""
36+
echo "Please git add openssl, and commit the new version:"
37+
echo ""
38+
echo "$ git add -A deps/openssl/openssl"
39+
echo "$ git commit -m \"deps: upgrade openssl sources to quictls/openssl-$OPENSSL_VERSION\""
40+
echo ""
41+
}
42+
43+
regenerate() {
44+
command -v perl >/dev/null 2>&1 || { echo >&2 "Error: 'Perl' required but not installed."; exit 1; }
45+
command -v nasm >/dev/null 2>&1 || { echo >&2 "Error: 'nasm' required but not installed."; exit 1; }
46+
command -v as >/dev/null 2>&1 || { echo >&2 "Error: 'GNU as' required but not installed."; exit 1; }
47+
perl -e "use Text::Template">/dev/null 2>&1 || { echo >&2 "Error: 'Text::Template' Perl module required but not installed."; exit 1; }
48+
49+
echo "Regenerating platform-dependent files..."
50+
51+
make -C "$DEPS_DIR/openssl/config" clean
52+
# Needed for compatibility with nasm on 32-bit Windows
53+
# See https://github.com/nodejs/node/blob/main/doc/contributing/maintaining-openssl.md#2-execute-make-in-depsopensslconfig-directory
54+
sed -i 's/#ifdef/%ifdef/g' "$DEPS_DIR/openssl/openssl/crypto/perlasm/x86asm.pl"
55+
sed -i 's/#endif/%endif/g' "$DEPS_DIR/openssl/openssl/crypto/perlasm/x86asm.pl"
56+
make -C "$DEPS_DIR/openssl/config"
57+
58+
echo "All done!"
59+
echo ""
60+
echo "Please commit the regenerated files:"
61+
echo ""
62+
echo "$ git add -A deps/openssl/config/archs deps/openssl/openssl"
63+
echo "$ git commit -m \"deps: update archs files for openssl\""
64+
echo ""
65+
}
66+
67+
help() {
68+
echo "Shell script to update OpenSSL in the source tree to a specific version"
69+
echo "Sub-commands:"
70+
printf "%-23s %s\n" "help" "show help menu and commands"
71+
printf "%-23s %s\n" "download" "download and replace OpenSSL source code with new version"
72+
printf "%-23s %s\n" "regenerate" "regenerate platform-specific files"
73+
echo ""
74+
exit "${1:-0}"
75+
}
76+
77+
main() {
78+
if [ ${#} -eq 0 ]; then
79+
help 0
80+
fi
81+
82+
trap cleanup INT TERM EXIT
83+
84+
BASE_DIR=$(cd "$(dirname "$0")/../.." && pwd)
85+
DEPS_DIR="$BASE_DIR/deps"
86+
87+
case ${1} in
88+
help | download | regenerate )
89+
$1 "${2}"
90+
;;
91+
* )
92+
echo "unknown command: $1"
93+
help 1
94+
exit 1
95+
;;
96+
esac
97+
}
98+
99+
main "$@"

0 commit comments

Comments
 (0)