Files
org-buildout/scripts/bw-install.sh
T
TSYS Group COO dce7164889 feat: container-based Bitwarden CLI using native Rust binary (no Node.js)
Replace the Node.js @bitwarden/cli dependency with the pre-compiled
native Rust binary (v2026.7.0) for CMMC/ITAR/STIG audit readiness.
The Node.js dependency tree was a significant attack surface that
would fail security audits.

Infrastructure:
- docker/bw-native/Dockerfile: minimal debian-slim + native bw binary
- scripts/bw-cli.sh: host wrapper handling full auth lifecycle
  (config, API-key login, unlock, sync) inside the container
- scripts/bw-entrypoint.sh: container entrypoint for auth lifecycle
- scripts/bw-install.sh: one-command installer (download, build, deploy)

Root causes fixed:
- ~/.config/bw/env values now single-quoted (master password has $
  chars that shell expansion corrupted, truncating 32→16 chars)
- Added BW_SERVER for self-hosted instance (pwvault.turnsys.com)
- Entrypoint bw config server tolerates re-run (|| true)

All scripts pass shellcheck with zero warnings including info-level.
Verified: bw status (unlocked, coo@turnsys.com), generate, list items.

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
2026-09-07 14:51:13 -05:00

126 lines
4.1 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# bw-install.sh — Install the container-based Bitwarden CLI wrapper.
#
# Downloads the native Rust bw binary, builds the Docker image, and installs
# the host-side wrapper plus container entrypoint to the user's local paths.
# No Node.js is involved at any layer.
#
# Usage:
# bw-install.sh Download, build, and install everything
# bw-install.sh --check Verify installation status without changes
#
# Prerequisites:
# - docker on PATH
# - BW env file at ~/.config/bw/env (see prereq-check.sh in TSYSGroupAIOS)
#
# After install, ~/.local/bin/bw provides transparent CLI access. Add
# ~/.local/bin to PATH if not already (most distros do this via ~/.profile).
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$HERE/.." && pwd)"
BW_VERSION="2026.7.0"
BW_IMAGE="reachableceo-bw-native:${BW_VERSION}"
BW_BINARY_URL="https://github.com/bitwarden/clients/releases/download/cli-v${BW_VERSION}/bw-linux-${BW_VERSION}.zip"
INSTALL_BIN="${HOME}/.local/bin"
INSTALL_LIB="${HOME}/.local/share/bw"
BUILD_DIR=""
# --- Helpers ---
log_info() { printf '\033[0;34m\033[0m %s\n' "$*"; }
log_ok() { printf '\033[0;32m✓\033[0m %s\n' "$*"; }
log_warn() { printf '\033[1;33m⚠\033[0m %s\n' "$*" >&2; }
log_error() { printf '\033[0;31m✗\033[0m %s\n' "$*" >&2; }
log_step() { printf '\n\033[1m== %s ==\033[0m\n' "$*"; }
die() { log_error "$*"; exit 1; }
# --- Cleanup on exit ---
cleanup() {
[ -n "$BUILD_DIR" ] && rm -rf "$BUILD_DIR"
}
trap cleanup EXIT
# --- Check mode ---
if [ "${1:-}" = "--check" ]; then
log_step "BW CLI installation check"
if command -v docker >/dev/null 2>&1; then
log_ok "docker on PATH"
else
log_error "docker not on PATH"
fi
if docker image inspect "$BW_IMAGE" >/dev/null 2>&1; then
log_ok "Docker image ${BW_IMAGE} exists"
else
log_error "Docker image ${BW_IMAGE} missing"
fi
if [ -x "${INSTALL_BIN}/bw" ]; then
log_ok "Host wrapper at ${INSTALL_BIN}/bw"
else
log_error "Host wrapper at ${INSTALL_BIN}/bw missing"
fi
if [ -f "${INSTALL_LIB}/entrypoint.sh" ]; then
log_ok "Entrypoint at ${INSTALL_LIB}/entrypoint.sh"
else
log_error "Entrypoint at ${INSTALL_LIB}/entrypoint.sh missing"
fi
exit 0
fi
# --- Prerequisites ---
command -v docker >/dev/null 2>&1 || die "docker not found on PATH"
log_step "Installing container-based Bitwarden CLI (native Rust, no Node.js)"
# --- Step 1: Download and extract the native binary ---
BUILD_DIR=$(mktemp -d)
log_info "Downloading bw ${BW_VERSION} native binary..."
docker run --rm -v "${BUILD_DIR}:/build" alpine:3.20 \
sh -c "apk add --no-cache unzip >/dev/null 2>&1 && \
wget -q -O /build/bw.zip '${BW_BINARY_URL}' && \
unzip -o /build/bw.zip -d /build/ && \
rm /build/bw.zip && \
chmod +x /build/bw"
[ -f "${BUILD_DIR}/bw" ] || die "download failed: bw binary not found"
log_ok "Downloaded native binary"
# --- Step 2: Build the Docker image ---
log_info "Building Docker image ${BW_IMAGE}..."
DOCKERFILE_DIR="${REPO_ROOT}/docker/bw-native"
if [ ! -f "${DOCKERFILE_DIR}/Dockerfile" ]; then
die "Dockerfile not found: ${DOCKERFILE_DIR}/Dockerfile"
fi
cp "${BUILD_DIR}/bw" "${DOCKERFILE_DIR}/bw"
docker build -t "$BW_IMAGE" "$DOCKERFILE_DIR"
rm -f "${DOCKERFILE_DIR}/bw"
log_ok "Built image ${BW_IMAGE}"
# --- Step 3: Install host-side wrapper and entrypoint ---
mkdir -p "$INSTALL_BIN" "$INSTALL_LIB"
cp "${HERE}/bw-cli.sh" "${INSTALL_BIN}/bw"
chmod 755 "${INSTALL_BIN}/bw"
log_ok "Installed wrapper to ${INSTALL_BIN}/bw"
cp "${HERE}/bw-entrypoint.sh" "${INSTALL_LIB}/entrypoint.sh"
chmod 755 "${INSTALL_LIB}/entrypoint.sh"
log_ok "Installed entrypoint to ${INSTALL_LIB}/entrypoint.sh"
# --- Step 4: Verify ---
log_info "Verifying installation..."
if "${INSTALL_BIN}/bw" --version >/dev/null 2>&1; then
log_ok "bw CLI is operational"
else
log_warn "bw wrapper installed but verification call failed"
log_warn "check ~/.config/bw/env credentials and try: bw status"
fi
log_step "Installation complete"
log_info "Usage: bw status | bw list items | bw get password \"Item Name\""