Graph Throttling

Microsoft Graph ist ein unter der Adresse https://graph.microsoft.com öffentlich erreichbarer Webservice, welcher nach erfolgreicher Authentifizierung bestimmte Aktionen zulässt. Damit steht es natürlich unter Feuer durch DoS-Attacken, weswegen anonyme Zugriffe möglich schnell "erledigt" werden müssen. Dank OAUTH ist das gut möglich aber auch authentifizierte Zugriffe sollten keine "Überlast" produzieren und einige API-Aufrufen werden von Microsoft sogar gesondert berechnet.

Als Entwickler müssen Sie daher mit mehreren Herausforderungen bei der Nutzung von Graph oder anderen Webdiensten umgehen können.

  1. Authentifizierung
    Böse Clients könnten über die Authentifizierung versuchen gültige Benutzerdaten zu erhalten. Dagegen muss sich der Service schützen und die Programmierer müssen natürlich eine geeignete Anmeldung umsetzen.
  2. API Änderungen
    Auch Graph bekommt neuen Funktionen und Erweiterungen. Microsoft trennt Ende 2022 immer noch nach "/1.0" und "/beta" aber hat noch nichts abgeschaltet. Irgendwann kommt das aber auch.
  3. Throttling
    Um Überlastungen durch Clients zu verhindern, nimmt sich Microsoft die Freiheit heraus, Anfragen zu drosseln, d.h. Microsoft
  4. Accounting/Abrechnung
    Wenn Sie z.B. die Teams Export API nutzen, dann kostet jeder Aufruf. Hier sollten sie als Entwickler eine Protokollierung einbauen, um ihre Aufrufe zu zählen und damit die zu erwartenden Kosten abschätzen zu können und ggfls. sogar die Funktion einzustellen.
  5. Paketverluste
    Der Zugriff von ihrer Software über Internet zu Microsoft Graph ist kein gesichertes LAN. Es kann schon mal passieren, dass die Latenzzeit hochgeht oder sogar Pakete komplett verloren gehen. Bis zu einem gewissen Grad kann dies der TCP-Stack heilen aber dennoch sollten Sie auch damit umgehen können, dass der Service einen unerwarteten Fehler liefert oder nicht erreichbar ist.

Anonym DoS

Die Authentifizierung an Microsoft Graph ist sehr gut dokumentiert und basiert auf Tokens, d.h. Sie können gerne anonym auf Microsoft Graph zugreifen aber bekommen natürlich einen 401-Fehler samt Information zum Authentication Server:

Da Microsoft Graph nur "Bearer" unterstützt, muss es sich gar nicht erst mit anderen Anmeldeverfahren wie Basic, NTLM, Kerberos etc. rumschlagen. Der erster Webserver schaut in den Request und wenn er kein gültiges Auth-Token findet, liefert er immer wieder den gleichen Fehlercode zurück. Das kann also schon ein vorgelagerter Loadbalancer/ReverseProxy einfordern und damit die eigentlichen Server vor diesen Attacken schützen.

Ich habe nun keine tausende Anfragen gestellt und beobachtet, wie Microsoft darauf reagiert. Ich kann mir schon vorstellen, dass Sie irgendwann die Antwortzeit verzögern oder Rückantworten an die Source-IP temporär unterbinden. Das habe ich aber nicht weiter untersucht

Es ist auch nicht hilfreich, da eine gute Applikation das nicht mach und wenn Angreifer per verteilter DoS-Attacke ein System lahmlegen wollen, dann hilft eh nur Bandbreite. Die lassen sich auch nicht von ausbleibenden oder künstlich verlangsamten Antworten abhalten.

Throtting

Das reguläre Throttling wird auf authentifizierte Clients angewendet. Sie stellen also eine geplante, gut formatierte Anfrage an die Graph-API aber Microsoft Graph meint, dass Sie schon in der Vergangenheit zu viel Last produziert haben. Sie können sich das wie ihr Bankkonto vorstellen, auf das jeden Monat ihr Einkommen überwiesen wird und sie dann über den Monat davon zehren. Das Konto können Sie aber nicht überziehen. Wenn es leer ist, müssen wie bis zum nächten Gehalt wieder warten. Der Vergleich hinkt natürlich, wenn die Überweisungen kommen nicht nur jeden Monat und ein am Ende nicht aufgebrauchtes Volumen wird nicht angespart. Das Prinzip sollte aber verstanden sein.

Microsoft Graph reagiert auf einen Request mit einer 429-Antwort mit z.B. folgender Payload:

HTTP/1.1 429 Too Many Requests
Content-Length: 312
Content-Type: application/json
Retry-After: 10

{
  "error": {
    "code": "TooManyRequests",
    "innerError": {
      "code": "429",
      "date": "2022-03-17T10:21:31",
      "message": "Please retry after",
      "request-id": "c361cd6c-c38a-48c1-91ec-08500ddbf6cc ",
      "status": "429"
    },
    "message": "Please retry again later."
  }
}

