Scopes
Was ein Key tun darf.
Das Vokabular
Eine geschlossene Menge, resource:action. Klein genug, um sie einem Menschen als Checkbox-Liste zu zeigen, und stabil genug, dass eine gespeicherte Berechtigung ein Jahr später noch dasselbe bedeutet. In demselben Vokabular ist eine Workspace-ROLLE geschrieben, und es steuert den Zugang zu MCP-Tools, sodass ein Client mit Lesezugriff ein Sende-Tool nicht einmal sieht. Ein Alphabet, drei Oberflächen.
| Scope | Gewährt |
|---|---|
| emails:send | E-Mail senden |
| emails:read | Gesendete Nachrichten und ihren Zustellstatus lesen |
| drafts:read | Entwürfe lesen |
| drafts:write | Entwürfe erstellen und bearbeiten |
| threads:read | Threads und Nachrichten lesen |
| threads:write | Threads mit Labels versehen, als gelesen markieren und archivieren |
| labels:read | Labels lesen |
| labels:write | Labels erstellen und bearbeiten |
| contacts:read | Kontakte lesen |
| contacts:write | Kontakte hinzufügen, bearbeiten und entfernen |
| audiences:read | Audiences lesen und sehen, wer darin ist |
| audiences:write | Audiences erstellen und bearbeiten sowie ändern, wer darin ist |
| calendar:read | Kalendereinträge und Einladungen lesen |
| calendar:write | Kalendereinträge erstellen, ändern und beantworten |
| templates:read | E-Mail-Templates lesen und in der Vorschau ansehen |
| templates:write | E-Mail-Templates erstellen, bearbeiten und damit senden |
| domains:read | Domains und ihren DNS-Status lesen |
| domains:write | Domains verifizieren und konfigurieren |
| webhooks:read | Webhook-Endpunkte und Zustellungen lesen |
| webhooks:write | Webhooks erstellen, bearbeiten und testen |
| rules:read | Mail-Regeln lesen und testen |
| rules:write | Mail-Regeln erstellen, bearbeiten und neu anordnen |
| connections:read | Lesen, welche Postfächer verbunden sind |
| members:read | Sehen, wer im Workspace ist und was diese Personen halten |
| members:write | Personen hinzufügen und entfernen sowie ändern, worauf sie zugreifen können |
| roles:read | Die Rollen lesen, die dieser Workspace definiert |
| roles:write | Rollen erstellen, bearbeiten und löschen |
| settings:read | Postfacheinstellungen lesen, einschließlich der Signatur |
| settings:write | Postfacheinstellungen und die Signatur ändern |
| keys:write | Das eigene Secret ersetzen, ohne dass jemand die Konsole öffnet |
Ein Key, der ohne durchdachte Scope-Liste erstellt wird, erhält emails:send und sonst nichts. Der sichere Standard für ein Credential ist das Engste, was es noch nützlich macht.
Ein Key wird durch die Rolle hinter ihm gedeckelt
Ein Key kann gegen eine ROLLE ausgestellt werden, und eine Rolle ist eine Obergrenze und keine zweite Berechtigung. Was der Key tatsächlich darf, sind seine eigenen Scopes GESCHNITTEN mit den Berechtigungen dieser Rolle (key.scopes ∩ role.permissions), einmal an der Grenze berechnet, bei jeder Anfrage, bevor irgendein Endpunkt erreicht wird. Nichts dahinter weiß, dass es Rollen gibt: Ein Scope, den die Rolle nicht hält, steht schlicht nicht in der Liste, die die Scope-Prüfungen lesen.
Die beiden Listen werden also zusammen gelesen, und keine gewinnt für sich allein. Ein Key mit emails:send unter einer Rolle, die diesen Scope nicht hält, darf nicht senden; eine Rolle mit emails:send gibt einem Key, der ihn nie angefragt hat, gar nichts. Einen Scope anzuhaken heißt, Befugnis zu verlangen, und die Rolle entscheidet, wie viel vom Verlangten Sie bekommen.
Ein Key OHNE Rolle hat keine Obergrenze und ist damit so weit wie der Workspace, gegen den er ausgestellt wurde. Genau das trägt jeder Key, der vor der Einführung von Rollen erstellt wurde, und genau das bekommt ein Owner noch immer, wenn er das Feld unberührt lässt; eine Rolle von null ist also der WEITESTE Zustand, in dem ein Key sein kann, nicht der engste. Deshalb müssen Sie beim Löschen einer Rolle auch angeben, wohin ihre Keys sollen: Sie verwaist zurückzulassen würde jeden einzelnen davon stillschweigend befördern.
Die Schnittmenge wird pro Anfrage aufgelöst und nicht bei der Ausstellung auf den Key gestempelt. Das macht das Verengen einer Rolle zu einem sofortigen Entzug, wirksam beim nächsten Aufruf des Clients und ohne dass der Key rotiert werden muss, und das Erweitern wirkt auf genau dieselbe Weise sofort; das ist die Hälfte, die man sich merken sollte.
GET /ping und GET /keys/self melden scopes neben grantedScopes und roleId, und zwar wegen eines ganz bestimmten Fehlerfalls. scopes ist die effektive Liste und die einzige, die überhaupt etwas autorisiert; grantedScopes ist das, womit der Key ausgestellt wurde. Alles, was in der zweiten steht und in der ersten fehlt, hat die Rolle weggenommen, und dieser Unterschied ist die vollständige Antwort auf „mein Key hat emails:send und ich bekomme insufficient_scope“. Die Lösung ist eine Änderung der Rolle und kein weiterer Key.
curl "$OE/ping" -H "$AUTH" { "ok": true, "keyId": "4c1b257a66287fd113bd89d0", "mode": "live", "scopes": ["emails:read", "threads:read"], "roleId": "role_c40a95f21cc65d31c2a89e07", "grantedScopes": ["emails:send", "emails:read", "threads:read"], "workspaceId": "10417196-e324-4283-af98-66ec62167c47"}Fünf Berechtigungen erreichen einen Key nie: api-keys:read, api-keys:write, billing:read, billing:write und workspace:manage. Sie sind Berechtigungen, aber keine Scopes, keine noch so großzügige Rolle kann sie also auf ein Token legen: einen weiteren Key ausstellen, ändern, was ein anderer Key darf, oder den Plan wechseln, das tut nur eine angemeldete Person. Das Einzige, was ein Key mit sich selbst tun darf, ist sein eigenes Secret zu ersetzen, hinter dem Scope keys:write. GET /roles/permissions markiert die fünf mit scope: false, und das ist es, was eine einzige Komponente sowohl die Rollenmatrix als auch die Checkbox-Liste bei der Key-Erstellung rendern lässt.
roles:write ist faktisch das gesamte Vokabular, und etwas anderes zu behaupten wäre die gefährlichere Dokumentation. Ein Key, der ihn hält, kann genau die Rolle per PATCH ändern, die ihn deckelt, und sich selbst alles Übrige geben, und weil die Obergrenze pro Anfrage aufgelöst wird, gilt die weitere schon beim allernächsten Aufruf. Das ist kein Loch, das gestopft werden müsste, denn ein Rolleneditor, der keine Rollen bearbeiten kann, ist kein Rolleneditor. Es ist ein Grund, roles:write keinem Key zu geben, der nur je die Mitgliederliste lesen musste.
Sendebereich
Unabhängig von den Scopes kann ein Key darin verengt werden, als was er senden darf. Er trägt zwei Listen. domainAllowlist enthält ganze Domains, und ein Key, der eine Domain hält, darf als jede Adresse darauf senden, auch als Adressen, die nach dem Key angelegt wurden. addressAllowlist enthält einzelne Adressen. Lassen Sie beide leer, ist der Key so weit wie der Workspace, nie weiter. GET /keys/self zeigt beide Listen, und GET /addresses meldet, was ein bestimmter Key tatsächlich verwenden darf; das ist die Antwort auf ein unerklärliches from_address_forbidden.
Dieselbe Menge verengt, was der Key liest. Gesendete Mail, Tracking und Kalender antworten nur für Adressen, als die der Key senden darf; ein Key, der auf eine Domain eingeschränkt ist, sendet und liest also nicht im Namen einer anderen. Eine ganze Domain erlaubt dem Key außerdem, den Tracking-Host dieser Domain zu setzen, was ein auf einzelne Adressen beschränkter Key nicht kann.
Also drei Verengungen, und sie wirken zusammen, statt einander zu überschreiben: die Scopes auf dem Key, die Berechtigungen der Rolle darüber und die Domains und Adressen, die er in einen From-Header setzen darf. Ein Versand braucht alle drei, und eine Ablehnung nennt nur die erste, auf die sie gestoßen ist.