mirror of
https://github.com/gravitational/teleport.git
synced 2026-11-02 23:31:08 +08:00
In the context of Discover, we want to ease the installation process of Teleport. Our current focus is Databases. Adding a database resource requires at least one Database service/agent running with matching labels for that resource. The focus of this PR is to ease the installation of those agents. Those service/agents are currently installed in a multi step flow: - install Teleport on the host (select OS/arch/distribution format) - configure the service by running `teleport configure db ...` - start the application (possibly configuring the systemd unit file. As you can see, this is a lot of steps. This PR adds a new installation script: install-database.sh This script is actually the same used for installing Server Nodes or App Service/Agents but now can also install database service/agents. So, how does the new flow look like? After adding the Database info (type, hostname, port and labels), and if there's no agent available, a new step appears: add a database agent. The user provides a list of labels they want the agent to monitor. Those labels are stored as SuggestedAgentMatcherLabels within the token which is generate after confirming the labels. The user then gets an URL which they can use to install the agent. This URL contains the token and when invoked creates the install-database.sh script containing the `db_service` configuration. The field `db_service.resources.0.labels` contains the previously defined labels. This script is almost the same that exists today for installing Server Nodes and App services/agents, it only changes the `teleport.yaml` configuration. When the user run this command, the UI gets notified and can then proceed to the next step. **Demo** ```bash root@marcoacme-node-001:/shared# install-database.sh 2022-10-20 16:56:27 UTC [teleport-installer] TELEPORT_VERSION: 11.0.0-rc.1 2022-10-20 16:56:27 UTC [teleport-installer] TARGET_HOSTNAME: 127.0.0.1.nip.io 2022-10-20 16:56:27 UTC [teleport-installer] TARGET_PORT: 3080 2022-10-20 16:56:27 UTC [teleport-installer] JOIN_TOKEN: 6417b719b68d979ac01d3039f4246ce3 2022-10-20 16:56:27 UTC [teleport-installer] CA_PIN_HASHES: sha256:9fa22af321476074164f40aa901e291df92f3dbeea1b1f641bc5bf47efd00174 2022-10-20 16:56:27 UTC [teleport-installer] Checking TCP connectivity to Teleport server (127.0.0.1.nip.io:3080) 2022-10-20 16:56:27 UTC [teleport-installer] Couldn't find nc, telnet or /dev/tcp to do a connection test 2022-10-20 16:56:27 UTC [teleport-installer] Going to blindly continue without testing connectivity 2022-10-20 16:56:27 UTC [teleport-installer] Detected host: linux-gnu, using Teleport binary type linux 2022-10-20 16:56:27 UTC [teleport-installer] Detected arch: x86_64, using Teleport arch amd64 2022-10-20 16:56:27 UTC [teleport-installer] Detected distro type: debian 2022-10-20 16:56:27 UTC [teleport-installer] Using Teleport distribution: deb 2022-10-20 16:56:27 UTC [teleport-installer] Created temp dir /tmp/teleport-PWn6zEcG9P 2022-10-20 16:56:27 UTC [teleport-installer] Downloading Teleport deb release 11.0.0-rc.1 2022-10-20 16:56:27 UTC [teleport-installer] Running curl -fsSL --retry 5 --retry-delay 5 https://get.gravitational.com/teleport_11.0.0-rc.1_amd64.deb 2022-10-20 16:56:27 UTC [teleport-installer] Downloading to /tmp/teleport-PWn6zEcG9P/teleport_11.0.0-rc.1_amd64.deb 2022-10-20 16:56:50 UTC [teleport-installer] Downloaded file size: 119220326 bytes 2022-10-20 16:56:50 UTC [teleport-installer] Will use sha256sum to validate the checksum of the downloaded file 2022-10-20 16:56:52 UTC [teleport-installer] The downloaded file's checksum validated correctly 2022-10-20 16:56:52 UTC [teleport-installer] Using dpkg to install /tmp/teleport-PWn6zEcG9P/teleport_11.0.0-rc.1_amd64.deb Selecting previously unselected package teleport. (Reading database ... 8182 files and directories currently installed.) Preparing to unpack .../teleport_11.0.0-rc.1_amd64.deb ... Unpacking teleport (11.0.0-rc.1) ... Setting up teleport (11.0.0-rc.1) ... 2022-10-20 16:56:54 UTC [teleport-installer] Found: Teleport v11.0.0-rc.1 git:v11.0.0-rc.1-0-g6950d74 go1.19.2 2022-10-20 16:56:54 UTC [teleport-installer] Writing Teleport database service config to /etc/teleport.yaml 2022-10-20 16:56:54 UTC [teleport-installer] Host does not appear to be using systemd 2022-10-20 16:56:54 UTC [teleport-installer] ---> This host is not running systemd, so Teleport cannot be started automatically when it exits. 2022-10-20 16:56:54 UTC [teleport-installer] ---> Please investigate an alternative way to keep Teleport running. 2022-10-20 16:56:54 UTC [teleport-installer] ---> You can find information in our documentation: https://goteleport.com/docs/ 2022-10-20 16:56:54 UTC [teleport-installer] ---> For now, Teleport will be started in the foreground - you can press Ctrl+C to exit. Run this command to start Teleport in future: /usr/local/bin/teleport start --config=/etc/teleport.yaml ------------------------------------------------------------------------ | IMPORTANT: TELEPORT WILL STOP RUNNING AFTER YOU CLOSE THIS TERMINAL! | | YOU MUST CONFIGURE A SERVICE MANAGER TO MAKE IT RUN ON STARTUP! | ------------------------------------------------------------------------ 2022-10-20 16:56:54 UTC [teleport-installer] Starting Teleport in the foreground 2022-10-20T16:56:54Z INFO Starting Teleport v11.0.0-rc.1 common/teleport.go:435 2022-10-20T16:56:54Z [PROC:1] INFO Generating new host UUID: 51b404d7-e501-43f1-83dc-8298c1fcab2b. pid:379.1 service/service.go:874 2022-10-20T16:56:54Z [PROC:1] INFO Joining the cluster with a secure token. pid:379.1 service/connect.go:582 2022-10-20T16:56:54Z [PROC:1] INFO Joining the cluster with a secure token. pid:379.1 service/connect.go:582 2022-10-20T16:56:55Z [AUTH] INFO Attempting registration via proxy server. auth/register.go:239 2022-10-20T16:56:55Z [AUTH] INFO Attempting registration via proxy server. auth/register.go:239 ... root@marcoacme-node-001:/shared# cat /etc/teleport.yaml version: v3 teleport: nodename: marcoacme-node-001 auth_token: 6417b719b68d979ac01d3039f4246ce3 ca_pin: - sha256:9fa22af321476074164f40aa901e291df92f3dbeea1b1f641bc5bf47efd00174 proxy_server: 127.0.0.1.nip.io:3080 log: output: stderr severity: INFO auth_service: enabled: no ssh_service: enabled: no proxy_service: enabled: no db_service: enabled: "yes" resources: - labels: dev: prod ``` **Tech Details** Request to create token with `suggested_agent_matcher_labels`: ```shell curl 'https://127.0.0.1.nip.io:3080/v1/webapi/token' \ -H 'accept: application/json' \ -H 'content-type: application/json; charset=utf-8' \ --data-raw ' { "roles":["Db"], "join_method":"token", "allow":[], "suggested_agent_matcher_labels": {"dev":"prod"} } ' ``` Closes #17446
905 lines
36 KiB
Bash
Executable File
905 lines
36 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
SCRIPT_NAME="teleport-installer"
|
|
|
|
# default values
|
|
ALIVE_CHECK_DELAY=3
|
|
CONNECTIVITY_TEST_METHOD=""
|
|
COPY_COMMAND="cp"
|
|
DISTRO_TYPE=""
|
|
IGNORE_CONNECTIVITY_CHECK="${TELEPORT_IGNORE_CONNECTIVITY_CHECK:-false}"
|
|
LAUNCHD_CONFIG_PATH="/Library/LaunchDaemons"
|
|
LOG_FILENAME="$(mktemp -t ${SCRIPT_NAME}.log.XXXXXXXXXX)"
|
|
MACOS_STDERR_LOG="/var/log/teleport-stderr.log"
|
|
MACOS_STDOUT_LOG="/var/log/teleport-stdout.log"
|
|
SYSTEMD_UNIT_PATH="/lib/systemd/system/teleport.service"
|
|
TARGET_PORT_DEFAULT=443
|
|
TELEPORT_ARCHIVE_PATH="teleport"
|
|
TELEPORT_BINARY_DIR="/usr/local/bin"
|
|
TELEPORT_BINARY_LIST="teleport tctl tsh"
|
|
TELEPORT_CONFIG_PATH="/etc/teleport.yaml"
|
|
TELEPORT_DATA_DIR="/var/lib/teleport"
|
|
TELEPORT_DOCS_URL="https://goteleport.com/docs/"
|
|
TELEPORT_FORMAT=""
|
|
|
|
# initialise variables (because set -u disallows unbound variables)
|
|
f=""
|
|
l=""
|
|
DISABLE_TLS_VERIFICATION=false
|
|
NODENAME=$(hostname)
|
|
IGNORE_CHECKS=false
|
|
OVERRIDE_FORMAT=""
|
|
QUIET=false
|
|
APP_INSTALL_DECISION=""
|
|
INTERACTIVE=false
|
|
|
|
# the default value of each variable is a templatable Go value so that it can
|
|
# optionally be replaced by the server before the script is served up
|
|
TELEPORT_VERSION='{{.version}}'
|
|
TARGET_HOSTNAME='{{.hostname}}'
|
|
TARGET_PORT='{{.port}}'
|
|
JOIN_TOKEN='{{.token}}'
|
|
JOIN_METHOD='{{.joinMethod}}'
|
|
JOIN_METHOD_FLAG=""
|
|
[ -n "$JOIN_METHOD" ] && JOIN_METHOD_FLAG="--join-method ${JOIN_METHOD}"
|
|
|
|
# inject labels into the configuration
|
|
LABELS='{{.labels}}'
|
|
LABELS_FLAG=()
|
|
[ -n "$LABELS" ] && LABELS_FLAG=(--labels "${LABELS}")
|
|
|
|
# When all stanza generators have been updated to use the new
|
|
# `teleport <service> configure` commands CA_PIN_HASHES can be removed along
|
|
# with the script passing it in in `join_tokens.go`.
|
|
CA_PIN_HASHES='{{.caPinsOld}}'
|
|
CA_PINS='{{.caPins}}'
|
|
ARG_CA_PIN_HASHES=""
|
|
APP_INSTALL_MODE='{{.appInstallMode}}'
|
|
APP_NAME='{{.appName}}'
|
|
APP_URI='{{.appURI}}'
|
|
DB_INSTALL_MODE='{{.databaseInstallMode}}'
|
|
|
|
# usage message
|
|
# shellcheck disable=SC2086
|
|
usage() { echo "Usage: $(basename $0) [-v teleport_version] [-h target_hostname] [-p target_port> [-j join_token ] [-c ca_pin_hash]... [-q] [-l log_filename] [-a app_name] [-u app_uri] " 1>&2; exit 1; }
|
|
while getopts ":v:h:p:j:c:f:ql:ika:u:" o; do
|
|
case "${o}" in
|
|
v) TELEPORT_VERSION=${OPTARG};;
|
|
h) TARGET_HOSTNAME=${OPTARG};;
|
|
p) TARGET_PORT=${OPTARG};;
|
|
j) JOIN_TOKEN=${OPTARG};;
|
|
c) ARG_CA_PIN_HASHES="${ARG_CA_PIN_HASHES} ${OPTARG}";;
|
|
f) f=${OPTARG}; if [[ ${f} != "tarball" && ${f} != "deb" && ${f} != "rpm" && ${f} != "rpm-centos6" ]]; then usage; fi;;
|
|
q) QUIET=true;;
|
|
l) l=${OPTARG};;
|
|
i) IGNORE_CHECKS=true; COPY_COMMAND="cp -f";;
|
|
k) DISABLE_TLS_VERIFICATION=true;;
|
|
a) APP_INSTALL_MODE=true && APP_NAME=${OPTARG};;
|
|
u) APP_INSTALL_MODE=true && APP_URI=${OPTARG};;
|
|
*) usage;;
|
|
esac
|
|
done
|
|
shift $((OPTIND-1))
|
|
|
|
if [[ "${ARG_CA_PIN_HASHES}" != "" ]]; then
|
|
CA_PIN_HASHES="${ARG_CA_PIN_HASHES}"
|
|
fi
|
|
|
|
# function to construct a go template variable
|
|
# go's template parser is a bit finicky, so we dynamically build the value one character at a time
|
|
construct_go_template() {
|
|
OUTPUT="{"
|
|
OUTPUT+="{"
|
|
OUTPUT+="."
|
|
OUTPUT+="${1}"
|
|
OUTPUT+="}"
|
|
OUTPUT+="}"
|
|
echo "${OUTPUT}"
|
|
}
|
|
|
|
# check whether we are root, exit if not
|
|
assert_running_as_root() {
|
|
if ! [ "$(id -u)" = 0 ]; then
|
|
echo "This script must be run as root." 1>&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# function to check whether variables are either blank or set to the default go template value
|
|
# (because they haven't been set by the go script generator or a command line argument)
|
|
# returns 1 if the variable is set to a default/zero value
|
|
# returns 0 otherwise (i.e. it needs to be set interactively)
|
|
check_variable() {
|
|
VARIABLE_VALUE="${!1}"
|
|
GO_TEMPLATE_NAME=$(construct_go_template "${2}")
|
|
if [[ "${VARIABLE_VALUE}" == "" ]] || [[ "${VARIABLE_VALUE}" == "${GO_TEMPLATE_NAME}" ]]; then
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# function to check whether a provided value is "truthy" i.e. it looks like you're trying to say "yes"
|
|
is_truthy() {
|
|
declare -a TRUTHY_VALUES
|
|
TRUTHY_VALUES=("y" "Y" "yes" "YES" "ye" "YE" "yep" "YEP" "ya" "YA")
|
|
CHECK_VALUE="$1"
|
|
for ARRAY_VALUE in "${TRUTHY_VALUES[@]}"; do [[ "${CHECK_VALUE}" == "${ARRAY_VALUE}" ]] && return 0; done
|
|
return 1
|
|
}
|
|
|
|
# function to read input until the value you get is non-empty
|
|
read_nonblank_input() {
|
|
INPUT=""
|
|
VARIABLE_TO_ASSIGN="$1"
|
|
shift
|
|
PROMPT="$*"
|
|
until [[ "${INPUT}" != "" ]]; do
|
|
echo -n "${PROMPT}"
|
|
read -r INPUT
|
|
done
|
|
printf -v "${VARIABLE_TO_ASSIGN}" '%s' "${INPUT}"
|
|
}
|
|
|
|
# error if we're not root
|
|
assert_running_as_root
|
|
|
|
# set/read values interactively if not provided
|
|
# users will be prompted to enter their own value if all the following are true:
|
|
# - the current value is blank, or equal to the default Go template value
|
|
# - the value has not been provided by command line argument
|
|
! check_variable TELEPORT_VERSION version && INTERACTIVE=true && read_nonblank_input TELEPORT_VERSION "Enter Teleport version to install (without v): "
|
|
! check_variable TARGET_HOSTNAME hostname && INTERACTIVE=true && read_nonblank_input TARGET_HOSTNAME "Enter target hostname to connect to: "
|
|
! check_variable TARGET_PORT port && INTERACTIVE=true && { echo -n "Enter target port to connect to [${TARGET_PORT_DEFAULT}]: "; read -r TARGET_PORT; }
|
|
! check_variable JOIN_TOKEN token && INTERACTIVE=true && read_nonblank_input JOIN_TOKEN "Enter Teleport join token as provided: "
|
|
! check_variable CA_PIN_HASHES caPins && INTERACTIVE=true && read_nonblank_input CA_PIN_HASHES "Enter CA pin hash (separate multiple hashes with spaces): "
|
|
[ -n "${f}" ] && OVERRIDE_FORMAT=${f}
|
|
[ -n "${l}" ] && LOG_FILENAME=${l}
|
|
# if app service mode is not set (or is the default value) and we are running interactively (i.e. the user has provided some input already),
|
|
# prompt the user to choose whether to enable app_service
|
|
if [[ "${INTERACTIVE}" == "true" ]]; then
|
|
if ! check_variable APP_INSTALL_MODE appInstallMode; then
|
|
APP_INSTALL_MODE="false"
|
|
echo -n "Would you like to enable and configure Teleport's app_service, to use Teleport as a reverse proxy for a web application? [y/n, default: n] "
|
|
read -r APP_INSTALL_DECISION
|
|
if is_truthy "${APP_INSTALL_DECISION}"; then
|
|
APP_INSTALL_MODE="true"
|
|
fi
|
|
fi
|
|
fi
|
|
# prompt for extra needed values if we're running in app service mode
|
|
if [[ "${APP_INSTALL_MODE}" == "true" ]]; then
|
|
! check_variable APP_NAME appName && read_nonblank_input APP_NAME "Enter app name to install (must be DNS-compatible; less than 63 characters, no spaces, only - or _ as punctuation): "
|
|
! check_variable APP_URI appURI && read_nonblank_input APP_URI "Enter app URI (the host running the Teleport app service must be able to connect to this): "
|
|
# generate app public addr by concatenating values
|
|
APP_PUBLIC_ADDR="${APP_NAME}.${TARGET_HOSTNAME}"
|
|
fi
|
|
|
|
# set default target port if value not provided
|
|
if [[ "${TARGET_PORT}" == "" ]]; then
|
|
TARGET_PORT=${TARGET_PORT_DEFAULT}
|
|
fi
|
|
|
|
# clear log file if provided
|
|
if [[ "${LOG_FILENAME}" != "" ]]; then
|
|
if [ -f "${LOG_FILENAME}" ]; then
|
|
echo -n "" > "${LOG_FILENAME}"
|
|
fi
|
|
fi
|
|
|
|
# log functions
|
|
log_date() { echo -n "$(date '+%Y-%m-%d %H:%M:%S %Z')"; }
|
|
log() {
|
|
LOG_LINE="$(log_date) [${SCRIPT_NAME}] $*"
|
|
if [[ ${QUIET} != "true" ]]; then
|
|
echo "${LOG_LINE}"
|
|
fi
|
|
if [[ "${LOG_FILENAME}" != "" ]]; then
|
|
echo "${LOG_LINE}" >> "${LOG_FILENAME}"
|
|
fi
|
|
}
|
|
# writes a line with no timestamp or starting data, always prints
|
|
log_only() {
|
|
LOG_LINE="$*"
|
|
echo "${LOG_LINE}"
|
|
if [[ "${LOG_FILENAME}" != "" ]]; then
|
|
echo "${LOG_LINE}" >> "${LOG_FILENAME}"
|
|
fi
|
|
}
|
|
# writes a line by itself as a header
|
|
log_header() {
|
|
LOG_LINE="$*"
|
|
echo ""
|
|
echo "${LOG_LINE}"
|
|
echo ""
|
|
if [[ "${LOG_FILENAME}" != "" ]]; then
|
|
echo "${LOG_LINE}" >> "${LOG_FILENAME}"
|
|
fi
|
|
}
|
|
# important log lines, print even when -q (quiet) is passed
|
|
log_important() {
|
|
LOG_LINE="$(log_date) [${SCRIPT_NAME}] ---> $*"
|
|
echo "${LOG_LINE}"
|
|
if [[ "${LOG_FILENAME}" != "" ]]; then
|
|
echo "${LOG_LINE}" >> "${LOG_FILENAME}"
|
|
fi
|
|
}
|
|
log_cleanup_message() {
|
|
log_only "This script does not overwrite any existing settings or Teleport installations."
|
|
log_only "Please clean up by running any of the following steps as necessary:"
|
|
log_only "- stop any running Teleport processes"
|
|
log_only " - pkill -f teleport"
|
|
log_only "- remove any data under ${TELEPORT_DATA_DIR}, along with the directory itself"
|
|
log_only " - rm -rf ${TELEPORT_DATA_DIR}"
|
|
log_only "- remove any configuration at ${TELEPORT_CONFIG_PATH}"
|
|
log_only " - rm -f ${TELEPORT_CONFIG_PATH}"
|
|
log_only "- remove any Teleport binaries (${TELEPORT_BINARY_LIST}) installed under ${TELEPORT_BINARY_DIR}"
|
|
for BINARY in ${TELEPORT_BINARY_LIST}; do EXAMPLE_DELETE_COMMAND+="${TELEPORT_BINARY_DIR}/${BINARY} "; done
|
|
log_only " - rm -f ${EXAMPLE_DELETE_COMMAND}"
|
|
log_only "Run this installer again when done."
|
|
log_only
|
|
}
|
|
|
|
# other functions
|
|
# check whether a named program exists
|
|
check_exists() { NAME=$1; if type "${NAME}" >/dev/null 2>&1; then return 0; else return 1; fi; }
|
|
# checks for the existence of a list of named binaries and exits with error if any of them don't exist
|
|
check_exists_fatal() {
|
|
for TOOL in "$@"; do
|
|
if ! check_exists "${TOOL}"; then
|
|
log_important "Error: cannot find ${TOOL} - it needs to be installed"
|
|
exit 1
|
|
fi
|
|
done
|
|
}
|
|
# check connectivity to the given host/port and make a request to see if Teleport is listening
|
|
# uses the global variable CONNECTIVITY_TEST_METHOD to return the name of the checker, as return
|
|
# values aren't really a thing that exists in bash
|
|
check_connectivity() {
|
|
HOST=$1
|
|
PORT=$2
|
|
# check with nc
|
|
if check_exists nc; then
|
|
CONNECTIVITY_TEST_METHOD="nc"
|
|
if nc -z -w3 "${HOST}" "${PORT}" >/dev/null 2>&1; then return 0; else return 1; fi
|
|
# if there's no nc, check with telnet
|
|
elif check_exists telnet; then
|
|
CONNECTIVITY_TEST_METHOD="telnet"
|
|
if echo -e '\x1dclose\x0d' | telnet "${HOST}" "${PORT}" >/dev/null 2>&1; then return 0; else return 1; fi
|
|
# if there's no nc or telnet, try and use /dev/tcp
|
|
elif [ -f /dev/tcp ]; then
|
|
CONNECTIVITY_TEST_METHOD="/dev/tcp"
|
|
if (head -1 < "/dev/tcp/${HOST}/${PORT}") >/dev/null 2>&1; then return 0; else return 1; fi
|
|
else
|
|
return 255
|
|
fi
|
|
}
|
|
# check whether a teleport DEB is already installed and exit with error if so
|
|
check_deb_not_already_installed() {
|
|
check_exists_fatal dpkg awk
|
|
DEB_INSTALLED=$(dpkg -l | awk '{print $2}' | grep -E ^teleport || true)
|
|
if [[ ${DEB_INSTALLED} != "" ]]; then
|
|
log_important "It looks like there is already a Teleport DEB package installed (name: ${DEB_INSTALLED})."
|
|
log_important "You will need to remove that package before using this script."
|
|
exit 1
|
|
fi
|
|
}
|
|
# check whether a teleport RPM is already installed and exit with error if so
|
|
check_rpm_not_already_installed() {
|
|
check_exists_fatal rpm
|
|
RPM_INSTALLED=$(rpm -qa | grep -E ^teleport || true)
|
|
if [[ ${RPM_INSTALLED} != "" ]]; then
|
|
log_important "It looks like there is already a Teleport RPM package installed (name: ${RPM_INSTALLED})."
|
|
log_important "You will need to remove that package before using this script."
|
|
exit 1
|
|
fi
|
|
}
|
|
# function to check if given variable is set
|
|
check_set() {
|
|
CHECK_KEY=${1} || true
|
|
CHECK_VALUE=${!1} || true
|
|
if [[ "${CHECK_VALUE}" == "" ]]; then
|
|
log "Required variable ${CHECK_KEY} is not set"
|
|
exit 1
|
|
else
|
|
log "${CHECK_KEY}: ${CHECK_VALUE}"
|
|
fi
|
|
}
|
|
# checks that teleport binary can be found in path and runs 'teleport version'
|
|
check_teleport_binary() {
|
|
FOUND_TELEPORT_VERSION=$(${TELEPORT_BINARY_DIR}/teleport version)
|
|
if [[ "${FOUND_TELEPORT_VERSION}" == "" ]]; then
|
|
log "Cannot find Teleport binary"
|
|
return 1
|
|
else
|
|
log "Found: ${FOUND_TELEPORT_VERSION}";
|
|
return 0
|
|
fi
|
|
}
|
|
# wrapper to download with curl
|
|
download() {
|
|
URL=$1
|
|
OUTPUT_PATH=$2
|
|
CURL_COMMAND="curl -fsSL --retry 5 --retry-delay 5"
|
|
# optionally allow disabling of TLS verification (can be useful on older distros
|
|
# which often have an out-of-date set of CA certificate bundle which won't validate)
|
|
if [[ ${DISABLE_TLS_VERIFICATION} == "true" ]]; then
|
|
CURL_COMMAND+=" -k"
|
|
fi
|
|
log "Running ${CURL_COMMAND} ${URL}"
|
|
log "Downloading to ${OUTPUT_PATH}"
|
|
# handle errors with curl
|
|
if ! ${CURL_COMMAND} -o "${OUTPUT_PATH}" "${URL}"; then
|
|
log_important "curl error downloading ${URL}"
|
|
log "On an older OS, this may be related to the CA certificate bundle being too old."
|
|
log "You can pass the hidden -k flag to this script to disable TLS verification - this is not recommended!"
|
|
exit 1
|
|
fi
|
|
# check that the file has a non-zero size as an extra validation
|
|
check_exists_fatal wc xargs
|
|
FILE_SIZE="$(wc -c <"${OUTPUT_PATH}" | xargs)"
|
|
if [ "${FILE_SIZE}" -eq 0 ]; then
|
|
log_important "The downloaded file has a size of 0 bytes, which means an error occurred. Cannot continue."
|
|
exit 1
|
|
else
|
|
log "Downloaded file size: ${FILE_SIZE} bytes"
|
|
fi
|
|
# if we have a hashing utility installed, also download and validate the checksum
|
|
SHA_COMMAND=""
|
|
# shasum is installed by default on MacOS and some distros
|
|
if check_exists shasum; then
|
|
SHA_COMMAND="shasum -a 256"
|
|
# sha256sum is installed by default in some other distros
|
|
elif check_exists sha256sum; then
|
|
SHA_COMMAND="sha256sum"
|
|
fi
|
|
if [[ "${SHA_COMMAND}" != "" ]]; then
|
|
log "Will use ${SHA_COMMAND} to validate the checksum of the downloaded file"
|
|
SHA_URL="${URL}.sha256"
|
|
SHA_PATH="${OUTPUT_PATH}.sha256"
|
|
${CURL_COMMAND} -o "${SHA_PATH}" "${SHA_URL}"
|
|
if ${SHA_COMMAND} --status -c "${SHA_PATH}"; then
|
|
log "The downloaded file's checksum validated correctly"
|
|
else
|
|
SHA_EXPECTED=$(cat "${SHA_PATH}")
|
|
SHA_ACTUAL=$(${SHA_COMMAND} "${OUTPUT_PATH}")
|
|
if check_exists awk; then
|
|
SHA_EXPECTED=$(echo "${SHA_EXPECTED}" | awk '{print $1}')
|
|
SHA_ACTUAL=$(echo "${SHA_ACTUAL}" | awk '{print $1}')
|
|
fi
|
|
log_important "Checksum of the downloaded file did not validate correctly"
|
|
log_important "Expected: ${SHA_EXPECTED}"
|
|
log_important "Got: ${SHA_ACTUAL}"
|
|
log_important "Try rerunning this script from the start. If the issue persists, contact Teleport support."
|
|
exit 1
|
|
fi
|
|
else
|
|
log "shasum/sha256sum utilities not found, will skip checksum validation"
|
|
fi
|
|
}
|
|
# gets the filename from a full path (https://target.site/path/to/file.tar.gz -> file.tar.gz)
|
|
get_download_filename() { echo "${1##*/}"; }
|
|
# gets the pid of any running teleport process (and converts newlines to spaces)
|
|
get_teleport_pid() {
|
|
check_exists_fatal pgrep xargs
|
|
pgrep teleport | xargs echo
|
|
}
|
|
# returns a command which will start teleport using the config
|
|
get_teleport_start_command() {
|
|
echo "${TELEPORT_BINARY_DIR}/teleport start --config=${TELEPORT_CONFIG_PATH}"
|
|
}
|
|
# installs the teleport-provided launchd config
|
|
install_launchd_config() {
|
|
log "Installing Teleport launchd config to ${LAUNCHD_CONFIG_PATH}"
|
|
${COPY_COMMAND} ./${TELEPORT_ARCHIVE_PATH}/examples/launchd/com.goteleport.teleport.plist ${LAUNCHD_CONFIG_PATH}/com.goteleport.teleport.plist
|
|
}
|
|
# installs the teleport-provided systemd unit
|
|
install_systemd_unit() {
|
|
log "Installing Teleport systemd unit to ${SYSTEMD_UNIT_PATH}"
|
|
${COPY_COMMAND} ./${TELEPORT_ARCHIVE_PATH}/examples/systemd/teleport.service ${SYSTEMD_UNIT_PATH}
|
|
log "Reloading unit files (systemctl daemon-reload)"
|
|
systemctl daemon-reload
|
|
}
|
|
# formats the arguments as a yaml list
|
|
get_yaml_list() {
|
|
name="${1}"
|
|
list="${2}"
|
|
indentation="${3}"
|
|
echo "${indentation}${name}:"
|
|
for item in ${list}; do
|
|
echo "${indentation}- ${item}"
|
|
done
|
|
}
|
|
|
|
# installs the provided teleport config (for app service)
|
|
install_teleport_app_config() {
|
|
log "Writing Teleport app service config to ${TELEPORT_CONFIG_PATH}"
|
|
CA_PINS_CONFIG=$(get_yaml_list "ca_pin" "${CA_PIN_HASHES}" " ")
|
|
cat << EOF > ${TELEPORT_CONFIG_PATH}
|
|
version: v3
|
|
teleport:
|
|
nodename: ${NODENAME}
|
|
auth_token: ${JOIN_TOKEN}
|
|
${CA_PINS_CONFIG}
|
|
proxy_server: ${TARGET_HOSTNAME}:${TARGET_PORT}
|
|
log:
|
|
output: stderr
|
|
severity: INFO
|
|
auth_service:
|
|
enabled: no
|
|
ssh_service:
|
|
enabled: no
|
|
proxy_service:
|
|
enabled: no
|
|
app_service:
|
|
enabled: yes
|
|
apps:
|
|
- name: "${APP_NAME}"
|
|
uri: "${APP_URI}"
|
|
public_addr: ${APP_PUBLIC_ADDR}
|
|
EOF
|
|
}
|
|
# installs the provided teleport config (for database service)
|
|
install_teleport_database_config() {
|
|
log "Writing Teleport database service config to ${TELEPORT_CONFIG_PATH}"
|
|
CA_PINS_CONFIG=$(get_yaml_list "ca_pin" "${CA_PIN_HASHES}" " ")
|
|
|
|
# This file is processed by `shellschek` as part of the lint step
|
|
# It detects an issue because of un-set variables - $index and $line. This check is called SC2154.
|
|
# However, that's not an issue, because those variables are replaced when we run go's text/template engine over it.
|
|
# When executing the script, those are no long variables but actual values.
|
|
# shellcheck disable=SC2154
|
|
cat << EOF > ${TELEPORT_CONFIG_PATH}
|
|
version: v3
|
|
teleport:
|
|
nodename: ${NODENAME}
|
|
auth_token: ${JOIN_TOKEN}
|
|
${CA_PINS_CONFIG}
|
|
proxy_server: ${TARGET_HOSTNAME}:${TARGET_PORT}
|
|
log:
|
|
output: stderr
|
|
severity: INFO
|
|
auth_service:
|
|
enabled: no
|
|
ssh_service:
|
|
enabled: no
|
|
proxy_service:
|
|
enabled: no
|
|
db_service:
|
|
enabled: "yes"
|
|
resources:
|
|
- labels:{{range $index, $line := .db_service_resource_labels}}
|
|
{{$line -}}
|
|
{{end}}
|
|
EOF
|
|
}
|
|
# installs the provided teleport config (for node service)
|
|
install_teleport_node_config() {
|
|
log "Writing Teleport node service config to ${TELEPORT_CONFIG_PATH}"
|
|
${TELEPORT_BINARY_DIR}/teleport node configure \
|
|
--token ${JOIN_TOKEN} \
|
|
${JOIN_METHOD_FLAG} \
|
|
--ca-pin ${CA_PINS} \
|
|
--proxy ${TARGET_HOSTNAME}:${TARGET_PORT} \
|
|
"${LABELS_FLAG[@]}" \
|
|
--output ${TELEPORT_CONFIG_PATH}
|
|
}
|
|
# checks whether the given host is running MacOS
|
|
is_macos_host() { if [[ ${OSTYPE} == "darwin"* ]]; then return 0; else return 1; fi }
|
|
# checks whether teleport is already running on the host
|
|
is_running_teleport() {
|
|
check_exists_fatal pgrep
|
|
TELEPORT_PID=$(get_teleport_pid)
|
|
if [[ "${TELEPORT_PID}" != "" ]]; then return 0; else return 1; fi
|
|
}
|
|
# checks whether the given host is running systemd as its init system
|
|
is_using_systemd() { if [ -d /run/systemd/system ]; then return 0; else return 1; fi }
|
|
# prints a warning if the host isn't running systemd
|
|
no_systemd_warning() {
|
|
log_important "This host is not running systemd, so Teleport cannot be started automatically when it exits."
|
|
log_important "Please investigate an alternative way to keep Teleport running."
|
|
log_important "You can find information in our documentation: ${TELEPORT_DOCS_URL}"
|
|
log_important "For now, Teleport will be started in the foreground - you can press Ctrl+C to exit."
|
|
log_only
|
|
log_only "Run this command to start Teleport in future:"
|
|
log_only "$(get_teleport_start_command)"
|
|
log_only
|
|
log_only "------------------------------------------------------------------------"
|
|
log_only "| IMPORTANT: TELEPORT WILL STOP RUNNING AFTER YOU CLOSE THIS TERMINAL! |"
|
|
log_only "| YOU MUST CONFIGURE A SERVICE MANAGER TO MAKE IT RUN ON STARTUP! |"
|
|
log_only "------------------------------------------------------------------------"
|
|
log_only
|
|
}
|
|
# print a message giving the name of the node and a link to the docs
|
|
# gives some debugging instructions if the service didn't start successfully
|
|
print_welcome_message() {
|
|
log_only ""
|
|
if is_running_teleport; then
|
|
log_only "Teleport has been started."
|
|
log_only ""
|
|
if is_using_systemd; then
|
|
log_only "View its status with 'sudo systemctl status teleport.service'"
|
|
log_only "View Teleport logs using 'sudo journalctl -u teleport.service'"
|
|
log_only "To stop Teleport, run 'sudo systemctl stop teleport.service'"
|
|
log_only "To start Teleport again if you stop it, run 'sudo systemctl start teleport.service'"
|
|
elif is_macos_host; then
|
|
log_only "View Teleport logs in '${MACOS_STDERR_LOG}' and '${MACOS_STDOUT_LOG}'"
|
|
log_only "To stop Teleport, run 'sudo launchctl unload ${LAUNCHD_CONFIG_PATH}/com.goteleport.teleport.plist'"
|
|
log_only "To start Teleport again if you stop it, run 'sudo launchctl load ${LAUNCHD_CONFIG_PATH}/com.goteleport.teleport.plist'"
|
|
fi
|
|
log_only ""
|
|
log_only "You can see this node connected in the Teleport web UI or 'tsh ls' with the name '${NODENAME}'"
|
|
log_only "Find more details on how to use Teleport here: https://goteleport.com/docs/user-manual/"
|
|
else
|
|
log_important "The Teleport service was installed, but it does not appear to have started successfully."
|
|
if is_using_systemd; then
|
|
log_important "Check the Teleport service's status with 'systemctl status teleport.service'"
|
|
log_important "View Teleport logs with 'journalctl -u teleport.service'"
|
|
elif is_macos_host; then
|
|
log_important "Check Teleport logs in '${MACOS_STDERR_LOG}' and '${MACOS_STDOUT_LOG}'"
|
|
fi
|
|
log_important "Contact Teleport support for further assistance."
|
|
fi
|
|
log_only ""
|
|
}
|
|
# start teleport in foreground (when there's no systemd)
|
|
start_teleport_foreground() {
|
|
log "Starting Teleport in the foreground"
|
|
# shellcheck disable=SC2091
|
|
$(get_teleport_start_command)
|
|
}
|
|
# start teleport via launchd (after installing config)
|
|
start_teleport_launchd() {
|
|
log "Starting Teleport via launchctl. It will automatically be started whenever the system reboots."
|
|
launchctl load ${LAUNCHD_CONFIG_PATH}/com.goteleport.teleport.plist
|
|
sleep ${ALIVE_CHECK_DELAY}
|
|
}
|
|
# start teleport via systemd (after installing unit)
|
|
start_teleport_systemd() {
|
|
log "Starting Teleport via systemd. It will automatically be started whenever the system reboots."
|
|
systemctl enable teleport.service
|
|
systemctl start teleport.service
|
|
sleep ${ALIVE_CHECK_DELAY}
|
|
}
|
|
# checks whether teleport binaries exist on the host
|
|
teleport_binaries_exist() {
|
|
for BINARY_NAME in teleport tctl tsh; do
|
|
if [ -f ${TELEPORT_BINARY_DIR}/${BINARY_NAME} ]; then return 0; else return 1; fi
|
|
done
|
|
}
|
|
# checks whether a teleport config exists on the host
|
|
teleport_config_exists() { if [ -f ${TELEPORT_CONFIG_PATH} ]; then return 0; else return 1; fi; }
|
|
# checks whether a teleport data dir exists on the host
|
|
teleport_datadir_exists() { if [ -d ${TELEPORT_DATA_DIR} ]; then return 0; else return 1; fi; }
|
|
|
|
# error out if any required values are not set
|
|
check_set TELEPORT_VERSION
|
|
check_set TARGET_HOSTNAME
|
|
check_set TARGET_PORT
|
|
check_set JOIN_TOKEN
|
|
check_set CA_PIN_HASHES
|
|
if [[ "${APP_INSTALL_MODE}" == "true" ]]; then
|
|
check_set APP_NAME
|
|
check_set APP_URI
|
|
check_set APP_PUBLIC_ADDR
|
|
fi
|
|
|
|
###
|
|
# main script starts here
|
|
###
|
|
# check connectivity to teleport server/port
|
|
if [[ "${IGNORE_CONNECTIVITY_CHECK}" == "true" ]]; then
|
|
log "TELEPORT_IGNORE_CONNECTIVITY_CHECK=true, not running connectivity check"
|
|
else
|
|
log "Checking TCP connectivity to Teleport server (${TARGET_HOSTNAME}:${TARGET_PORT})"
|
|
if ! check_connectivity "${TARGET_HOSTNAME}" "${TARGET_PORT}"; then
|
|
# if we don't have a connectivity test method assigned, we know we couldn't run the test
|
|
if [[ ${CONNECTIVITY_TEST_METHOD} == "" ]]; then
|
|
log "Couldn't find nc, telnet or /dev/tcp to do a connection test"
|
|
log "Going to blindly continue without testing connectivity"
|
|
else
|
|
log_important "Couldn't open a connection to the Teleport server (${TARGET_HOSTNAME}:${TARGET_PORT}) via ${CONNECTIVITY_TEST_METHOD}"
|
|
log_important "This issue will need to be fixed before the script can continue."
|
|
log_important "If you think this is an error, add 'export TELEPORT_IGNORE_CONNECTIVITY_CHECK=true && ' before the curl command which runs the script."
|
|
exit 1
|
|
fi
|
|
else
|
|
log "Connectivity to Teleport server (via ${CONNECTIVITY_TEST_METHOD}) looks good"
|
|
fi
|
|
fi
|
|
|
|
# use OSTYPE variable to figure out host type/arch
|
|
if [[ "${OSTYPE}" == "linux-gnu"* ]]; then
|
|
# linux host, now detect arch
|
|
TELEPORT_BINARY_TYPE="linux"
|
|
ARCH=$(uname -m)
|
|
log "Detected host: ${OSTYPE}, using Teleport binary type ${TELEPORT_BINARY_TYPE}"
|
|
if [[ ${ARCH} == "armv7l" ]]; then
|
|
TELEPORT_ARCH="arm"
|
|
elif [[ ${ARCH} == "aarch64" ]]; then
|
|
TELEPORT_ARCH="arm64"
|
|
elif [[ ${ARCH} == "x86_64" ]]; then
|
|
TELEPORT_ARCH="amd64"
|
|
elif [[ ${ARCH} == "i686" ]]; then
|
|
TELEPORT_ARCH="386"
|
|
else
|
|
log_important "Error: cannot detect architecture from uname -m: ${ARCH}"
|
|
exit 1
|
|
fi
|
|
log "Detected arch: ${ARCH}, using Teleport arch ${TELEPORT_ARCH}"
|
|
# if the download format is already set, we have no need to detect distro
|
|
if [[ ${TELEPORT_FORMAT} == "" ]]; then
|
|
# detect distro
|
|
# if /etc/os-release doesn't exist, we need to use some other logic
|
|
if [ ! -f /etc/os-release ]; then
|
|
if [ -f /etc/centos-release ]; then
|
|
if grep -q 'CentOS release 6' /etc/centos-release; then
|
|
DISTRO_TYPE="centos6"
|
|
TELEPORT_FORMAT="rpm-centos6"
|
|
fi
|
|
elif [ -f /etc/redhat-release ]; then
|
|
if grep -q 'Red Hat Enterprise Linux Server release 5' /etc/redhat-release; then
|
|
log_important "Detected host type: RHEL5 [$(cat /etc/redhat-release)]"
|
|
log_important "Teleport will not work on RHEL5-based servers due to the glibc version being too low."
|
|
exit 1
|
|
elif grep -q 'Red Hat Enterprise Linux Server release 6' /etc/redhat-release; then
|
|
DISTRO_TYPE="redhat"
|
|
TELEPORT_FORMAT="rpm-centos6"
|
|
log "Detected host type: RHEL6 [$(cat /etc/redhat-release)]"
|
|
fi
|
|
fi
|
|
# use ID_LIKE value from /etc/os-release (if set)
|
|
# this is 'debian' on ubuntu/raspbian, 'centos rhel fedora' on amazon linux etc
|
|
else
|
|
check_exists_fatal cut
|
|
DISTRO_TYPE=$(grep ID_LIKE /etc/os-release | cut -d= -f2) || true
|
|
if [[ ${DISTRO_TYPE} == "" ]]; then
|
|
# use exact ID value from /etc/os-release if ID_LIKE is not set
|
|
DISTRO_TYPE=$(grep -w ID /etc/os-release | cut -d= -f2)
|
|
fi
|
|
if [[ ${DISTRO_TYPE} =~ "debian" ]]; then
|
|
TELEPORT_FORMAT="deb"
|
|
elif [[ ${DISTRO_TYPE} =~ "centos"* ]] || [[ ${DISTRO_TYPE} =~ "rhel" ]] || [[ ${DISTRO_TYPE} =~ "fedora"* ]]; then
|
|
TELEPORT_FORMAT="rpm"
|
|
else
|
|
log "Couldn't match a distro type using /etc/os-release, falling back to tarball installer"
|
|
TELEPORT_FORMAT="tarball"
|
|
fi
|
|
fi
|
|
log "Detected distro type: ${DISTRO_TYPE}"
|
|
#suse, also identified as sles, uses a different path for its systemd then other distro types like ubuntu
|
|
if [[ ${DISTRO_TYPE} =~ "suse"* ]] || [[ ${DISTRO_TYPE} =~ "sles"* ]]; then
|
|
SYSTEMD_UNIT_PATH="/etc/systemd/system/teleport.service"
|
|
fi
|
|
fi
|
|
elif [[ "${OSTYPE}" == "darwin"* ]]; then
|
|
# macos host, now detect arch
|
|
TELEPORT_BINARY_TYPE="darwin"
|
|
ARCH=$(uname -m)
|
|
log "Detected host: ${OSTYPE}, using Teleport binary type ${TELEPORT_BINARY_TYPE}"
|
|
if [[ ${ARCH} == "aarch64" || ${ARCH} == "arm64" ]]; then
|
|
TELEPORT_ARCH="arm64"
|
|
log_important "Error: detected ${ARCH} but Teleport doesn't build binaries for this architecture yet, exiting"
|
|
exit 1
|
|
elif [[ ${ARCH} == "x86_64" ]]; then
|
|
TELEPORT_ARCH="amd64"
|
|
else
|
|
log_important "Error: unsupported architecture from uname -m: ${ARCH}"
|
|
exit 1
|
|
fi
|
|
log "Detected MacOS ${ARCH} architecture, using Teleport arch ${TELEPORT_ARCH}"
|
|
TELEPORT_FORMAT="tarball"
|
|
else
|
|
log_important "Error - unsupported platform: ${OSTYPE}"
|
|
exit 1
|
|
fi
|
|
log "Using Teleport distribution: ${TELEPORT_FORMAT}"
|
|
|
|
# create temporary directory and exit cleanup logic
|
|
TEMP_DIR=$(mktemp -d -t teleport-XXXXXXXXXX)
|
|
log "Created temp dir ${TEMP_DIR}"
|
|
pushd "${TEMP_DIR}" >/dev/null 2>&1
|
|
|
|
finish() {
|
|
popd >/dev/null 2>&1
|
|
rm -rf "${TEMP_DIR}"
|
|
}
|
|
trap finish EXIT
|
|
|
|
# optional format override (mostly for testing)
|
|
if [[ ${OVERRIDE_FORMAT} != "" ]]; then
|
|
TELEPORT_FORMAT="${OVERRIDE_FORMAT}"
|
|
log "Overriding TELEPORT_FORMAT to ${OVERRIDE_FORMAT}"
|
|
fi
|
|
|
|
# check whether teleport is running already
|
|
# if it is, we exit gracefully with an error
|
|
if is_running_teleport; then
|
|
if [[ ${IGNORE_CHECKS} != "true" ]]; then
|
|
TELEPORT_PID=$(get_teleport_pid)
|
|
log_header "Warning: Teleport appears to already be running on this host (pid: ${TELEPORT_PID})"
|
|
log_cleanup_message
|
|
exit 1
|
|
else
|
|
log "Ignoring is_running_teleport as requested"
|
|
fi
|
|
fi
|
|
|
|
# check for existing config file
|
|
if teleport_config_exists; then
|
|
if [[ ${IGNORE_CHECKS} != "true" ]]; then
|
|
log_header "Warning: There is already a Teleport config file present at ${TELEPORT_CONFIG_PATH}."
|
|
log_cleanup_message
|
|
exit 1
|
|
else
|
|
log "Ignoring teleport_config_exists as requested"
|
|
fi
|
|
fi
|
|
|
|
# check for existing data directory
|
|
if teleport_datadir_exists; then
|
|
if [[ ${IGNORE_CHECKS} != "true" ]]; then
|
|
log_header "Warning: Found existing Teleport data directory (${TELEPORT_DATA_DIR})."
|
|
log_cleanup_message
|
|
exit 1
|
|
else
|
|
log "Ignoring teleport_datadir_exists as requested"
|
|
fi
|
|
fi
|
|
|
|
# check for existing binaries
|
|
if teleport_binaries_exist; then
|
|
if [[ ${IGNORE_CHECKS} != "true" ]]; then
|
|
log_header "Warning: Found existing Teleport binaries under ${TELEPORT_BINARY_DIR}."
|
|
log_cleanup_message
|
|
exit 1
|
|
else
|
|
log "Ignoring teleport_binaries_exist as requested"
|
|
fi
|
|
fi
|
|
|
|
# handle centos6 installations
|
|
if [[ ${TELEPORT_FORMAT} == "rpm-centos6" ]]; then
|
|
# Error if arch != amd64, as we don't have CentOS 6 packages for any other arch
|
|
if [[ ${TELEPORT_ARCH} != "amd64" ]]; then
|
|
log_important "Your distro appears to be CentOS/RHEL 6 and your arch is ${ARCH}."
|
|
log_important "Teleport only produces amd64 binaries for CentOS 6, so this script cannot install Teleport on this host."
|
|
log_important "Contact Teleport support for further assistance."
|
|
exit 1
|
|
fi
|
|
# override the format to 'tarball' (as that's how centos6 binaries are packaged)
|
|
# also override DISTRO_TYPE to centos6 as that's used for the URL check below
|
|
log "Overriding format for centos6 installation to use tarball"
|
|
TELEPORT_FORMAT="tarball"
|
|
DISTRO_TYPE="centos6"
|
|
fi
|
|
|
|
# select correct URL/installation method based on distro
|
|
if [[ ${TELEPORT_FORMAT} == "tarball" ]]; then
|
|
# handle centos6 URL override
|
|
if [[ ${DISTRO_TYPE} == "centos6" ]]; then
|
|
URL="https://get.gravitational.com/teleport-v${TELEPORT_VERSION}-${TELEPORT_BINARY_TYPE}-${TELEPORT_ARCH}-centos6-bin.tar.gz"
|
|
else
|
|
URL="https://get.gravitational.com/teleport-v${TELEPORT_VERSION}-${TELEPORT_BINARY_TYPE}-${TELEPORT_ARCH}-bin.tar.gz"
|
|
fi
|
|
# check that needed tools are installed
|
|
check_exists_fatal curl tar
|
|
# download tarball
|
|
log "Downloading Teleport ${TELEPORT_FORMAT} release ${TELEPORT_VERSION}"
|
|
DOWNLOAD_FILENAME=$(get_download_filename "${URL}")
|
|
download "${URL}" "${TEMP_DIR}/${DOWNLOAD_FILENAME}"
|
|
# extract tarball
|
|
tar -xzf "${TEMP_DIR}/${DOWNLOAD_FILENAME}" -C "${TEMP_DIR}"
|
|
# install binaries to /usr/local/bin
|
|
for BINARY in ${TELEPORT_BINARY_LIST}; do
|
|
${COPY_COMMAND} "${TELEPORT_ARCHIVE_PATH}/${BINARY}" "${TELEPORT_BINARY_DIR}/"
|
|
done
|
|
elif [[ ${TELEPORT_FORMAT} == "deb" ]]; then
|
|
# convert teleport arch to deb arch
|
|
if [[ ${TELEPORT_ARCH} == "amd64" ]]; then
|
|
DEB_ARCH="amd64"
|
|
elif [[ ${TELEPORT_ARCH} == "386" ]]; then
|
|
DEB_ARCH="i386"
|
|
elif [[ ${TELEPORT_ARCH} == "arm" ]]; then
|
|
DEB_ARCH="arm"
|
|
elif [[ ${TELEPORT_ARCH} == "arm64" ]]; then
|
|
DEB_ARCH="arm64"
|
|
fi
|
|
URL="https://get.gravitational.com/teleport_${TELEPORT_VERSION}_${DEB_ARCH}.deb"
|
|
check_deb_not_already_installed
|
|
# check that needed tools are installed
|
|
check_exists_fatal curl dpkg
|
|
# download deb and register cleanup operation
|
|
log "Downloading Teleport ${TELEPORT_FORMAT} release ${TELEPORT_VERSION}"
|
|
DOWNLOAD_FILENAME=$(get_download_filename "${URL}")
|
|
download "${URL}" "${TEMP_DIR}/${DOWNLOAD_FILENAME}"
|
|
# install deb
|
|
log "Using dpkg to install ${TEMP_DIR}/${DOWNLOAD_FILENAME}"
|
|
dpkg -i "${TEMP_DIR}/${DOWNLOAD_FILENAME}"
|
|
elif [[ ${TELEPORT_FORMAT} == "rpm" ]]; then
|
|
# convert teleport arch to rpm arch
|
|
if [[ ${TELEPORT_ARCH} == "amd64" ]]; then
|
|
RPM_ARCH="x86_64"
|
|
elif [[ ${TELEPORT_ARCH} == "386" ]]; then
|
|
RPM_ARCH="i386"
|
|
elif [[ ${TELEPORT_ARCH} == "arm" ]]; then
|
|
RPM_ARCH="arm"
|
|
elif [[ ${TELEPORT_ARCH} == "arm64" ]]; then
|
|
RPM_ARCH="arm64"
|
|
fi
|
|
URL="https://get.gravitational.com/teleport-${TELEPORT_VERSION}-1.${RPM_ARCH}.rpm"
|
|
check_rpm_not_already_installed
|
|
# check for package managers
|
|
if check_exists dnf; then
|
|
log "Found 'dnf' package manager, using it"
|
|
PACKAGE_MANAGER_COMMAND="dnf -y install"
|
|
elif check_exists yum; then
|
|
log "Found 'yum' package manager, using it"
|
|
PACKAGE_MANAGER_COMMAND="yum -y localinstall"
|
|
else
|
|
PACKAGE_MANAGER_COMMAND=""
|
|
log "Cannot find 'yum' or 'dnf' package manager commands, will try installing the rpm manually instead"
|
|
fi
|
|
# check that needed tools are installed
|
|
check_exists_fatal curl
|
|
log "Downloading Teleport ${TELEPORT_FORMAT} release ${TELEPORT_VERSION}"
|
|
DOWNLOAD_FILENAME=$(get_download_filename "${URL}")
|
|
download "${URL}" "${TEMP_DIR}/${DOWNLOAD_FILENAME}"
|
|
# install with package manager if available
|
|
if [[ ${PACKAGE_MANAGER_COMMAND} != "" ]]; then
|
|
log "Installing Teleport release from ${TEMP_DIR}/${DOWNLOAD_FILENAME} using ${PACKAGE_MANAGER_COMMAND}"
|
|
# install rpm with package manager
|
|
${PACKAGE_MANAGER_COMMAND} "${TEMP_DIR}/${DOWNLOAD_FILENAME}"
|
|
# use rpm if we couldn't find a package manager
|
|
else
|
|
# install RPM (in upgrade mode)
|
|
log "Using rpm to install ${TEMP_DIR}/${DOWNLOAD_FILENAME}"
|
|
rpm -Uvh "${TEMP_DIR}/${DOWNLOAD_FILENAME}"
|
|
fi
|
|
else
|
|
log_important "Can't figure out what Teleport format to use"
|
|
exit 1
|
|
fi
|
|
|
|
# check that teleport binary can be found and runs
|
|
if ! check_teleport_binary; then
|
|
log_important "The Teleport binary could not be found at ${TELEPORT_BINARY_DIR} as expected."
|
|
log_important "This usually means that there was an error during installation."
|
|
log_important "Check this log for obvious signs of error and contact Teleport support"
|
|
log_important "for further assistance."
|
|
exit 1
|
|
fi
|
|
|
|
# install teleport config
|
|
# check the mode and write the appropriate config type
|
|
if [[ "${APP_INSTALL_MODE}" == "true" ]]; then
|
|
install_teleport_app_config
|
|
elif [[ "${DB_INSTALL_MODE}" == "true" ]]; then
|
|
install_teleport_database_config
|
|
else
|
|
install_teleport_node_config
|
|
fi
|
|
|
|
# install systemd unit if applicable (linux hosts)
|
|
if is_using_systemd; then
|
|
log "Host is using systemd"
|
|
# we only need to manually install the systemd config if teleport was installed via tarball
|
|
# all other packages will deploy it automatically
|
|
if [[ ${TELEPORT_FORMAT} == "tarball" ]]; then
|
|
install_systemd_unit
|
|
fi
|
|
start_teleport_systemd
|
|
print_welcome_message
|
|
# install launchd config on MacOS hosts
|
|
elif is_macos_host; then
|
|
log "Host is running MacOS"
|
|
install_launchd_config
|
|
start_teleport_launchd
|
|
print_welcome_message
|
|
# not a MacOS host and no systemd available, print a warning
|
|
# and temporarily start Teleport in the foreground
|
|
else
|
|
log "Host does not appear to be using systemd"
|
|
no_systemd_warning
|
|
start_teleport_foreground
|
|
fi
|