SQL Server: Sicherheit für Entwickler

Row Level Security

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Mit Row Level Security bietet SQL Server (endlich) eine Methode an, um einen zeilenbasierten Ansatz zu ermöglichen. Mit Hilfe eigener Funktionen kann bestimmt werden, ob die Zeile einer Tabelle für einen Nutzer verfügbar ist oder nicht.
12:23

Transkript

Ein weiteres Sicherheitsmerkmal, was SQL Server 2016 bieten wird, ist das Row Level Security. Mit der Row Level Security haben Sie die Möglichkeit, eine zeilenbasierte Berechtigung zu etablieren mit einer eigenen Filterfunktion. Diese Filterfunktion werden Security Policies zusammengeschaltet und bieten die Möglichkeit, zum Beispiel auf den Inhalt einer Tabelle auch Rücksicht zu nehmen. Das heißt, ich kann in eine Zeile schauen, welchem Vertriebsgebiet, welchem Bereich, welche Abteilung dieser Zeile zugeordnet ist, kann gleichzeitig in irgendeiner Form ermitteln, zu welchem Bereich z.B. der Benutzer gehört und nur wenn das matcht zum Beispiel, kann ich eine Zeile zurückliefern. Das kann bei exzessiver Benutzung natürlich durchaus auf die Performance gehen, bietet aber wirklich die Möglichkeit, sehr, sehr feingranular die einzelnen Informationen gefiltert an den Benutzer herauszugeben oder nicht. Und es war ein Feature, was sehr, sehr viele Kunden von Microsoft gefordert haben. Und ich zeige Ihnen jetzt mal, wie das Ganze aktuell in der Praxis aussieht. So, ich bin dann hier im SQL Server Management Studio, muss einiges an Vorbereitungen erledigen, damit ich das Demo durchführen kann. Ich muss zunächst eine Datenbank anlegen. Ich benötige einige User, mit denen ich experimentieren kann, ich habe hier einmal den Chef und 2 Mitarbeiter. Ich lege entsprechende Rollen an, einmal für North und einmal für South, das bedeutet, ich kann eine Funktion implementieren, die den Zugriff auf einer Tabellenzeile gestattet, wenn der User Mitglied in einer bestimmten Rolle ist. Das heißt, ich lege hier entsprechend die Rollen an und verteile die Mitgliedschaften, dann lege ich 3 Tabellen an, die entsprechend ein paar Daten haben. Wichtig ist, hier die letzte Spalte bei allen Tabellen, dort steht drin, auf welche Rolle entsprechend der Zugriff entfallen soll. Das Gleiche noch mal mit Invoices und last but not least für so etwas wie Orders. Hier steht dann sogar der Name des Users direkt drin. Ich kann also ein bisschen flexibel in meiner Programmierung sein und habe damit die Vorbereitung erst einmal soweit abgeschlossen. Was natürlich noch ganz gut benötigt wird, ist an der Stelle eine entsprechende Berechtigung auf die Tabellen, damit die einzelnen Logins auch drauf zugreifen. Da das jetzt hier nicht das Thema ist, gehe ich da einfach ein bisschen großzügig hin und gebe der Public-Rolle die entsprechenden Rechte. Wichtig, hier unten gebe ich auch der Public-Rolle das Recht SHOWPLAN, damit ich mir ein Ausführungsplan später anzeigen lassen kann. So, als Nächstes benötige ich eine Funktion, die für mich die Filterarbeit erledigt. An dieser Funktion hat der SQL Server einige Anforderungen, zum einen muss es eine Tabellenwertfunktion sein, sie muss mit WITH SCHEMABINDING angelegt werden. Und die Regel ist eigentlich relativ einfach: Für jede Zeile aus den Datentabellen wird diese Funktion einmal aufgerufen. Und sie hat jetzt die Wahl, quasi entweder mindestens eine Zeile zurückzuliefern, das bedeutet, für einen SQL Server, dass die entsprechende Zeile aus der Datentabelle zurückgeliefert wird oder keine Zeilen zurückliefert, das bedeutet, dass die entsprechende Zeile aus der Datentabelle herausgefiltert wird. Was genau in der Zeile hier steht, die diese Funktion zurückliefert, ist unerheblich. Ja, es sollte nur natürlich so sein, dass die Ausführung dieser Abfrage möglichst ressourcenschonend und möglichst schnell vonstattengeht. Die Funktion kann über Parameter verfügen, theoretisch auch über mehrere und damit habe ich die Möglichkeit, auf den Inhalt der einzelnen Datenzeilen zuzugreifen. Ich scrolle mal noch ein kleines Stückchen nach oben. Sie sehen, hier gab es ja Spalten, wo ich angeben konnte entsprechend, welche Rollen oder welche User auf die einzelnen Zeilen Zugriff haben sollen. Und das kann ich mir im weiteren Verlauf hier als Parameter geben lassen, sodass ich hier eine Abfrage habe, die einfach prüft, entspricht das mein aktuellen USER_NAME, ja oder nein? Oder bin ich schlicht Mitglied in dieser Roller, die da angegeben wird? Und wenn ich NULL habe, dann soll er einfach ein Test auf die Public-Rolle machen, da ist bekanntlich ja jeder Mitglied. Und wenn das letztendlich gegeben ist, das heißt, entweder der Benutzername oder der Benutzer ist Mitglied der angegebenen Rolle auf 1 steht, bedeutet das im Wesentlichen, dass dieses Prädikat erfüllt ist. Und damit liefert diese keine Abfrage eine Zeile zurück, das wiederum sagt dem SQL Server dann, dass er die entsprechende Datenzeile einfließen lassen soll. So, die Funktion kann ich anlegen. Damit tut Ihr aber erstmal nicht wirklich etwas. Ich brauche noch etwas, was sich Security Filter beziehungsweise Security Policy nennt. Und hiermit kann ich quasi die Verdrahtung machen zwischen dieser Funktion, die ich gerade angelegt habe, dem Security Policy oder dem Filter und einzelnen Filterprädikaten, die auf die Tabellen, die ich vorher angelegt habe, gemünzt sind. Das bedeutet, ich könnte hier zum Beispiel sagen, ich möchte ein Security Policy anlegen mit dem und dem Namen und zu dieser Policy gehören eine Reihe von Filter Predicates, die rufen quasi alle die Funktion auf. Und das ist die Spalte, die dann quasi aus dieser Tabelle genommen wird und der Funktion übergeben, damit die entscheiden kann, ob der einzelne User Zugriff haben soll oder nicht. Da ich 3 Tabellen oben angelegt habe, habe ich hier unten auch 3 Prädikate, die entsprechend unterschiedliche Spalten übergeben bekommen, weil der Name der entsprechenden Spalte jeweils ein anderer ist, das heißt, das kann ich anlegen. Diese Policy kann ich später auch wieder ausschalten, ich kann mehrere haben. Standardmäßig ist eine Policy erstmal sofort aktiv, wenn ich die jetzt hier an der Stelle anlege. Und ich kann mir in der Datenbank auch anzeigen, wo ich diese Policy finde, nämlich in der Datenbank, unter Security, unter Security Policies ist exakt meine Policy zu finden, die ich gerade angelegt habe. Ich kann auch hier auf Eigenschaften gehen und mir zum Beispiel die Security Predicates anzeigen lassen, die ich entsprechend definiert habe. Und Sie sehen hier schon, auch die kann ich einzeln ein- oder ausschalten. Hier gibt es eine Spalte, die da heißt Enabled. So, ich kann nun ein zweites oder ein weiteres Security Policy anlegen, hier zum Beispiel mit dem STATE=OFF, das heißt, in dem Fall ist dieses Security Policy nicht sofort aktiv. Das ist auch zum Teil notwendig, weil ich kann zwar beliebig viele Security Policies haben. Ich kann sie einzeln ein- oder ausschalten, jedoch darf ich nicht zu einem Zeitpunkt 2 Policies aktiviert haben, die über 2 Filter Predicates verfügen, die auf ein und dieselbe Tabelle gehen. Das heißt, eine Tabelle wird nur einmal entsprechend gefiltert. Und da ich hier auf die gleichen Tabellen gehe, mit den Funktionen in dem Fall sogar, muss ich beim Anlegen hier darauf achten, dass diese nicht aktiv ist, kann ich dann anlegen, kann hier aktualisieren. Und Sie sehen, entsprechend ist dann die zweite Policy als nicht aktiv gekennzeichnet. Jetzt könnte ich hingehen und zum Beispiel versuchen, die einzuschalten. Und Sie sehen, das funktioniert nicht, weil er gibt mir eine Fehlermeldung aus, die sagt, okay, es funktioniert nicht, du kannst keine 2 Policies gleichzeitig aktiviert haben, die Prädikate auf ein und dieselbe Tabelle definieren. Das funktioniert nicht, das heißt, jede Tabelle wird nur maximal einmal gefiltert. So, jetzt können wir den ganzen Zauber einfach mal ausprobieren. Ich habe hier ein kleines Testskript, dann war es entsprechend in dem Userkontext oder im Sicherheitskontext des Benutzers ausgeführt wird. Und Sie sehen, es funktioniert. Na ja, nicht ganz, was ich nämlich nicht machen kann, ist, ich kann kein TRUNCATE TABLE ausführen, das heißt, ich kommentiere das noch mal kurz aus, und wie Sie sehen, hier geht es durch, die Ergebnisse kann ich auch anzeigen. Und ich bekomme die entsprechenden Ergebnisse, so wie das festgelegt ist, also zum Beispiel der Chef ist, ich scrolle mal hoch, damit das klar wird, der Chef ist zum Beispiel Mitglied in der Rolle North, Mitglied in der Rolle South und heißt selber noch Chef, das heißt, er bekommt alle Zeilen soweit angezeigt. Wenn ich hier weiter runterscrolle, dann wiederholt sich das Bild quasi, also das funktioniert für den Chef soweit. Ich gehe dann wieder runter. Wie gesagt, wichtiger Hinweis, das war zu weit, wichtiger Hinweis, TRUNCATE TABLE funktioniert nicht an der Stelle, das heißt, das hier ist immer zum Scheitern verurteilt. Interessanterweise, wenn ich das Statement so ausführe, kann ich das einmal als Chef machen. Ja, wenn ich das jetzt einfach gezielt ausführe, dann sagt er mir einfach, er findet die Tabelle nicht, obwohl die sehr wohl vorhanden ist. Ich denke mal, die Fehlermeldung wird wahrscheinlich im Release Candidate auch noch ein bisschen verfeinert werden. Momentan gibt es einfach nur diese Fehlermeldung. Ich kommentiere das einfach mal aus. So, dann gehe ich mal weiter, gehe wieder aus der Rolle des Chefs raus und zum Beispiel in die des Employee1 rein, der entsprechend Zugriff auf den Norden hat. Und Sie sehen hier, es ist Mitglied von PUBLIC, er ist Mitglied entsprechend auch eigentlich dieser Rolle, weil dahinter steht nämlich wiederum die Public-Rolle. Ich scrolle noch mal hoch, damit dass hier eine Funktion noch mal kurz zu sehen ist IS_MEMBER, er hat nämlich noch ein Aufruf von ISNULL und wenn da wirklich NULL drinsteht, dann nehme ich einfach PUBLIC. Das heißt, überall, wo entsprechend einfach nichts drinsteht, wird NULL verwendet. Und ich kriege die Daten dann von PUBLIC und von North angezeigt, ich kriege dann entsprechend hier ebenfalls North und so weiter und so fort. Das funktioniert also ziemlich gut. Und ich kann jetzt noch mal hingehen und das Ganze für den Süden noch mal durchführen. Und Sie sehen, hier das andere Bild, die Zeilen habe ich auf jeden Fall immer dabei und South an der Stelle. Dann kann ich einzelne Policies ein- oder ausschalten. Sie haben schon gesehen, das geht hier entsprechend auch über die Oberfläche. Ich kann das auch mit T-SQL machen, ich kann das auch für einzelne Security Predicates machen, wenn ich das möchte oder Filter Predicates machen, das heißt, ich kann da wirklich sehr, sehr genau vorgehen. Hier einmal ein Beispiel, wie ich das mit Security Policies mache, ich sage einfach STATE=OFF oder STATE=ON. Und wenn ich möchte, kann ich mir entsprechend über diese DMVs auch anzeigen, was ich denn in der Tat wirklich habe, also welche Policies und welche Predicates ich habe. Und wenn ich das ausführe, dann zeigt er mir das hier noch einmal in epischer Breite an, inklusive auch dem Teil, der zum Beispiel festlegt, welche Funktion, mit welcher Spalte ausgeführt wird. So, Sie sehen, die Row Level Security ist durchaus eine sehr mächtige Sache. Ich behaupte mal, dass der ein oder andere das schon mal für sich in anderer Art und Weise selber entwickelt hat in dem ein oder anderen Projekt. Hier ist es jetzt in dem SQL Server integriert und das macht auch durchaus Sinn, weil ich habe hier die Möglichkeit, das Ganze so ein bisschen auch über die Oberfläche zu verwalten. Und ich habe zudem die Möglichkeit, wenn ich beispielsweise einen Filter durchführe für meinen User Employee2, der im Süden aktiv ist, kann ich den Ausführungsplan markieren. Und ich sehe zum Beispiel, dass ich hier dann der Filter automatisch immer dazugesetzt wird. Und es macht schon Sinn an der Stelle. Das heißt, ich muss mich nicht selber darum kümmern, dass ich entsprechend selber filtere, ich könnte das irgendwo vergessen, ich muss keine Sicherheit schaffen in Form von möglicherweise irgendwelchen Sichten oder Ähnliches, damit ich auf die Daten sicher zugreifen kann, und niemand quasi ein Weg drumherum findet und trotzdem auf die Originaldaten zugreifen kann. Ich denke, das ist auf jeden Fall ein Feature, was eine große Zukunft vor sich haben wird, und wir schauen mal, wie das letztendlich dann auch im Release Candidate aussehen wird.

SQL Server: Sicherheit für Entwickler

Lernen Sie, wie sich das Thema Sicherheit im Entickleralltag mit Microsofts Datenbankserver umsetzen lässt.

2 Std. 31 min (25 Videos)
Derzeit sind keine Feedbacks vorhanden...
Hersteller:
Exklusiv für Abo-Kunden
Erscheinungsdatum:15.01.2016

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!