Sfoglia il codice sorgente

add interface up and teardown option to ci script

abhishek9686 23 ore fa
parent
commit
061ae11bac
3 ha cambiato i file con 195 aggiunte e 113 eliminazioni
  1. 6 24
      controllers/ext_client.go
  2. 0 89
      scripts/ci-runner.sh
  3. 189 0
      scripts/netmaker-ci-runner.sh

+ 6 - 24
controllers/ext_client.go

@@ -466,23 +466,6 @@ func getExtClientHAConf(w http.ResponseWriter, r *http.Request) {
 	extclient.IngressGatewayID = targetGwID
 	extclient.Network = networkid
 	extclient.Tags = make(map[models.TagID]struct{})
-	// extclient.Tags[models.TagID(fmt.Sprintf("%s.%s", extclient.Network,
-	// 	models.RemoteAccessTagName))] = struct{}{}
-	// set extclient dns to ingressdns if extclient dns is not explicitly set
-	if (extclient.DNS == "") && (gwnode.IngressDNS != "") {
-		network, _ := logic.GetNetwork(gwnode.Network)
-		dns := gwnode.IngressDNS
-		if len(network.NameServers) > 0 {
-			if dns == "" {
-				dns = strings.Join(network.NameServers, ",")
-			} else {
-				dns += "," + strings.Join(network.NameServers, ",")
-			}
-
-		}
-		extclient.DNS = dns
-
-	}
 
 	listenPort := logic.GetPeerListenPort(host)
 	extclient.IngressGatewayEndpoint = fmt.Sprintf("%s:%d", host.EndpointIP.String(), listenPort)
@@ -506,6 +489,11 @@ func getExtClientHAConf(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}
+	logic.SetDNSOnWgConfig(&gwnode, &client)
+	defaultDNS := ""
+	if client.DNS != "" {
+		defaultDNS = "DNS = " + client.DNS
+	}
 	addrString := client.Address
 	if addrString != "" {
 		addrString += "/32"
@@ -551,13 +539,6 @@ func getExtClientHAConf(w http.ResponseWriter, r *http.Request) {
 	} else {
 		gwendpoint = fmt.Sprintf("%s:%d", host.EndpointIP.String(), host.ListenPort)
 	}
-	defaultDNS := ""
-	if client.DNS != "" {
-		defaultDNS = "DNS = " + client.DNS
-	} else if gwnode.IngressDNS != "" {
-		defaultDNS = "DNS = " + gwnode.IngressDNS
-	}
-
 	defaultMTU := 1420
 	if host.MTU != 0 {
 		defaultMTU = host.MTU
@@ -630,6 +611,7 @@ Endpoint = %s
 
 	name := client.ClientID + ".conf"
 	w.Header().Set("Content-Type", "application/config")
+	w.Header().Set("Client-ID", client.ClientID)
 	w.Header().Set("Content-Disposition", "attachment; filename=\""+name+"\"")
 	w.WriteHeader(http.StatusOK)
 	_, err = fmt.Fprint(w, config)

+ 0 - 89
scripts/ci-runner.sh

@@ -1,89 +0,0 @@
-#!/usr/bin/env bash
-# Fetch WireGuard config from Netmaker via /api/v1/client_conf/{network} and bring it up.
-# Required env:
-#   NETMAKER_BASE_URL, NETMAKER_API_JWT, NETMAKER_NETWORK
-#   WG_IFACE (default: netmaker), WG_CONF_DIR (default: /etc/wireguard)
-
-set -euo pipefail
-
-# --- Fail fast if mandatory variables missing ---
-: "${NETMAKER_BASE_URL:?ERROR: NETMAKER_BASE_URL not set}"
-: "${NETMAKER_NETWORK:?ERROR: NETMAKER_NETWORK not set}"
-: "${NETMAKER_API_JWT:?ERROR: NETMAKER_API_JWT not set}"
-
-# --- Ensure required packages are present ---
-echo "[*] Checking dependencies ..."
-DEPS=(curl jq wg-quick ip)
-MISSING=()
-for bin in "${DEPS[@]}"; do
-  if ! command -v "$bin" >/dev/null 2>&1; then
-    MISSING+=("$bin")
-  fi
-done
-
-if [[ ${#MISSING[@]} -gt 0 ]]; then
-  echo "[*] Installing missing deps: ${MISSING[*]} ..."
-  if command -v apt-get >/dev/null 2>&1; then
-    sudo apt-get update -y
-    sudo apt-get install -y wireguard-tools jq curl iproute2 resolvconf
-  elif command -v yum >/dev/null 2>&1; then
-    sudo yum install -y wireguard-tools jq curl iproute iproute-tc
-  elif command -v dnf >/dev/null 2>&1; then
-    sudo dnf install -y wireguard-tools jq curl iproute
-  else
-    echo "ERROR: Package manager not found. Install ${MISSING[*]} manually." >&2
-    exit 1
-  fi
-else
-  echo "[*] All dependencies found."
-fi
-
-# --- Inputs & defaults ---
-BASE_URL="${NETMAKER_BASE_URL:?NETMAKER_BASE_URL not set}"
-NETWORK="${NETMAKER_NETWORK:?NETMAKER_NETWORK not set}"
-JWT="${NETMAKER_API_JWT:?NETMAKER_API_JWT not set}"
-WG_IFACE="${WG_IFACE:-netmaker}"
-WG_CONF_DIR="${WG_CONF_DIR:-/etc/wireguard}"
-TMP_CONF="/tmp/${WG_IFACE}.conf"
-
-EP="${BASE_URL}/api/v1/client_conf/${NETWORK}"
-
-echo "[*] Requesting client configuration from: ${EP}"
-
-HDRS=(-H "Authorization: Bearer ${JWT}")
-[[ -n "${NM_CLIENT_LABEL:-}" ]]    && HDRS+=(-H "X-NM-Client-Label: ${NM_CLIENT_LABEL}")
-[[ -n "${NM_REQUESTED_NAME:-}" ]]  && HDRS+=(-H "X-NM-Requested-Name: ${NM_REQUESTED_NAME}")
-
-# --- Fetch config ---
-HTTP_STATUS="$(curl -sS -L -w '%{http_code}' -o "${TMP_CONF}" "${HDRS[@]}" "${EP}")"
-
-if [[ "${HTTP_STATUS}" != "200" ]]; then
-  echo "ERROR: client_conf returned HTTP ${HTTP_STATUS}" >&2
-  curl -sS -L "${HDRS[@]}" "${EP}" | head -c 400 >&2 || true
-  exit 1
-fi
-
-# --- Sanity check ---
-if ! grep -q "^\[Interface\]" "${TMP_CONF}"; then
-  echo "ERROR: Response does not look like a WireGuard config." >&2
-  head -n 20 "${TMP_CONF}" >&2 || true
-  exit 1
-fi
-
-# --- Add interface-name for traceability ---
-if ! grep -q "^#interface-name=" "${TMP_CONF}"; then
-  echo "#interface-name=${WG_IFACE}" | cat - "${TMP_CONF}" > "${TMP_CONF}.tmp" && mv "${TMP_CONF}.tmp" "${TMP_CONF}"
-fi
-
-# --- Move into place ---
-sudo mkdir -p "${WG_CONF_DIR}"
-sudo mv "${TMP_CONF}" "${WG_CONF_DIR}/${WG_IFACE}.conf"
-sudo chmod 600 "${WG_CONF_DIR}/${WG_IFACE}.conf"
-
-# --- Bring it up ---
-echo "[*] Bringing up ${WG_IFACE} ..."
-sudo wg-quick up "${WG_IFACE}"
-
-echo "==== ${WG_IFACE} is up ===="
-ip addr show "${WG_IFACE}" || true
-wg show "${WG_IFACE}" || true

+ 189 - 0
scripts/netmaker-ci-runner.sh

@@ -0,0 +1,189 @@
+#!/usr/bin/env bash
+# Netmaker CI helper: bring WireGuard up/down and manage ephemeral client lifecycle.
+# Subcommands:
+#   up   - fetch config, capture Client-ID, bring interface up, save state
+#   down - bring interface down, delete local conf, delete client via API
+#
+# Env vars (can be overridden by flags):
+#   NETMAKER_BASE_URL   (required)  e.g. https://nm.example.com   or pass --base-url
+#   NETMAKER_NETWORK    (required)  e.g. corpnet                  or pass --network
+#   NETMAKER_API_JWT    (required)  Bearer token                  or pass --jwt
+#   WG_IFACE            (default netmaker)                           or pass --iface
+#   WG_CONF_DIR         (default /etc/wireguard)                  or pass --confdir
+#   NETMAKER_STATE_FILE (default RUNNER_TEMP or /tmp)
+# You may also pass --client-id on `down` to avoid relying on the state file.
+
+set -euo pipefail
+
+# ---------- defaults ----------
+WG_IFACE="${WG_IFACE:-netmaker}"
+WG_CONF_DIR="${WG_CONF_DIR:-/etc/wireguard}"
+SUBCMD=""
+CLIENT_ID_OVERRIDE=""
+
+usage() {
+  cat <<USAGE
+Usage:
+  $0 up   [--iface IFACE] [--confdir DIR] [--base-url URL] [--network NET] [--jwt TOKEN]
+  $0 down [--iface IFACE] [--confdir DIR] [--base-url URL] [--network NET] [--jwt TOKEN] [--client-id ID]
+
+Flags override env vars. Env vars documented at top of the script.
+Examples:
+  NETMAKER_BASE_URL=https://nm.example.com NETMAKER_NETWORK=corpnet NETMAKER_API_JWT=... $0 up
+  $0 down --base-url https://nm.example.com --network corpnet --jwt ... --client-id icy-water
+USAGE
+}
+
+# ---------- arg parse ----------
+if [[ $# -lt 1 ]]; then usage; exit 2; fi
+SUBCMD="$1"; shift || true
+
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+    --iface)      WG_IFACE="$2"; shift 2;;
+    --confdir)    WG_CONF_DIR="$2"; shift 2;;
+    --base-url)   NETMAKER_BASE_URL="$2"; shift 2;;
+    --network)    NETMAKER_NETWORK="$2"; shift 2;;
+    --jwt)        NETMAKER_API_JWT="$2"; shift 2;;
+    --client-id)  CLIENT_ID_OVERRIDE="$2"; shift 2;;
+    -h|--help)    usage; exit 0;;
+    *) echo "Unknown arg: $1" >&2; usage; exit 2;;
+  esac
+done
+
+STATE_FILE="${NETMAKER_STATE_FILE:-${RUNNER_TEMP:-/tmp}/netmaker_ci_${WG_IFACE}.env}"
+
+require_env() {
+  : "${NETMAKER_BASE_URL:?ERROR: NETMAKER_BASE_URL not set}"
+  : "${NETMAKER_NETWORK:?ERROR: NETMAKER_NETWORK not set}"
+  : "${NETMAKER_API_JWT:?ERROR: NETMAKER_API_JWT not set}"
+}
+
+install_deps() {
+  echo "[*] Checking dependencies ..."
+  local need=(curl jq wg-quick ip)
+  local miss=()
+  for b in "${need[@]}"; do command -v "$b" >/dev/null 2>&1 || miss+=("$b"); done
+  if [[ ${#miss[@]} -eq 0 ]]; then
+    echo "[*] All dependencies present."
+    return
+  fi
+  echo "[*] Installing missing deps: ${miss[*]}"
+  if command -v apt-get >/dev/null 2>&1; then
+    sudo apt-get update -y
+    sudo apt-get install -y wireguard-tools jq curl iproute2 resolvconf
+  elif command -v yum >/dev/null 2>&1; then
+    sudo yum install -y wireguard-tools jq curl iproute iproute-tc
+  elif command -v dnf >/dev/null 2>&1; then
+    sudo dnf install -y wireguard-tools jq curl iproute
+  else
+    echo "ERROR: no supported package manager found; install: curl jq wireguard-tools iproute" >&2
+    exit 1
+  fi
+}
+
+do_up() {
+  require_env
+  install_deps
+
+  local ep="${NETMAKER_BASE_URL}/api/v1/client_conf/${NETMAKER_NETWORK}"
+  local tmp_conf="/tmp/${WG_IFACE}.conf"
+  local tmp_hdr="/tmp/${WG_IFACE}.headers"
+
+  echo "[*] Requesting client config: ${ep}"
+  # Optional headers
+  declare -a hdrs
+  hdrs=(-H "Authorization: Bearer ${NETMAKER_API_JWT}")
+  [[ -n "${NM_CLIENT_LABEL:-}"   ]] && hdrs+=(-H "X-NM-Client-Label: ${NM_CLIENT_LABEL}")
+  [[ -n "${NM_REQUESTED_NAME:-}" ]] && hdrs+=(-H "X-NM-Requested-Name: ${NM_REQUESTED_NAME}")
+
+  local code
+  code="$(curl -sS -L --dump-header "${tmp_hdr}" -w '%{http_code}' -o "${tmp_conf}" "${hdrs[@]}" "${ep}")"
+  if [[ "${code}" != "200" ]]; then
+    echo "ERROR: client_conf HTTP ${code}" >&2
+    curl -sS -L "${hdrs[@]}" "${ep}" | head -c 400 >&2 || true
+    exit 1
+  fi
+  grep -q "^\[Interface\]" "${tmp_conf}" || { echo "ERROR: not a WireGuard conf"; head -n 20 "${tmp_conf}"; exit 1; }
+
+  # --- Extract Client-ID (one-liner, trim spaces/quotes) ---
+  local client_id
+  client_id="$(grep -i '^Client-ID:' "${tmp_hdr}" | head -n1 | cut -d: -f2- | tr -d '\r' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/^"//; s/"$//' -e "s/^'//; s/'$//")"
+  if [[ -z "${client_id}" ]]; then
+    echo "ERROR: Client-ID header missing in response; cannot manage lifecycle." >&2
+    exit 1
+  fi
+  echo "[*] Client-ID: ${client_id}"
+
+  # Optional marker
+  if ! grep -q "^#interface-name=" "${tmp_conf}"; then
+    echo "#interface-name=${WG_IFACE}" | cat - "${tmp_conf}" > "${tmp_conf}.tmp" && mv "${tmp_conf}.tmp" "${tmp_conf}"
+  fi
+
+  # Install & bring up
+  sudo mkdir -p "${WG_CONF_DIR}"
+  sudo mv "${tmp_conf}" "${WG_CONF_DIR}/${WG_IFACE}.conf"
+  sudo chmod 600 "${WG_CONF_DIR}/${WG_IFACE}.conf"
+  echo "[*] Bringing up ${WG_IFACE} ..."
+  sudo wg-quick up "${WG_IFACE}"
+
+  echo "==== ${WG_IFACE} is up ===="
+  ip addr show "${WG_IFACE}" || true
+  wg show "${WG_IFACE}" || true
+
+  # Persist state
+  cat > "${STATE_FILE}" <<EOF
+NETMAKER_BASE_URL='${NETMAKER_BASE_URL}'
+NETMAKER_NETWORK='${NETMAKER_NETWORK}'
+NETMAKER_API_JWT='${NETMAKER_API_JWT}'
+WG_IFACE='${WG_IFACE}'
+WG_CONF_DIR='${WG_CONF_DIR}'
+CLIENT_ID='${client_id}'
+EOF
+  chmod 600 "${STATE_FILE}"
+  echo "[*] Saved state: ${STATE_FILE}"
+}
+
+do_down() {
+  # Load state if present; flags/env can still override
+  if [[ -f "${STATE_FILE}" ]]; then
+    # shellcheck disable=SC1090
+    source "${STATE_FILE}"
+  fi
+
+  require_env
+
+  local client_id="${CLIENT_ID_OVERRIDE:-${CLIENT_ID:-}}"
+  echo "[*] Bringing down ${WG_IFACE} ..."
+  sudo wg-quick down "${WG_IFACE}" || echo "WARN: wg-quick down failed (already down?)."
+
+  # Remove local conf
+  if [[ -f "${WG_CONF_DIR}/${WG_IFACE}.conf" ]]; then
+    sudo shred -u "${WG_CONF_DIR}/${WG_IFACE}.conf" 2>/dev/null || sudo rm -f "${WG_CONF_DIR}/${WG_IFACE}.conf"
+  fi
+
+  # Delete ephemeral client on server (if we know its ID)
+  if [[ -n "${client_id}" ]]; then
+    local del_ep="${NETMAKER_BASE_URL}/api/extclients/${NETMAKER_NETWORK}/${client_id}"
+    echo "[*] Deleting client: DELETE ${del_ep}"
+    local http
+    http="$(curl -sS -o /dev/null -w '%{http_code}' -X DELETE -H "Authorization: Bearer ${NETMAKER_API_JWT}" "${del_ep}")"
+    if [[ "${http}" =~ ^20[0-9]$ ]]; then
+      echo "[*] Client deleted (HTTP ${http})."
+    else
+      echo "WARN: deletion returned HTTP ${http}; verify server state."
+    fi
+  else
+    echo "WARN: client id not known (missing --client-id and state file); skipping server delete."
+  fi
+
+  rm -f "${STATE_FILE}" || true
+  echo "[*] Teardown finished."
+}
+
+case "${SUBCMD}" in
+  up)   do_up ;;
+  down) do_down ;;
+  *)    usage; exit 2 ;;
+esac
+