Schulungsmaterial · Juniper Mist

Automatisierung und Skripterstellung in Mist

Deep Dive zu REST APIs, Tokens, Scope, sicheren Python-Skripten, Pagination, Rate Limits, Webhooks, WebSockets, Terraform, CI/CD, Tests, Drift und Rollback.

1. Lernziele

  • REST, Webhook, WebSocket und Terraform passend wählen
  • Organisation-, Site- und Device-Scope korrekt adressieren
  • Cloudregion und Tokenart sicher bestimmen
  • HTTP, JSON, Pagination und Rate Limits beherrschen
  • idempotente Soll-Ist-Skripte erstellen
  • Dry Run, Canary, Tests und Postconditions einbauen
  • Secrets, State und Audit sicher betreiben
  • Webhook-Ereignisse entkoppelt und duplikatsicher verarbeiten
  • Drift, Teilausfall und Rollback beherrschen
Leitfrage: Was geschieht beim zweiten Lauf, beim Timeout nach einem Write oder nach einer partiellen Massenänderung?

2. Automationsmodell

Mist ist laut Juniper API-driven. Technische Automatisierbarkeit ersetzt aber keine Scope-, Risiko- und Wirkungsprüfung.

Intent→Ist lesen→Diff→Plan→Apply→Verify
Sichere Automation = Sollzustand + deterministischer Diff + begrenzte Änderung + Postcondition
StufeBeispielRisiko
Read-onlyInventar/SLEunvollständige Daten
AssistedPlan mit Freigabeveralteter Plan
Closed-loopEvent → KorrekturFehltrigger
IaCdeklarative Sites/WLANsDrift/Ownership

3. Werkzeugvergleich

WerkzeugModellGeeignet
REST APIPull/RequestCRUD, Inventar, Statistik
WebhookPush/POSTAlarme, Events, Location
WebSocketStreamLive-Daten, BLE, PCAP
TerraformdeklarativDay 0/1 und Drift
Postman/API ExplorerinteraktivPrototyp und Payloadprüfung
Python/Go/PowerShellprogrammierbarWorkflows und Integration

4. Objekt- und Scope-Modell

ScopeIDObjekte
MSPmsp_idMandanten
Organizationorg_idSites, Inventory, Templates
Sitesite_idWLANs, Geräte, SLEs
DeviceID/MAC je EndpointAP, Switch, Gateway
Template/ProfileUUIDWLAN-, Switch-, Network-Template
Regel: Vor Writes werden ID, Name, Organisation und Site gemeinsam verifiziert. Namen allein sind nicht hinreichend eindeutig.

5. Cloudregion und API-Host

PortalREST APIRegion
manage.mist.comapi.mist.comGlobal 01
manage.eu.mist.comapi.eu.mist.comEMEA 01
manage.gc3.mist.comapi.gc3.mist.comEMEA 02
manage.ac6.mist.comapi.ac6.mist.comEMEA 03
manage.gc6.mist.comapi.gc6.mist.comEMEA 04

Der Host ist Konfiguration, keine hart codierte Konstante. Die vollständige aktuelle Liste liefert Juniper.

6. Authentisierung und Tokenwahl

Authorization: Token MIST_API_TOKEN_VALUE
Accept: application/json
Content-Type: application/json
MerkmalOrg TokenUser Token
Scopeeine OrganisationBenutzerzugriffe
RechteToken-Access-LevelBenutzerrechte
Rate Limitpro Org Tokenkumuliert pro Benutzer
EinsatzDienst/Apppersönliches Skript
Stand August 2026: Basic Authentication soll laut Juniper ab September 2026 entfallen. Neue und bestehende Integrationen müssen tokenbasiert arbeiten.

7. REST und HTTP

AbsichtMethodeKontrolle
CreatePOSTRead-before-Create
ReadGETPagination/Filter
UpdatePUTEndpoint- und Write-Schema
DeleteDELETEReferenzen/Freigabe
https://API_HOST/api/v1/sites/SITE_ID/stats/devices/DEVICE_ID

Partieller oder vollständiger Update ergibt sich aus der jeweiligen API-Referenz, nicht allein aus der Methode.

8. cURL-Grundmuster

export MIST_API_HOST="api.eu.mist.com"
export MIST_ORG_ID="00000000-0000-0000-0000-000000000000"

curl --fail-with-body --silent --show-error \
  --connect-timeout 5 --max-time 30 \
  -H "Authorization: Token $MIST_APITOKEN" \
  -H "Accept: application/json" \
  "https://$MIST_API_HOST/api/v1/orgs/$MIST_ORG_ID/sites?limit=1000"

Das Beispiel enthält Platzhalter. Endpoint und Schema werden vor Nutzung in der aktuellen Referenz geprüft.

9. Robuster Python-Basisklient

import os, random, time, requests

base = "https://" + os.environ["MIST_API_HOST"] + "/api/v1"
session = requests.Session()
session.headers.update({
    "Authorization": "Token " + os.environ["MIST_APITOKEN"],
    "Accept": "application/json",
    "Content-Type": "application/json",
    "User-Agent": "mist-automation/1.0"
})

