Provision LOCALSTACK_AUTH_TOKEN for every repository
LocalStack is a common enough dependency that declaring it per repository is busywork, and the token is already in the host environment when it is needed at all. It is now provisioned host-wide, through the same custom-secret path as the per-repository declarations, so the value stays out of the sandbox and the proxy substitutes it on requests to localstack.cloud. Provisioning is conditional on the sandbox having Docker. LocalStack runs as a container, so on a sandbox created from a non-docker template the credential would be dead weight, and the entry is skipped with a message rather than stored. An unset variable is skipped silently, which costs nothing on a machine that never uses LocalStack. The provisioning body moves into provision_secret so the host-wide and per-repository paths cannot drift apart.
This commit is contained in:
+78
-36
@@ -8,6 +8,13 @@ DEFAULT_MODE="${AI_SBX_MODE:-clone}"
|
||||
DEFAULT_TOKEN_DAYS="${AI_SBX_TOKEN_DAYS:-30}"
|
||||
DEFAULT_TEMPLATE="${AI_SBX_TEMPLATE:-}"
|
||||
DEFAULT_TOOLS="${AI_SBX_TOOLS:-bun}"
|
||||
|
||||
# VAR|host[,host...]|requirement. Provisioned for every repository when the
|
||||
# variable is present in the host environment. "docker" skips the entry on a
|
||||
# sandbox that cannot run containers, where the credential would be useless.
|
||||
HOST_WIDE_SECRETS=(
|
||||
"LOCALSTACK_AUTH_TOKEN|localstack.cloud,*.localstack.cloud|docker"
|
||||
)
|
||||
CLAUDE_HOME="${CLAUDE_HOME:-$HOME/.claude}"
|
||||
|
||||
# Only these leave the host. ~/.claude also holds OAuth credentials, shell
|
||||
@@ -76,6 +83,8 @@ Registry credentials are declared per repository in the user's config
|
||||
directory as a "secrets" file, one line of VAR|host|command each. The command
|
||||
runs on the host and its output becomes an sbx custom secret, so the sandbox
|
||||
sees a placeholder and the proxy substitutes the real value.
|
||||
LOCALSTACK_AUTH_TOKEN is provisioned for every repository when it is set on
|
||||
the host and the sandbox has Docker to make use of it.
|
||||
|
||||
AI_SBX_TOOLS lists mise tools installed globally in the sandbox, defaulting
|
||||
to bun because several Claude plugins run their hooks under it. Set it to an
|
||||
@@ -780,14 +789,80 @@ secret_placeholder() {
|
||||
printf 'sbx-cs-%s' "$digest"
|
||||
}
|
||||
|
||||
sandbox_has_docker() {
|
||||
sbx exec "$SANDBOX_NAME" \
|
||||
bash -lc 'command -v docker >/dev/null' \
|
||||
</dev/null >/dev/null 2>&1
|
||||
}
|
||||
|
||||
provision_secret() {
|
||||
local var="$1" hosts="$2" value="$3"
|
||||
local placeholder
|
||||
placeholder="$(secret_placeholder "$var")"
|
||||
|
||||
local -a host_args=()
|
||||
local host
|
||||
for host in ${hosts//,/ }; do
|
||||
host_args+=(--host "$host")
|
||||
done
|
||||
|
||||
# Piped rather than --value: the secret would otherwise be visible in the
|
||||
# process list to anything running as this user.
|
||||
printf '%s' "$value" |
|
||||
sbx secret set-custom "$SANDBOX_NAME" \
|
||||
"${host_args[@]}" \
|
||||
--env "$var" \
|
||||
--placeholder "$placeholder" >/dev/null 2>&1 ||
|
||||
{
|
||||
printf 'Could not store %s in the sandbox.\n' "$var" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
# A sandbox that already exists keeps whatever environment it was created
|
||||
# with, so the placeholder is exported explicitly.
|
||||
sbx exec "$SANDBOX_NAME" bash -c "
|
||||
persistent=/etc/sandbox-persistent.sh
|
||||
marker=$(printf '%q' "# ai-sbx secret $var")
|
||||
|
||||
grep -Fq \"\$marker\" \"\$persistent\" 2>/dev/null && exit 0
|
||||
|
||||
printf '%s\nexport %s=%s\n' \
|
||||
\"\$marker\" $(printf '%q' "$var") $(printf '%q' "$placeholder") \
|
||||
>>\"\$persistent\"
|
||||
" </dev/null >/dev/null 2>&1 || true
|
||||
|
||||
printf 'Provisioned %s for %s\n' "$var" "${hosts//,/, }"
|
||||
}
|
||||
|
||||
# Credentials worth provisioning for every repository rather than declaring per
|
||||
# repository, taken straight from the host environment. LocalStack only matters
|
||||
# when the agent can run containers, so it is skipped where Docker is absent.
|
||||
install_host_wide_secrets() {
|
||||
local entry var hosts requirement
|
||||
|
||||
for entry in "${HOST_WIDE_SECRETS[@]}"; do
|
||||
IFS='|' read -r var hosts requirement <<<"$entry"
|
||||
|
||||
[[ -n "${!var:-}" ]] || continue
|
||||
|
||||
if [[ "$requirement" == docker ]] && ! sandbox_has_docker; then
|
||||
printf 'Skipping %s: the sandbox has no Docker to run it.\n' "$var" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
provision_secret "$var" "$hosts" "${!var}" || true
|
||||
done
|
||||
}
|
||||
|
||||
install_sandbox_secrets() {
|
||||
install_host_wide_secrets
|
||||
|
||||
local declarations
|
||||
declarations="$(read_secret_declarations)" || return 0
|
||||
|
||||
[[ -n "$declarations" ]] || return 0
|
||||
|
||||
local var hosts command value placeholder
|
||||
local -a host_args
|
||||
local var hosts command value
|
||||
|
||||
while IFS='|' read -r var hosts command; do
|
||||
[[ -n "$var" ]] || continue
|
||||
@@ -804,40 +879,7 @@ install_sandbox_secrets() {
|
||||
continue
|
||||
}
|
||||
|
||||
placeholder="$(secret_placeholder "$var")"
|
||||
|
||||
host_args=()
|
||||
local host
|
||||
for host in ${hosts//,/ }; do
|
||||
host_args+=(--host "$host")
|
||||
done
|
||||
|
||||
# Piped rather than --value: the secret would otherwise be visible in
|
||||
# the process list to anything running as this user.
|
||||
if printf '%s' "$value" |
|
||||
sbx secret set-custom "$SANDBOX_NAME" \
|
||||
"${host_args[@]}" \
|
||||
--env "$var" \
|
||||
--placeholder "$placeholder" >/dev/null 2>&1; then
|
||||
|
||||
printf 'Provisioned %s for %s\n' "$var" "${hosts//,/, }"
|
||||
else
|
||||
printf 'Could not store %s in the sandbox.\n' "$var" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
# A sandbox that already exists keeps whatever environment it was
|
||||
# created with, so the placeholder is exported explicitly.
|
||||
sbx exec "$SANDBOX_NAME" bash -c "
|
||||
persistent=/etc/sandbox-persistent.sh
|
||||
marker=$(printf '%q' "# ai-sbx secret $var")
|
||||
|
||||
grep -Fq \"\$marker\" \"\$persistent\" 2>/dev/null && exit 0
|
||||
|
||||
printf '%s\nexport %s=%s\n' \
|
||||
\"\$marker\" $(printf '%q' "$var") $(printf '%q' "$placeholder") \
|
||||
>>\"\$persistent\"
|
||||
" </dev/null >/dev/null 2>&1 || true
|
||||
provision_secret "$var" "$hosts" "$value" || true
|
||||
|
||||
unset value
|
||||
done <<<"$declarations"
|
||||
|
||||
Reference in New Issue
Block a user