fix: install bws from the private tier, not the manifest
The previous commit put the bws install on the private/bws-secrets row as a tarball channel. That row can never install anything: selected_packages drops every row flagged `private`, which is the invariant that makes --unattended safe to run. The container proved it — unzip installed, bws did not, and the row still could not deliver on its promise. Nor can it be a safe row: the defaults preset ticks every safe package, so that would put a Bitwarden binary and a 12 MB GitHub download on every throwaway public VM, for a tool those machines have no credential to use. So ensure_bws lives in dotup and is called from cmd_private immediately after the token is written. Nothing installs bws unless something is about to hand it a token, and the manifest keeps its invariant. core/unzip stays a real package with the @needs edge — the release is a .zip and 24.04 minimal has no unzip.
This commit is contained in:
@@ -379,6 +379,61 @@ norm() { printf '%s\n' "$*" | tr ' ' '\n' | grep . | tr '\n' ' ' | sed 's/ $//';
|
||||
# Used wherever a URL that may carry a credential is about to be printed.
|
||||
redact_url() { printf '%s\n' "$1" | sed 's#://[^/@]*@#://<redacted>@#'; }
|
||||
|
||||
# The Bitwarden Secrets Manager CLI, installed by the PRIVATE tier only.
|
||||
#
|
||||
# It cannot be a manifest row. `selected_packages` drops every row flagged
|
||||
# `private` -- "private is never a package" is the invariant that lets
|
||||
# --unattended be safe -- so a private row can never install anything. And it
|
||||
# must not be a `safe` row either: the defaults preset ticks every safe package,
|
||||
# which would put a Bitwarden binary and a 12 MB GitHub download on every
|
||||
# throwaway public VM, for a tool those machines have no credential to use.
|
||||
#
|
||||
# So it lives here, called from cmd_private beside the token it exists to read.
|
||||
# Nothing installs bws unless something is about to hand it a token.
|
||||
ensure_bws() {
|
||||
have bws && { say " bws $(bws --version 2>/dev/null | awk '{print $2}') already present"; return 0; }
|
||||
command -v unzip >/dev/null 2>&1 || { err "bws needs unzip; install it and re-run"; return 1; }
|
||||
# musl, not gnu: the gnu build pins a glibc newer than some LTS images
|
||||
# carry, and this has to work on whatever a fresh VM turns out to be.
|
||||
case $(uname -s) in
|
||||
Darwin) t=macos-universal ;;
|
||||
*) case $(uname -m) in
|
||||
x86_64|amd64) t=x86_64-unknown-linux-musl ;;
|
||||
aarch64|arm64) t=aarch64-unknown-linux-musl ;;
|
||||
*) err "no bws build for $(uname -m)"; return 1 ;;
|
||||
esac ;;
|
||||
esac
|
||||
# sdk-sm is a monorepo with per-component tags, so the `latest` release is
|
||||
# usually a python SDK rather than bws. Filter by tag prefix.
|
||||
v=$(curl -fsSL 'https://api.github.com/repos/bitwarden/sdk-sm/releases?per_page=40' 2>/dev/null \
|
||||
| sed -n 's/.*"tag_name": *"bws-v\([0-9.]*\)".*/\1/p' | head -1)
|
||||
[ -n "$v" ] || { err "could not resolve the current bws version"; return 1; }
|
||||
b=https://github.com/bitwarden/sdk-sm/releases/download/bws-v$v
|
||||
say " fetching bws $v"
|
||||
curl -fsSL "$b/bws-$t-$v.zip" -o /tmp/bws.zip 2>/dev/null \
|
||||
|| { err "bws download failed"; return 1; }
|
||||
# A binary about to hold the key to every other credential is worth verifying.
|
||||
if have sha256sum && curl -fsSL "$b/bws-sha256-checksums-$v.txt" -o /tmp/bws.sums 2>/dev/null; then
|
||||
want=$(awk -v f="bws-$t-$v.zip" '$2==f || $2=="*"f {print $1}' /tmp/bws.sums | head -1)
|
||||
got=$(sha256sum /tmp/bws.zip | awk '{print $1}')
|
||||
if [ -n "$want" ] && [ "$want" != "$got" ]; then
|
||||
err "bws checksum mismatch — refusing to install"
|
||||
rm -f /tmp/bws.zip /tmp/bws.sums; return 1
|
||||
fi
|
||||
[ -n "$want" ] && say " bws checksum verified"
|
||||
rm -f /tmp/bws.sums
|
||||
else
|
||||
warn " bws checksums unavailable — installing unverified"
|
||||
fi
|
||||
mkdir -p "$HOME/.local/bin" /tmp/bws.d
|
||||
unzip -oq /tmp/bws.zip -d /tmp/bws.d 2>/dev/null \
|
||||
|| { err "bws extract failed"; rm -rf /tmp/bws.zip /tmp/bws.d; return 1; }
|
||||
install -m 755 "$(find /tmp/bws.d -type f -name bws | head -1)" "$HOME/.local/bin/bws" \
|
||||
|| { err "bws install failed"; rm -rf /tmp/bws.zip /tmp/bws.d; return 1; }
|
||||
rm -rf /tmp/bws.zip /tmp/bws.d
|
||||
say " bws $v installed to ~/.local/bin"
|
||||
}
|
||||
|
||||
run() {
|
||||
if [ "$DRYRUN" -eq 1 ]; then printf ' + %s\n' "$*"; return 0; fi
|
||||
printf '%s + %s%s\n' "$DIM" "$*" "$R" >&2
|
||||
@@ -574,59 +629,6 @@ install_bespoke() {
|
||||
run_sh "${SUDO:+$SUDO }rm -rf /usr/local/go && ${SUDO:+$SUDO }tar -xzf /tmp/go.tgz -C /usr/local" \
|
||||
|| { note_fail "$key" "tarball extract failed"; continue; }
|
||||
run_sh "rm -f /tmp/go.tgz" ;;
|
||||
private/bws-secrets)
|
||||
# The Bitwarden Secrets Manager CLI. Without it the private tier
|
||||
# fetches nothing: `dotsecrets` shells out to `bws secret get`, so
|
||||
# this row promising seven API keys and not installing the binary
|
||||
# was a promise it could not keep.
|
||||
#
|
||||
# User-level, ~/.local/bin, no sudo. It is a single static binary
|
||||
# and the private tier is per-user by definition.
|
||||
if have bws && [ "$DRYRUN" -eq 0 ]; then
|
||||
say " bws $(bws --version 2>/dev/null | awk '{print $2}') already present — leaving it"
|
||||
continue
|
||||
fi
|
||||
# musl, not gnu: the gnu build pins a glibc newer than some LTS
|
||||
# images carry, and this has to work on whatever a fresh VM is.
|
||||
case $(uname -s) in
|
||||
Darwin) t=macos-universal ;;
|
||||
*) case $(uname -m) in
|
||||
x86_64|amd64) t=x86_64-unknown-linux-musl ;;
|
||||
aarch64|arm64) t=aarch64-unknown-linux-musl ;;
|
||||
*) note_fail "$key" "no bws build for $(uname -m)"; continue ;;
|
||||
esac ;;
|
||||
esac
|
||||
if [ "$DRYRUN" -eq 1 ]; then v=2.X.Y
|
||||
else
|
||||
# Releases are tagged per-component in this monorepo, so the
|
||||
# `latest` endpoint points at whatever shipped last -- often a
|
||||
# python SDK, not bws. Filter by tag prefix instead.
|
||||
v=$(curl -fsSL 'https://api.github.com/repos/bitwarden/sdk-sm/releases?per_page=40' 2>/dev/null \
|
||||
| sed -n 's/.*"tag_name": *"bws-v\([0-9.]*\)".*/\1/p' | head -1)
|
||||
fi
|
||||
[ -n "$v" ] || { note_fail "$key" "could not resolve the current bws version"; continue; }
|
||||
b=https://github.com/bitwarden/sdk-sm/releases/download/bws-v$v
|
||||
run_sh "curl -fsSL '$b/bws-$t-$v.zip' -o /tmp/bws.zip" \
|
||||
|| { note_fail "$key" "download failed"; continue; }
|
||||
# Bitwarden publishes checksums; a binary that is about to hold the
|
||||
# key to every other credential is worth verifying.
|
||||
if [ "$DRYRUN" -eq 0 ] && have sha256sum; then
|
||||
if curl -fsSL "$b/bws-sha256-checksums-$v.txt" -o /tmp/bws.sums 2>/dev/null; then
|
||||
want=$(awk -v f="bws-$t-$v.zip" '$2==f || $2=="*"f {print $1}' /tmp/bws.sums | head -1)
|
||||
got=$(sha256sum /tmp/bws.zip | awk '{print $1}')
|
||||
if [ -n "$want" ] && [ "$want" != "$got" ]; then
|
||||
note_fail "$key" "checksum mismatch — refusing to install"
|
||||
rm -f /tmp/bws.zip /tmp/bws.sums; continue
|
||||
fi
|
||||
[ -n "$want" ] && say " checksum verified"
|
||||
else
|
||||
warn " bws: checksums unavailable — installing unverified"
|
||||
fi
|
||||
rm -f /tmp/bws.sums
|
||||
fi
|
||||
run_sh "mkdir -p \"\$HOME/.local/bin\" && unzip -oq /tmp/bws.zip -d /tmp/bws.d && install -m 755 \"\$(find /tmp/bws.d -type f -name bws | head -1)\" \"\$HOME/.local/bin/bws\"" \
|
||||
|| { note_fail "$key" "extract failed"; rm -rf /tmp/bws.zip /tmp/bws.d; continue; }
|
||||
run_sh "rm -rf /tmp/bws.zip /tmp/bws.d" ;;
|
||||
core/chezmoi)
|
||||
# Circular by nature: dotup arrives *via* chezmoi. Present already
|
||||
# in every case that matters; here for the one where it is not.
|
||||
@@ -787,6 +789,7 @@ cmd_private() {
|
||||
( umask 077; printf '%s\n' "$p_tok" > "$BWS_TOKEN" )
|
||||
chmod 600 "$BWS_TOKEN"
|
||||
say " bws token written, mode 600"
|
||||
ensure_bws
|
||||
else err "the blob carried no BWS_ACCESS_TOKEN"; fi
|
||||
fi
|
||||
unset p_tok
|
||||
|
||||
@@ -118,4 +118,4 @@ virt libvirt invasive libvirt-daemon-system - daemon + group membership
|
||||
virt virt-manager invasive virt-manager -
|
||||
@private one password, typed after the install finishes
|
||||
private private-repo private - - ~/.local/share/dotfiles-private — agent config, ssh config
|
||||
private bws-secrets private -tarball -tarball installs bws, then 7 API keys into ~/.config/zsh/secrets.zsh
|
||||
private bws-secrets private - - bws + 7 API keys into ~/.config/zsh/secrets.zsh; the tier installs bws itself
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 17 and column 49.
|
Reference in New Issue
Block a user