Files
matt 4d60fdd139 Initial commit: Imperva WAF demo lab
Flight-booking app scaffolded from the source running on the GCP host,
plus the four-screen frontend and three OWASP attack endpoints (SQLi,
reflected XSS, path traversal) built and locally verified against a
live uvicorn/vite dev pair. Includes deploy.sh (local build -> ship
over ssh -> swap on host) and docs/ carried over from the handoff.
2026-07-29 11:08:56 -07:00

124 lines
3.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Local build -> ship over ssh -> swap on host. No container registry (see docs/DECISIONS.md D8).
#
# Run this from a real terminal on your workstation (NOT inside a sandboxed
# coding-agent shell) with the `gcp-lab` podman connection already configured:
#
# podman system connection add gcp-lab \
# --identity ~/.ssh/google_compute_engine \
# ssh://matt@35.203.147.44:22/run/user/1001/podman/podman.sock
#
# Usage:
# ./deploy.sh # build both, ship both, swap both containers
# VERSION=v2 ./deploy.sh # tag images v2 instead of a timestamp
# ./deploy.sh --build --ship --swap # explicit equivalent of the default
# ./deploy.sh --restart-caddy # after editing imperva-proxy/Caddyfile
set -euo pipefail
# --- config -------------------------------------------------------------
HOST="35.203.147.44"
HOST_USER="matt"
SSH_KEY="$HOME/.ssh/google_compute_engine"
CONNECTION="gcp-lab"
VERSION="${VERSION:-$(date +%Y%m%d%H%M%S)}"
REMOTE_PROXY_DIR="/home/matt/imperva-proxy"
BACKEND_IMAGE="backend-api"
FRONTEND_IMAGE="frontend-vue"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# --- steps ----------------------------------------------------------------
do_build() {
echo "==> Building ${BACKEND_IMAGE}:${VERSION}"
podman build -t "${BACKEND_IMAGE}:${VERSION}" -t "${BACKEND_IMAGE}:latest" ./backend
echo "==> Building ${FRONTEND_IMAGE}:${VERSION}"
podman build -t "${FRONTEND_IMAGE}:${VERSION}" -t "${FRONTEND_IMAGE}:latest" ./frontend
}
do_ship() {
echo "==> Shipping ${BACKEND_IMAGE}:${VERSION} over ssh"
podman save "${BACKEND_IMAGE}:${VERSION}" | ssh -i "$SSH_KEY" "${HOST_USER}@${HOST}" podman load
echo "==> Shipping ${FRONTEND_IMAGE}:${VERSION} over ssh"
podman save "${FRONTEND_IMAGE}:${VERSION}" | ssh -i "$SSH_KEY" "${HOST_USER}@${HOST}" podman load
}
do_swap() {
echo "==> Swapping backend-api container"
podman --connection "$CONNECTION" rm -f backend-api >/dev/null 2>&1 || true
podman --connection "$CONNECTION" run -d \
--name backend-api \
--restart always \
-p 8000:8000 \
"${BACKEND_IMAGE}:${VERSION}"
echo "==> Swapping frontend-vue container"
podman --connection "$CONNECTION" rm -f frontend-vue >/dev/null 2>&1 || true
podman --connection "$CONNECTION" run -d \
--name frontend-vue \
--restart always \
-p 8080:8080 \
"${FRONTEND_IMAGE}:${VERSION}"
}
do_restart_caddy() {
echo "==> Copying Caddyfile to host"
scp -i "$SSH_KEY" ./imperva-proxy/Caddyfile "${HOST_USER}@${HOST}:${REMOTE_PROXY_DIR}/Caddyfile"
echo "==> Validating Caddyfile on host"
podman --connection "$CONNECTION" exec caddy-proxy caddy validate --config /etc/caddy/Caddyfile
echo "==> Restarting caddy-proxy"
podman --connection "$CONNECTION" restart caddy-proxy
}
check_connection() {
if ! podman system connection list --format '{{.Name}}' 2>/dev/null | grep -qx "$CONNECTION"; then
echo "error: podman connection '${CONNECTION}' is not configured." >&2
echo " podman system connection add ${CONNECTION} --identity ${SSH_KEY} ssh://${HOST_USER}@${HOST}:22/run/user/1001/podman/podman.sock" >&2
exit 1
fi
}
# --- arg parsing ------------------------------------------------------
RUN_BUILD=false
RUN_SHIP=false
RUN_SWAP=false
RUN_RESTART_CADDY=false
if [ "$#" -eq 0 ]; then
RUN_BUILD=true
RUN_SHIP=true
RUN_SWAP=true
else
for arg in "$@"; do
case "$arg" in
--build) RUN_BUILD=true ;;
--ship) RUN_SHIP=true ;;
--swap) RUN_SWAP=true ;;
--restart-caddy) RUN_RESTART_CADDY=true ;;
*)
echo "unknown flag: $arg" >&2
exit 1
;;
esac
done
fi
if [ "$RUN_SHIP" = true ] || [ "$RUN_SWAP" = true ] || [ "$RUN_RESTART_CADDY" = true ]; then
check_connection
fi
[ "$RUN_BUILD" = true ] && do_build
[ "$RUN_SHIP" = true ] && do_ship
[ "$RUN_SWAP" = true ] && do_swap
[ "$RUN_RESTART_CADDY" = true ] && do_restart_caddy
echo "==> Done (version: ${VERSION})"