diff --git a/sim/cluster0/populate_lab_setup.sh b/sim/cluster0/populate_lab_setup.sh index 7ed3934..42b70d6 100644 --- a/sim/cluster0/populate_lab_setup.sh +++ b/sim/cluster0/populate_lab_setup.sh @@ -75,6 +75,7 @@ run_phase_app() { run_script "$ROOT/scripts/compose-lab-backend.sh" run_script "$ROOT/scripts/deploy-ac-hub.sh" if is_primary_node; then + run_script "$ROOT/scripts/deploy-remote-access-lab.sh" || journal_warn remote_access_lab "WG/RSSH install failed (non-fatal)" run_script "$ROOT/scripts/ensure-auth-email-bearer.sh" || journal_warn auth_bearer "mint failed" run_script "$ROOT/scripts/compose-lab-backend.sh" fi diff --git a/sim/cluster0/scripts/compose-lab-backend.sh b/sim/cluster0/scripts/compose-lab-backend.sh index fb6e38c..1f1227d 100755 --- a/sim/cluster0/scripts/compose-lab-backend.sh +++ b/sim/cluster0/scripts/compose-lab-backend.sh @@ -136,6 +136,29 @@ API_BEARER_PHP="" if [ -n "$API_BEARER_TOKEN" ]; then API_BEARER_PHP="$(printf '%s' "$API_BEARER_TOKEN" | sed "s/'/\\\\'/g")" fi +WG_ENDPOINT_CFG="${WG_ENDPOINT:-}" +WG_SERVER_PUBLIC_KEY_CFG="${WG_SERVER_PUBLIC_KEY:-}" +WG_PROVISION="${WG_PROVISION_PEERS:-0}" +if [ -f /etc/wireguard/keys/server.publickey ] && [ -z "$WG_SERVER_PUBLIC_KEY_CFG" ]; then + WG_SERVER_PUBLIC_KEY_CFG="$(cat /etc/wireguard/keys/server.publickey)" +fi +if [ -z "$WG_ENDPOINT_CFG" ] && [ -n "$WG_SERVER_PUBLIC_KEY_CFG" ]; then + WG_ENDPOINT_CFG="${CAST01_HOST:-cast01}.${CAST_DOMAIN:-intra.raptor.org}:51820" + WG_PROVISION=1 +fi +WG_PROVISION_PHP=false +RSSH_PROVISION_PHP=false +[ "$WG_PROVISION" = "1" ] && WG_PROVISION_PHP=true +RSSH_BASTION_HOST_CFG="${RSSH_BASTION_HOST:-}" +RSSH_BASTION_PORT_CFG="${RSSH_BASTION_PORT:-22}" +if [ -z "$RSSH_BASTION_HOST_CFG" ] && [ -n "$WG_SERVER_PUBLIC_KEY_CFG" ]; then + RSSH_BASTION_HOST_CFG="${CAST01_HOST:-cast01}.${CAST_DOMAIN:-intra.raptor.org}" +fi +RSSH_PROVISION="${RSSH_PROVISION_USERS:-0}" +if [ -n "$RSSH_BASTION_HOST_CFG" ]; then + RSSH_PROVISION=1 +fi +[ "$RSSH_PROVISION" = "1" ] && RSSH_PROVISION_PHP=true URL_SHORTENER_API_BASE_CFG="${URL_SHORTENER_API_BASE:-${SHORT_LINKS_PUBLIC_BASE}}" URL_SHORTENER_API_HOST_CFG="${URL_SHORTENER_API_HOST:-}" mkdir -p "${COMPOSED}/config" @@ -165,10 +188,27 @@ return [ 'rbac' => ['default_company_slug' => 'default', 'default_company_id' => 1], 'analytics' => ['enabled' => false, 'measurement_id' => '', 'debug' => false], 'remote_access' => [ - 'wg_endpoint' => '', - 'wg_server_public_key' => '', - 'provision_peers' => false, - 'require_wg_tools' => false, + 'wg_endpoint' => '${WG_ENDPOINT_CFG}', + 'wg_server_public_key' => '${WG_SERVER_PUBLIC_KEY_CFG}', + 'wg_interface' => 'wg0', + 'wg_server_allowed_ips' => '172.200.2.1/32', + 'wg_client_ip_prefix' => '172.200.2.', + 'wg_client_ip_min' => 10, + 'wg_client_ip_max' => 250, + 'wg_set_prefix' => 'sudo -n ', + 'provision_peers' => ${WG_PROVISION_PHP:-false}, + 'require_wg_tools' => ${WG_PROVISION_PHP:-false}, + 'session_ttl_s' => 3600, + 'min_poll_interval_s' => 45, + 'rssh' => [ + 'bastion_host' => '${RSSH_BASTION_HOST_CFG}', + 'bastion_port' => ${RSSH_BASTION_PORT_CFG:-22}, + 'local_forward_port' => 8022, + 'remote_port_min' => 18000, + 'remote_port_max' => 18999, + 'provision_users' => ${RSSH_PROVISION_PHP:-false}, + 'bastion_user_script' => __DIR__ . '/../scripts/rssh_bastion_user.sh', + ], ], 'auth' => [ 'encryption_key' => '${AUTH_KEY}', diff --git a/sim/cluster0/scripts/deploy-remote-access-lab.sh b/sim/cluster0/scripts/deploy-remote-access-lab.sh new file mode 100755 index 0000000..ee7f405 --- /dev/null +++ b/sim/cluster0/scripts/deploy-remote-access-lab.sh @@ -0,0 +1,79 @@ +#!/bin/sh +# Lab WireGuard + RSSH bastion on cast01 primary (ac/* cluster). +set -eu +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +# shellcheck source=/dev/null +. "$ROOT/scripts/lib/common.sh" +load_cluster_env +load_secrets_lab 2>/dev/null || true + +is_primary_node || { log "deploy-remote-access-lab: skip (not primary)"; exit 0; } + +WG_EXAMPLES="${AC_WORKSPACE_ROOT:-/var/www/ac/workspace}/ac-ms-remote-access/examples/wireguard" +[ -d "$WG_EXAMPLES" ] || die "missing $WG_EXAMPLES (init ac-ms-remote-access submodule)" + +WG_IF="${WG_INTERFACE:-wg0}" +WG_PORT="${WG_LISTEN_PORT:-51820}" +WG_NET_PREFIX="${WG_CLIENT_IP_PREFIX:-172.200.2.}" +WG_DIR="/etc/wireguard" +WG_CONF="${WG_DIR}/${WG_IF}.conf" +SUDOERS_DST="/etc/sudoers.d/androidcast-wg" + +mkdir -p "$WG_DIR" "${WG_DIR}/keys" +chmod 700 "${WG_DIR}/keys" + +if [ -z "${WG_SERVER_PRIVATE_KEY:-}" ] || [ -z "${WG_SERVER_PUBLIC_KEY:-}" ]; then + if [ ! -f "${WG_DIR}/keys/server.privatekey" ]; then + log "generating lab WG server keys" + wg genkey | tee "${WG_DIR}/keys/server.privatekey" | wg pubkey > "${WG_DIR}/keys/server.publickey" + chmod 600 "${WG_DIR}/keys/server.privatekey" + fi + WG_SERVER_PRIVATE_KEY="$(cat "${WG_DIR}/keys/server.privatekey")" + WG_SERVER_PUBLIC_KEY="$(cat "${WG_DIR}/keys/server.publickey")" +fi + +if [ ! -f "$WG_CONF" ] || [ "${FORCE_WG_CONF:-0}" = "1" ]; then + log "writing ${WG_CONF} listen=${WG_PORT}" + cat > "$WG_CONF" </dev/null || wg-quick up "$WG_IF" 2>/dev/null || true +rc-update add "wg-quick@${WG_IF}" default 2>/dev/null || true + +# RSSH: ephemeral ra-* users via sshd snippet (lab — port 22 on cast01) +RSSH_SSHD="/etc/ssh/sshd_config.d/90-androidcast-ra.conf" +if [ ! -f "$RSSH_SSHD" ] || [ "${FORCE_RSSH_SSHD:-0}" = "1" ]; then + log "install ${RSSH_SSHD}" + cat > "$RSSH_SSHD" <<'EOF' +# Android Cast lab RSSH bastion — Match User ra-* +Match User ra-* + PasswordAuthentication yes + PubkeyAuthentication no + AllowTcpForwarding yes + GatewayPorts no + X11Forwarding no + PermitTTY no +EOF + rc-service sshd reload 2>/dev/null || rc-service sshd restart 2>/dev/null || true +fi + +BASTION_SCRIPT="${COMPOSE_BACKEND:-/var/www/ac/composed/backend}/scripts/rssh_bastion_user.sh" +if [ -f "$ROOT/lab-seeds/backend/scripts/rssh_bastion_user.sh" ] && [ ! -x "$BASTION_SCRIPT" ]; then + mkdir -p "$(dirname "$BASTION_SCRIPT")" + install -m 755 "$ROOT/lab-seeds/backend/scripts/rssh_bastion_user.sh" "$BASTION_SCRIPT" +fi + +log "deploy-remote-access-lab_ok pub=${WG_SERVER_PUBLIC_KEY} endpoint=${WG_ENDPOINT:-cast01:${WG_PORT}}" diff --git a/sim/cluster0/secrets.lab.env.example b/sim/cluster0/secrets.lab.env.example index 0260d59..1841c79 100644 --- a/sim/cluster0/secrets.lab.env.example +++ b/sim/cluster0/secrets.lab.env.example @@ -13,10 +13,15 @@ AUTH_ENCRYPTION_KEY=lab-cluster-dev-32-char-min-secret!! # WG_SERVER_PRIVATE_KEY= # WG_SERVER_PUBLIC_KEY= # WG_ENDPOINT=cast01.intra.raptor.org:51820 +# WG_PROVISION_PEERS=1 # RSSH bastion (lab) # RSSH_BASTION_HOST=cast01.intra.raptor.org # RSSH_BASTION_PORT=22 +# RSSH_PROVISION_USERS=1 + +# Iodine DNS tunnel (FE UDP 5350 — dev test password in app dev settings) +# IODINE_UDP_PORT=5350 # Outbound mail (msmtp → Gmail — copy MSMTP_APP_PASSWORD from alpine-be /etc/androidcast/msmtp.secret) # Use quotes if the app password contains spaces.