[misc] Share one license collection script across the UBI images (#8055)

* [self-hosted] Add a UBI image variant for the combined server

OpenShift and other Red Hat environments expect UBI-based images that run
as an arbitrary non-root UID. The proxy and rootless client already ship
-ubi variants; this adds the same for netbird-server, published as
<version>-ubi and ubi-latest for amd64 and arm64.

* [self-hosted] Check the license output path before creating temp files

The existing-output exit ran before the cleanup trap was registered, so it
left the two mktemp files behind.

* [self-hosted] Certify the netbird-server UBI image

Adds netbird-server to the Red Hat certification components. Its Partner
Connect component ID goes in the REDHAT_CERT_ID_NETBIRD_SERVER repository
variable.

* [misc] Share one license collection script across the UBI images

The client, proxy and combined images each carried a near-identical copy of
collect-licenses.sh, and the signal and relay variants would add two more.
The copies differed only in the Go package, build tags, component license
and the proxy's web licenses, which are now options of one script in
release_files/. The client gains the staged write the others already had.
This commit is contained in:
Nicolas Frati
2026-10-06 10:25:57 +02:00
committed by GitHub
parent d6340ba0de
commit ab79aebd88
5 changed files with 41 additions and 172 deletions
+109
View File
@@ -0,0 +1,109 @@
#!/bin/sh
#
# Collect the license terms shipped in /licenses of the UBI images: NetBird's
# own licenses, the Go standard library terms, and the root license files of
# every module the Go package links on the given architectures.
#
# -l FILE component license, copied as AGPL-3.0.txt (path from repo root)
# -t TAGS build tags used for the dependency walk
# -w add the proxy web UI's third-party licenses (needs proxy/web/node_modules)
set -eu
usage() {
printf '%s\n' "usage: $0 [-l LICENSE_FILE] [-t TAGS] [-w] OUTPUT_DIRECTORY PACKAGE GOARCH..." >&2
exit 2
}
component_license=""
tags=""
web=false
while getopts l:t:w opt; do
case "$opt" in
l) component_license=$OPTARG ;;
t) tags=$OPTARG ;;
w) web=true ;;
*) usage ;;
esac
done
shift $((OPTIND - 1))
[ "$#" -ge 3 ] || usage
repo_root=$(CDPATH='' cd -- "$(dirname "$0")/.." && pwd)
output_name=$(basename "$1")
if [ -z "$output_name" ] || [ "$output_name" = . ] || [ "$output_name" = .. ] || [ "$output_name" = / ]; then
printf '%s\n' "OUTPUT_DIRECTORY must name a directory" >&2
exit 2
fi
output_parent=$(CDPATH='' cd -- "$(dirname "$1")" && pwd)
output="$output_parent/$output_name"
package=$2
shift 2
if [ -e "$output" ] || [ -L "$output" ]; then
printf 'output directory already exists: %s\n' "$output" >&2
exit 1
fi
modules=$(mktemp "${TMPDIR:-/tmp}/netbird-licenses.modules.XXXXXX")
sorted_modules=$(mktemp "${TMPDIR:-/tmp}/netbird-licenses.sorted.XXXXXX")
# Assemble beside the target and rename on success, so a failed run leaves
# nothing behind that would block the next attempt.
staging=$(mktemp -d "$output_parent/.$output_name.XXXXXX")
trap 'rm -f "$modules" "$sorted_modules"; rm -rf "$staging"' EXIT HUP INT TERM
mkdir "$staging/third_party"
if [ -n "$component_license" ]; then
cp "$repo_root/$component_license" "$staging/AGPL-3.0.txt"
fi
cp "$repo_root/LICENSE" "$staging/BSD-3-Clause.txt"
if [ "$web" = true ]; then
node "$repo_root/proxy/web/scripts/third-party-licenses.mjs" >"$staging/Web-THIRD-PARTY-LICENSES"
fi
cd "$repo_root"
for arch in "$@"; do
GOOS=${GOOS:-linux} GOARCH="$arch" CGO_ENABLED=${CGO_ENABLED:-0} \
go list -deps -tags "$tags" -f '{{with .Module}}{{if .Replace}}{{.Replace.Path}}{{"\t"}}{{.Replace.Version}}{{"\t"}}{{.Replace.Dir}}{{else}}{{.Path}}{{"\t"}}{{.Version}}{{"\t"}}{{.Dir}}{{end}}{{end}}' "$package" >>"$modules"
done
LC_ALL=C sort -u "$modules" >"$sorted_modules"
goroot=$(go env GOROOT)
for term in LICENSE PATENTS; do
if [ ! -f "$goroot/$term" ]; then
printf 'missing Go standard-library term: %s\n' "$goroot/$term" >&2
exit 1
fi
cp "$goroot/$term" "$staging/Go-$term"
done
while IFS=' ' read -r module version module_dir; do
[ -n "$module" ] || continue
[ "$module" = "github.com/netbirdio/netbird" ] && continue
if [ -z "$version" ] || [ ! -d "$module_dir" ]; then
printf 'cannot collect terms for module %s at version %s\n' "$module" "$version" >&2
exit 1
fi
destination="$staging/third_party/$module/$version"
mkdir -p "$destination"
printf 'module: %s\nversion: %s\n' "$module" "$version" >"$destination/MODULE"
found=false
for term in \
"$module_dir"/LICENSE* "$module_dir"/License* "$module_dir"/license* \
"$module_dir"/LICENCE* "$module_dir"/Licence* "$module_dir"/licence* \
"$module_dir"/COPYING* "$module_dir"/Copying* "$module_dir"/copying* \
"$module_dir"/NOTICE* "$module_dir"/Notice* "$module_dir"/notice* \
"$module_dir"/PATENTS* "$module_dir"/Patents* "$module_dir"/patents*; do
[ -f "$term" ] || continue
cp "$term" "$destination/"
found=true
done
if [ "$found" = false ]; then
printf 'no root license terms found for module %s at %s\n' "$module" "$module_dir" >&2
exit 1
fi
done <"$sorted_modules"
mv "$staging" "$output"