Aus der JSON-Payload können Sie nur den Fehler entnehmen. Interessanter ist aber der "Retry-After:"-Header. Dieser gibt vor, wie viele Sekunden sie den nächsten Request verzögern müssen. Eine frühere Anfrage wir wieder mit dem Fehler quittiert. Microsoft geht hier also nicht den Weg, die Antwort einfach z.B. 10 Sekunden zu verzögern, was per HTTP durchaus möglich wäre (Siehe HTTP Chunked), sondern liefert aktiv einen Fehlercode, den sie Abfangen müssen. Die Retry-Limits sind übrigens je nach Bereich auch unterschiedlich:

Es ist kontraproduktiv, diese Meldung zu ignorieren und es weiter zu versuchen. Jeder auch fehlgeschlagene Versuch wird in die Berechnung mit einbezogen und verzögert die nächsten Anfragen immer weiter.

Am besten implementieren sie ein 429-Handling von Anfang an in ihrer Applikation, indem Sie jeden Request entsprechend prüfen und eigene Performance-Counter oder Logs zum Throttling schreiben. Sonst suchen vielleicht lange an der falschen Stelle, wenn die Performance nicht wie erwartet ist.

Nun kann es aber schon den Bedarf zu geben, viele Änderungen zu überwachen oder Massendaten mit Graph zu verarbeiten. Dann sollten Sie folgende Alternativen kennen

Option: Webhook

Auf der Seite Teams ausgehend WebHooks und Graph CallReport Webhook habe ich in Zusammenhang mit Teams schon das Thema "Webhook" beschrieben. Die gleiche Technik gibt es für Microsoft Graph. Sie können als Entwickler einen eigenen Webservice aufrufen und dann über Graph eine "Subscription" einrichten. Dann wird ihr öffentlich im Internet erreichbarer Webhook von Graph aufgerufen.

Die Ausgestaltung des Webhooks bleibt dabei ihnen überlassen. Dass muss nicht ihr eigenes Programm sein, welches 24h per HTTPS mit gültigem Zertifikat aus dem Internet oder zumindest von den Microsoft IP-Bereichen erreichbar ist. Sie können dazu auch eine PHP-Seite auf ihrer Marketingseite missbrauchen, die eine Mail sendet oder Azure Functions, die den eingehenden Request dann irgendwo hin weitergibt.

Option: Batches

Keine direkte Lösung gegen Throttling aber ein Weg die Grenze hinauszuschieben ist die Kombination mehrerer Anforderungen als "Batch". Dies ist möglich und für größere Massenänderung auch ratsam, z.B. Verwalten von vielen Benutzern im AzureAD. Allerdings wird auch die Programmierung etwas komplexer, wenn Sie verschiedene Aktionen nun zusammenfassen

Option: Delta Query

Nicht alle Änderungen von Daten lassen sich per Webhook abonnieren. Dann sollten Sie prüfen, ob es ein "Delta-Query" gibt. Sie holen sich dann z.B. nicht alle Benutzer eines AD oder alle Emails in einem Ordner sondern übergeben einen Cookie oder "State Token" mit dem vorherigen Stand und die Cloud liefert ihnen dann nur die Änderungen seit dem letzten Abruf. Diese Verfahren ist ebenfalls schon sehr lange im an verschiedenen Stellen im Einsatz. Microsoft nutzt diese Art der Delta-Übertragung z.B. bei der Replikation zwischen Domain Controllern, der Abfrage von Mobilclient per ActiveSync oder Migrationen per EWS.

Daher finden Sie diese Option meist bei den Graph-Zugriffen auf Exchange Inhalte wie Mails, Termine und Kontakte

Option: Data Connect

Manchmal möchten sie aber große Datenmengen aus der Microsoft Cloud per Graph abrufen. Es macht schon einen Unterschied, ob sie per Graph eine Excel-Datei auf OneDrive zeilenweise lesen oder die komplette Datei auf einmal herunter laden. Da gleiche Prinzip gilt auch für andere Datentöpfe. Interessant ist dies insbesondere, wenn sie große Datenmengen für eigene Analysen in ein anderes System überführen wollen. Die Beispiele von Microsoft sprechen hier häufig von der Überführung von Daten in ein "Machine Learning"-System. Das könnte z.B. ein Export alle Teams CallRecord sein

Allerdings kostet diese Schnittstelle, so dass sie eine Azure Subscription zur Abrechnung dafür brauchen


Quelle: Microsoft Graph Data Connect VORSCHAU – Preise  https://azure.microsoft.com/de-de/pricing/details/graph-data-connect/

Overview of Microsoft Graph Data Connect
https://www.microsoft.com/en-us/videoplayer/embed/RWEJsy?autoplay=false&postJsllMsg=true

Throttling simulieren

Wenn Sie ihre eigene Applikation gegen Throttling testen wollen, müssten sie eigentlich erst einmal sehr viele Requests stellen. bis Microsoft das Skript dann wirklich mit einem 429-Code ausbremst. Früher war das tatsächlich der Fall aber mittlerweile gibt es einen kleinen Proxy, der das Verhalten einfach simuliert. Ihr Applikation verbindet sich mit dem Proxy, der dann die Anfragen an Graph weiter leitet aber dazwischen eben "stört".

Weitere Links