feat(260504-bw4): add --with-ssh and --ssh-key flags to claudebox
This commit is contained in:
parent
29996a2d40
commit
41ebf10458
1 changed files with 107 additions and 0 deletions
107
claudebox.sh
107
claudebox.sh
|
|
@ -4,6 +4,8 @@ DRY_RUN=false
|
||||||
CHECK_MODE=false
|
CHECK_MODE=false
|
||||||
SHELL_MODE=false
|
SHELL_MODE=false
|
||||||
GC_MODE=false
|
GC_MODE=false
|
||||||
|
WITH_SSH=false
|
||||||
|
SSH_KEYS=()
|
||||||
CLAUDE_ARGS=()
|
CLAUDE_ARGS=()
|
||||||
|
|
||||||
while (( $# > 0 )); do
|
while (( $# > 0 )); do
|
||||||
|
|
@ -13,6 +15,12 @@ while (( $# > 0 )); do
|
||||||
--check) CHECK_MODE=true ;;
|
--check) CHECK_MODE=true ;;
|
||||||
--shell) SHELL_MODE=true ;;
|
--shell) SHELL_MODE=true ;;
|
||||||
--gc) GC_MODE=true ;;
|
--gc) GC_MODE=true ;;
|
||||||
|
--with-ssh) WITH_SSH=true ;;
|
||||||
|
--ssh-key)
|
||||||
|
shift
|
||||||
|
[[ $# -gt 0 ]] || { echo "Error: --ssh-key requires a path" >&2; exit 1; }
|
||||||
|
SSH_KEYS+=("${1/#\~/$HOME}")
|
||||||
|
;;
|
||||||
--) shift; CLAUDE_ARGS+=("$@"); break ;;
|
--) shift; CLAUDE_ARGS+=("$@"); break ;;
|
||||||
*) CLAUDE_ARGS+=("$1") ;;
|
*) CLAUDE_ARGS+=("$1") ;;
|
||||||
esac
|
esac
|
||||||
|
|
@ -20,6 +28,22 @@ while (( $# > 0 )); do
|
||||||
done
|
done
|
||||||
export SKIP_AUDIT # consumed by Plan 02 audit display
|
export SKIP_AUDIT # consumed by Plan 02 audit display
|
||||||
|
|
||||||
|
# Validate and resolve SSH key paths
|
||||||
|
for _i in "${!SSH_KEYS[@]}"; do
|
||||||
|
_key="${SSH_KEYS[$_i]}"
|
||||||
|
# Expand ~ if not already done
|
||||||
|
_key="${_key/#\~/$HOME}"
|
||||||
|
# Make absolute
|
||||||
|
if [[ "$_key" != /* ]]; then
|
||||||
|
_key="$PWD/$_key"
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$_key" || ! -r "$_key" ]]; then
|
||||||
|
echo "Error: --ssh-key path does not exist or is not readable: $_key" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
SSH_KEYS[$_i]="$_key"
|
||||||
|
done
|
||||||
|
|
||||||
# Garbage-collect stale instance directories (D-11, INST-04)
|
# Garbage-collect stale instance directories (D-11, INST-04)
|
||||||
gc_instances() {
|
gc_instances() {
|
||||||
local removed=0
|
local removed=0
|
||||||
|
|
@ -106,6 +130,30 @@ else
|
||||||
BOLD="" RESET="" DIM="" CYAN="" YELLOW="" GREEN="" RED=""
|
BOLD="" RESET="" DIM="" CYAN="" YELLOW="" GREEN="" RED=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# SSH agent validation (must be after ANSI vars are set)
|
||||||
|
if [[ "$WITH_SSH" == true ]]; then
|
||||||
|
if [[ -v SSH_AUTH_SOCK && -S "$SSH_AUTH_SOCK" ]]; then
|
||||||
|
: # agent is running, keep WITH_SSH=true
|
||||||
|
else
|
||||||
|
echo "${YELLOW}Warning: --with-ssh given but SSH_AUTH_SOCK is unset or not a socket; agent will not be forwarded.${RESET}" >&2
|
||||||
|
WITH_SSH=false
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Compute SSH active state
|
||||||
|
if [[ "$WITH_SSH" == true ]] || (( ${#SSH_KEYS[@]} > 0 )); then
|
||||||
|
SSH_ACTIVE=true
|
||||||
|
else
|
||||||
|
SSH_ACTIVE=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine if known_hosts should be mounted
|
||||||
|
if [[ "$SSH_ACTIVE" == true && -f "$HOME/.ssh/known_hosts" ]]; then
|
||||||
|
KNOWN_HOSTS_MOUNT=true
|
||||||
|
else
|
||||||
|
KNOWN_HOSTS_MOUNT=false
|
||||||
|
fi
|
||||||
|
|
||||||
# Mask sensitive values (D-04)
|
# Mask sensitive values (D-04)
|
||||||
mask_value() {
|
mask_value() {
|
||||||
local name="$1" value="$2"
|
local name="$1" value="$2"
|
||||||
|
|
@ -290,6 +338,13 @@ for var in "${HOST_ALLOWLIST[@]}"; do
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# SSH_AUTH_SOCK: pass into sandbox when agent forwarding is active
|
||||||
|
if [[ "$WITH_SSH" == true ]]; then
|
||||||
|
ENV_ARGS+=(--setenv SSH_AUTH_SOCK "$SSH_AUTH_SOCK")
|
||||||
|
AUDIT_HOST_KEYS+=(SSH_AUTH_SOCK)
|
||||||
|
AUDIT_HOST_VALS[SSH_AUTH_SOCK]="$SSH_AUTH_SOCK"
|
||||||
|
fi
|
||||||
|
|
||||||
# CLAUDEBOX_EXTRA_ENV escape hatch (D-03, comma-separated)
|
# CLAUDEBOX_EXTRA_ENV escape hatch (D-03, comma-separated)
|
||||||
if [[ -v CLAUDEBOX_EXTRA_ENV ]]; then
|
if [[ -v CLAUDEBOX_EXTRA_ENV ]]; then
|
||||||
IFS=',' read -ra EXTRAS <<< "$CLAUDEBOX_EXTRA_ENV"
|
IFS=',' read -ra EXTRAS <<< "$CLAUDEBOX_EXTRA_ENV"
|
||||||
|
|
@ -367,6 +422,22 @@ print_audit() {
|
||||||
if [[ "$CREDS_MOUNT" == true ]]; then
|
if [[ "$CREDS_MOUNT" == true ]]; then
|
||||||
printf ' %-12s %s (read-write)\n' "credentials" "$CREDS_FILE" >&2
|
printf ' %-12s %s (read-write)\n' "credentials" "$CREDS_FILE" >&2
|
||||||
fi
|
fi
|
||||||
|
if [[ "$SSH_ACTIVE" == true ]]; then
|
||||||
|
if [[ "$WITH_SSH" == true ]]; then
|
||||||
|
printf ' %-12s %s (read-write, --with-ssh)\n' "agent" "$SSH_AUTH_SOCK" >&2
|
||||||
|
fi
|
||||||
|
for _key in "${SSH_KEYS[@]}"; do
|
||||||
|
_base=$(basename "$_key")
|
||||||
|
printf ' %-12s %s (read-only)\n' "ssh-key" "$_key" >&2
|
||||||
|
if [[ -f "${_key}.pub" ]]; then
|
||||||
|
printf ' %-12s %s (read-only)\n' "ssh-key" "${_key}.pub" >&2
|
||||||
|
fi
|
||||||
|
unset _base
|
||||||
|
done
|
||||||
|
if [[ "$KNOWN_HOSTS_MOUNT" == true ]]; then
|
||||||
|
printf ' %-12s %s (read-only)\n' "known_hosts" "$HOME/.ssh/known_hosts" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
echo "" >&2
|
echo "" >&2
|
||||||
|
|
||||||
|
|
@ -442,6 +513,24 @@ if [[ "$DRY_RUN" == true ]]; then
|
||||||
if [[ "$CREDS_MOUNT" == true ]]; then
|
if [[ "$CREDS_MOUNT" == true ]]; then
|
||||||
echo " --bind $CREDS_FILE $HOME/.claude/.credentials.json \\"
|
echo " --bind $CREDS_FILE $HOME/.claude/.credentials.json \\"
|
||||||
fi
|
fi
|
||||||
|
if [[ "$SSH_ACTIVE" == true ]]; then
|
||||||
|
echo " --dir $HOME/.ssh \\"
|
||||||
|
if [[ "$WITH_SSH" == true ]]; then
|
||||||
|
echo " --bind $SSH_AUTH_SOCK $SSH_AUTH_SOCK \\"
|
||||||
|
fi
|
||||||
|
for _dry_key in "${SSH_KEYS[@]}"; do
|
||||||
|
_dry_base=$(basename "$_dry_key")
|
||||||
|
echo " --ro-bind $_dry_key $HOME/.ssh/$_dry_base \\"
|
||||||
|
if [[ -f "${_dry_key}.pub" ]]; then
|
||||||
|
echo " --ro-bind ${_dry_key}.pub $HOME/.ssh/${_dry_base}.pub \\"
|
||||||
|
fi
|
||||||
|
unset _dry_base
|
||||||
|
done
|
||||||
|
if [[ "$KNOWN_HOSTS_MOUNT" == true ]]; then
|
||||||
|
echo " --ro-bind $HOME/.ssh/known_hosts $HOME/.ssh/known_hosts \\"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
unset _dry_key
|
||||||
printf ' --ro-bind %q %s/.gitconfig \\\n' "$GITCONFIG_TMP" "$HOME"
|
printf ' --ro-bind %q %s/.gitconfig \\\n' "$GITCONFIG_TMP" "$HOME"
|
||||||
echo " --bind $CWD $CWD \\"
|
echo " --bind $CWD $CWD \\"
|
||||||
echo " --chdir $CWD \\"
|
echo " --chdir $CWD \\"
|
||||||
|
|
@ -485,6 +574,24 @@ fi
|
||||||
if [[ "$CREDS_MOUNT" == true ]]; then
|
if [[ "$CREDS_MOUNT" == true ]]; then
|
||||||
BWRAP_ARGS+=(--bind "$CREDS_FILE" "$HOME/.claude/.credentials.json")
|
BWRAP_ARGS+=(--bind "$CREDS_FILE" "$HOME/.claude/.credentials.json")
|
||||||
fi
|
fi
|
||||||
|
if [[ "$SSH_ACTIVE" == true ]]; then
|
||||||
|
BWRAP_ARGS+=(--dir "$HOME/.ssh")
|
||||||
|
if [[ "$WITH_SSH" == true ]]; then
|
||||||
|
BWRAP_ARGS+=(--bind "$SSH_AUTH_SOCK" "$SSH_AUTH_SOCK")
|
||||||
|
fi
|
||||||
|
for _key in "${SSH_KEYS[@]}"; do
|
||||||
|
_base=$(basename "$_key")
|
||||||
|
BWRAP_ARGS+=(--ro-bind "$_key" "$HOME/.ssh/$_base")
|
||||||
|
if [[ -f "${_key}.pub" ]]; then
|
||||||
|
BWRAP_ARGS+=(--ro-bind "${_key}.pub" "$HOME/.ssh/${_base}.pub")
|
||||||
|
fi
|
||||||
|
unset _base
|
||||||
|
done
|
||||||
|
if [[ "$KNOWN_HOSTS_MOUNT" == true ]]; then
|
||||||
|
BWRAP_ARGS+=(--ro-bind "$HOME/.ssh/known_hosts" "$HOME/.ssh/known_hosts")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
unset _key
|
||||||
BWRAP_ARGS+=(
|
BWRAP_ARGS+=(
|
||||||
--ro-bind "$GITCONFIG_TMP" "$HOME/.gitconfig"
|
--ro-bind "$GITCONFIG_TMP" "$HOME/.gitconfig"
|
||||||
--bind "$CWD" "$CWD"
|
--bind "$CWD" "$CWD"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue