A single bash script that runs a coding harness (pi by default) inside a rootless Ubuntu 24.04 container with only the current directory mounted at /project, an explicit egress allowlist and an explicit environment: nothing is passed in that was not named on the command line or in a config file. Network enforcement here is empirical rather than assumed (tests/spike_network.sh, docs/networking.md). The original design -- a sidecar proxy on an internal network -- does not work rootless on this host, so allow mode runs pasta with --map-host-loopback, installs an inet aisb ruleset inside the container that drops every egress path except the gate's, and relays through a squid gate bound to the host's loopback that resolves names itself and refuses anything unlisted. The entrypoint checks that the default-drop rule really exists before setpriv drops to uid 1000 with an empty capability set, and exits 77/78 rather than run unenforced. The Containerfile, the entrypoint, the squid config generator and the ruleset renderer all live in bin/ai-sandbox, and the image is tagged by content hash, so a policy change can never silently reuse a stale image. Tests are pure bash: 161 assertions start no container and touch no network, 256 run real ones, including proof that a raw socket, a stripped proxy env and DNS all stay blocked while an allowlisted host works over both http and CONNECT. LLM-Generated: true
65 lines
2.2 KiB
Bash
Executable File
65 lines
2.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# install.sh -- put ai-sandbox on PATH and wire up an alias.
|
|
#
|
|
# ./install.sh install to ~/.local/bin, print the alias line
|
|
# ./install.sh --alias pi also append the alias to ~/.bashrc
|
|
# ./install.sh --prefix DIR install somewhere else
|
|
# ./install.sh --uninstall remove what this script installed
|
|
set -Eeuo pipefail
|
|
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PREFIX="${HOME}/.local/bin"
|
|
ALIAS_NAME=""
|
|
UNINSTALL=0
|
|
|
|
while (($#)); do
|
|
case "$1" in
|
|
--prefix) PREFIX="${2:?--prefix needs a directory}"; shift 2 ;;
|
|
--prefix=*) PREFIX="${1#*=}"; shift ;;
|
|
--alias) ALIAS_NAME="${2:?--alias needs a name, e.g. --alias pi}"; shift 2 ;;
|
|
--alias=*) ALIAS_NAME="${1#*=}"; shift ;;
|
|
--uninstall) UNINSTALL=1; shift ;;
|
|
-h|--help) sed -n '2,10p' "$0"; exit 0 ;;
|
|
*) echo "unknown option: $1" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
target="$PREFIX/ai-sandbox"
|
|
rcfile="${HOME}/.bashrc"
|
|
|
|
if (( UNINSTALL )); then
|
|
[[ -L "$target" || -f "$target" ]] && { rm -f "$target"; echo "removed $target"; } || echo "nothing at $target"
|
|
if [[ -n "$ALIAS_NAME" ]]; then
|
|
tmp="$(mktemp)"
|
|
grep -v "^alias ${ALIAS_NAME}=" "$rcfile" > "$tmp" 2>/dev/null || true
|
|
mv "$tmp" "$rcfile"; echo "removed the ${ALIAS_NAME} alias from $rcfile"
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
[[ -x "$HERE/bin/ai-sandbox" ]] || { echo "bin/ai-sandbox is missing or not executable" >&2; exit 1; }
|
|
command -v podman > /dev/null || echo "warning: podman is not installed; ai-sandbox needs it"
|
|
|
|
mkdir -p "$PREFIX"
|
|
ln -sfn "$HERE/bin/ai-sandbox" "$target"
|
|
echo "installed $target -> $HERE/bin/ai-sandbox"
|
|
|
|
if [[ -n "$ALIAS_NAME" ]]; then
|
|
line="alias ${ALIAS_NAME}='${target}'"
|
|
if grep -qxF "$line" "$rcfile" 2>/dev/null; then
|
|
echo "alias already present in $rcfile"
|
|
else
|
|
printf '\n# added by ai-sandbox install.sh\n%s\n' "$line" >> "$rcfile"
|
|
echo "added to $rcfile: $line"
|
|
fi
|
|
else
|
|
echo
|
|
echo "To use it as a harness wrapper, add this to $rcfile:"
|
|
echo " alias pi='$target'"
|
|
echo "then: source $rcfile && cd your/project && pi --allow api.anthropic.com --env ANTHROPIC_API_KEY"
|
|
fi
|
|
|
|
echo
|
|
echo "next: $target doctor # sanity-check this machine"
|
|
echo " $target build # build the sandbox image now (otherwise built on first run)"
|