def api(method, path, **kwargs):
    for attempt in range(5):
        r = session.request(method, base + path, timeout=(5, 30), **kwargs)
        if r.status_code == 429:
            time.sleep(int(r.headers.get("Retry-After", "60")) + random.random())
            continue
        if 500 <= r.status_code < 600:
            time.sleep(min(2 ** attempt + random.random(), 30))
            continue
        r.raise_for_status()
        return r
    raise RuntimeError("request failed after retries")

Write-Retries brauchen Fachlogik gegen Doppelwirkung. Nach einem Timeout wird zuerst der Istzustand gelesen.

10. HTTP-Fehler behandeln

CodeBedeutungReaktion
200API erfolgreichPostcondition prüfen
400Payload falschSchema korrigieren
401Auth falschToken/Host prüfen
403Recht fehltScope/Access Level
404Objekt/Endpoint fehltID/Deprecation
429Rate LimitRetry-After
5xxServerfehlerbegrenzter Backoff

11. Pagination vollständig lesen

def get_all(path, limit=1000):
    page, result = 1, []
    while True:
        r = api("GET", path, params={"limit": limit, "page": page})
        body = r.json()
        batch = body if isinstance(body, list) else body.get("results", [])
        if not isinstance(batch, list):
            raise TypeError("unexpected response schema")
        result.extend(batch)
        total = int(r.headers.get("X-Page-Total", len(result)))
        if not batch or len(result) >= total or len(batch) < limit:
            return result
        page += 1

Juniper nennt häufig 100 als Default und 1000 als Maximum. Manche Endpoints nutzen einen next-Verweis. Der konkrete Endpoint entscheidet.

12. Rate Limit und Backoff

Juniper dokumentiert derzeit 5.000 Calls je Stunde. Der Login-Endpoint wird nach wenigen Fehlversuchen früher begrenzt.

Budget = Frequenz × Endpoints × Sites × Seiten × Worker
  • Org-Level statt vieler Site-Abfragen
  • Webhook statt Event-Polling
  • stabile Referenzdaten cachen
  • Retry-After und Jitter respektieren
  • Parallelität begrenzen

13. Idempotenz

MusterWirkung
Read before Createkein doppeltes Objekt
Compare before UpdateNOOP statt unnötigem Write
PostconditionWirkung nachweisen
Operation LedgerRun-ID und Teilfortschritt
Ambiguous Resultnach Timeout Ist prüfen
Delete GuardOwner, Scope und Freigabe
Retry-fähig ist nicht automatisch idempotent.

14. Reconciliation Loop

desired = load_and_validate("desired/site.json")
current = read_current(desired["id"])
diff = normalized_diff(current, desired)

if not diff:
    print("NOOP")
elif dry_run:
    print_plan(diff)
else:
    require_approval(diff)
    backup(current)
    apply(build_write_payload(desired))
    verify(desired)
Load→Discover→Normalize→Plan→Apply→Verify

15. Bulk und Parallelität

RisikoKontrolle
Blast RadiusCanary/Batchlimit
Rate Limitbegrenzter Workerpool
TeilfortschrittCheckpoint/Resume
ReihenfolgeDependency Graph
Eventual Consistencybegrenztes Verify-Polling
abweichende SitesPreflight-Matrix

16. Webhooks

RESTWebhook
Client fragtMist pusht POST
API-Budgetkein REST-Call-Limit laut Juniper
beliebige Abfragedefinierte Topics
Polling-Latenzereignisnah

Org- und Site-Webhooks liefern unter anderem Alarme, Device Events oder Location-Daten. Kritische Workflows werden entkoppelt.

17. Produktionsreifer Receiver

TLS→Auth/Schema→Queue→204→Worker→Action
def receive(request):
    raw = request.get_data(cache=False)
    verify_source_and_secret(request.headers, raw)
    event = validate_event(raw)
    key = stable_event_key(event)
    if not store.seen(key):
        queue.publish({"key": key, "event": event})
        store.mark_seen(key)
    return "", 204
  • schnell bestätigen, asynchron arbeiten
  • Duplikate und Reihenfolge tolerieren
  • Payloadgröße und Schema begrenzen
  • Dead Letter Queue und Replay
  • keine Produktivdaten an öffentliche Tester

18. WebSockets

wss://api-ws.eu.mist.com/api-ws/v1/stream
{"subscribe": "/sites/SITE_ID/pcaps"}
PflichtKontrolle
Regionpassender api-ws-Host
Authdokumentierte Tokenmethode
SubscriptionSite und Channel
ReconnectBackoff und Resubscribe
BackpressureQueue/Consumerlimit

Use Cases: Live-Dashboard, BLE, Device-Statistiken und PCAP-Streaming.

19. Terraform Provider

terraform {
  required_providers {
    mist = {
      source  = "Juniper/mist"
      version = "~> 0.9"
    }
  }
}
provider "mist" { host = var.mist_api_host }

