Farbschema: Dunkel
Sie befinden sich hier: start » de » Dokumentation » Datenintegration und Datenzugriff » WKL Database Gateway » Konzepte » Rechte: Regeln und Reichweite

Rechte: Regeln und Reichweite

Was ein Aufrufer erreicht, legen Regeln fest: welche Aliasse, welche Arten von Objekten und welche Objekte, welche Methoden und ob nur lesend. Regeln erhalten Dienstschlüssel, Personen, Windows-Konten und -Gruppen sowie SQL-Anmeldungen. Diese Seite erklärt, wie Regeln zusammenwirken.

Wichtige Funktionen

  • Zuschnitt je Aufrufer und je Alias.
  • Mehrere Regeln für verschiedene Aliasse, jede als Ganzes beurteilt.
  • Rechte je Tabelle, Sicht und Prozedur; eine Sicht ohne Rechte auf ihre Tabellen.
  • Ein persönlicher Schlüssel schränkt die Rechte seiner Person ein, gewährt aber nie mehr.

Grundkonzepte

Zuschnitt je Aufrufer

Regeln stehen unter Gateway:Security:Clients: erlaubte Aliasse, Ressourcenarten, Verben und ein Nur-Lese-Kennzeichen. Ein Aufrufer ohne passende Regel erreicht nichts. Ein Schlüssel ohne Regel verhindert den Start, weil er zwar anmelden, aber nichts erreichen würde.

Zwei Aufrufer dürfen nicht denselben Schlüssel tragen; die Startprüfung weist eine solche Konfiguration ab. Die Zuordnung geschieht über den Schlüssel: Trügen zwei Aufrufer denselben, würde jede Anfrage dem zugerechnet, den die Konfiguration zuletzt nennt, und der andere wäre von außen nicht mehr erreichbar. Welcher das ist, hinge an der Reihenfolge der Einträge – das wäre kein Zuschnitt. Die Meldung nennt beide Aufrufer und nie den Schlüssel, auch nicht als Prüfsumme: Eine Startmeldung landet in einem Protokoll und oft danach in einem Vorgang.

Reichweite je Alias

Eine Regel darf aus mehreren Einträgen mit derselben Id bestehen, und jeder Eintrag nennt seine eigenen Aliasse. Das ist für den häufigen Fall gedacht, dass eine Anwendung eine Datenbank nur liest und in eine zweite schreiben muss:

"Clients": [
  { "Id": "fachanwendung", "Databases": [ "fachdaten" ],
    "Resources": [ "views" ],                "Verbs": [ "GET" ],          "ReadOnly": true  },
 
  { "Id": "fachanwendung", "Databases": [ "anmeldung" ],
    "Resources": [ "views", "procedures" ],  "Verbs": [ "GET", "POST" ],  "ReadOnly": false }
]

Ohne diese Möglichkeit gälte die Reichweite eines Aufrufers für alle seine Aliasse gemeinsam. Eine Anwendung, die irgendwo schreiben muss, wäre damit überall schreibfähig, wo sie liest – und was das bedeutet, hängt davon ab, was in der anderen Datenbank steht. Den Katalog liest der Dienst aus der Datenbank, niemand pflegt ihn von Hand; erreichbar ist also alles, was dort existiert. In einer Datenbank mit vielen Prozeduren würde eine gemeinsame Reichweite sie alle aufrufbar machen.

Zwei Einträge mit derselben Id dürfen denselben Alias nicht nennen, und * steht nicht neben einem zweiten Eintrag. Beides verhindert den Start mit einer Meldung, die die Id und den doppelten Alias nennt. Sonst entschiede die Reihenfolge der Einträge, welche Reichweite gilt, und beide Einträge sähen für sich genommen richtig aus. Weil so höchstens ein Eintrag einer Id auf eine Anfrage passen kann, spielt die Reihenfolge keine Rolle. Verschiedene Regeln (verschiedene Id), etwa die Regeln einer Person aus mehreren Windows-Gruppen, dürfen denselben Alias nennen; ihre Rechte addieren sich.

Ein Eintrag wird als Ganzes beurteilt. Den Alias aus dem einen und das Verb aus dem anderen zu nehmen, würde zwei enge Erlaubnisse zu einer weiten addieren, die niemand aufgeschrieben hat. Im Beispiel oben wird ein POST gegen fachdaten abgewiesen, obwohl derselbe Aufrufer POST gegen anmeldung darf.

Ein einzelner Eintrag, der * neben einem konkreten Alias nennt, bleibt zulässig – innerhalb eines Eintrags können sich die beiden nicht widersprechen.

Rechte je Objekt

Eine Regel kann die Objekte nennen, für die sie gilt (Objects), und einzelne davon ausnehmen (ExceptObjects). Beide Listen haben die Form der Tabellenlisten eines Alias: *, schema.* oder schema.name, die Namen so geschrieben, wie der Dienst sie führt (Sonderzeichen kodiert, siehe Namen mit Sonderzeichen). Groß- und Kleinschreibung zählt nicht.

