#!/bin/sh # Pin the KKR staging hostnames to the dev box in /etc/hosts. HAProxy :443 on the # box passes them through by SNI over the nasran tunnel. # curl agent.sufi.my | sh enable # curl agent.sufi.my | sh -s -- off remove # A hosts entry beats system DNS, WARP and DoH-less resolvers alike, and leaves # all other DNS untouched. Everything runs inside main(), called on the last # line: a truncated `curl | sh` download therefore executes nothing. # Reports the outcome (OS, result, error text) to the server it was fetched from; # set KKR_NO_REPORT=1 to disable. set -eu # BOX, HOSTS_LIST, HEALTH_URL and VER come from config.json; the Worker fills the {{...}} placeholders. BOX="210.187.49.155" HOSTS_LIST="myinfra-stg.kkr.gov.my kube.kkr.gov.my git.kkr.gov.my myinfra-auth.kkr.gov.my" HEALTH_URL="https://myinfra-stg.kkr.gov.my/api/health" VER="2026-10-29.1" BEGIN="# BEGIN kkr-agent" END="# END kkr-agent" FILE="/etc/hosts" REPORT_URL="https://agent.sufi.my/log" TMP="" REPORTED=0 say() { printf '==> %s\n' "$*"; } # report : best effort, never blocks or fails the install. report() { [ -n "${KKR_NO_REPORT:-}" ] && return 0 REPORTED=1 curl -s -m 5 -o /dev/null -X POST "$REPORT_URL" \ --data-urlencode "ev=$1" --data-urlencode "ver=$VER" --data-urlencode "os=$(uname -sr)" \ --data-urlencode "msg=$(printf '%s' "$2" | tr '\n' ' ' | cut -c1-300)" 2>/dev/null || true } die() { printf 'error: %s\n' "$*" >&2; report fail "$*"; exit 1; } # Runs on every exit: remove the temp file, and report a failure no die() already reported. finish() { rc=$? [ -n "$TMP" ] && rm -f "$TMP" [ "$rc" -ne 0 ] && [ "$REPORTED" -eq 0 ] && report fail "unexpected exit $rc" return 0 } trap finish EXIT SUDO="" [ "$(id -u)" -eq 0 ] || SUDO="sudo" # Copy of /etc/hosts cleaned of every earlier attempt: our marker lines, and any # uncommented line naming one of our hosts (manual pins, an old or partial block, # a block whose END marker is missing). Never skips ranges, so unrelated lines # always survive. Re-runs are idempotent. strip() { awk -v b="$BEGIN" -v e="$END" -v n="$HOSTS_LIST" ' BEGIN { split(n, a, " "); for (i in a) mine[a[i]] = 1 } $0 == b || $0 == e { next } $1 !~ /^#/ { for (i = 2; i <= NF; i++) if ($i in mine) next } { print }' "$FILE" } # Drop every resolver cache so the new pins apply at once. flush() { case "$(uname -s)" in Darwin) $SUDO dscacheutil -flushcache; $SUDO killall -HUP mDNSResponder 2>/dev/null || true ;; Linux) $SUDO resolvectl flush-caches 2>/dev/null || true $SUDO nscd -i hosts 2>/dev/null || true $SUDO systemd-resolve --flush-caches 2>/dev/null || true ;; esac } apply() { TMP=$(mktemp) strip > "$TMP" if [ "$1" = "on" ]; then { echo "$BEGIN"; for h in $HOSTS_LIST; do printf '%s %s\n' "$BOX" "$h"; done; echo "$END"; } >> "$TMP" fi $SUDO cp "$FILE" "$FILE.kkr-agent.bak" $SUDO cp "$TMP" "$FILE" flush } verify() { for h in $HOSTS_LIST; do got=$(curl -s -m 5 -o /dev/null -w '%{remote_ip}' "https://$h/" || true) [ "$got" = "$BOX" ] || die "$h resolves to '${got:-nothing}', expected $BOX. A VPN or proxy may be overriding /etc/hosts." done # Retry: the tunnel on the box can take a few seconds to answer after a cold start, # and sometimes stalls for tens of seconds, so the last attempt waits longer. for t in 10 10 30; do code=$(curl -s -m "$t" -o /dev/null -w '%{http_code}' "$HEALTH_URL" || true) [ "$code" = "200" ] && { say "Connected: $HEALTH_URL returned 200"; report ok "connected"; return 0; } sleep 2 done # The pins are in place and resolve to the box, so a slow health check is a warning, not a failed install. say "WARNING: hosts pinned, but $HEALTH_URL returned ${code:-no answer}. The box may be slow; retry in a minute." report slow "health returned ${code:-none}" return 0 } main() { case "$(uname -s)" in Darwin|Linux) ;; MINGW*|MSYS*|CYGWIN*) die "Windows: open PowerShell as Administrator and run: irm agent.sufi.my | iex" ;; *) die "unsupported OS: $(uname -s)" ;; esac [ -n "${KKR_NO_REPORT:-}" ] || say "Reports the result (OS, ok/fail, error text) to $REPORT_URL. Disable: KKR_NO_REPORT=1" if [ "${1:-}" = "off" ]; then apply off; say "Removed KKR entries from $FILE (backup: $FILE.kkr-agent.bak)"; report off "removed" else apply on; verify fi } main "$@"