resource "mist_site" "berlin" {
  org_id       = var.org_id
  name         = "DE-BER-01"
  country_code = "DE"
  timezone     = "Europe/Berlin"
}
Provider pinnen: Ressourcenschema und Verhalten ändern sich. Changelog, Plan und Regressionstest sind Teil jedes Upgrades.

20. Terraform State und Ownership

ThemaRegel
Remote Stateverschlüsselt, gesperrt, versioniert
SecretsState als sensibel behandeln
Importbestehende Ressourcen importieren
Ownershipnicht parallel Portal/Skript/Terraform
DestroySchutz und manuelle Freigabe

State ist keine vollständige Mist-Sicherung.

21. GitOps und CI/CD

1. Static Checks
Formatter, Linter, Types, Secret Scan.
2. Tests
Unit, Contract und Mock.
3. Test-Org
begrenzte Integration.
4. Plan
Diff und Blast Radius.
5. Review
Vier-Augen-Freigabe.
6. Canary
repräsentative Site.
7. Wellen
Stop-KPI überwachen.
8. Evidence
Run-ID, Diff, SLE, Ergebnis.

22. Secrets und Least Privilege

Anti-PatternAlternative
Token in Git/HCLVault oder CI Secret Store
Header im DebuglogRedaction
ein Admin-TokenToken je Dienst, Minimalrecht
Prod-Token im NotebookTest-Org und Testtoken
keine RotationOwner, Turnus, Sperrprozess
# .gitignore
.env
*.tfstate
*.tfstate.*
secrets/

23. Teststrategie

TestBeweis
UnitDiff/Normalizer
ContractResponse verarbeitbar
Mock429/500/Timeout
Integrationechte Test-Org
Idempotencyzweiter Lauf NOOP
Canarybegrenzte Produktion
RegressionProvider/API-Upgrade
Dry Run → Apply → Verify → zweiter Apply = NOOP

24. Logging und Audit

LoggenNicht loggen
Run-ID, Scope, Objekt-IDToken/Cookies
Diff, Status, Dauerunnötige Personendaten
Retry und Postconditionungefilterte Debugantwort

Metriken: Request Rate, 2xx/4xx/5xx, 429, Retry-Anzahl, Queue-Alter, Laufzeit, NOOP/Change/Failure und Verify-Fehler.

25. Backup und Rollback

Vor ÄnderungNach Fehler
Ist exportierenTeilfortschritt bestimmen
Write-Felder isolierenalten Body nicht blind schreiben
Abhängigkeitensicher kompensieren
Canary/Stopweitere Wellen stoppen
PostconditionsRollback verifizieren

Cloud-Änderungen über mehrere Ressourcen sind nicht automatisch transaktional.

26. Use Cases

FallWerkzeugGuardrail
Site-BaselineTerraform/ReconcilerCanary
WLAN-RolloutTemplate/IaCVLAN/AAA
InventarRESTPagination
SLE-ExportRESTZeit/Rate
Device-Down-TicketWebhook/QueueDedupe
Zone EntryLocation WebhookDatenschutz
Live-PCAPWebSocketZugriff/Retention
ComplianceRead-only Scriptversionierter Sollzustand

27. Systematische Fehlersuche

SymptomPrüfung
401Token-Prefix, Wert, Region
403Tokenart/Access Level
404Host, Path, ID, Deprecation
400JSON und Write-Schema
429Budget und Retry-After
nur 100 ObjektePagination
DublettenPOST-Retry
Terraform ReplaceForceNew, Import, Drift
Webhook mehrfachDedupe-Key
200 ohne WirkungPostcondition/Devicezustand
DNS/TLS → Host → Auth → Scope → Endpoint → Payload → API → Cloud → Gerät → Nutzer

28. Produktionscheckliste

Code

  • Host variabel
  • Tokenart bewusst
  • Timeouts
  • Status/JSON
  • Pagination
  • 429/Backoff
  • Idempotenz
  • Dry Run
  • Postcondition

Betrieb

  • Least Privilege
  • Secret Store
  • Test/Prod getrennt
  • Canary/Batch
  • Audit/Run-ID
  • Backup/Kompensation
  • Queue/Dedupe
  • Monitoring
  • Runbook

Häufige Fehlannahmen

AussageBewertungRichtig
API-driven heißt risikofrei.FalschScope/Wirkung prüfen.
api.mist.com passt immer.FalschRegion bestimmt Host.
200 beweist Funktion.FalschPostcondition fehlt.
Retry ist immer sicher.FalschPOST kann doppeln.
Erste Seite ist alles.FalschPagination.
Webhook exakt einmal.Nicht annehmenDedupe.
State ist Backup.Falschnur Terraform-Sicht.

29. Offizielle Grundlagen

Fachstand: August 2026. API-Pfade, Schemas, Limits, Topics und Providerressourcen ändern sich. Maßgeblich sind aktuelle API Reference, Cloudregion, gepinnte Versionen und Tests in der eigenen Organisation.