"Clients": [
  { "Id": "lager-lesen", "Databases": [ "fachdaten" ],
    "Resources": [ "views" ], "Objects": [ "dbo.viewLagerbestand" ],
    "Verbs": [ "GET" ], "ReadOnly": true },
 
  { "Id": "lager-pflege", "Databases": [ "fachdaten" ],
    "Resources": [ "tables" ], "Objects": [ "lager.*" ], "ExceptObjects": [ "lager.Preise" ],
    "Verbs": [ "GET", "PATCH" ], "ReadOnly": false }
]
  • Ohne Liste gilt die Regel für alle Objekte ihrer Arten. Die Arten unter Resources gelten weiter: Ein Objekt unter Objects erreicht der Aufrufer nur, wenn seine Art erlaubt ist.
  • Ausnehmen gewinnt innerhalb der Regel. Zwischen den Regeln einer Person addieren sich die Rechte wie überall: Gewährt eine andere Regel das Objekt, bleibt es erreichbar.
  • Eine Sicht braucht kein Recht auf ihre Tabellen. Geprüft wird nur das Objekt, das die Anfrage nennt. SQL Server liest die Tabellen hinter der Sicht über die Besitzkette, wie für jede Anmeldung, die nur die Sicht lesen darf. So geben Sie einen Teil einer Tabelle frei: Sicht anlegen, Sicht freigeben.
  • Was ein Aufrufer nicht lesen darf, gibt es für ihn nicht. Dienstdokument, $metadata und die Kataloglisten des Treibers zeigen nur erlaubte Objekte; eine Anfrage an ein anderes Objekt beantwortet der Dienst mit 404 wie bei einem Objekt, das es nicht gibt. Ein lesbares Objekt, das der Aufrufer so nicht ändern darf, beantwortet er mit 403.
  • Nicht neben sql. Eine eigene Anweisung erreicht alles, was die Anmeldung erreicht, unter der sie läuft – die des Alias oder, bei einer SQL-Anmeldung und unter Impersonate, die eigene der Person. Der Dienst liest den Text nicht und kann dort keine Objektliste durchsetzen; eine Regel mit sql und einer Objektliste verhindert deshalb den Start bzw. das Speichern. Dasselbe gilt für Aufrufer, deren Anweisungen unter ihrer eigenen Anmeldung laufen (siehe Durchreichepfad): Dort begrenzt die Objektliste eine eigene Anweisung nicht. Geprüfte Anweisungen ohne sql prüft der Dienst dagegen Objekt für Objekt gegen die Objektliste.

Zeilenweise Einschränkung

Die Regeln des Dienstes enden bei Alias, Ressourcenart, Objekt, Verb und Nur-Lese-Kennzeichen. Eine Regel je Zeile kennt der Dienst nicht, und er bekommt auch keine: Ob eine Person eine bestimmte Zeile sehen oder ändern darf, beantwortet die Datenbank – mit einer Sicht, die filtert, und mit Prozeduren, die prüfen. Zwei Berechtigungssysteme, die sich überschneiden, wären am Ende beide falsch.

Voraussetzung: Die Anweisung läuft als Person. Eine Sicht kann nur nach der Person filtern, wenn SQL Server die Person kennt. Das ist der Fall

  • an einem Alias mit Persons: Impersonate, für Aufrufer mit eigener Anmeldung in SQL Server (Windows-Konto oder eine bei der Person eingetragene SQL-Anmeldung): Der Dienst wechselt mit EXECUTE AS LOGIN. SUSER_SNAME() und USER_NAME() nennen dann die Person, ORIGINAL_LOGIN() den Dienst; SUSER_SID() gibt die SID der Person zurück, in der Anweisung ebenso wie in Spaltenvorgaben und Triggern; siehe So geben Sie Personen an SQL Server weiter;
  • bei der Anmeldung mit einer SQL-Anmeldung per HTTP Basic: Die Anweisung läuft auf einer eigenen Verbindung mit dieser Anmeldung.

Die Falle ist die Voreinstellung. An einem Alias mit Persons: Service – der Vorgabe – laufen alle Anweisungen unter der Anmeldung des Alias. SUSER_SNAME() und SUSER_SID() nennen dann das Konto des Dienstes, für jeden Aufrufer gleich. Eine Sicht, die darauf filtert, meldet keinen Fehler: Sie liefert je nach Filter nichts oder alles. Dasselbe gilt für Aufrufer mit einem Dienstschlüssel: Er wechselt nie die Identität, auch an einem Alias mit Impersonate nicht.

Was in welchem Fall ankommt:

