| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- #!/usr/bin/env bash
- # Copyright The Helm Authors.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- # The install script is based off of the MIT-licensed script from glide,
- # the package manager for Go: https://github.com/Masterminds/glide.sh/blob/master/get
- : ${BINARY_NAME:="helm"}
- : ${USE_SUDO:="true"}
- : ${DEBUG:="false"}
- : ${VERIFY_CHECKSUM:="true"}
- : ${VERIFY_SIGNATURES:="false"}
- : ${HELM_INSTALL_DIR:="/usr/local/bin"}
- : ${GPG_PUBRING:="pubring.kbx"}
- HAS_CURL="$(type "curl" &> /dev/null && echo true || echo false)"
- HAS_WGET="$(type "wget" &> /dev/null && echo true || echo false)"
- HAS_OPENSSL="$(type "openssl" &> /dev/null && echo true || echo false)"
- HAS_GPG="$(type "gpg" &> /dev/null && echo true || echo false)"
- HAS_GIT="$(type "git" &> /dev/null && echo true || echo false)"
- HAS_TAR="$(type "tar" &> /dev/null && echo true || echo false)"
- # initArch discovers the architecture for this system.
- initArch() {
- ARCH=$(uname -m)
- case $ARCH in
- armv5*) ARCH="armv5";;
- armv6*) ARCH="armv6";;
- armv7*) ARCH="arm";;
- aarch64) ARCH="arm64";;
- x86) ARCH="386";;
- x86_64) ARCH="amd64";;
- i686) ARCH="386";;
- i386) ARCH="386";;
- esac
- }
- # initOS discovers the operating system for this system.
- initOS() {
- OS=$(echo `uname`|tr '[:upper:]' '[:lower:]')
- case "$OS" in
- # Minimalist GNU for Windows
- mingw*|cygwin*) OS='windows';;
- esac
- }
- # runs the given command as root (detects if we are root already)
- runAsRoot() {
- if [ $EUID -ne 0 -a "$USE_SUDO" = "true" ]; then
- sudo "${@}"
- else
- "${@}"
- fi
- }
- # verifySupported checks that the os/arch combination is supported for
- # binary builds, as well whether or not necessary tools are present.
- verifySupported() {
- local supported="darwin-amd64\ndarwin-arm64\nlinux-386\nlinux-amd64\nlinux-arm\nlinux-arm64\nlinux-loong64\nlinux-ppc64le\nlinux-s390x\nlinux-riscv64\nwindows-amd64\nwindows-arm64"
- if ! echo "${supported}" | grep -q "${OS}-${ARCH}"; then
- echo "No prebuilt binary for ${OS}-${ARCH}."
- echo "To build from source, go to https://github.com/helm/helm"
- exit 1
- fi
- if [ "${HAS_CURL}" != "true" ] && [ "${HAS_WGET}" != "true" ]; then
- echo "Either curl or wget is required"
- exit 1
- fi
- if [ "${VERIFY_CHECKSUM}" == "true" ] && [ "${HAS_OPENSSL}" != "true" ]; then
- echo "In order to verify checksum, openssl must first be installed."
- echo "Please install openssl or set VERIFY_CHECKSUM=false in your environment."
- exit 1
- fi
- if [ "${VERIFY_SIGNATURES}" == "true" ]; then
- if [ "${HAS_GPG}" != "true" ]; then
- echo "In order to verify signatures, gpg must first be installed."
- echo "Please install gpg or set VERIFY_SIGNATURES=false in your environment."
- exit 1
- fi
- if [ "${OS}" != "linux" ]; then
- echo "Signature verification is currently only supported on Linux."
- echo "Please set VERIFY_SIGNATURES=false or verify the signatures manually."
- exit 1
- fi
- fi
- if [ "${HAS_GIT}" != "true" ]; then
- echo "[WARNING] Could not find git. It is required for plugin installation."
- fi
- if [ "${HAS_TAR}" != "true" ]; then
- echo "[ERROR] Could not find tar. It is required to extract the helm binary archive."
- exit 1
- fi
- }
- # checkDesiredVersion checks if the desired version is available.
- checkDesiredVersion() {
- if [ "x$DESIRED_VERSION" == "x" ]; then
- # Get tag from release URL
- local latest_release_url="https://get.helm.sh/helm4-latest-version"
- local latest_release_response=""
- if [ "${HAS_CURL}" == "true" ]; then
- latest_release_response=$( curl -L --silent --show-error --fail "$latest_release_url" 2>&1 || true )
- elif [ "${HAS_WGET}" == "true" ]; then
- latest_release_response=$( wget "$latest_release_url" -q -O - 2>&1 || true )
- fi
- TAG=$( echo "$latest_release_response" | grep '^v[0-9]' )
- if [ "x$TAG" == "x" ]; then
- printf "Could not retrieve the latest release tag information from %s: %s\n" "${latest_release_url}" "${latest_release_response}"
- exit 1
- fi
- else
- TAG=$DESIRED_VERSION
- fi
- }
- # checkHelmInstalledVersion checks which version of helm is installed and
- # if it needs to be changed.
- checkHelmInstalledVersion() {
- if [[ -f "${HELM_INSTALL_DIR}/${BINARY_NAME}" ]]; then
- local version=$("${HELM_INSTALL_DIR}/${BINARY_NAME}" version --template="{{ .Version }}")
- if [[ "$version" == "$TAG" ]]; then
- echo "Helm ${version} is already ${DESIRED_VERSION:-latest}"
- return 0
- else
- echo "Helm ${TAG} is available. Changing from version ${version}."
- return 1
- fi
- else
- return 1
- fi
- }
- # downloadFile downloads the latest binary package and also the checksum
- # for that binary.
- downloadFile() {
- HELM_DIST="helm-$TAG-$OS-$ARCH.tar.gz"
- DOWNLOAD_URL="https://get.helm.sh/$HELM_DIST"
- CHECKSUM_URL="$DOWNLOAD_URL.sha256"
- HELM_TMP_ROOT="$(mktemp -dt helm-installer-XXXXXX)"
- HELM_TMP_FILE="$HELM_TMP_ROOT/$HELM_DIST"
- HELM_SUM_FILE="$HELM_TMP_ROOT/$HELM_DIST.sha256"
- echo "Downloading $DOWNLOAD_URL"
- if [ "${HAS_CURL}" == "true" ]; then
- curl -SsL "$CHECKSUM_URL" -o "$HELM_SUM_FILE"
- curl -SsL "$DOWNLOAD_URL" -o "$HELM_TMP_FILE"
- elif [ "${HAS_WGET}" == "true" ]; then
- wget -q -O "$HELM_SUM_FILE" "$CHECKSUM_URL"
- wget -q -O "$HELM_TMP_FILE" "$DOWNLOAD_URL"
- fi
- }
- # verifyFile verifies the SHA256 checksum of the binary package
- # and the GPG signatures for both the package and checksum file
- # (depending on settings in environment).
- verifyFile() {
- if [ "${VERIFY_CHECKSUM}" == "true" ]; then
- verifyChecksum
- fi
- if [ "${VERIFY_SIGNATURES}" == "true" ]; then
- verifySignatures
- fi
- }
- # installFile installs the Helm binary.
- installFile() {
- HELM_TMP="$HELM_TMP_ROOT/$BINARY_NAME"
- mkdir -p "$HELM_TMP"
- tar xf "$HELM_TMP_FILE" -C "$HELM_TMP"
- HELM_TMP_BIN="$HELM_TMP/$OS-$ARCH/helm"
- echo "Preparing to install $BINARY_NAME into ${HELM_INSTALL_DIR}"
- runAsRoot cp "$HELM_TMP_BIN" "$HELM_INSTALL_DIR/$BINARY_NAME"
- echo "$BINARY_NAME installed into $HELM_INSTALL_DIR/$BINARY_NAME"
- }
- # verifyChecksum verifies the SHA256 checksum of the binary package.
- verifyChecksum() {
- printf "Verifying checksum... "
- local sum=$(openssl sha1 -sha256 ${HELM_TMP_FILE} | awk '{print $2}')
- local expected_sum=$(cat ${HELM_SUM_FILE})
- if [ "$sum" != "$expected_sum" ]; then
- echo "SHA sum of ${HELM_TMP_FILE} does not match. Aborting."
- exit 1
- fi
- echo "Done."
- }
- # verifySignatures obtains the latest KEYS file from GitHub main branch
- # as well as the signature .asc files from the specific GitHub release,
- # then verifies that the release artifacts were signed by a maintainer's key.
- verifySignatures() {
- printf "Verifying signatures... "
- local keys_filename="KEYS"
- local github_keys_url="https://raw.githubusercontent.com/helm/helm/main/${keys_filename}"
- if [ "${HAS_CURL}" == "true" ]; then
- curl -SsL "${github_keys_url}" -o "${HELM_TMP_ROOT}/${keys_filename}"
- elif [ "${HAS_WGET}" == "true" ]; then
- wget -q -O "${HELM_TMP_ROOT}/${keys_filename}" "${github_keys_url}"
- fi
- local gpg_keyring="${HELM_TMP_ROOT}/keyring.gpg"
- local gpg_homedir="${HELM_TMP_ROOT}/gnupg"
- mkdir -p -m 0700 "${gpg_homedir}"
- local gpg_stderr_device="/dev/null"
- if [ "${DEBUG}" == "true" ]; then
- gpg_stderr_device="/dev/stderr"
- fi
- gpg --batch --quiet --homedir="${gpg_homedir}" --import "${HELM_TMP_ROOT}/${keys_filename}" 2> "${gpg_stderr_device}"
- gpg --batch --no-default-keyring --keyring "${gpg_homedir}/${GPG_PUBRING}" --export > "${gpg_keyring}"
- local github_release_url="https://github.com/helm/helm/releases/download/${TAG}"
- if [ "${HAS_CURL}" == "true" ]; then
- curl -SsL "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" -o "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc"
- curl -SsL "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" -o "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc"
- elif [ "${HAS_WGET}" == "true" ]; then
- wget -q -O "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc"
- wget -q -O "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc"
- fi
- local error_text="If you think this might be a potential security issue,"
- error_text="${error_text}\nplease see here: https://github.com/helm/community/blob/master/SECURITY.md"
- local num_goodlines_sha=$(gpg --verify --keyring="${gpg_keyring}" --status-fd=1 "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" 2> "${gpg_stderr_device}" | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
- if [[ ${num_goodlines_sha} -lt 2 ]]; then
- echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256!"
- echo -e "${error_text}"
- exit 1
- fi
- local num_goodlines_tar=$(gpg --verify --keyring="${gpg_keyring}" --status-fd=1 "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" 2> "${gpg_stderr_device}" | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
- if [[ ${num_goodlines_tar} -lt 2 ]]; then
- echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz!"
- echo -e "${error_text}"
- exit 1
- fi
- echo "Done."
- }
- # fail_trap is executed if an error occurs.
- fail_trap() {
- result=$?
- if [ "$result" != "0" ]; then
- if [[ -n "$INPUT_ARGUMENTS" ]]; then
- echo "Failed to install $BINARY_NAME with the arguments provided: $INPUT_ARGUMENTS"
- help
- else
- echo "Failed to install $BINARY_NAME"
- fi
- echo -e "\tFor support, go to https://github.com/helm/helm."
- fi
- cleanup
- exit $result
- }
- # testVersion tests the installed client to make sure it is working.
- testVersion() {
- set +e
- HELM="$(command -v $BINARY_NAME)"
- if [ "$?" = "1" ]; then
- echo "$BINARY_NAME not found. Is $HELM_INSTALL_DIR on your "'$PATH?'
- exit 1
- fi
- set -e
- }
- # help provides possible cli installation arguments
- help () {
- echo "Accepted cli arguments are:"
- echo -e "\t[--help|-h ] ->> prints this help"
- echo -e "\t[--version|-v <desired_version>] . When not defined it fetches the latest release tag from the Helm CDN"
- echo -e "\te.g. --version v4.0.0 or -v canary"
- echo -e "\t[--no-sudo] ->> install without sudo"
- }
- # cleanup temporary files to avoid https://github.com/helm/helm/issues/2977
- cleanup() {
- if [[ -d "${HELM_TMP_ROOT:-}" ]]; then
- rm -rf "$HELM_TMP_ROOT"
- fi
- }
- # Execution
- #Stop execution on any error
- trap "fail_trap" EXIT
- set -e
- # Set debug if desired
- if [ "${DEBUG}" == "true" ]; then
- set -x
- fi
- # Parsing input arguments (if any)
- export INPUT_ARGUMENTS="${@}"
- set -u
- while [[ $# -gt 0 ]]; do
- case $1 in
- '--version'|-v)
- shift
- if [[ $# -ne 0 ]]; then
- export DESIRED_VERSION="${1}"
- if [[ "$1" != "v"* ]]; then
- echo "Expected version arg ('${DESIRED_VERSION}') to begin with 'v', fixing..."
- export DESIRED_VERSION="v${1}"
- fi
- else
- echo -e "Please provide the desired version. e.g. --version v4.0.0 or -v canary"
- exit 0
- fi
- ;;
- '--no-sudo')
- USE_SUDO="false"
- ;;
- '--help'|-h)
- help
- exit 0
- ;;
- *) exit 1
- ;;
- esac
- shift
- done
- set +u
- initArch
- initOS
- verifySupported
- checkDesiredVersion
- if ! checkHelmInstalledVersion; then
- downloadFile
- verifyFile
- installFile
- fi
- testVersion
- cleanup
|