tailscale-toggle.sh hinzugefügt
This commit is contained in:
147
tailscale-toggle.sh
Normal file
147
tailscale-toggle.sh
Normal file
@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# ts-menu.sh — Interaktives Menü zum Sperren/Entsperren von Tailscale-Geräten
|
||||
#
|
||||
# Nutzt `gum` für die Menüführung und die Tailscale-API (authorized-Flag),
|
||||
# um einzelne Geräte vom Tailnet zu trennen bzw. wieder zuzulassen.
|
||||
#
|
||||
# Voraussetzungen:
|
||||
# - gum (https://github.com/charmbracelet/gum)
|
||||
# - curl, jq
|
||||
# - API-Access-Token: https://login.tailscale.com/admin/settings/keys
|
||||
#
|
||||
# Konfiguration in ~/.ts-toggle.conf:
|
||||
# TAILSCALE_API_KEY="tskey-api-xxxxx"
|
||||
# TAILSCALE_TAILNET="deine-org.ts.net"
|
||||
#
|
||||
# Verwendung:
|
||||
# ./ts-menu.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CONF_FILE="${HOME}/.ts-toggle.conf"
|
||||
[[ -f "$CONF_FILE" ]] && source "$CONF_FILE"
|
||||
|
||||
API_KEY="${TAILSCALE_API_KEY:-}"
|
||||
TAILNET="${TAILSCALE_TAILNET:-}"
|
||||
API_BASE="https://api.tailscale.com/api/v2"
|
||||
|
||||
die() {
|
||||
gum style --foreground 1 "Fehler: $*" >&2 2>/dev/null || echo "Fehler: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
command -v gum >/dev/null 2>&1 || { echo "Fehler: gum wird benötigt (https://github.com/charmbracelet/gum)."; exit 1; }
|
||||
command -v curl >/dev/null 2>&1 || die "curl wird benötigt."
|
||||
command -v jq >/dev/null 2>&1 || die "jq wird benötigt."
|
||||
[[ -n "$API_KEY" ]] || die "TAILSCALE_API_KEY ist nicht gesetzt (siehe ~/.ts-toggle.conf)."
|
||||
[[ -n "$TAILNET" ]] || die "TAILSCALE_TAILNET ist nicht gesetzt (siehe ~/.ts-toggle.conf)."
|
||||
|
||||
api_get() {
|
||||
curl -sf -u "${API_KEY}:" "${API_BASE}/$1"
|
||||
}
|
||||
|
||||
api_post() {
|
||||
curl -sf -u "${API_KEY}:" -H "Content-Type: application/json" \
|
||||
-X POST -d "$2" "${API_BASE}/$1"
|
||||
}
|
||||
|
||||
fetch_devices() {
|
||||
api_get "tailnet/${TAILNET}/devices"
|
||||
}
|
||||
|
||||
# Zeigt eine Auswahlliste der Geräte und gibt die gewählte Device-ID aus
|
||||
choose_device() {
|
||||
local devices="$1"
|
||||
local selection id
|
||||
|
||||
selection=$(echo "$devices" | jq -r '
|
||||
.devices[] | [.id, .name, (if .authorized then "✅ aktiv" else "⛔ gesperrt" end)] | @tsv' \
|
||||
| awk -F'\t' '{printf "%-35s %s\n", $2, $3, $1}' \
|
||||
| gum choose --header "Gerät auswählen" --height 15) || return 1
|
||||
|
||||
[[ -z "$selection" ]] && return 1
|
||||
|
||||
local name
|
||||
name=$(echo "$selection" | awk '{print $1}')
|
||||
id=$(echo "$devices" | jq -r --arg n "$name" '.devices[] | select(.name==$n) | .id')
|
||||
echo "$id"
|
||||
}
|
||||
|
||||
action_toggle() {
|
||||
local devices id name authorized new_value action_label
|
||||
|
||||
devices=$(gum spin --title "Lade Geräteliste..." --show-output -- bash -c "curl -sf -u '${API_KEY}:' '${API_BASE}/tailnet/${TAILNET}/devices'") \
|
||||
|| { gum style --foreground 1 "Konnte Geräteliste nicht laden."; return; }
|
||||
|
||||
id=$(choose_device "$devices") || return
|
||||
[[ -z "$id" ]] && return
|
||||
|
||||
name=$(echo "$devices" | jq -r --arg id "$id" '.devices[] | select(.id==$id) | .name')
|
||||
authorized=$(echo "$devices" | jq -r --arg id "$id" '.devices[] | select(.id==$id) | .authorized')
|
||||
|
||||
if [[ "$authorized" == "true" ]]; then
|
||||
new_value="false"
|
||||
action_label="sperren"
|
||||
else
|
||||
new_value="true"
|
||||
action_label="entsperren"
|
||||
fi
|
||||
|
||||
if gum confirm "Gerät '$name' jetzt $action_label?"; then
|
||||
gum spin --title "Setze Status..." -- \
|
||||
curl -sf -u "${API_KEY}:" -H "Content-Type: application/json" \
|
||||
-X POST -d "{\"authorized\": ${new_value}}" \
|
||||
"${API_BASE}/device/${id}/authorized" >/dev/null
|
||||
|
||||
if [[ "$new_value" == "false" ]]; then
|
||||
gum style --foreground 1 --bold "⛔ '$name' wurde gesperrt."
|
||||
else
|
||||
gum style --foreground 2 --bold "✅ '$name' wurde entsperrt."
|
||||
fi
|
||||
else
|
||||
gum style --foreground 3 "Abgebrochen."
|
||||
fi
|
||||
}
|
||||
|
||||
action_list() {
|
||||
local devices
|
||||
devices=$(gum spin --title "Lade Geräteliste..." --show-output -- bash -c "curl -sf -u '${API_KEY}:' '${API_BASE}/tailnet/${TAILNET}/devices'") \
|
||||
|| { gum style --foreground 1 "Konnte Geräteliste nicht laden."; return; }
|
||||
|
||||
echo "$devices" | jq -r '
|
||||
["NAME","OS","STATUS"],
|
||||
(.devices[] | [.name, .os, (if .authorized then "aktiv" else "GESPERRT" end)])
|
||||
| @tsv' | gum table --separator=$'\t' --columns "Name,OS,Status"
|
||||
}
|
||||
|
||||
main_menu() {
|
||||
while true; do
|
||||
clear
|
||||
gum style --border rounded --padding "1 2" --border-foreground 6 \
|
||||
"🔒 Tailscale Geräteverwaltung — Tailnet: ${TAILNET}"
|
||||
|
||||
choice=$(gum choose \
|
||||
"Gerät sperren/entsperren" \
|
||||
"Geräteliste anzeigen" \
|
||||
"Beenden" \
|
||||
--header "Was möchtest du tun?")
|
||||
|
||||
case "$choice" in
|
||||
"Gerät sperren/entsperren")
|
||||
action_toggle
|
||||
gum input --placeholder "Enter drücken zum Fortfahren..." >/dev/null || true
|
||||
;;
|
||||
"Geräteliste anzeigen")
|
||||
action_list
|
||||
gum input --placeholder "Enter drücken zum Fortfahren..." >/dev/null || true
|
||||
;;
|
||||
"Beenden"|"")
|
||||
echo "Bis dann 👋"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
main_menu
|
||||
Reference in New Issue
Block a user