Ausführungssemantik, Einschränkungen und Sicherheit
Diese Seite fasst zusammen, wie sich ein Script zur Laufzeit verhält (Reihenfolge, Transaktionen, Fehler, Sperren), welchen statischen Einschränkungen es bei der Speicherung unterliegt und sein Sicherheitsmodell. Zur Syntax siehe den Statement-Katalog und die Wertausdrücke; für praktische Kombinationen siehe das Cookbook.
Ausführungsreihenfolge
statementswerden von oben nach unten sequenziell ausgeführt. Sobald die Ausführung einReturnerreicht, endet sie an diesem Punkt.- Die Ausführung erfolgt inline auf dem Pfad, der die Aufrufanfrage verarbeitet. Die Antwort des Aufrufs ist unmittelbar das Ausführungsergebnis (zur Form der Antwort siehe Anfrage und Antwort in der Script-Übersicht), und die Zeit für eine einzelne Ausführung wird unten unter Zeitbudget behandelt.
Ausführungssemantik
Guard (Vorbedingungen)
Es gibt kein dediziertes Guard-Statement. Man drückt es mit If und then:[Return] aus. Bei einer Verletzung der Bedingung wird ein Ergebnis zurückgegeben und die nachfolgenden Statements werden nicht ausgeführt (ein Script ohne Guard ist selbstverständlich ebenfalls möglich).
{ "type": "If", "condition": { "<": [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] },
"then": [ { "type": "Return", "value": { "ok": false, "reason": "insufficient credit" }, "statusCode": 402 } ] }Keine Transaktionen und Best-Effort-Kompensation
Ein Script ist keine Transaktion. Bei einem Fehler versucht die Engine, die bisher ausgeführten Vorgänge zu kompensieren (Kompensation), und gibt die Fehlerursache zurück, jedoch mit den folgenden Einschränkungen (als Designkompromiss in Kauf genommen).
- Das Rückgängigmachen einer Löschung erzeugt eine neue
sys.id, wodurch Referenzen, die darauf zeigten, brechen. - Externe Effekte (
Http) sind irreversibel (ein bereits abgesetzter Aufruf und dessen Kosten lassen sich nicht rückgängig machen). - Wenn die Kompensation gar nicht ausgeführt wird, kann ein nicht kompensierter Zustand zurückbleiben.
Wenn Sie echte Atomarität benötigen, kompensieren Sie im Script selbst oder platzieren Sie nicht rückgängig zu machende Vorgänge (etwa externe Aufrufe) ganz am Ende. Am gefährlichsten ist die Reihenfolge, die "sich durchkettet, aber nicht zurückrollen lässt und dennoch sicher aussieht".
Optimistisches Sperren
Update-/Patch-Konkurrenz grenzen Sie über das version-Feld von ResourceUpdate und ResourcePatch ein. Geben Sie version (ein Wertausdruck, Int) an, wird nur dann aktualisiert, wenn es mit der aktuellen sys.version des Ziels übereinstimmt; bei Nichtübereinstimmung wird mit einem Versionskonfliktfehler abgebrochen (lokal mit Try/catch behandelbar). Lassen Sie es weg, gilt last-write-wins ohne Prüfung. Üblicherweise liest man zuerst mit ResourceRead oder ResourceFind und übergibt diese sys.version (siehe Optimistisches Sperren mit CAS im Cookbook).
Schreibvorgänge gehen an origin
Schreibvorgänge landen immer in origin (draft), und die Sichtbarkeit auf der Auslieferung (CDA/ACDA) wird über publish gesteuert (das publish von ResourceCreate/ResourceUpdate/ResourcePatch oder ResourcePublish/ResourceUnpublish).
Was als Fehler zählt
Schlägt während der Ausführung ein Statement fehl, wird die Ausführung an dieser Stelle abgebrochen, sofern kein Try diesen Fehler behandelt. Die Engine versucht dabei, die bis dahin ausgeführten Vorgänge rückgängig zu machen. Das Rückgängigmachen hat Grenzen; Einzelheiten behandelt Keine Transaktionen und Best-Effort-Kompensation.
Steht das fehlgeschlagene Statement in einem Try, können Sie diesen Fehler im catch behandeln. Innerhalb des catch referenzieren Sie den Inhalt des Fehlers ({ message }) über /error. Welches Statement fehlgeschlagen ist, steht nicht darin.
Die folgenden Fälle werden als Fehler behandelt.
- Ein Ressourcenvorgang schlägt fehl (kein Ziel vorhanden, ein Versionskonflikt, ein nicht unterstützter Vorgang usw.)
Httpschlägt fehl (siehe Zwei Arten, wie Http fehlschlägt)- Eine Media-Dateitransformation schlägt fehl (siehe Wenn eine Dateitransformation fehlschlägt)
- Eine für das jeweilige Statement festgelegte, zur Laufzeit geprüfte Obergrenze wird überschritten (z. B. Obergrenzen für Wertlängen)
Return ist kein Fehler. Es beendet die Ausführung regulär vorzeitig und geht daher nicht an catch über.
Zwei Arten, wie Http fehlschlägt
Ein Fehlschlag von Http fällt in eine von zwei Arten, je nachdem, ob er als status-Antwort behandelt wird. Von diesem Unterschied hängt ab, ob retry und ignoreStatusCode greifen.
| Merkmal | Als status-Antwort behandelt | Sofortiger Fehlschlag |
|---|---|---|
| Betroffene Fälle | Die Ziel-API antwortet mit einem status von 400 oder höher; eine Zeitüberschreitung (status 504); keine Verbindung zur Ziel-API oder die Antwort konnte nicht gelesen werden (status 502); der Antwort-Body überschreitet 10MiB (status 502) | responseType ist "Json", aber der Body einer erfolgreichen Antwort ist kein JSON; die zu sendende Datei überschreitet das Download-Limit; die Datei-URL antwortet mit einem status außerhalb von 2xx oder ist nicht erreichbar; der Wert eines part hat ein ungültiges Format |
retry | Wird so oft wiederholt wie angegeben | Wird nicht wiederholt |
ignoreStatusCode: true | Wird nicht als Fehler gewertet, und { status, body } wird als Ergebnis gebunden | Greift nicht, es wird als Fehler behandelt |
Try/catch | Im catch behandelbar | Im catch behandelbar |
Die Bedingungen, unter denen die Dateiübertragung fehlschlägt, behandelt Eine Datei als Body senden im Detail.
Serverseitige Aggregation nur für die Anzahl
Die Anzahl zählt ResourceCount auf dem Server. Da dabei keine Elemente gelesen werden, gilt die Obergrenze für die Anzahl verarbeiteter Elemente hier nicht.
Für sum und group-by gibt es keine dedizierten Servervorgänge. Solche Aggregationen müssen Sie selbst berechnen, indem Sie mit ResourceForEach iterieren und mit SetVar und JsonLogic rechnen, weshalb Sie an die Obergrenze für die Anzahl verarbeiteter Elemente gebunden sind (für das Aggregieren von Millionen von Datensätzen ungeeignet). Wenn Sie nur die Anzahl brauchen, iterieren Sie nicht, sondern verwenden ResourceCount.
Kein Warten oder Verzögern
Ein Script hat kein Delay-Statement. Ein Script wird einmal ausgeführt und ist dann fertig und wartet oder pollt intern nicht, bis ein externer Job fertig ist.
Statische Einschränkungen (bei der Speicherung validiert)
Das Folgende wird geprüft, wenn ein Script gespeichert wird (beim Erstellen/Ändern). Bei einer Verletzung wird die Speicherung abgelehnt (der Fehler tritt zum Autorenzeitpunkt auf, nicht zur Laufzeit). Welche Verletzung mit welchem Code abgelehnt wird, behandelt der Abschnitt Fehler.
| Einschränkung | Wert |
|---|---|
Maximale externe Aufrufe (Http, EmailSend) pro Definition | Tarifabhängig (siehe Tarife) |
Maximale Gesamtzahl verarbeiteter Elemente bei ResourceForEach (ohne deklariertes limit wird bis zu diesem Wert iteriert; verbleiben dabei Treffer, schlägt es fehl) | 10.000 |
Maximale SetVar pro Definition (inklusive verschachtelter) | 10 |
Maximale Cache pro Definition (inklusive verschachtelter, unabhängig von der Operation zusammengezählt) | 5. Bei Überschreitung Speichern abgelehnt |
Cache im Block von Loop oder ResourceForEach | Speichern abgelehnt |
Cache.key | Nur Literal, maximal 128 Zeichen. Bei einem Wertausdruck Speichern abgelehnt |
Cache.ttl | Zwischen 1 und 30 Sekunden, ohne Angabe 5 Sekunden. Außerhalb dieses Bereichs Speichern abgelehnt |
| Maximale Gesamtzahl an Statements pro Definition (inklusive verschachtelter) | Tarifabhängig (siehe Tarife) |
Obergrenze für Http.retry | 2 |
Anfrage-Body-Felder eines Http (body, urlBody, multipartBody) | Nur eines der drei. Bei zwei oder mehr Speichern abgelehnt |
Anzahl der parts in Http.multipartBody | Mindestens 1. Wenn leer, Speichern abgelehnt |
value und url eines multipartBody-part | Genau eines. Wenn beide angegeben oder beide leer sind, Speichern abgelehnt |
fileName eines multipartBody-part | Nur in einem part mit url. Ohne url angegeben Speichern abgelehnt |
Länge von Regex.pattern | 128 Zeichen |
Maximale secrets pro Definition | 20 |
key in secrets | 1-64 Zeichen, nur lateinische Buchstaben, Ziffern, _ und -. Bei zwei gleichen key Speichern abgelehnt |
value in secrets | 1-4.096 Zeichen. Außerhalb dieses Bereichs Speichern abgelehnt |
{ /secrets… }-Referenz | Genau /secrets/<deklarierter key>. Andernfalls Speichern abgelehnt |
| Ein Statement, das einen ServiceUser erstellt oder löscht | Speichern abgelehnt. Nur die drei Lese-Statements sowie ResourceUpdate und ResourcePatch nehmen diese Ressource an |
createdBy: ":self" in where, wenn anonymousCallEnabled true ist | Speichern abgelehnt |
transformations einer Media-Ingest-Anweisung (Dateitransformation) | Nur ein Array. Das type eines Elements ist PdfWatermark, color ist #RRGGBB. text ist in seinem gesamten geschriebenen String (einschließlich der Pfade in { /pointer }) eine einzelne Zeile aus zulässigen Zeichen. Bei einem Verstoß Speichern abgelehnt |
Länge eines literalen text von PdfWatermark | 1-64 Zeichen. Außerhalb dieses Bereichs Speichern abgelehnt. Ein text mit { /pointer } wird beim Speichern nicht geprüft, sondern bei der Ausführung anhand des aufgelösten Werts |
Die festen Limits in der Tabelle oben sind von der Plattform vorgegebene Werte und daher unabhängig vom Tarif gleich. Dagegen sind die Gesamtzahl der Statements und die Anzahl externer Aufrufe pro Definition tarifabhängige Limits. Diese beiden sind keine Validierungsfehler, sondern Tariflimits: Bei Überschreitung wird das Speichern bzw. Ändern wegen Überschreitung des Tariflimits abgelehnt (dieselbe Definition ist in einem höheren Tarif erlaubt) und durch ein Upgrade freigegeben. Die tarifabhängigen Zahlen finden Sie unter Tarife.
Der Media-Datei-Ingest wird, anders als externe Aufrufe wie
HttpundEmailSend, nicht auf das Limit für externe Aufrufe pro Definition angerechnet.
ResourceForEachist ein zusammengesetztes Statement mit eigenen Kindern und wird daher selbst nicht auf die Anzahl externer Aufrufe angerechnet. Gezählt werden die externen Aufruf-Statements (Http,EmailSend) inonEach(statisch als 1 gezählt, aber bei der Iteration pro Element tatsächlich ausgeführt).onEachkann externe Aufrufe oder einen Media-Datei-Ingest enthalten, und das gilt ebenso für den body vonLoop. Wie oft eine Iteration tatsächlich läuft, geht nicht in diese Zählung ein, sondern kommt stattdessen unten im Zeitbudget als Multiplikation zum Tragen.
Obergrenzen für Wertlängen (Laufzeit)
Die Statements für Signatur und Textverarbeitung sowie Cache haben eine Obergrenze für die Größe des Werts, den sie behandeln. Gemeint ist nicht die Länge des Ausdrucks, sondern die Länge des Werts, zu dem der Ausdruck aufgelöst wird (die sechzehn Zeichen { /rawPayload } zeigen auf mehrere Dutzend KB), und deshalb wird sie nicht beim Speichern, sondern während der Ausführung geprüft.
| Ziel | Obergrenze | Bei Überschreitung |
|---|---|---|
Das value von Signature | 65.536 Zeichen | Dieses Statement schlägt fehl (status 422) |
Das value von Hash | 128 Zeichen | Dieses Statement schlägt fehl (status 422) |
Das value von Regex | 10.240 Zeichen (10KiB) | Dieses Statement schlägt fehl (status 400) |
Das value von Cache | 10.240 Byte (10KiB) | Dieses Statement schlägt fehl (status 422) |
- Alle vier sind wie jeder andere Laufzeitfehlschlag und lassen sich daher mit
Try/catchlokal behandeln. - Die Obergrenze von
Signatureist an der Body-Größe ausgerichtet, die reale Anbieter senden (Zahlungsereignisse liegen bei einigen KB, Bestell-Webhooks erreichen mehrere Dutzend KB).Hashist die Stelle, an der einige Felder aneinandergehängt werden, und daher viel enger. - Die 128 Zeichen von
Regex.patternsind die Prüfung beim Speichern aus den Statischen Einschränkungen oben. Diese Länge ist keine Vorrichtung gegen ein Durchdrehen des Patterns ((a+)+$ist auch mit sechs Zeichen gefährlich). Dagegen wirken die Regel, dass ein Pattern nur als Literal geschrieben werden darf, und das Zeitbudget unten; die Länge verspricht nur eine Größe, die ein Mensch lesen und prüfen kann.
Zeitbudget (Laufzeit)
Die für eine einzelne Ausführung erlaubte Zeit beträgt höchstens 180 Sekunden. Die tatsächlich erlaubte Zeit richtet sich nach der Script-Definition (beim Senden von Dateien auch nach dem Tarif) und ergibt sich aus den grundlegenden 30 Sekunden plus der Zeit, die externe Aufrufe nutzen können.
Dieses Budget gilt für die gesamte Ausführung. Davon unabhängig muss eine einzelne Http-Anfrage innerhalb ihres timeoutMs abgeschlossen sein.
Grundbudget von 30 Sekunden
Alle Arbeiten, die keine externen Aufrufe sind, etwa das Lesen und Schreiben von Ressourcen oder das Empfangen und Verarbeiten einer Media-Datei, werden innerhalb dieser 30 Sekunden erledigt. Einem Script ohne externe Aufrufe werden 30 Sekunden gewährt.
Zeit, die pro Statement hinzukommt
Die Zeiten hintereinander stehender Statements werden alle addiert.
| Statement | Hinzukommende Zeit |
|---|---|
Http | timeoutMs (ohne Angabe 30 Sekunden). Beim Senden von Dateien wird pro Datei die Download-Zeit (Tabelle unten) addiert, und ist retry angegeben, wird das Ganze mit der Anzahl der Versuche (1 + retry) multipliziert |
EmailSend | timeoutMs (ohne Angabe 10 Sekunden). Da nicht wiederholt wird, wird die Zeit nur einmal addiert |
If | Die Zeit des längeren der beiden Zweige then und else |
Parallel | Die Zeit des längsten unter den branches |
Try | Die Summe der Zeiten von body, catch und finally |
Loop | Die Zeit von body multipliziert mit maxIterations (ohne Angabe 10.000) |
ResourceForEach | Die Zeit von onEach multipliziert mit limit (ohne Angabe 10.000) |
| Andere Statements (die keine anderen Statements enthalten) | Es wird nichts addiert. Sie werden innerhalb des Grundbudgets von 30 Sekunden erledigt |
Enthält eine Iteration keinen externen Aufruf, bleibt die hinzukommende Zeit auch nach der Multiplikation mit der Anzahl der Iterationen 0. Eine solche Iteration muss daher innerhalb des Grundbudgets von 30 Sekunden abgeschlossen sein.
Download-Zeit pro Datei
| Plan | Download-Zeit |
|---|---|
| Free | etwa 5,2 Sekunden |
| Basic | etwa 10,5 Sekunden |
| Pro | etwa 10,5 Sekunden |
| Enterprise | etwa 107,4 Sekunden |
Dieser Wert ist die Zeit, die nötig ist, um die Datenmenge des Download-Limits des Tarifs mit 10.000.000 Byte pro Sekunde zu empfangen.
Rechenbeispiel
Ein Script, das im Pro-Tarif ein Http aufruft, das zwei Fotos sendet (timeoutMs 30 Sekunden, retry 1), wird wie folgt berechnet.
Http: (30 Sekunden + 10,5 Sekunden × 2) × 2 = etwa 102 Sekunden- Gesamte Ausführung: 30 Sekunden + 102 Sekunden = etwa 132 Sekunden
132 Sekunden sind kürzer als 180 Sekunden, daher werden diesem Script 132 Sekunden gewährt.
Wenn 180 Sekunden überschritten werden
Auch wenn der berechnete Wert 180 Sekunden überschreitet, wird das Script gespeichert und ausgeführt. Erreicht die Ausführung jedoch 180 Sekunden, wird sie an diesem Punkt abgebrochen.
Anzahllimits pro Plan
Bei einem Script ist die Anzahl pro Organization je nach Plan begrenzt.
| Plan | Script-Anzahl |
|---|---|
| Free | 10 |
| Basic | 30 |
| Pro | 100 |
| Enterprise | Unbegrenzt |
Davon getrennt sind auch die Anzahl der Statements und der externen Aufrufe (Http, EmailSend), die eine Script-Definition enthalten kann, je nach Tarif begrenzt. Überschreitet eine Definition beim Speichern oder Ändern das Limit dieses Tarifs, wird sie abgelehnt; die konkreten Zahlen finden Sie unter Tarife.
Wenn das Limit erreicht ist, wird das Erstellen eines neuen Script abgelehnt.
Größe von Http-Dateidownloads
Wenn Http eine Datei, die als Anfrage-Body gesendet werden soll, von einer URL abruft (urlBody, der url-part von multipartBody), ist die Größe, die pro Datei-URL empfangen werden kann, je nach Tarif begrenzt. Maßgeblich ist der Tarif der Organization, zu der der Space gehört, dem das Script gehört.
| Plan | Maximale Größe pro Datei-URL |
|---|---|
| Free | 50MiB |
| Basic | 100MiB |
| Pro | 100MiB |
| Enterprise | 1GiB |
- Das Limit gilt für jede URL einzeln. Gibt es mehrere
url-parts, muss jede Datei innerhalb dieses Limits liegen. - Wird versucht, eine Datei zu senden, die das Limit überschreitet, schlägt dieses
Httpfehl (siehe Zwei Arten, wie Http fehlschlägt). - Dieses Limit ist auch die Grundlage für die Download-Zeit, die zum Zeitbudget addiert wird.
Sicherheitsmodell
secrets
Geheimwerte wie externe API-Schlüssel, der Secret Key eines Zahlungsdienstleisters (PG), Webhook-Signaturschlüssel oder ein vorab berechneter Basic …-Authentifizierungswert werden nicht wörtlich in ein Statement geschrieben. Sie deklarieren sie in den secrets der Definition und lesen sie im Statement mit { /secrets/<key> }. Auch öffentlich bekannte Testschlüssel legen Sie an derselben Stelle ab. Wenn Sie dann auf den echten Schlüssel umstellen, bleiben die Statements unverändert, und Sie ändern nur den Wert in secrets.
"secrets": [
{ "key": "LLM_API_KEY", "value": "sk-...", "description": "API-Schlüssel für LLM-Aufrufe" },
{ "key": "WEBHOOK_SIGNING_SECRET", "value": "whsec_...", "description": "" }
],
"statements": [
{ "type": "Http", "method": "POST", "url": "https://api.openai.com/v1/chat/completions",
"headers": [ { "key": "Authorization", "value": "Bearer { /secrets/LLM_API_KEY }" } ],
"body": { /* ... */ }, "name": "llm" }
]| Feld | Erforderlich | Regel |
|---|---|---|
key | Erforderlich | 1-64 Zeichen, nur lateinische Buchstaben, Ziffern, _ und -. Muss innerhalb eines Script eindeutig sein. |
value | Erforderlich | Ein String mit 1-4.096 Zeichen. Er ist ein statischer Wert und wird nicht als Template ausgewertet; ein darin stehendes { /… } wird also wörtlich verwendet. |
description | Erforderlich | Die Beschreibung des Zwecks, 0-128 Zeichen. Auch ein leerer String "" ist zulässig. |
- Speichern: WEEGLOO verschlüsselt
valueund speichert es sicher. Ein Statement liest mit{ /secrets/<key> }den ursprünglichen Wert. - Abfrage: In API-Antworten, die ein Script zurückgeben (Abfrage, Erstellen, Ändern), wird
valueals ursprünglicher Wert zurückgegeben. Rollen, die dieses Script lesen können, sehen den Wert, halten Sie die Leseberechtigung daher eng. Mitglieder (ServiceUser) können eine Script-Definition nicht lesen (Abfrage und Autorenschaft sind CMA-exklusiv, und auf der ACMA gibt es keine Script-API). - Ändern: Eine vollständige Änderung (PUT) ersetzt die gesamte Definition. Senden Sie sie ohne
secrets, werden die deklarierten Geheimwerte gelöscht; verweist ein Statement noch mit{ /secrets/… }auf einen dieser Werte, wird das Speichern abgelehnt. Senden Siesecretsdeshalb bei jeder Änderung mit. Es genügt, die Werte aus der Abfrageantwort unverändert zurückzusenden. - Der Wert während der Ausführung: Was mit dem gelesenen Wert geschieht, bestimmt das Statement. Geben Sie ihn mit
Returnzurück, bleibt er in der Ausführungsantwort und im ScriptLog erhalten; legen Sie ihn inSetVar,Cacheoder Content ab, bleibt er dort als ursprünglicher Wert stehen. Senden Sie einen Geheimwert nur an die externe API, die ihn benötigt. - App Bundle: Wird ein Script in ein App Bundle gepackt, wird das
valueinsecretsdurch******verdeckt, währendkeyunddescriptionunverändert übernommen werden. Ein Script, das durch die Installation dieses App Bundle entsteht, enthält die Geheimwerte im Zustand******. Erst wenn die installierende Seite die echten Werte einträgt, funktionieren die Statements, die diese Werte lesen. Werte, die außerhalb vonsecretsstehen (die Header vonHttp, dassecretvonSignatureusw.), werden nicht verdeckt, sondern unverändert übernommen.
Ein Script kann bis zu 20 secrets enthalten. Die Pointer-Regeln werden unter /secrets in den Wertausdrücken behandelt.
Ausführungsidentität und Autorisierung
- Ausführungsidentität: Während der Ausführung wird jeder Ressourcenvorgang unter der Identität des Benutzers ausgeführt, der
/executeaufgerufen hat. DercreatedBy/updatedByeiner erstellten oder geänderten Ressource ist der Aufrufer, und auch eincreatedBy: ":self"-Scope wird anhand des Aufrufers aufgelöst. Die Ausnahme ist der anonyme Aufruf. Eine Ausführung, die über/execute/anonymoushereinkommt, hat keinen Aufrufer, daher werden beide anhand des Autors aufgelöst (Anonymer Aufruf). - Es gibt zwei Autorisierungsgrenzen, und zur Laufzeit prüft die Engine die Ressourcenberechtigungen nicht pro Statement erneut.
- Zum Autorenzeitpunkt (Speicherung): Beim Speichern eines Script wird geprüft, ob der Autor die von seinen Statements verwendeten Ressourcen- und Aktionsberechtigungen tatsächlich besitzt. Fehlt auch nur eine, wird die Speicherung abgelehnt. Mit anderen Worten: Ein Script, das einen unautorisierten Vorgang enthält, wird von vornherein nicht gespeichert. Diese Prüfung erhält jedes Statement, das eine Ressource auswählt, ob Leaf oder blockbesitzendes
ResourceForEach. Auch eine schon gespeicherte Definition wird beim Ändern erneut geprüft, sodass sich eine Definition nach dem Entzug der Berechtigung nicht mehr ändern und speichern lässt.- Das Mitgliederverzeichnis (ServiceUser) wird nicht über die Berechtigungs-Map, sondern über die Einstellungsachse geprüft. Um in den drei Lese-Statements sowie in
ResourceUpdateundResourcePatchresource: "ServiceUser"zu verwenden, müssen diesettingsder SpaceRole des AutorsSETTING_SERVICE_LOGIN(oderSETTING_ALL) enthalten (siehe settings der SpaceRole). Denn das Mitgliederverzeichnis ist auch auf allen anderen Wegen eine Ressource, die von den Space-Einstellungen verwaltet wird. - Ein Statement, das ein Mitglied erstellt oder löscht, lässt sich mit keiner Rolle speichern. Da ein Script ein Mitglied nicht erstellen oder löschen kann, wird es nicht wegen fehlender Berechtigung (
403), sondern als falsch geschriebenes Statement (400) abgelehnt. Es ist also keine Lücke, die man mit zusätzlichen Berechtigungen schließen kann. Die einzigen erlaubten Änderungen sindroleOverrideundenableLoginüberResourceUpdateundResourcePatch(Mit dem Mitgliederverzeichnis arbeiten).
- Das Mitgliederverzeichnis (ServiceUser) wird nicht über die Berechtigungs-Map, sondern über die Einstellungsachse geprüft. Um in den drei Lese-Statements sowie in
- Zum Aufrufzeitpunkt (
/execute): Es wird nur die Execute-Berechtigung des Aufrufers auf das Script geprüft. Ohne sie ergibt sich403. Nach bestandener Prüfung werden die Ressourcenberechtigungen pro Statement zur Laufzeit nicht erneut überprüft, und die Ausführung läuft. Das funktioniert wie die Berechtigung zum Ausführen einer Funktion in der Programmierung. Wer die Berechtigung hat, die Funktion auszuführen, wird nach der Berechtigung für die einzelnen Vorgänge darin nicht erneut gefragt. Auf dem Weg des anonymen Aufrufs gibt es diese Prüfung nicht. Denn es gibt keinen Aufrufer, den man prüfen könnte, und deshalb ist das Öffnen dieses Wegs dasselbe wie ein Script ohne Authentifizierung zu veröffentlichen.
- Zum Autorenzeitpunkt (Speicherung): Beim Speichern eines Script wird geprüft, ob der Autor die von seinen Statements verwendeten Ressourcen- und Aktionsberechtigungen tatsächlich besitzt. Fehlt auch nur eine, wird die Speicherung abgelehnt. Mit anderen Worten: Ein Script, das einen unautorisierten Vorgang enthält, wird von vornherein nicht gespeichert. Diese Prüfung erhält jedes Statement, das eine Ressource auswählt, ob Leaf oder blockbesitzendes
- Blockieren des direkten Aufrufs (
directCallEnabled): Ist dasdirectCallEnabledeines Scriptfalse, wird bereits der direkte/execute-Aufruf selbst abgelehnt. Dieses Gate greift erst, nachdem die Prüfung der Execute-Berechtigung bestanden ist, und blockiert daher auch dann, wenn die Execute-Berechtigung vorhanden ist. Ein Aufrufer ohne Execute-Berechtigung erhält bereits403, bevor der Aufruf dieses Gate erreicht. Dieses Gate gibt es nur an diesem Endpunkt, daher führen die Anbindungsaktion (script) eines Webhook und ein Scheduler das Script unverändert aus. Der Standardwert isttrue(direkter Aufruf erlaubt). - Anonymer Aufruf (
anonymousCallEnabled): Der Standardwert istfalse. Setzen Sie ihn auftrue, wird nur dieses Script auch über einen eigenen Weg ohne Authentifizierung (/execute/anonymous) ausgeführt, und die Ausführungsidentität ist dann nicht der Aufrufer, sondern der Autor. Von den beiden Grenzen oben fehlt auf diesem Weg die Prüfung zum Aufrufzeitpunkt (Execute-Berechtigung), daher übernimmt das Script die tatsächliche Authentifizierung selbst (die Signaturprüfung der empfangenen Anfrage). Die Bedingungen zum Einschalten und die Speicherregeln werden unter Anonymer Aufruf behandelt. - Eigentümer-Scope:
createdBy: ":self"in einemwhere-Filter bedeutet "nur das, was der aktuelle Aufrufer erstellt hat" (z. B. nur die eigene Wallet abfragen). In einem Script, das anonyme Aufrufe erlaubt, lässt sich dieser Filter nicht verwenden. Da es keinen Aufrufer gibt und er zum Autor aufgelöst wird, trifft die ursprüngliche Bedeutung eines Eigentümer-Scope nicht mehr zu. - Delegierte Berechtigungen (Vorsicht für Autoren): Verbindet man die beiden obigen Grenzen, ist das Ausführen eines Script gleichbedeutend mit einem Handeln mit den an das Script delegierten Berechtigungen des Autors. Der Aufrufer braucht nur Execute, und die Statements innerhalb des Script laufen genau in dem Umfang, für den der Autor bei der Speicherung autorisiert war. Dadurch kann ein Ressourcenvorgang, den der Aufrufer selbst nicht durchführen könnte, dennoch über das Script geschehen. Da die dem Autor erteilten Berechtigungen die effektive Reichweite dieses Script bestimmen, überlegen Sie sorgfältig, welche Vorgänge Sie in ein Script aufnehmen.
Zusammenfassende Checkliste
Prüfen Sie vor dem Speichern Folgendes.
- Haben Sie den anonymen Aufruf (
anonymousCallEnabled) eingeschaltet, steht inwherekeincreatedBy: ":self", und ein Statement, das die empfangene Anfrage prüft (etwaSignature), steht an erster Stelle. - Die externen Aufrufe (
Http,EmailSend) und die Gesamtzahl der Statements liegen innerhalb des Tariflimits,SetVarist höchstens 10 undCachehöchstens 5. - Wenn Sie
Cacheverwendet haben, haben Siekeyals Literal geschrieben und es nicht innerhalb vonLoopoderResourceForEachplatziert. - Wenn Sie mit
ResourceForEacheine große Menge durchlaufen, haben Sie einlimitdeklariert oder geprüft, dass die Menge vollständig durchlaufbar ist. - Haben Sie eine Iteration (
Loop,ResourceForEach) aufgenommen, haben Sie geprüft, dass diese Iteration als Multiplikation in das Zeitbudget eingeht (ohne externen Aufruf ist das Grundbudget von 30 Sekunden die Grenze). - Geheimwerte wie externe API-Schlüssel oder Signaturschlüssel haben Sie in
secretsdeklariert und mit{ /secrets/<key> }gelesen. Kein Geheimwert steht wörtlich in einem Statement. - Wenn Sie mit einer vollständigen Änderung (PUT) speichern, haben Sie
secretsmitgesendet. - Die Nachricht für die Signaturprüfung haben Sie nicht über
/payload, sondern über{ /rawPayload }genommen. - Gibt es ein Statement, das mit einem Mitglied (ServiceUser) arbeitet, besitzt der Autor
SETTING_SERVICE_LOGIN, und ein Statement, das diese Ressource erstellt oder löscht, haben Sie nicht aufgenommen. - Nicht rückgängig zu machende Vorgänge (externe Aufrufe) wurden möglichst weit hinten platziert.
- Wenn Sie mit
HttpDateien senden, haben Sie nur eines der Anfrage-Body-Felder (body,urlBody,multipartBody) angegeben und geprüft, dass jede Datei innerhalb des Download-Limits pro Tarif liegt. - Wenn Sie Update-/Patch-Konkurrenz befürchten, verwenden Sie das
version-Feld vonResourceUpdateoderResourcePatch. - Um ein Ergebnis zurückzugeben, haben Sie
Return.valueangegeben.
Fehler
Dies sind die Codes, die auftreten, wenn die Form der Definition eine statische Einschränkung verletzt und das Speichern deshalb abgelehnt wird. Die Codes für Verstöße gegen die Regeln der Wertausdrücke stehen unter Fehler bei den Wertausdrücken, die Codes, die beim Aufrufen und Löschen auftreten, unter Fehler bei den Endpunkten. Codes, die allen Ressourcen gemeinsam sind, finden Sie unter Gemeinsame Fehler.
| Code | Bedingung |
|---|---|
WGL400066 | Eine Definition enthält mehr als 5 Cache-Statements. |
WGL400068 | Ein Cache-Statement steht im Block von Loop oder ResourceForEach. |
WGL400067 | Im key eines Cache-Statements steht kein Literal, sondern eine { /pointer }-Referenz. |
WGL400065 | Das ttl eines Cache-Statements liegt außerhalb des erlaubten Bereichs. |
WGL400063 | In einem Cache-Statement steht ein Feld, das nicht zur jeweiligen action gehört (ttl bei Get, defaultValue bei Set). |
WGL400060 | Im resource von ResourceCreate, ResourceDelete oder eines Statements für Veröffentlichung und Archivierung steht "ServiceUser". Das Mitgliederverzeichnis nehmen nur die drei Lese-Statements sowie ResourceUpdate und ResourcePatch an. |
WGL400077 | Im resource von ResourceCount steht eine Ressource, die sich nicht zählen lässt. Media und das Mitgliederverzeichnis (ServiceUser) lassen sich nicht zählen. |
WGL400037 | In einem EmailSend stehen to und toServiceUser zugleich, oder beide sind leer. Schreiben Sie genau eines davon. |
WGL400054 | Die Summe der Empfänger eines EmailSend (to 1 + cc + bcc) überschreitet 50. |
WGL400039 | Das timeoutMs eines EmailSend überschreitet die Obergrenze. |
WGL400101 | In einem EmailSend stehen body und templateBody zugleich, oder beide sind leer. Schreiben Sie genau eines davon. |
WGL400102 | Das templateBody.source eines EmailSend ist nicht genau ein Pointer auf ein Content, das ein ResourceRead oder ein ResourceFind dieses Script gelesen hat. Auch Zeichen vor oder hinter dem Pointer führen zur Ablehnung. |
WGL400061 | In einem Script, das anonyme Aufrufe erlaubt (anonymousCallEnabled), steht im where eines Lese-Statements createdBy: ":self". |
WGL400023 | Eine Definition enthält mehr als 10 SetVar-Statements. |
WGL400026 | Das retry eines Http-Statements überschreitet die Obergrenze 2. |
WGL400087 | In einem Http stehen zwei oder mehr Anfrage-Body-Felder (body, urlBody, multipartBody). |
WGL400088 | Das multipartBody eines Http enthält keinen einzigen part. |
WGL400089 | In einem part von multipartBody stehen sowohl value als auch url, oder keines von beiden. |
WGL400090 | In einem part von multipartBody steht fileName ohne url. |
WGL400036 | ResourceForEach überschreitet die Obergrenze für die Anzahl der Elemente, die dieses Statement verarbeiten kann. |
WGL400094 | In secrets gibt es zwei oder mehr Einträge mit demselben key. |
WGL400095 | Eine Definition enthält mehr als 20 secrets. |
WGL400086 | Das value eines secrets-Eintrags liegt außerhalb von 1-4.096 Zeichen. Der Fehler enthält das value nicht. |
WGL400086 | Das text eines PdfWatermark ohne { /pointer } liegt außerhalb von 1-64 Zeichen. |
WGL400096 | Die transformations einer Media-Ingest-Anweisung sind kein Array, das type eines Elements ist nicht PdfWatermark, bei PdfWatermark fehlt text oder ist ein Objekt oder Array, color hat nicht das Format #RRGGBB, oder das text in seiner geschriebenen Form enthält unzulässige Zeichen oder einen Zeilenumbruch. |
WGL429005 | Die Gesamtzahl der Statements in einer Definition überschreitet das Tariflimit. |
WGL429006 | Die Anzahl der externen Aufrufe (Http, EmailSend) in einer Definition überschreitet das Tariflimit. |
WGL403015 | Der Autor besitzt die Berechtigungen für die Ressourcen und Aktionen nicht, die die Statements der Definition verwenden. Selbst wenn die Berechtigung vorliegt, wird das Speichern abgelehnt, sobald an dieser Erlaubnis ein Filter contentType, createdBy oder tag hängt. Es muss eine Erlaubnis ohne Bedingung sein. Die einzige Ausnahme ist Content Create: Hier wird auch eine Erlaubnis anerkannt, die einen contentType-Bereich festlegt, und dieser Bereich wird mit dem im Statement angegebenen contentType abgeglichen (für Media Create gilt diese Ausnahme nicht). Denselben Code erhalten Sie auch, wenn im resource eines Lese-Statements "ServiceUser" steht, der Autor aber SETTING_SERVICE_LOGIN nicht besitzt. |
Verwandte Dokumente
- Wertausdrücke: Regeln für Werte und Bedingungen.
- Statement-Katalog: die Felder und Ergebnisse jedes Statements.
- Cookbook: eine Sammlung vollständiger Beispiele.
- Script-Ressource und Endpunkte: die
Script-Ressourcenstruktur und HTTP-Endpunkte wie/execute. - Script-Übersicht: die Struktur der obersten Ebene und die Zeit für eine einzelne Ausführung.