AufruferPersons: Service (Vorgabe)Persons: Impersonate
Windows-Konto mit eigener Anmeldung in SQL ServerAnmeldung des Alias, SESSION_CONTEXT leerdie eigene Anmeldung
Windows-Konto ohne eigene AnmeldungAnmeldung des Alias, SESSION_CONTEXT leerabgewiesen, 403
Person mit eingetragener SQL-Anmeldung (persönlicher Schlüssel)Anmeldung des Alias; Person in SESSION_CONTEXTdiese SQL-Anmeldung
Person ohne eigene Anmeldung (persönlicher Schlüssel)Anmeldung des Alias; Person in SESSION_CONTEXTAnmeldung des Alias; Person in SESSION_CONTEXT
SQL-Anmeldung per HTTP Basicdie eigene Anmeldungdie eigene Anmeldung
DienstschlüsselAnmeldung des Alias, ohne PersonAnmeldung des Alias, ohne Person
Identität aus der Verwaltung gewählt (Sammelanmeldung)die Sammelanmeldung; Person in SESSION_CONTEXTdie Sammelanmeldung; Person in SESSION_CONTEXT

SESSION_CONTEXT setzt der Dienst für Aufrufer mit persönlichem Schlüssel und für eine gewählte Datenbank-Identität, an jedem Alias und vor jedem Wechsel, nur lesend: wkl.person (Name der Person), wkl.key (Kennung des persönlichen Schlüssels oder NULL) und wkl.role (gewählte Identität oder NULL). Der Verbindungspool setzt die Werte zurück, bevor die Verbindung an die nächste Anfrage geht.

Beispiel 1: Filter auf die Anmeldung der Person. Für einen Alias mit Persons: Impersonate. Verglichen wird über SUSER_SID(), nicht über den Namen: Ein umbenanntes Windows-Konto behält in SQL Server seinen alten Anmeldenamen, die SID bleibt (siehe „Der Dienst kann diese Anmeldung in SQL Server nicht annehmen“ nach Umbenennen eines Kontos).

CREATE VIEW maske.auftrag_liste AS
SELECT a.auftrag_id, a.betreff, a.bereich_id
FROM dbo.auftrag AS a
WHERE EXISTS (SELECT 1
              FROM iam.konto_bereich AS kb
              WHERE kb.bereich_id = a.bereich_id
                AND kb.login_sid = SUSER_SID());

Beispiel 2: Filter auf die Person aus SESSION_CONTEXT. Für Aufrufer ohne eigene Anmeldung (persönlicher Schlüssel an einem Alias mit Persons: Service). Der Wert ist der Name der Person in der Verwaltung; eine Umbenennung dort ändert ihn.

CREATE VIEW maske.auftrag_liste_schluessel AS
SELECT a.auftrag_id, a.betreff, a.bereich_id
FROM dbo.auftrag AS a
WHERE EXISTS (SELECT 1
              FROM iam.konto_bereich AS kb
              WHERE kb.bereich_id = a.bereich_id
                AND kb.person_name = CAST(SESSION_CONTEXT(N'wkl.person') AS nvarchar(256)));

Daraus folgt eine Entscheidung: Entweder Sie verbinden beide Bedingungen in einer Sicht (… = SUSER_SID() OR … = SESSION_CONTEXT(N'wkl.person')) und nehmen hin, dass der Dienst den Namen der Person verbürgt, oder Sie stellen den Alias auf Persons: Impersonate, geben jeder Person eine eigene Anmeldung und verwenden nur Beispiel 1. Dann weist der Dienst ein Windows-Konto ohne eigene Anmeldung mit 403 ab. Ein persönlicher Schlüssel ohne eingetragene SQL-Anmeldung läuft dagegen auch dort unter der Anmeldung des Alias – für ihn liefert SUSER_SID() das Konto des Dienstes, und ein Filter nach Beispiel 1 zeigt ihm nichts oder alles. Tragen Sie bei solchen Aliassen jeder Person mit Schlüssel eine SQL-Anmeldung ein, oder verbinden Sie beide Bedingungen.

Welche Wege die Identität wechseln. Alle sechs Datenwege öffnen ihre Verbindung über dieselbe Sitzung: Lesen (auch $apply), Einzelsatz, Zählen, Prozeduraufruf, Schreiben in Tabellen und die Durchreiche.

Der Katalog nicht. $metadata, Spalten, Schlüssel und die Liste der Objekte liest der Dienst unter der Anmeldung des Alias, und welche Objekte ein Aufrufer sieht, entscheiden die Regeln des Dienstes. Das hat zwei Folgen:

  • Eine Sicht, die Zeilen filtert, zeigt in $metadata trotzdem alle ihre Spalten.
  • Den Schlüssel einer Sicht (aus den Browse-Metadaten von SQL Server) ermittelt der Dienst unter der Anmeldung des Alias, nicht unter der der Person.

Verwandte Themen

de/wiki/data-conectivity/database-gateway/concepts/rights-and-scope.txt · Zuletzt geändert: von Wolfgang van der Stille