mirror of
https://github.com/gravitational/teleport
synced 2024-10-19 16:53:57 +00:00
99ad5c59a4
Changes how `make pkg-tsh` works so instead of building an installer for the `tsh` binary, placed under `/usr/local/bin`, we install an app to `/Applications/tsh-vXXX.app` and link its `tsh` binary to `/usr/local/bin`. The app shell is necessary to distribute a provisioning profile along with the signed/entitled/notarized binary. All of that is required for Touch ID to work. Naked `tsh` binaries are unable to use Touch ID, even if built with the correct build tags. I've elected to split the logic from `build-package.sh` into a separate script - it already does too much as-is. `build-pkg-tsh.sh` is more idiomatic, clears additional `shellcheck` rules and is easier to dry-run. #9160 * Build macOS installer for tsh.app * Add resources to build the tshdev app Moved from e/ * Add resources to build the tsh app (prod) * Use production values * Remove 'tsh' mode from build-package.tsh * Appease buildbox linter * Clarify one-time setup
358 lines
12 KiB
Bash
Executable file
358 lines
12 KiB
Bash
Executable file
#!/bin/bash
|
|
set -e
|
|
|
|
usage() {
|
|
echo "Usage: $(basename $0) [-t <oss/ent>] [-v <version>] [-p <package type>] <-a [amd64/x86_64]|[386/i386]|arm|arm64> <-r fips> <-s tarball source dir>" 1>&2
|
|
exit 1
|
|
}
|
|
|
|
# Don't follow sourced script.
|
|
#shellcheck disable=SC1090
|
|
#shellcheck disable=SC1091
|
|
. "$(dirname "$0")/build-common.sh"
|
|
|
|
while getopts ":t:v:p:a:r:s:n" o; do
|
|
case "${o}" in
|
|
t)
|
|
t=${OPTARG}
|
|
if [[ ${t} != "oss" && ${t} != "ent" ]]; then usage; fi
|
|
;;
|
|
v)
|
|
v=${OPTARG}
|
|
;;
|
|
p)
|
|
p=${OPTARG}
|
|
if [[ ${p} != "rpm" && ${p} != "deb" && ${p} != "pkg" ]]; then usage; fi
|
|
;;
|
|
a)
|
|
a=${OPTARG}
|
|
if [[ ${a} != "amd64" && ${a} != "x86_64" && ${a} != "386" && ${a} != "i386" && ${a} != "arm" && ${a} != "arm64" ]]; then usage; fi
|
|
;;
|
|
r)
|
|
r=${OPTARG}
|
|
if [[ ${r} != "fips" ]]; then usage; fi
|
|
;;
|
|
s)
|
|
s=${OPTARG}
|
|
;;
|
|
n)
|
|
# Dry-run mode.
|
|
# Only affects parts of the script, use at your own peril!
|
|
DRY_RUN_PREFIX='echo + '
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
shift $((OPTIND-1))
|
|
|
|
if [ -z "${t}" ] || [ -z "${v}" ] || [ -z "${p}" ]; then
|
|
usage
|
|
fi
|
|
|
|
TELEPORT_TYPE="$t"
|
|
TELEPORT_VERSION="$v"
|
|
PACKAGE_TYPE="$p"
|
|
ARCH="$a"
|
|
RUNTIME="$r"
|
|
TARBALL_DIRECTORY="$s"
|
|
GNUPG_DIR=${GNUPG_DIR:-/tmp/gnupg}
|
|
|
|
# linux package configuration
|
|
LINUX_BINARY_DIR=/usr/local/bin
|
|
LINUX_SYSTEMD_DIR=/lib/systemd/system
|
|
LINUX_CONFIG_DIR=/etc
|
|
LINUX_DATA_DIR=/var/lib/teleport
|
|
|
|
# extra package information for linux
|
|
MAINTAINER="info@goteleport.com"
|
|
LICENSE="Apache-2.0"
|
|
VENDOR="Gravitational"
|
|
DESCRIPTION="Teleport is a gateway for managing access to clusters of Linux servers via SSH or the Kubernetes API"
|
|
DOCS_URL="https://goteleport.com/docs"
|
|
|
|
# check that curl is installed
|
|
if [[ ! $(type curl) ]]; then
|
|
echo "curl must be installed"
|
|
exit 2
|
|
fi
|
|
|
|
# check that tar is installed
|
|
if [[ ! $(type tar) ]]; then
|
|
echo "tar must be installed"
|
|
exit 11
|
|
fi
|
|
|
|
# check that docker is installed when fpm is needed to build
|
|
if [[ "${PACKAGE_TYPE}" != "pkg" ]]; then
|
|
if [[ ! $(type docker) ]]; then
|
|
echo "docker must be installed to build non-OSX packages"
|
|
exit 3
|
|
fi
|
|
fi
|
|
|
|
# check that pkgbuild is installed if building for OS X and set variables appropriately
|
|
if [[ "${PACKAGE_TYPE}" == "pkg" ]]; then
|
|
if ! uname | grep -q Darwin; then
|
|
echo "You must be running on OS X to build .pkg files"
|
|
exit 4
|
|
fi
|
|
if [[ "${ARCH}" != "" ]]; then
|
|
echo "arch parameter is ignored when building for OS X"
|
|
unset ARCH
|
|
fi
|
|
if [[ "${RUNTIME}" != "" ]]; then
|
|
echo "runtime parameter is ignored when building for OS X"
|
|
unset RUNTIME
|
|
fi
|
|
PLATFORM="darwin"
|
|
ARCH="amd64"
|
|
if [[ ! $(type pkgbuild) ]]; then
|
|
echo "You need to install pkgbuild"
|
|
echo "Run: xcode-select --install"
|
|
exit 5
|
|
fi
|
|
else
|
|
PLATFORM="linux"
|
|
# if arch isn't set for other package types, throw an error
|
|
if [[ "${ARCH}" == "" ]]; then
|
|
usage
|
|
fi
|
|
|
|
# set docker image appropriately
|
|
if [[ "${PACKAGE_TYPE}" == "deb" ]]; then
|
|
DOCKER_IMAGE="quay.io/gravitational/fpm-debian:8"
|
|
elif [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
|
|
DOCKER_IMAGE="quay.io/gravitational/fpm-centos:8"
|
|
fi
|
|
fi
|
|
|
|
# handle differences between 'gravitational' arch and system arch
|
|
if [[ "${ARCH}" == "386" || "${ARCH}" == "i386" ]]; then
|
|
TEXT_ARCH="32-bit x86"
|
|
TARBALL_ARCH="386"
|
|
DEB_PACKAGE_ARCH="i386"
|
|
DEB_OUTPUT_ARCH="i386"
|
|
RPM_PACKAGE_ARCH="i386"
|
|
RPM_OUTPUT_ARCH="i386"
|
|
elif [[ "${ARCH}" == "amd64" || "${ARCH}" == "x86_64" ]]; then
|
|
TEXT_ARCH="64-bit x86"
|
|
TARBALL_ARCH="amd64"
|
|
DEB_PACKAGE_ARCH="amd64"
|
|
DEB_OUTPUT_ARCH="amd64"
|
|
RPM_PACKAGE_ARCH="x86_64"
|
|
RPM_OUTPUT_ARCH="x86_64"
|
|
elif [[ "${ARCH}" == "arm" ]]; then
|
|
TEXT_ARCH="32-bit ARM"
|
|
TARBALL_ARCH="arm"
|
|
# 32-bit arm can be hardfloat and softfloat, and we build for linux-gnueabihf
|
|
DEB_PACKAGE_ARCH="armhf"
|
|
DEB_OUTPUT_ARCH="arm" # backwards compatibility
|
|
RPM_PACKAGE_ARCH="armv7hl"
|
|
RPM_OUTPUT_ARCH="arm" # backwards compatibility
|
|
elif [[ "${ARCH}" == "arm64" ]]; then
|
|
TEXT_ARCH="64-bit ARM"
|
|
TARBALL_ARCH="arm64"
|
|
DEB_PACKAGE_ARCH="arm64"
|
|
DEB_OUTPUT_ARCH="arm64"
|
|
RPM_PACKAGE_ARCH="aarch64"
|
|
RPM_OUTPUT_ARCH="arm64" # backwards compatibility
|
|
fi
|
|
|
|
# amd64 RPMs should use CentOS 7 compatible artifacts
|
|
if [[ "${PACKAGE_TYPE}" == "rpm" && "${RPM_PACKAGE_ARCH}" == "x86_64" ]]; then
|
|
OPTIONAL_TARBALL_SECTION+="-centos7"
|
|
fi
|
|
|
|
# set optional runtime section for filename
|
|
if [[ "${RUNTIME}" == "fips" ]]; then
|
|
OPTIONAL_RUNTIME_SECTION+="-fips"
|
|
fi
|
|
|
|
# set variables appropriately depending on type of package being built
|
|
if [[ "${TELEPORT_TYPE}" == "ent" ]]; then
|
|
TARBALL_FILENAME="teleport-ent-v${TELEPORT_VERSION}-${PLATFORM}-${TARBALL_ARCH}${OPTIONAL_TARBALL_SECTION}${OPTIONAL_RUNTIME_SECTION}-bin.tar.gz"
|
|
TAR_PATH="teleport-ent"
|
|
RPM_NAME="teleport-ent"
|
|
if [[ "${RUNTIME}" == "fips" ]]; then
|
|
TYPE_DESCRIPTION="[${TEXT_ARCH} Enterprise edition, built with FIPS support]"
|
|
RPM_NAME="teleport-ent-fips"
|
|
else
|
|
TYPE_DESCRIPTION="[${TEXT_ARCH} Enterprise edition]"
|
|
fi
|
|
else
|
|
TARBALL_FILENAME="teleport-v${TELEPORT_VERSION}-${PLATFORM}-${TARBALL_ARCH}${OPTIONAL_TARBALL_SECTION}${OPTIONAL_RUNTIME_SECTION}-bin.tar.gz"
|
|
TAR_PATH="teleport"
|
|
RPM_NAME="teleport"
|
|
if [[ "${RUNTIME}" == "fips" ]]; then
|
|
TYPE_DESCRIPTION="[${TEXT_ARCH} Open source edition, built with FIPS support]"
|
|
RPM_NAME="teleport-fips"
|
|
else
|
|
TYPE_DESCRIPTION="[${TEXT_ARCH} Open source edition]"
|
|
fi
|
|
fi
|
|
|
|
# set file list
|
|
if [[ "${PACKAGE_TYPE}" == "pkg" ]]; then
|
|
SIGN_PKG="true"
|
|
FILE_LIST="${TAR_PATH}/tsh ${TAR_PATH}/tctl ${TAR_PATH}/teleport ${TAR_PATH}/tbot"
|
|
BUNDLE_ID="com.gravitational.teleport"
|
|
if [[ "${TELEPORT_TYPE}" == "ent" ]]; then
|
|
PKG_FILENAME="teleport-ent-${TELEPORT_VERSION}.${PACKAGE_TYPE}"
|
|
else
|
|
PKG_FILENAME="teleport-${TELEPORT_VERSION}.${PACKAGE_TYPE}"
|
|
fi
|
|
else
|
|
FILE_LIST="${TAR_PATH}/tsh ${TAR_PATH}/tctl ${TAR_PATH}/teleport ${TAR_PATH}/tbot ${TAR_PATH}/examples/systemd/teleport.service"
|
|
LINUX_BINARY_FILE_LIST="${TAR_PATH}/tsh ${TAR_PATH}/tctl ${TAR_PATH}/tbot ${TAR_PATH}/teleport"
|
|
LINUX_SYSTEMD_FILE_LIST="${TAR_PATH}/examples/systemd/teleport.service"
|
|
EXTRA_DOCKER_OPTIONS=""
|
|
RPM_SIGN_STANZA=""
|
|
if [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
|
|
PACKAGE_ARCH="${RPM_PACKAGE_ARCH}"
|
|
OUTPUT_FILENAME="${TAR_PATH}-${TELEPORT_VERSION}-1${OPTIONAL_RUNTIME_SECTION}.${RPM_OUTPUT_ARCH}.rpm"
|
|
FILE_PERMISSIONS_STANZA="--rpm-user root --rpm-group root --rpm-use-file-permissions "
|
|
# the rpm/rpmmacros file suppresses the creation of .build-id files (see https://github.com/gravitational/teleport/issues/7040)
|
|
EXTRA_DOCKER_OPTIONS="-v $(pwd)/rpm/rpmmacros:/root/.rpmmacros"
|
|
# if we set this environment variable, don't sign RPMs (can be useful for building test RPMs
|
|
# without having the signing keys)
|
|
if [ "${UNSIGNED_RPM}" == "true" ]; then
|
|
echo "RPMs will not be signed as requested"
|
|
else
|
|
# the GNUPG_DIR location here is assumed to contain a complete ~/.gnupg directory structure
|
|
# with pubring.kbx and trustdb.gpg files, plus a private-keys-v1.d directory with signing keys
|
|
# it needs to contain the "Gravitational, Inc" private key and signing key.
|
|
# we also use the rpm-sign/rpmmacros file instead which contains extra directives used for signing.
|
|
EXTRA_DOCKER_OPTIONS="-v $(pwd)/rpm-sign/rpmmacros:/root/.rpmmacros -v $(pwd)/rpm-sign/popt-override:/etc/popt.d/rpmsign-override -v ${GNUPG_DIR}:/root/.gnupg"
|
|
RPM_SIGN_STANZA="--rpm-sign"
|
|
fi
|
|
elif [[ "${PACKAGE_TYPE}" == "deb" ]]; then
|
|
PACKAGE_ARCH="${DEB_PACKAGE_ARCH}"
|
|
OUTPUT_FILENAME="${TAR_PATH}_${TELEPORT_VERSION}${OPTIONAL_RUNTIME_SECTION}_${DEB_OUTPUT_ARCH}.deb"
|
|
FILE_PERMISSIONS_STANZA="--deb-user root --deb-group root "
|
|
fi
|
|
fi
|
|
|
|
# create a temporary directory and download specified Teleport version
|
|
pushd "$(mktemp -d)"
|
|
PACKAGE_TEMPDIR=$(pwd)
|
|
# automatically clean up on exit
|
|
trap 'rm -rf ${PACKAGE_TEMPDIR}' EXIT
|
|
mkdir -p ${PACKAGE_TEMPDIR}/buildroot
|
|
|
|
# Find or download tarball to the local file cache.
|
|
tarname="$TARBALL_FILENAME"
|
|
[[ -n "$TARBALL_DIRECTORY" ]] && tarname="$TARBALL_DIRECTORY/$TARBALL_FILENAME"
|
|
tarout='' # find_or_fetch_tarball writes to this
|
|
find_or_fetch_tarball "$tarname" tarout
|
|
TARBALL_DIRECTORY="$(dirname "$tarout")"
|
|
TARBALL_FILENAME="$(basename "$tarout")" # for consistency, shouldn't change
|
|
echo "Found ${TARBALL_DIRECTORY}/${TARBALL_FILENAME} - using it"
|
|
|
|
# extract necessary files from tarball
|
|
tar -C "$(pwd)" -xvzf ${TARBALL_DIRECTORY}/${TARBALL_FILENAME} ${FILE_LIST}
|
|
|
|
# move files into correct locations before building the package
|
|
if [[ "${PACKAGE_TYPE}" != "pkg" ]]; then
|
|
if [[ "${LINUX_BINARY_FILE_LIST}" != "" ]]; then
|
|
mkdir -p ${PACKAGE_TEMPDIR}/buildroot${LINUX_BINARY_DIR}
|
|
mv -v ${LINUX_BINARY_FILE_LIST} ${PACKAGE_TEMPDIR}/buildroot${LINUX_BINARY_DIR}
|
|
fi
|
|
if [[ "${LINUX_SYSTEMD_FILE_LIST}" != "" ]]; then
|
|
mkdir -p ${PACKAGE_TEMPDIR}/buildroot${LINUX_SYSTEMD_DIR}
|
|
mv -v ${LINUX_SYSTEMD_FILE_LIST} ${PACKAGE_TEMPDIR}/buildroot${LINUX_SYSTEMD_DIR}
|
|
fi
|
|
if [[ "${LINUX_CONFIG_FILE}" != "" ]]; then
|
|
mkdir -p ${PACKAGE_TEMPDIR}/buildroot${LINUX_CONFIG_DIR}
|
|
mv -v ${LINUX_CONFIG_FILE} ${PACKAGE_TEMPDIR}/buildroot${LINUX_CONFIG_DIR}
|
|
CONFIG_FILE_STANZA="--config-files /src/buildroot${LINUX_CONFIG_DIR}/${LINUX_CONFIG_FILE} "
|
|
fi
|
|
# /var/lib/teleport
|
|
# shellcheck disable=SC2174
|
|
mkdir -p -m0700 ${PACKAGE_TEMPDIR}/buildroot${LINUX_DATA_DIR}
|
|
fi
|
|
popd
|
|
|
|
if [[ "${PACKAGE_TYPE}" == "pkg" ]]; then
|
|
# erase any existing versions of the package in the output directory first
|
|
rm -f ${PKG_FILENAME}
|
|
|
|
if [[ "${SIGN_PKG}" == "true" ]]; then
|
|
# run codesign to sign binaries
|
|
for FILE in ${FILE_LIST}; do
|
|
$DRY_RUN_PREFIX codesign -s "${DEVELOPER_ID_APPLICATION}" \
|
|
-f \
|
|
-v \
|
|
--timestamp \
|
|
--options runtime \
|
|
${PACKAGE_TEMPDIR}/${FILE}
|
|
done
|
|
fi
|
|
|
|
# build the package for OS X
|
|
pkgbuild \
|
|
--root ${PACKAGE_TEMPDIR}/${TAR_PATH} \
|
|
--identifier ${BUNDLE_ID} \
|
|
--version ${TELEPORT_VERSION} \
|
|
--install-location /usr/local/bin \
|
|
${PKG_FILENAME}
|
|
|
|
if [[ "${SIGN_PKG}" == "true" ]]; then
|
|
# mark package as unsigned first
|
|
mv ${PKG_FILENAME} ${PKG_FILENAME}.unsigned
|
|
|
|
# run productsign to sign package
|
|
$DRY_RUN_PREFIX productsign \
|
|
--sign "${DEVELOPER_ID_INSTALLER}" \
|
|
--timestamp \
|
|
${PKG_FILENAME}.unsigned \
|
|
${PKG_FILENAME}
|
|
[[ -n "$DRY_RUN_PREFIX" ]] && cp "$PKG_FILENAME.unsigned" "$PKG_FILENAME"
|
|
|
|
# remove unsigned package after successful signing
|
|
rm -f ${PKG_FILENAME}.unsigned
|
|
|
|
notarize "$PKG_FILENAME" "$TEAMID" "$BUNDLE_ID"
|
|
fi
|
|
|
|
# checksum created packages
|
|
for PACKAGE in *."${PACKAGE_TYPE}"; do
|
|
shasum -a 256 ${PACKAGE} > ${PACKAGE}.sha256
|
|
done
|
|
else
|
|
# erase any existing packages of the same type/version/arch in the output directory first
|
|
rm -vf ${OUTPUT_FILENAME}
|
|
|
|
# build for other platforms
|
|
docker run -v ${PACKAGE_TEMPDIR}:/src --rm ${EXTRA_DOCKER_OPTIONS} ${DOCKER_IMAGE} \
|
|
fpm \
|
|
--input-type dir \
|
|
--output-type ${PACKAGE_TYPE} \
|
|
--name ${RPM_NAME} \
|
|
--version "${TELEPORT_VERSION}" \
|
|
--maintainer "${MAINTAINER}" \
|
|
--url "${DOCS_URL}" \
|
|
--license "${LICENSE}" \
|
|
--vendor "${VENDOR}" \
|
|
--description "${DESCRIPTION} ${TYPE_DESCRIPTION}" \
|
|
--architecture ${PACKAGE_ARCH} \
|
|
--package ${OUTPUT_FILENAME} \
|
|
--chdir /src/buildroot \
|
|
--directories ${LINUX_DATA_DIR} \
|
|
--provides teleport \
|
|
--prefix / \
|
|
--verbose \
|
|
${CONFIG_FILE_STANZA} \
|
|
${FILE_PERMISSIONS_STANZA} \
|
|
${RPM_SIGN_STANZA} .
|
|
|
|
# copy created package back to current directory
|
|
cp ${PACKAGE_TEMPDIR}/*."${PACKAGE_TYPE}" .
|
|
|
|
# checksum created packages
|
|
for FILE in *."${PACKAGE_TYPE}"; do
|
|
sha256sum ${FILE} > ${FILE}.sha256
|
|
done
|
|
fi
|