teleport/build.assets/build-pkg-tsh.sh
Alan Parra 0f386f273b
Make tsh installer non relocatable and drop version from app (#15018)
This is a twofold change with the aim of reducing possible pains with the tsh
installer.

- Dropping the version number from "tsh.app" makes it more alike other apps
  (including Connect)
- Making the installer non-relocatable makes it easy to reason about (and
  ensures our postinstall script is correct!)

A relocatable installer will look for the app in places other the specified
install path, according to the bundle ID. This means that if the user moves or
renames the app, the installer will overwrite it no matter where it is. It also
means our path assumptions can be wrong.

Note that the installer itself is still numbered, so it won't break Houston or
change the downloads page.
2022-07-29 11:18:27 -03:00

179 lines
4.8 KiB
Bash
Executable file

#!/bin/bash
set -eu
# Flag variables
TELEPORT_TYPE='' # -t, oss or ent
TELEPORT_VERSION='' # -v, version, without leading 'v'
TARBALL_DIRECTORY='' # -s
usage() {
log "Usage: $0 -t oss|eng -v version [-s tarball_directory] [-n]"
}
# make_non_relocatable_plist changes the default component plist of the $root
# package to non-relocatable.
# This makes install paths consistent, which also facilitates pathing in
# pre/postscripts.
# Creates component_plist.
# See `man pkgbuild` for reference.
make_non_relocatable_plist() {
local root="$1"
local component_plist="$2"
pkgbuild --analyze --root "$root" "$component_plist"
plutil -replace BundleIsRelocatable -bool NO "$component_plist"
}
main() {
local buildassets=''
buildassets="$(dirname "$0")"
# Don't follow sourced script.
#shellcheck disable=SC1090
#shellcheck disable=SC1091
. "$buildassets/build-common.sh"
local opt=''
while getopts "t:v:s:n" opt; do
case "$opt" in
t)
if [[ "$OPTARG" != "oss" && "$OPTARG" != "ent" ]]; then
log "$0: invalid value for -$opt, want 'oss' or 'ent'"
usage
exit 1
fi
TELEPORT_TYPE="$OPTARG"
;;
v)
TELEPORT_VERSION="$OPTARG"
;;
s)
# Find out the absolute path to -s.
if [[ "$OPTARG" != /* ]]; then
OPTARG="$PWD/$OPTARG"
fi
TARBALL_DIRECTORY="$OPTARG"
;;
n)
DRY_RUN_PREFIX='echo + ' # declared by build-common.sh
;;
*)
usage
exit 1
;;
esac
done
shift $((OPTIND-1))
# Cut leading 'v' from version, in case it's there.
if [[ "$TELEPORT_VERSION" == v* ]]; then
TELEPORT_VERSION="${TELEPORT_VERSION:1}"
fi
if [[ -z "$TELEPORT_TYPE" || -z "${TELEPORT_VERSION}" ]]; then
usage
exit 1
fi
# Verify environment varibles.
if [[ "${APPLE_USERNAME:-}" == "" ]]; then
echo "\
The APPLE_USERNAME environment variable needs to be set to the Apple ID used\
for notarization requests"
exit 1
fi
if [[ "${APPLE_PASSWORD:-}" == "" ]]; then
echo "\
The APPLE_PASSWORD environment variable needs to be set to an app-specific\
password created by APPLE_USERNAME"
exit 1
fi
# Use similar find-or-download logic as build-package.sh for compatibility
# purposes.
local ent=''
[[ "$TELEPORT_TYPE" == 'ent' ]] && ent='-ent'
local tarname=''
tarname="$(printf \
"teleport%s-v%s-darwin-amd64-bin.tar.gz" \
"$ent" "$TELEPORT_VERSION")"
[[ -n "$TARBALL_DIRECTORY" ]] && tarname="$TARBALL_DIRECTORY/$tarname"
tarout='' # find_or_fetch_tarball writes to this
find_or_fetch_tarball "$tarname" tarout
log "Using tarball at $tarout"
tarname="$tarout"
# Unpack tar, get ready to sign/notarize/package.
local tmp=''
tmp="$(mktemp -d)"
[[ -n "$DRY_RUN_PREFIX" ]] && log "tmp = $tmp"
$DRY_RUN_PREFIX trap "rm -fr '$tmp'" EXIT
# $tmp/ (eventually) looks like this:
# teleport/tsh # oss
# teleport-ent/tsh # ent
# scripts # cloned from build.assets
# root/tsh-vXXX.app # package root
# tsh-vXXX.pkg.unsigned # created by the script
# tsh-vXXX.pkg # created by the script
mkdir "$tmp/root"
# This creates either 'teleport/' or 'teleport-ent/' under tmp.
# We only care about the 'tsh' file for the script.
tar xzf "$tarname" -C "$tmp"
# Prepare app shell.
local skel="$buildassets/macos/$TSH_SKELETON"
local target="$tmp/root/tsh.app"
cp -r "$skel/tsh.app" "$target"
mkdir -p "$target/Contents/MacOS/"
cp "$tmp"/teleport*/tsh "$target/Contents/MacOS/"
# Sign app.
$DRY_RUN_PREFIX codesign -f \
-o kill,hard,runtime \
-s "$DEVELOPER_ID_APPLICATION" \
-i "$TSH_BUNDLEID" \
--entitlements "$skel"/tsh*.entitlements \
--timestamp \
"$target"
# Prepare and sign the installer package.
# Note that the installer does __NOT__ have a `v` in the version number.
target="$tmp/tsh-$TELEPORT_VERSION.pkg" # switches from app to pkg
local pkg_root="$tmp/root"
local pkg_component_plist="$tmp/tsh-component.plist"
local pkg_scripts="$buildassets/macos/scripts"
make_non_relocatable_plist "$pkg_root" "$pkg_component_plist"
pkgbuild \
--root "$pkg_root" \
--component-plist "$pkg_component_plist" \
--identifier "$TSH_BUNDLEID" \
--version "v$TELEPORT_VERSION" \
--install-location /Applications \
--scripts "$pkg_scripts" \
"$target.unsigned"
$DRY_RUN_PREFIX productsign \
--sign "$DEVELOPER_ID_INSTALLER" \
--timestamp \
"$target.unsigned" \
"$target"
# Make sure $target exists in case of dry runs.
if [[ -n "$DRY_RUN_PREFIX" ]]; then
cp "$target.unsigned" "$target"
fi
# Notarize.
notarize "$target" "$TEAMID" "$TSH_BUNDLEID"
# Copy resulting package to $PWD, generate hashes.
mv "$target" .
local bn=''
bn="$(basename "$target")"
shasum -a 256 "$bn" > "$bn.sha256"
}
main "$@"