github.com/stefanmcshane/helm@v0.0.0-20221213002717-88a4a2c6e77d/scripts/get-helm-3 (about) 1 #!/usr/bin/env bash 2 3 # Copyright The Helm Authors. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 # The install script is based off of the MIT-licensed script from glide, 18 # the package manager for Go: https://github.com/Masterminds/glide.sh/blob/master/get 19 20 : ${BINARY_NAME:="helm"} 21 : ${USE_SUDO:="true"} 22 : ${DEBUG:="false"} 23 : ${VERIFY_CHECKSUM:="true"} 24 : ${VERIFY_SIGNATURES:="false"} 25 : ${HELM_INSTALL_DIR:="/usr/local/bin"} 26 : ${GPG_PUBRING:="pubring.kbx"} 27 28 HAS_CURL="$(type "curl" &> /dev/null && echo true || echo false)" 29 HAS_WGET="$(type "wget" &> /dev/null && echo true || echo false)" 30 HAS_OPENSSL="$(type "openssl" &> /dev/null && echo true || echo false)" 31 HAS_GPG="$(type "gpg" &> /dev/null && echo true || echo false)" 32 HAS_GIT="$(type "git" &> /dev/null && echo true || echo false)" 33 34 # initArch discovers the architecture for this system. 35 initArch() { 36 ARCH=$(uname -m) 37 case $ARCH in 38 armv5*) ARCH="armv5";; 39 armv6*) ARCH="armv6";; 40 armv7*) ARCH="arm";; 41 aarch64) ARCH="arm64";; 42 x86) ARCH="386";; 43 x86_64) ARCH="amd64";; 44 i686) ARCH="386";; 45 i386) ARCH="386";; 46 esac 47 } 48 49 # initOS discovers the operating system for this system. 50 initOS() { 51 OS=$(echo `uname`|tr '[:upper:]' '[:lower:]') 52 53 case "$OS" in 54 # Minimalist GNU for Windows 55 mingw*|cygwin*) OS='windows';; 56 esac 57 } 58 59 # runs the given command as root (detects if we are root already) 60 runAsRoot() { 61 if [ $EUID -ne 0 -a "$USE_SUDO" = "true" ]; then 62 sudo "${@}" 63 else 64 "${@}" 65 fi 66 } 67 68 # verifySupported checks that the os/arch combination is supported for 69 # binary builds, as well whether or not necessary tools are present. 70 verifySupported() { 71 local supported="darwin-amd64\ndarwin-arm64\nlinux-386\nlinux-amd64\nlinux-arm\nlinux-arm64\nlinux-ppc64le\nlinux-s390x\nwindows-amd64" 72 if ! echo "${supported}" | grep -q "${OS}-${ARCH}"; then 73 echo "No prebuilt binary for ${OS}-${ARCH}." 74 echo "To build from source, go to https://github.com/helm/helm" 75 exit 1 76 fi 77 78 if [ "${HAS_CURL}" != "true" ] && [ "${HAS_WGET}" != "true" ]; then 79 echo "Either curl or wget is required" 80 exit 1 81 fi 82 83 if [ "${VERIFY_CHECKSUM}" == "true" ] && [ "${HAS_OPENSSL}" != "true" ]; then 84 echo "In order to verify checksum, openssl must first be installed." 85 echo "Please install openssl or set VERIFY_CHECKSUM=false in your environment." 86 exit 1 87 fi 88 89 if [ "${VERIFY_SIGNATURES}" == "true" ]; then 90 if [ "${HAS_GPG}" != "true" ]; then 91 echo "In order to verify signatures, gpg must first be installed." 92 echo "Please install gpg or set VERIFY_SIGNATURES=false in your environment." 93 exit 1 94 fi 95 if [ "${OS}" != "linux" ]; then 96 echo "Signature verification is currently only supported on Linux." 97 echo "Please set VERIFY_SIGNATURES=false or verify the signatures manually." 98 exit 1 99 fi 100 fi 101 102 if [ "${HAS_GIT}" != "true" ]; then 103 echo "[WARNING] Could not find git. It is required for plugin installation." 104 fi 105 } 106 107 # checkDesiredVersion checks if the desired version is available. 108 checkDesiredVersion() { 109 if [ "x$DESIRED_VERSION" == "x" ]; then 110 # Get tag from release URL 111 local latest_release_url="https://github.com/helm/helm/releases" 112 if [ "${HAS_CURL}" == "true" ]; then 113 TAG=$(curl -Ls $latest_release_url | grep 'href="/helm/helm/releases/tag/v3.[0-9]*.[0-9]*\"' | sed -E 's/.*\/helm\/helm\/releases\/tag\/(v[0-9\.]+)".*/\1/g' | head -1) 114 elif [ "${HAS_WGET}" == "true" ]; then 115 TAG=$(wget $latest_release_url -O - 2>&1 | grep 'href="/helm/helm/releases/tag/v3.[0-9]*.[0-9]*\"' | sed -E 's/.*\/helm\/helm\/releases\/tag\/(v[0-9\.]+)".*/\1/g' | head -1) 116 fi 117 else 118 TAG=$DESIRED_VERSION 119 fi 120 } 121 122 # checkHelmInstalledVersion checks which version of helm is installed and 123 # if it needs to be changed. 124 checkHelmInstalledVersion() { 125 if [[ -f "${HELM_INSTALL_DIR}/${BINARY_NAME}" ]]; then 126 local version=$("${HELM_INSTALL_DIR}/${BINARY_NAME}" version --template="{{ .Version }}") 127 if [[ "$version" == "$TAG" ]]; then 128 echo "Helm ${version} is already ${DESIRED_VERSION:-latest}" 129 return 0 130 else 131 echo "Helm ${TAG} is available. Changing from version ${version}." 132 return 1 133 fi 134 else 135 return 1 136 fi 137 } 138 139 # downloadFile downloads the latest binary package and also the checksum 140 # for that binary. 141 downloadFile() { 142 HELM_DIST="helm-$TAG-$OS-$ARCH.tar.gz" 143 DOWNLOAD_URL="https://get.helm.sh/$HELM_DIST" 144 CHECKSUM_URL="$DOWNLOAD_URL.sha256" 145 HELM_TMP_ROOT="$(mktemp -dt helm-installer-XXXXXX)" 146 HELM_TMP_FILE="$HELM_TMP_ROOT/$HELM_DIST" 147 HELM_SUM_FILE="$HELM_TMP_ROOT/$HELM_DIST.sha256" 148 echo "Downloading $DOWNLOAD_URL" 149 if [ "${HAS_CURL}" == "true" ]; then 150 curl -SsL "$CHECKSUM_URL" -o "$HELM_SUM_FILE" 151 curl -SsL "$DOWNLOAD_URL" -o "$HELM_TMP_FILE" 152 elif [ "${HAS_WGET}" == "true" ]; then 153 wget -q -O "$HELM_SUM_FILE" "$CHECKSUM_URL" 154 wget -q -O "$HELM_TMP_FILE" "$DOWNLOAD_URL" 155 fi 156 } 157 158 # verifyFile verifies the SHA256 checksum of the binary package 159 # and the GPG signatures for both the package and checksum file 160 # (depending on settings in environment). 161 verifyFile() { 162 if [ "${VERIFY_CHECKSUM}" == "true" ]; then 163 verifyChecksum 164 fi 165 if [ "${VERIFY_SIGNATURES}" == "true" ]; then 166 verifySignatures 167 fi 168 } 169 170 # installFile installs the Helm binary. 171 installFile() { 172 HELM_TMP="$HELM_TMP_ROOT/$BINARY_NAME" 173 mkdir -p "$HELM_TMP" 174 tar xf "$HELM_TMP_FILE" -C "$HELM_TMP" 175 HELM_TMP_BIN="$HELM_TMP/$OS-$ARCH/helm" 176 echo "Preparing to install $BINARY_NAME into ${HELM_INSTALL_DIR}" 177 runAsRoot cp "$HELM_TMP_BIN" "$HELM_INSTALL_DIR/$BINARY_NAME" 178 echo "$BINARY_NAME installed into $HELM_INSTALL_DIR/$BINARY_NAME" 179 } 180 181 # verifyChecksum verifies the SHA256 checksum of the binary package. 182 verifyChecksum() { 183 printf "Verifying checksum... " 184 local sum=$(openssl sha1 -sha256 ${HELM_TMP_FILE} | awk '{print $2}') 185 local expected_sum=$(cat ${HELM_SUM_FILE}) 186 if [ "$sum" != "$expected_sum" ]; then 187 echo "SHA sum of ${HELM_TMP_FILE} does not match. Aborting." 188 exit 1 189 fi 190 echo "Done." 191 } 192 193 # verifySignatures obtains the latest KEYS file from GitHub main branch 194 # as well as the signature .asc files from the specific GitHub release, 195 # then verifies that the release artifacts were signed by a maintainer's key. 196 verifySignatures() { 197 printf "Verifying signatures... " 198 local keys_filename="KEYS" 199 local github_keys_url="https://raw.githubusercontent.com/helm/helm/main/${keys_filename}" 200 if [ "${HAS_CURL}" == "true" ]; then 201 curl -SsL "${github_keys_url}" -o "${HELM_TMP_ROOT}/${keys_filename}" 202 elif [ "${HAS_WGET}" == "true" ]; then 203 wget -q -O "${HELM_TMP_ROOT}/${keys_filename}" "${github_keys_url}" 204 fi 205 local gpg_keyring="${HELM_TMP_ROOT}/keyring.gpg" 206 local gpg_homedir="${HELM_TMP_ROOT}/gnupg" 207 mkdir -p -m 0700 "${gpg_homedir}" 208 local gpg_stderr_device="/dev/null" 209 if [ "${DEBUG}" == "true" ]; then 210 gpg_stderr_device="/dev/stderr" 211 fi 212 gpg --batch --quiet --homedir="${gpg_homedir}" --import "${HELM_TMP_ROOT}/${keys_filename}" 2> "${gpg_stderr_device}" 213 gpg --batch --no-default-keyring --keyring "${gpg_homedir}/${GPG_PUBRING}" --export > "${gpg_keyring}" 214 local github_release_url="https://github.com/helm/helm/releases/download/${TAG}" 215 if [ "${HAS_CURL}" == "true" ]; then 216 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" 217 curl -SsL "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" -o "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" 218 elif [ "${HAS_WGET}" == "true" ]; then 219 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" 220 wget -q -O "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" 221 fi 222 local error_text="If you think this might be a potential security issue," 223 error_text="${error_text}\nplease see here: https://github.com/helm/community/blob/master/SECURITY.md" 224 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)') 225 if [[ ${num_goodlines_sha} -lt 2 ]]; then 226 echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256!" 227 echo -e "${error_text}" 228 exit 1 229 fi 230 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)') 231 if [[ ${num_goodlines_tar} -lt 2 ]]; then 232 echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz!" 233 echo -e "${error_text}" 234 exit 1 235 fi 236 echo "Done." 237 } 238 239 # fail_trap is executed if an error occurs. 240 fail_trap() { 241 result=$? 242 if [ "$result" != "0" ]; then 243 if [[ -n "$INPUT_ARGUMENTS" ]]; then 244 echo "Failed to install $BINARY_NAME with the arguments provided: $INPUT_ARGUMENTS" 245 help 246 else 247 echo "Failed to install $BINARY_NAME" 248 fi 249 echo -e "\tFor support, go to https://github.com/helm/helm." 250 fi 251 cleanup 252 exit $result 253 } 254 255 # testVersion tests the installed client to make sure it is working. 256 testVersion() { 257 set +e 258 HELM="$(command -v $BINARY_NAME)" 259 if [ "$?" = "1" ]; then 260 echo "$BINARY_NAME not found. Is $HELM_INSTALL_DIR on your "'$PATH?' 261 exit 1 262 fi 263 set -e 264 } 265 266 # help provides possible cli installation arguments 267 help () { 268 echo "Accepted cli arguments are:" 269 echo -e "\t[--help|-h ] ->> prints this help" 270 echo -e "\t[--version|-v <desired_version>] . When not defined it fetches the latest release from GitHub" 271 echo -e "\te.g. --version v3.0.0 or -v canary" 272 echo -e "\t[--no-sudo] ->> install without sudo" 273 } 274 275 # cleanup temporary files to avoid https://github.com/helm/helm/issues/2977 276 cleanup() { 277 if [[ -d "${HELM_TMP_ROOT:-}" ]]; then 278 rm -rf "$HELM_TMP_ROOT" 279 fi 280 } 281 282 # Execution 283 284 #Stop execution on any error 285 trap "fail_trap" EXIT 286 set -e 287 288 # Set debug if desired 289 if [ "${DEBUG}" == "true" ]; then 290 set -x 291 fi 292 293 # Parsing input arguments (if any) 294 export INPUT_ARGUMENTS="${@}" 295 set -u 296 while [[ $# -gt 0 ]]; do 297 case $1 in 298 '--version'|-v) 299 shift 300 if [[ $# -ne 0 ]]; then 301 export DESIRED_VERSION="${1}" 302 else 303 echo -e "Please provide the desired version. e.g. --version v3.0.0 or -v canary" 304 exit 0 305 fi 306 ;; 307 '--no-sudo') 308 USE_SUDO="false" 309 ;; 310 '--help'|-h) 311 help 312 exit 0 313 ;; 314 *) exit 1 315 ;; 316 esac 317 shift 318 done 319 set +u 320 321 initArch 322 initOS 323 verifySupported 324 checkDesiredVersion 325 if ! checkHelmInstalledVersion; then 326 downloadFile 327 verifyFile 328 installFile 329 fi 330 testVersion 331 cleanup