#!/bin/sh # SecureAI CLI installer. # # curl -fsSL https://get.corelayersecurity.com/install.sh | sh # # Environment: # SECUREAI_VERSION version to install (default: whatever stable.txt says) # SECUREAI_INSTALL_DIR where to put the binary (default: /usr/local/bin, # falling back to ~/.local/bin when that needs root) # SECUREAI_BASE_URL artifact host (default: https://get.corelayersecurity.com) # # This script is served from the same CloudFront distribution as the binaries # it downloads, and every download is checked against the published SHA256SUMS # before anything is written to your PATH. set -eu BASE_URL="${SECUREAI_BASE_URL:-https://get.corelayersecurity.com}" # Colour only when stdout is a terminal — piping to a file or a CI log should # not collect escape codes. if [ -t 1 ]; then BOLD="$(printf '\033[1m')"; DIM="$(printf '\033[2m')" RED="$(printf '\033[31m')"; GREEN="$(printf '\033[32m')"; OFF="$(printf '\033[0m')" else BOLD=""; DIM=""; RED=""; GREEN=""; OFF="" fi say() { printf ' %s\n' "$1"; } ok() { printf ' %sāœ“%s %-11s %s\n' "$GREEN" "$OFF" "$1" "$2"; } die() { printf ' %serror%s %s\n' "$RED" "$OFF" "$1" >&2; exit 1; } # --------------------------------------------------------------------------- # Prerequisites # --------------------------------------------------------------------------- if command -v curl >/dev/null 2>&1; then # No -S: every call site reports its own failure with the URL it wanted, and # curl's raw "curl: (22)" on top of that just reads as noise. fetch() { curl -fsL "$1" -o "$2"; } fetch_stdout() { curl -fsL "$1"; } elif command -v wget >/dev/null 2>&1; then fetch() { wget -qO "$2" "$1"; } fetch_stdout() { wget -qO- "$1"; } else die "need curl or wget to download." fi command -v tar >/dev/null 2>&1 || die "need tar to unpack the release." if command -v sha256sum >/dev/null 2>&1; then sha256_of() { sha256sum "$1" | cut -d' ' -f1; } elif command -v shasum >/dev/null 2>&1; then sha256_of() { shasum -a 256 "$1" | cut -d' ' -f1; } elif command -v openssl >/dev/null 2>&1; then sha256_of() { openssl dgst -sha256 "$1" | sed 's/.*= *//'; } else die "need sha256sum, shasum, or openssl to verify the download." fi # --------------------------------------------------------------------------- # Detect platform # --------------------------------------------------------------------------- os="$(uname -s)" case "$os" in Darwin) os="darwin" ;; Linux) os="linux" ;; MINGW*|MSYS*|CYGWIN*) die "on Windows use PowerShell instead: irm https://get.corelayersecurity.com/install.ps1 | iex" ;; *) die "unsupported operating system: $os" ;; esac arch="$(uname -m)" case "$arch" in x86_64|amd64) arch="amd64" ;; arm64|aarch64) arch="arm64" ;; *) die "unsupported architecture: $arch" ;; esac # --------------------------------------------------------------------------- # Resolve version # --------------------------------------------------------------------------- version="${SECUREAI_VERSION:-}" if [ -z "$version" ]; then # In a pipeline the exit status is tr's, not the download's, so check the # result rather than trusting `|| die` to fire. version="$(fetch_stdout "$BASE_URL/stable.txt" || true)" version="$(printf '%s' "$version" | tr -d ' \t\r\n')" [ -n "$version" ] || die "could not reach $BASE_URL/stable.txt. Check your network, or pin a version with SECUREAI_VERSION=0.1.0." fi version="${version#v}" printf '\n %ssecureai %s%s %s%s/%s%s\n\n' "$BOLD" "$version" "$OFF" "$DIM" "$os" "$arch" "$OFF" archive="secureai_${version}_${os}_${arch}.tar.gz" url="$BASE_URL/v$version/$archive" # --------------------------------------------------------------------------- # Download + verify # --------------------------------------------------------------------------- tmp="$(mktemp -d)" trap 'rm -rf "$tmp"' EXIT INT TERM fetch "$url" "$tmp/$archive" || die "no release for $os/$arch at $version. Looked for $url" ok "downloaded" "$archive" fetch "$BASE_URL/v$version/SHA256SUMS" "$tmp/SHA256SUMS" \ || die "release is missing its SHA256SUMS manifest; refusing to install." # Match the filename field exactly rather than with a regex — the archive name # contains dots, and awk exits 0 on no-match so `set -e` can't kill us silently. want="$(awk -v f="$archive" '$2 == f || $2 == "*" f { print $1; exit }' "$tmp/SHA256SUMS")" [ -n "$want" ] || die "$archive is not listed in SHA256SUMS; refusing to install." got="$(sha256_of "$tmp/$archive")" if [ "$want" != "$got" ]; then die "checksum mismatch for $archive — the download is corrupt or tampered with. expected $want got $got" fi ok "verified" "sha256" tar -xzf "$tmp/$archive" -C "$tmp" [ -f "$tmp/secureai" ] || die "archive did not contain a secureai binary." chmod +x "$tmp/secureai" # --------------------------------------------------------------------------- # Install # --------------------------------------------------------------------------- # Prefer an explicit choice, then a writable /usr/local/bin, then sudo, then a # per-user directory. Never silently ask for a password the caller didn't expect # when a working alternative exists. dir="${SECUREAI_INSTALL_DIR:-}" sudo="" if [ -z "$dir" ]; then if [ -d /usr/local/bin ] && [ -w /usr/local/bin ]; then dir="/usr/local/bin" elif [ "$(id -u)" = 0 ]; then dir="/usr/local/bin" elif command -v sudo >/dev/null 2>&1 && [ -t 0 ]; then dir="/usr/local/bin" sudo="sudo" say "${DIM}installing to $dir (sudo)${OFF}" else dir="$HOME/.local/bin" fi fi $sudo mkdir -p "$dir" || die "could not create $dir" $sudo install -m 0755 "$tmp/secureai" "$dir/secureai" 2>/dev/null \ || { $sudo cp "$tmp/secureai" "$dir/secureai" && $sudo chmod 0755 "$dir/secureai"; } \ || die "could not write to $dir. Re-run with SECUREAI_INSTALL_DIR=\$HOME/.local/bin" ok "installed" "$dir/secureai" # --------------------------------------------------------------------------- # Next steps # --------------------------------------------------------------------------- echo case ":$PATH:" in *":$dir:"*) ;; *) say "${BOLD}$dir is not on your PATH.${OFF} Add it:" echo say " echo 'export PATH=\"\$PATH:$dir\"' >> ~/.zshrc && exec \$SHELL" echo ;; esac say "${DIM}Point the CLI at your control plane, then sign in:${OFF}" echo say " export SECUREAI_SERVER=https://api.corelayersecurity.com" say " secureai login" echo say "${DIM}Docs: https://docs.corelayersecurity.com${OFF}" echo