github.com/anchore/syft@v1.38.2/install.sh (about) 1 #!/bin/sh 2 # note: we require errors to propagate (don't set -e) 3 set -u 4 5 PROJECT_NAME=syft 6 OWNER=anchore 7 REPO="${PROJECT_NAME}" 8 GITHUB_DOWNLOAD_PREFIX=https://github.com/${OWNER}/${REPO}/releases/download 9 INSTALL_SH_BASE_URL=https://get.anchore.io/${PROJECT_NAME} 10 LEGACY_INSTALL_SH_BASE_URL=https://raw.githubusercontent.com/${OWNER}/${PROJECT_NAME} 11 PROGRAM_ARGS=$@ 12 13 # signature verification options 14 15 # the location to the cosign binary (allowed to be overridden by the user) 16 COSIGN_BINARY=${COSIGN_BINARY:-cosign} 17 VERIFY_SIGN=false 18 # this is the earliest tag in the repo where cosign sign-blob was introduced in the release process (see the goreleaser config) 19 VERIFY_SIGN_SUPPORTED_VERSION=v0.104.0 20 # this is the earliest tag in the repo where the -v flag was introduced to this install.sh script 21 VERIFY_SIGN_FLAG_VERSION=v1.6.0 22 23 # do not change the name of this parameter (this must always be backwards compatible) 24 DOWNLOAD_TAG_INSTALL_SCRIPT=${DOWNLOAD_TAG_INSTALL_SCRIPT:-true} 25 26 # ------------------------------------------------------------------------ 27 # https://github.com/client9/shlib - portable posix shell functions 28 # Public domain - http://unlicense.org 29 # https://github.com/client9/shlib/blob/master/LICENSE.md 30 # but credit (and pull requests) appreciated. 31 # ------------------------------------------------------------------------ 32 33 is_command() ( 34 command -v "$1" >/dev/null 35 ) 36 37 echo_stderr() ( 38 echo "$@" 1>&2 39 ) 40 41 _logp=2 42 log_set_priority() { 43 _logp="$1" 44 } 45 46 log_priority() ( 47 if test -z "$1"; then 48 echo "$_logp" 49 return 50 fi 51 [ "$1" -le "$_logp" ] 52 ) 53 54 init_colors() { 55 RED='' 56 BLUE='' 57 PURPLE='' 58 BOLD='' 59 RESET='' 60 # check if stdout is a terminal 61 if test -t 1 && is_command tput; then 62 # see if it supports colors 63 ncolors=$(tput colors) 64 if test -n "$ncolors" && test $ncolors -ge 8; then 65 RED='\033[0;31m' 66 BLUE='\033[0;34m' 67 PURPLE='\033[0;35m' 68 BOLD='\033[1m' 69 RESET='\033[0m' 70 fi 71 fi 72 } 73 74 init_colors 75 76 log_tag() ( 77 case $1 in 78 0) echo "${RED}${BOLD}[error]${RESET}" ;; 79 1) echo "${RED}[warn]${RESET}" ;; 80 2) echo "[info]${RESET}" ;; 81 3) echo "${BLUE}[debug]${RESET}" ;; 82 4) echo "${PURPLE}[trace]${RESET}" ;; 83 *) echo "[$1]" ;; 84 esac 85 ) 86 87 88 log_trace_priority=4 89 log_trace() ( 90 priority=$log_trace_priority 91 log_priority "$priority" || return 0 92 echo_stderr "$(log_tag $priority)" "${@}" "${RESET}" 93 ) 94 95 log_debug_priority=3 96 log_debug() ( 97 priority=$log_debug_priority 98 log_priority "$priority" || return 0 99 echo_stderr "$(log_tag $priority)" "${@}" "${RESET}" 100 ) 101 102 log_info_priority=2 103 log_info() ( 104 priority=$log_info_priority 105 log_priority "$priority" || return 0 106 echo_stderr "$(log_tag $priority)" "${@}" "${RESET}" 107 ) 108 109 log_warn_priority=1 110 log_warn() ( 111 priority=$log_warn_priority 112 log_priority "$priority" || return 0 113 echo_stderr "$(log_tag $priority)" "${@}" "${RESET}" 114 ) 115 116 log_err_priority=0 117 log_err() ( 118 priority=$log_err_priority 119 log_priority "$priority" || return 0 120 echo_stderr "$(log_tag $priority)" "${@}" "${RESET}" 121 ) 122 123 uname_os_check() ( 124 os=$1 125 case "$os" in 126 darwin) return 0 ;; 127 dragonfly) return 0 ;; 128 freebsd) return 0 ;; 129 linux) return 0 ;; 130 android) return 0 ;; 131 nacl) return 0 ;; 132 netbsd) return 0 ;; 133 openbsd) return 0 ;; 134 plan9) return 0 ;; 135 solaris) return 0 ;; 136 windows) return 0 ;; 137 esac 138 log_err "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib" 139 return 1 140 ) 141 142 uname_arch_check() ( 143 arch=$1 144 case "$arch" in 145 386) return 0 ;; 146 amd64) return 0 ;; 147 arm64) return 0 ;; 148 armv5) return 0 ;; 149 armv6) return 0 ;; 150 armv7) return 0 ;; 151 ppc64) return 0 ;; 152 ppc64le) return 0 ;; 153 mips) return 0 ;; 154 mipsle) return 0 ;; 155 mips64) return 0 ;; 156 mips64le) return 0 ;; 157 s390x) return 0 ;; 158 amd64p32) return 0 ;; 159 esac 160 log_err "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib" 161 return 1 162 ) 163 164 unpack() ( 165 archive=$1 166 167 log_trace "unpack(archive=${archive})" 168 169 case "${archive}" in 170 *.tar.gz | *.tgz) tar --no-same-owner -xzf "${archive}" ;; 171 *.tar) tar --no-same-owner -xf "${archive}" ;; 172 *.zip) unzip -q "${archive}" ;; 173 *.dmg) extract_from_dmg "${archive}" ;; 174 *) 175 log_err "unpack unknown archive format for ${archive}" 176 return 1 177 ;; 178 esac 179 ) 180 181 extract_from_dmg() ( 182 dmg_file=$1 183 184 mount_point="/Volumes/tmp-dmg" 185 hdiutil attach -quiet -nobrowse -mountpoint "${mount_point}" "${dmg_file}" 186 cp -fR "${mount_point}/." ./ 187 hdiutil detach -quiet -force "${mount_point}" 188 ) 189 190 http_download_curl() ( 191 local_file=$1 192 source_url=$2 193 header=$3 194 195 log_trace "http_download_curl(local_file=$local_file, source_url=$source_url, header=$header)" 196 197 if [ -z "$header" ]; then 198 code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url") 199 else 200 code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url") 201 fi 202 203 if [ "$code" != "200" ]; then 204 log_err "received HTTP status=$code for url='$source_url'" 205 return 1 206 fi 207 return 0 208 ) 209 210 http_download_wget() ( 211 local_file=$1 212 source_url=$2 213 header=$3 214 215 log_trace "http_download_wget(local_file=$local_file, source_url=$source_url, header=$header)" 216 217 if [ -z "$header" ]; then 218 wget -q -O "$local_file" "$source_url" 219 else 220 wget -q --header "$header" -O "$local_file" "$source_url" 221 fi 222 ) 223 224 http_download() ( 225 log_debug "http_download(url=$2)" 226 if is_command curl; then 227 http_download_curl "$@" 228 return 229 elif is_command wget; then 230 http_download_wget "$@" 231 return 232 fi 233 log_err "http_download unable to find wget or curl" 234 return 1 235 ) 236 237 http_copy() ( 238 tmp=$(mktemp) 239 http_download "${tmp}" "$1" "$2" || return 1 240 body=$(cat "$tmp") 241 rm -f "${tmp}" 242 echo "$body" 243 ) 244 245 hash_sha256() ( 246 TARGET=${1:-/dev/stdin} 247 if is_command gsha256sum; then 248 hash=$(gsha256sum "$TARGET") || return 1 249 echo "$hash" | cut -d ' ' -f 1 250 elif is_command sha256sum; then 251 hash=$(sha256sum "$TARGET") || return 1 252 echo "$hash" | cut -d ' ' -f 1 253 elif is_command shasum; then 254 hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1 255 echo "$hash" | cut -d ' ' -f 1 256 elif is_command openssl; then 257 hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1 258 echo "$hash" | cut -d ' ' -f a 259 else 260 log_err "hash_sha256 unable to find command to compute sha-256 hash" 261 return 1 262 fi 263 ) 264 265 hash_sha256_verify() ( 266 target=$1 267 checksums=$2 268 if [ -z "$checksums" ]; then 269 log_err "hash_sha256_verify checksum file not specified as argument" 270 return 1 271 fi 272 target_basename=${target##*/} 273 want=$(grep "${target_basename}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1) 274 if [ -z "$want" ]; then 275 log_err "hash_sha256_verify unable to find checksum for '${target}' in '${checksums}'" 276 return 1 277 fi 278 got=$(hash_sha256 "$target") 279 if [ "$want" != "$got" ]; then 280 log_err "hash_sha256_verify checksum for '$target' did not verify ${want} vs $got" 281 return 1 282 fi 283 ) 284 285 # ------------------------------------------------------------------------ 286 # End of functions from https://github.com/client9/shlib 287 # ------------------------------------------------------------------------ 288 289 # asset_file_exists [path] 290 # 291 # returns 1 if the given file does not exist 292 # 293 asset_file_exists() ( 294 path="$1" 295 if [ ! -f "${path}" ]; then 296 return 1 297 fi 298 ) 299 300 301 # github_release_json [owner] [repo] [version] 302 # 303 # outputs release json string 304 # 305 github_release_json() ( 306 owner=$1 307 repo=$2 308 version=$3 309 test -z "$version" && version="latest" 310 giturl="https://github.com/${owner}/${repo}/releases/${version}" 311 json=$(http_copy "$giturl" "Accept:application/json") 312 313 log_trace "github_release_json(owner=${owner}, repo=${repo}, version=${version}) returned '${json}'" 314 315 test -z "$json" && return 1 316 echo "${json}" 317 ) 318 319 # extract_value [key-value-pair] 320 # 321 # outputs value from a colon delimited key-value pair 322 # 323 extract_value() ( 324 key_value="$1" 325 IFS=':' read -r _ value << EOF 326 ${key_value} 327 EOF 328 echo "$value" 329 ) 330 331 # extract_json_value [json] [key] 332 # 333 # outputs value of the key from the given json string 334 # 335 extract_json_value() ( 336 json="$1" 337 key="$2" 338 key_value=$(echo "${json}" | grep -o "\"$key\":[^,]*[,}]" | tr -d '",}') 339 340 extract_value "$key_value" 341 ) 342 343 # github_release_tag [release-json] 344 # 345 # outputs release tag string 346 # 347 github_release_tag() ( 348 json="$1" 349 tag=$(extract_json_value "${json}" "tag_name") 350 test -z "$tag" && return 1 351 echo "$tag" 352 ) 353 354 # github_release_asset_url [release-url-prefix] [name] [version] [output-dir] [filename] 355 # 356 # outputs the url to the release asset 357 # 358 github_release_asset_url() ( 359 download_url="$1" 360 name="$2" 361 version="$3" 362 filename="$4" 363 364 complete_filename="${name}_${version}_${filename}" 365 complete_url="${download_url}/${complete_filename}" 366 367 echo "${complete_url}" 368 ) 369 370 # download_github_release_checksums_files [release-url-prefix] [name] [version] [output-dir] [filename] 371 # 372 # outputs path to the downloaded checksums related file 373 # 374 download_github_release_checksums_files() ( 375 download_url="$1" 376 name="$2" 377 version="$3" 378 output_dir="$4" 379 filename="$5" 380 381 log_trace "download_github_release_checksums_files(url=${download_url}, name=${name}, version=${version}, output_dir=${output_dir}, filename=${filename})" 382 383 complete_filename="${name}_${version}_${filename}" 384 complete_url=$(github_release_asset_url "${download_url}" "${name}" "${version}" "${filename}") 385 output_path="${output_dir}/${complete_filename}" 386 387 http_download "${output_path}" "${complete_url}" "" 388 asset_file_exists "${output_path}" 389 390 log_trace "download_github_release_checksums_files() returned '${output_path}' for file '${complete_filename}'" 391 392 echo "${output_path}" 393 ) 394 395 # download_github_release_checksums [release-url-prefix] [name] [version] [output-dir] 396 # 397 # outputs path to the downloaded checksums file 398 # 399 download_github_release_checksums() ( 400 download_github_release_checksums_files "$@" "checksums.txt" 401 ) 402 403 # github_release_checksums_sig_url [release-url-prefix] [name] [version] 404 # 405 # outputs the url to the release checksums signature file 406 # 407 github_release_checksums_sig_url() ( 408 github_release_asset_url "$@" "checksums.txt.sig" 409 ) 410 411 # github_release_checksums_cert_url [release-url-prefix] [name] [version] 412 # 413 # outputs the url to the release checksums certificate file 414 # 415 github_release_checksums_cert_url() ( 416 github_release_asset_url "$@" "checksums.txt.pem" 417 ) 418 419 # search_for_asset [checksums-file-path] [name] [os] [arch] [format] 420 # 421 # outputs name of the asset to download 422 # 423 search_for_asset() ( 424 checksum_path="$1" 425 name="$2" 426 os="$3" 427 arch="$4" 428 format="$5" 429 430 log_trace "search_for_asset(checksum-path=${checksum_path}, name=${name}, os=${os}, arch=${arch}, format=${format})" 431 432 asset_glob="${name}_.*_${os}_${arch}.${format}" 433 output_path=$(grep -o "${asset_glob}" "${checksum_path}" || true) 434 435 log_trace "search_for_asset() returned '${output_path}'" 436 437 echo "${output_path}" 438 ) 439 440 # uname_os 441 # 442 # outputs an adjusted os value 443 # 444 uname_os() ( 445 os=$(uname -s | tr '[:upper:]' '[:lower:]') 446 case "$os" in 447 cygwin_nt*) os="windows" ;; 448 mingw*) os="windows" ;; 449 msys_nt*) os="windows" ;; 450 esac 451 452 uname_os_check "$os" 453 454 log_trace "uname_os() returned '${os}'" 455 456 echo "$os" 457 ) 458 459 # uname_arch 460 # 461 # outputs an adjusted architecture value 462 # 463 uname_arch() ( 464 arch=$(uname -m) 465 case $arch in 466 x86_64) arch="amd64" ;; 467 x86) arch="386" ;; 468 i686) arch="386" ;; 469 i386) arch="386" ;; 470 aarch64) arch="arm64" ;; 471 armv5*) arch="armv5" ;; 472 armv6*) arch="armv6" ;; 473 armv7*) arch="armv7" ;; 474 esac 475 476 uname_arch_check "${arch}" 477 478 log_trace "uname_arch() returned '${arch}'" 479 480 echo "${arch}" 481 ) 482 483 # get_release_tag [owner] [repo] [tag] 484 # 485 # outputs tag string 486 # 487 get_release_tag() ( 488 owner="$1" 489 repo="$2" 490 tag="$3" 491 492 log_trace "get_release_tag(owner=${owner}, repo=${repo}, tag=${tag})" 493 494 json=$(github_release_json "${owner}" "${repo}" "${tag}") 495 real_tag=$(github_release_tag "${json}") 496 if test -z "${real_tag}"; then 497 return 1 498 fi 499 500 log_trace "get_release_tag() returned '${real_tag}'" 501 502 echo "${real_tag}" 503 ) 504 505 # tag_to_version [tag] 506 # 507 # outputs version string 508 # 509 tag_to_version() ( 510 tag="$1" 511 value="${tag#v}" 512 513 log_trace "tag_to_version(tag=${tag}) returned '${value}'" 514 515 echo "$value" 516 ) 517 518 # get_binary_name [os] [arch] [default-name] 519 # 520 # outputs a the binary string name 521 # 522 get_binary_name() ( 523 os="$1" 524 arch="$2" 525 binary="$3" 526 original_binary="${binary}" 527 528 case "${os}" in 529 windows) binary="${binary}.exe" ;; 530 esac 531 532 log_trace "get_binary_name(os=${os}, arch=${arch}, binary=${original_binary}) returned '${binary}'" 533 534 echo "${binary}" 535 ) 536 537 538 # get_format_name [os] [arch] [default-format] 539 # 540 # outputs an adjusted file format 541 # 542 get_format_name() ( 543 os="$1" 544 arch="$2" 545 format="$3" 546 original_format="${format}" 547 548 case ${os} in 549 windows) format=zip ;; 550 esac 551 552 log_trace "get_format_name(os=${os}, arch=${arch}, format=${original_format}) returned '${format}'" 553 554 echo "${format}" 555 ) 556 557 # download_and_install_asset [release-url-prefix] [download-path] [install-path] [name] [os] [arch] [version] [format] [binary] 558 # 559 # attempts to download the archive and install it to the given path. 560 # 561 download_and_install_asset() ( 562 download_url="$1" 563 download_path="$2" 564 install_path=$3 565 name="$4" 566 os="$5" 567 arch="$6" 568 version="$7" 569 format="$8" 570 binary="$9" 571 572 if ! asset_filepath=$(download_asset "${download_url}" "${download_path}" "${name}" "${os}" "${arch}" "${version}" "${format}"); then 573 log_err "could not download asset for os='${os}' arch='${arch}' format='${format}'" 574 return 1 575 fi 576 577 # don't continue if we couldn't download an asset 578 if [ -z "${asset_filepath}" ]; then 579 log_err "could not find release asset for os='${os}' arch='${arch}' format='${format}' " 580 return 1 581 fi 582 583 install_asset "${asset_filepath}" "${install_path}" "${binary}" 584 ) 585 586 # verify_sign [checksums-file-path] [certificate-reference] [signature-reference] [version] 587 # 588 # attempts verify the signature of the checksums file from the release workflow in Github Actions run against the main branch. 589 # 590 verify_sign() { 591 checksums_file=$1 592 cert_reference=$2 593 sig_reference=$3 594 595 log_trace "verifying artifact $1" 596 597 log_file=$(mktemp) 598 599 ${COSIGN_BINARY} \ 600 verify-blob "$checksums_file" \ 601 --certificate "$cert_reference" \ 602 --signature "$sig_reference" \ 603 --certificate-identity "https://github.com/${OWNER}/${REPO}/.github/workflows/release.yaml@refs/heads/main" \ 604 --certificate-oidc-issuer "https://token.actions.githubusercontent.com" > "${log_file}" 2>&1 605 606 if [ $? -ne 0 ]; then 607 log_err "$(cat "${log_file}")" 608 rm -f "${log_file}" 609 return 1 610 fi 611 612 rm -f "${log_file}" 613 } 614 615 616 # download_asset [release-url-prefix] [download-path] [name] [os] [arch] [version] [format] [binary] 617 # 618 # outputs the path to the downloaded asset asset_filepath 619 # 620 download_asset() ( 621 download_url="$1" 622 destination="$2" 623 name="$3" 624 os="$4" 625 arch="$5" 626 version="$6" 627 format="$7" 628 629 log_trace "download_asset(url=${download_url}, destination=${destination}, name=${name}, os=${os}, arch=${arch}, version=${version}, format=${format})" 630 631 checksums_filepath=$(download_github_release_checksums "${download_url}" "${name}" "${version}" "${destination}") 632 633 log_trace "checksums content:\n$(cat ${checksums_filepath})" 634 635 asset_filename=$(search_for_asset "${checksums_filepath}" "${name}" "${os}" "${arch}" "${format}") 636 637 # don't continue if we couldn't find a matching asset from the checksums file 638 if [ -z "${asset_filename}" ]; then 639 return 1 640 fi 641 642 if [ "$VERIFY_SIGN" = true ]; then 643 checksum_sig_file_url=$(github_release_checksums_sig_url "${download_url}" "${name}" "${version}") 644 log_trace "checksums signature url: ${checksum_sig_file_url}" 645 646 checksums_cert_file_url=$(github_release_checksums_cert_url "${download_url}" "${name}" "${version}") 647 log_trace "checksums certificate url: ${checksums_cert_file_url}" 648 649 if ! verify_sign "${checksums_filepath}" "${checksums_cert_file_url}" "${checksum_sig_file_url}"; then 650 log_err "signature verification failed" 651 return 1 652 fi 653 log_info "signature verification succeeded" 654 fi 655 656 asset_url="${download_url}/${asset_filename}" 657 asset_filepath="${destination}/${asset_filename}" 658 http_download "${asset_filepath}" "${asset_url}" "" 659 660 hash_sha256_verify "${asset_filepath}" "${checksums_filepath}" 661 662 log_trace "download_asset_by_checksums_file() returned '${asset_filepath}'" 663 664 echo "${asset_filepath}" 665 ) 666 667 # install_asset [asset-path] [destination-path] [binary] 668 # 669 install_asset() ( 670 asset_filepath="$1" 671 destination="$2" 672 binary="$3" 673 674 log_trace "install_asset(asset=${asset_filepath}, destination=${destination}, binary=${binary})" 675 676 # don't continue if we don't have anything to install 677 if [ -z "${asset_filepath}" ]; then 678 return 679 fi 680 681 archive_dir=$(dirname "${asset_filepath}") 682 683 # unarchive the downloaded archive to the temp dir 684 (cd "${archive_dir}" && unpack "${asset_filepath}") 685 686 # create the destination dir 687 test ! -d "${destination}" && install -d "${destination}" 688 689 # install the binary to the destination dir 690 install "${archive_dir}/${binary}" "${destination}/" 691 ) 692 693 # compare two semver strings. Returns 0 if version1 >= version2, 1 otherwise. 694 # Note: pre-release (-) and metadata (+) are not supported. 695 compare_semver() { 696 # remove leading 'v' if present 697 version1=${1#v} 698 version2=${2#v} 699 700 IFS=. read -r major1 minor1 patch1 <<EOF 701 $version1 702 EOF 703 IFS=. read -r major2 minor2 patch2 <<EOF 704 $version2 705 EOF 706 707 if [ "$major1" -gt "$major2" ]; then 708 return 0 709 elif [ "$major1" -lt "$major2" ]; then 710 return 1 711 fi 712 713 if [ "$minor1" -gt "$minor2" ]; then 714 return 0 715 elif [ "$minor1" -lt "$minor2" ]; then 716 return 1 717 fi 718 719 if [ "$patch1" -gt "$patch2" ]; then 720 return 0 721 elif [ "$patch1" -lt "$patch2" ]; then 722 return 1 723 fi 724 725 # versions are equal 726 return 0 727 } 728 729 prep_signature_verification() { 730 version="$1" 731 732 if [ "$VERIFY_SIGN" != true ]; then 733 return 0 734 fi 735 736 # is there any cryptographic material produced at release that we can use for signature verification? 737 if ! compare_semver "$version" "$VERIFY_SIGN_SUPPORTED_VERSION"; then 738 log_err "${PROJECT_NAME} release '$version' does not support signature verification" 739 log_err "you can still install ${PROJECT_NAME} by removing the -v flag or using a release that supports signature verification (>= '$VERIFY_SIGN_SUPPORTED_VERSION')" 740 log_err "aborting installation" 741 return 1 742 else 743 log_trace "${PROJECT_NAME} release '$version' supports signature verification (>= '$VERIFY_SIGN_SUPPORTED_VERSION')" 744 fi 745 746 # will invoking an earlier version of this script work (considering the -v flag)? 747 if ! compare_semver "$version" "$VERIFY_SIGN_FLAG_VERSION"; then 748 # the -v argument did not always exist, so we cannot be guaranteed that invoking an earlier version of this script 749 # will work (error with "illegal option -v"). However, the user requested signature verification, so we will 750 # attempt to install the application with this version of the script (keeping signature verification). 751 DOWNLOAD_TAG_INSTALL_SCRIPT=false 752 log_debug "provided version install script does not support -v flag (>= '$VERIFY_SIGN_FLAG_VERSION'), using current script for installation" 753 else 754 log_trace "provided version install script supports -v flag (>= '$VERIFY_SIGN_FLAG_VERSION')" 755 fi 756 757 # check to see if the cosign binary is installed 758 if is_command "${COSIGN_BINARY}"; then 759 log_trace "${COSIGN_BINARY} binary is installed" 760 else 761 log_err "signature verification is requested but ${COSIGN_BINARY} binary is not installed (see https://docs.sigstore.dev/system_config/installation/ to install it)" 762 return 1 763 fi 764 } 765 766 main() ( 767 # parse arguments 768 769 # note: never change default install directory (this must always be backwards compatible) 770 install_dir=${install_dir:-./bin} 771 772 # note: never change the program flags or arguments (this must always be backwards compatible) 773 while getopts "b:dvh?x" arg; do 774 case "$arg" in 775 b) install_dir="$OPTARG" ;; 776 d) 777 if [ "$_logp" = "$log_info_priority" ]; then 778 # -d == debug 779 log_set_priority $log_debug_priority 780 else 781 # -dd (or -ddd...) == trace 782 log_set_priority $log_trace_priority 783 fi 784 ;; 785 v) VERIFY_SIGN=true;; 786 h | \?) 787 cat <<EOF 788 Download and install a released binary for ${OWNER}/${REPO} from the github releases page 789 790 Usage: $0 [-v] [-b DIR] [-d] [TAG] 791 -b DIR the installation directory (defaults to ./bin) 792 -d turns on debug logging 793 -dd turns on trace logging 794 -v verify checksum signature (requires cosign binary to be installed). 795 TAG the specific release to use (if missing, then the latest will be used) 796 EOF 797 exit 0 798 ;; 799 x) set -x ;; 800 esac 801 done 802 shift $((OPTIND - 1)) 803 804 set +u 805 tag=$1 806 807 if [ -z "${tag}" ]; then 808 log_info "checking github for the current release tag" 809 tag="" 810 else 811 log_info "checking github for release tag='${tag}'" 812 fi 813 set -u 814 815 if ! tag=$(get_release_tag "${OWNER}" "${REPO}" "${tag}"); then 816 log_err "unable to find tag='${tag}'" 817 log_err "do not specify a version or select a valid version from https://github.com/${OWNER}/${REPO}/releases" 818 return 1 819 fi 820 821 # run the application 822 823 version=$(tag_to_version "${tag}") 824 os=$(uname_os) 825 arch=$(uname_arch) 826 format=$(get_format_name "${os}" "${arch}" "tar.gz") 827 binary=$(get_binary_name "${os}" "${arch}" "${PROJECT_NAME}") 828 download_url="${GITHUB_DOWNLOAD_PREFIX}/${tag}" 829 830 if ! prep_signature_verification "$version"; then 831 return 1 832 fi 833 834 # we always use the install.sh script that is associated with the tagged release. Why? the latest install.sh is not 835 # guaranteed to be able to install every version of the application. We use the DOWNLOAD_TAG_INSTALL_SCRIPT env var 836 # to indicate if we should continue processing with the existing script or to download the script from the given tag. 837 if [ "${DOWNLOAD_TAG_INSTALL_SCRIPT}" = "true" ]; then 838 export DOWNLOAD_TAG_INSTALL_SCRIPT=false 839 log_info "fetching release script for tag='${tag}'" 840 if ! install_script=$(http_copy "${INSTALL_SH_BASE_URL}/${tag}/install.sh" ""); then 841 log_warn "failed to fetch from ${INSTALL_SH_BASE_URL}, trying fallback URL" 842 install_script=$(http_copy "${LEGACY_INSTALL_SH_BASE_URL}/${tag}/install.sh" "") 843 fi 844 echo "${install_script}" | sh -s -- ${PROGRAM_ARGS} 845 exit $? 846 fi 847 848 log_info "using release tag='${tag}' version='${version}' os='${os}' arch='${arch}'" 849 850 download_dir=$(mktemp -d) 851 trap 'rm -rf -- "$download_dir"' EXIT 852 853 log_debug "downloading files into ${download_dir}" 854 855 # don't continue if we couldn't install the asset 856 if ! download_and_install_asset "${download_url}" "${download_dir}" "${install_dir}" "${PROJECT_NAME}" "${os}" "${arch}" "${version}" "${format}" "${binary}"; then 857 log_err "failed to install ${PROJECT_NAME}" 858 return 1 859 fi 860 861 log_info "installed ${install_dir}/${binary}" 862 ) 863 864 # entrypoint 865 866 set +u 867 if [ -z "${TEST_INSTALL_SH}" ]; then 868 set -u 869 main "$@" 870 exit $? 871 fi 872 set -u