Modulsignierung (Datenbankmodul)

Bei Datenbankanwendungen muss der Zugriff auf zugrunde liegende Tabellen und Objekte innerhalb des Anwendungsschemas häufig durch Verfahren oder Sichten auf der Einstiegsebene ermöglicht werden. Die Absicht besteht darin, den Endbenutzern Zugriff auf die Objekte auf der Einstiegsebene zu gewähren, die dann ihrerseits im Namen des Benutzers auf die darunter liegenden Objekte zugreifen. Den Endbenutzern muss auf diese Weise kein Zugriff auf alle Objekte im Anwendungsschema gewährt werden. Dieser Ansatz dient zwei Zielen:

  • Die Berechtigungsverwaltung wird insofern vereinfacht, als Berechtigungen nur für eine kleinere Teilmenge von Objekten und nicht für alle Objekte im Anwendungsschema verwaltet werden müssen.

  • Es wird verhindert, dass der Endbenutzer Zugriff auf das zugrunde liegende Schemalayout besitzt, da nur die Einstiegspunkte offen gelegt werden.

MicrosoftSQL Server verfügt über eine Reihe von Features, mit deren Hilfe sich diese Szenarien erreichen lassen, z. B. die Besitzverkettung und das Verwenden der EXECUTE AS-Anweisung. Ab SQL Server 2005 bietet SQL Server auch die Möglichkeit, Module innerhalb der Datenbank zu signieren. Die Modulsignierung bietet ähnliche Möglichkeiten, ändert aber nicht den Ausführungskontext. Ein Modul in diesem Kontext bezieht sich auf eine gespeicherte Prozedur, eine Funktion, einen Trigger oder eine Assembly. Weitere Informationen finden Sie unter CREATE ROLE (Transact-SQL) und Verwenden von EXECUTE AS zum Erstellen benutzerdefinierter Berechtigungssätze.

Modulsignaturen

SQL Server 2005 bot erstmals die Möglichkeit, Module innerhalb der Datenbank zu signieren, wie z. B. gespeicherte Prozeduren, Funktionen, Trigger oder Assemblys. Beachten Sie dabei, dass DLL-Trigger (Data Definition Language) nicht signiert werden können. Bei einer digitalen Signatur handelt es sich um einen Datendigest, der mit dem privaten Schlüssel des Signaturgebers verschlüsselt wurde. Durch den privaten Schlüssel ist sichergestellt, dass die digitale Signatur eindeutig vom Träger oder Besitzer der Signatur stammt.

Zum Signieren der Daten erstellt der Signaturgeber einen Datendigest, verschlüsselt diesen mit einem privaten Schlüssel und fügt den verschlüsselten Digestwert an die Daten an. Der Signaturempfänger überprüft die Signatur, indem er den verschlüsselten, an die Daten angefügten Digestwert mithilfe des öffentlichen Schlüssels des Signaturgebers entschlüsselt. Der Signaturempfänger vergleicht diesen verschlüsselten Digestwert mit dem Digestwert, der für die angefügten Daten berechnet wurde. Wichtig ist, dass sowohl der Signaturgeber als auch der Signaturempfänger zum Erstellen des Datendigests dieselbe Hashfunktion verwenden.

VorsichtshinweisVorsicht

Die Modulsignierung sollte nur zum Erteilen von Berechtigungen, niemals zum Verweigern oder Aufheben von Berechtigungen verwendet werden.

Szenario

Angenommen, der Zugriff auf die sys.sysprocesses-Sicht soll mithilfe der gespeicherten Prozedur usp_sysprocesses hergestellt werden. Benutzer können auf die in sys.sysprocesses enthaltenen Informationen nur zugreifen, wenn sie die usp_sysprocesses-Prozedur durchlaufen. Da die Objekte usp_sysprocesses und sys.sysprocesses unterschiedliche Besitzer aufweisen, kann die Besitzverkettung nicht verwendet werden.

Zuerst muss mithilfe der CREATE CERTIFICATE-Anweisung auf dem Server ein Zertifikat aus einem Schlüsselpaar erstellt werden. Anschließend wird dem Zertifikat die Berechtigung erteilt, eine Auswahl aus der sys.sysprocesses-Tabelle vorzunehmen. Da von SQL Server jedoch nur Prinzipalen Berechtigungen erteilt werden, muss zuerst mithilfe der CREATE LOGIN-Anweisung ein Anmeldename aus dem Zertifikat erstellt werden. Dieser Anmeldename benötigt keine Verbindungsberechtigungen für den Server, er dient lediglich als Berechtigungsplatzhalter und ist nicht zum Herstellen von Verbindungen mit der Serverinstanz gedacht. Diesem dem Zertifikat zugeordneten Anmeldenamen können dann mithilfe der GRANT VIEW SERVER STATE TO-Anweisung SELECT-Berechtigungen für die sys.sysprocesses-Tabelle erteilt werden. Nachdem die gespeicherte Prozedur usp_sysprocesses erstellt wurde, kann sie mithilfe der ADD SIGNATURE-Anweisung mit dem Zertifikat (eigentlich mit dem privaten Schlüssel, der dem Zertifikat entspricht) signiert werden. Eine neue Rolle wird erstellt, und ihr wird die Ausführungsberechtigung für die gespeicherte Prozedur usp_sysprocesses erteilt. Alle Benutzer, die Mitglied dieser Rolle sind, verfügen dann über die Berechtigungen zum Ausführen der gespeicherten Prozedur usp_sysprocesses und dadurch über die SELECT-Berechtigung für die sys.sysprocess-Sicht. Wenn Sie ein signiertes Modul ausführen, werden die dem Prinzipal mit der GRANT-Anweisung erteilten, mit dem Signierungszertifikat verbundenen Berechtigungen vorübergehend für die Dauer des Aufrufs mithilfe von UNION in Ihr Laufzeit-Sicherheitstoken aufgenommen. Sobald die Ausführungskontrolle zurückgegeben wird, werden diese Berechtigungen von Ihrem Sicherheitstoken wieder entfernt. Auf diese Weise verfügen Sie, allerdings nur für die Dauer der Modulausführung, über einen zusätzlichen Satz Berechtigungen. Alle anderen Benutzer oder Rollen, denen für diese Prozedur EXECUTE-Berechtigungen erteilt werden, verfügen über dieselben Möglichkeiten.

Beispiel

Das folgende Transact-SQL-Skript ist ein Beispiel für das oben aufgeführte Szenario. Aus einem Schlüsselpaar wird ein Zertifikat erstellt und einem neuen Anmeldenamen zugeordnet. Zuerst muss mit dem im .NET Framework SDK enthaltenen MakeCert-Tool ein Testschlüsselpaar erstellt werden. Anschließend werden dem mit dem Zertifikat verbundenen Anmeldenamen SELECT-Berechtigungen für die sys.sysproceses-Sicht erteilt. In der neuen Datenbank wird die verwaltete gespeicherte Prozedur usp_sysprocesses erstellt und mit dem Zertifikat signiert. Die SysProcRole-Rolle wird erstellt, und der Rolle wird die Ausführungsberechtigung für die gespeicherte Prozedur usp_sysprocesses erteilt. Ein Testbenutzer wird erstellt und der SysProcRole-Rolle hinzugefügt. Der Testbenutzer führt für sys.sysprocess eine SELECT-Anweisung aus und führt dann, um den Vergleich vornehmen zu können, die gespeicherte Prozedur usp_sysprocesses aus. Das Skript bereinigt danach die Testumgebung.

use master
go

-- Create a test database.
CREATE DATABASE db_Demo
go

-- Create a certificate on the server. A test key pair can be created
-- using the MakeCert tool that ships with the .NET Framework SDK.
CREATE CERTIFICATE SysProcCert FROM FILE = 'e:\programming\testCert.cer'
go

-- Create a login and map it to the certificate.
CREATE LOGIN login_SysProcCert FROM CERTIFICATE SysProcCert
Go

-- Revoke the connect permission.
REVOKE CONNECT SQL FROM login_SysProcCert ;
go 
 
-- Grant the certificate, through the login, permission to select from sys.sysprocesses view.
GRANT VIEW SERVER STATE TO login_SysProcCert
go

-- Create a test login.
CREATE LOGIN bob WITH PASSWORD = '<enterStrongPasswordHere>'
go

-- Connect to the test database.
use db_Demo
go

-- Create the master key for the test database (used to protect 
-- private keys and certificates in the database).
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<enterStrongPasswordHere>' 

-- Create a certificate from a private key.
CREATE CERTIFICATE SysProcCert FROM FILE = 'e:\programming\testCert.cer'
WITH PRIVATE KEY
(FILE = 'e:\programming\testCert.pvk', 
 DECRYPTION BY PASSWORD= '<enterStrongPasswordHere>', 
 ENCRYPTION BY PASSWORD='<enterStrongPasswordHere>')
go 

-- Create the assembly on the server. The assembly DLL must be signed.
CREATE ASSEMBLY SysStoredProcedures
FROM 'E:\programming\SysStoredProcs.dll'
WITH PERMISSION_SET = SAFE
go 

-- Create the managed stored procedure on the server.
CREATE PROCEDURE usp_sysprocesses
AS EXTERNAL NAME SysStoredProcedures.StoredProcedures.usp_sysprocesses
go 

-- Add the signature to the stored procedure.
ADD SIGNATURE TO [dbo].[usp_sysprocesses] 
BY CERTIFICATE SysProcCert WITH PASSWORD = '<enterStrongPasswordHere>'
go 

-- Create a role.
CREATE ROLE SysProcRole
go

-- Create a test user
CREATE USER bob
go

-- Add the test user to the role.
EXEC sp_addrolemember 'SysProcRole', 'bob'
go

-- Grant execute permissions on the stored procedure to the new role.
GRANT EXECUTE ON [dbo].[usp_sysprocesses] TO SysProcRole
go
 
-- Connect as the test user.
EXECUTE AS LOGIN = 'bob'
use db_Demo
go
 
-- User only has permission to see their own processes.
SELECT * FROM sys.sysprocesses
go

-- Execute the stored procedure, which has been signed.
exec usp_sysprocesses
go

-- REVERT
REVERT
----------------------------------------------------------------------
-- Cleanup

use db_Demo
go

use master
go

DROP DATABASE db_Demo
go 

DROP login login_SysProcCert
DROP login bob
go

DROP CERTIFICATE SysProcCert
go

Nachstehend wird der Quellcode für die gespeicherte Prozedur usp_sysprocesses aufgeführt, mit dem eine SELECT *-Anweisung für die sys.sysprocesses-Sicht ausgeführt wird. Die Assembly muss signiert werden, wenn sie erstellt wird.

C#

using System;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void usp_sysprocesses()
{
    using(SqlConnection connection = new SqlConnection("context connection=true"))
    {
        connection.Open();
        SqlCommand command = new SqlCommand("SELECT * FROM sys.sysprocesses", connection);
        SqlContext.Pipe.ExecuteAndSend(command);
    }
}
};

Visual Basic

Imports System
Imports System.Data.SqlClient
Imports Microsoft.SqlServer.Server

Partial Public Class StoredProcedures
<Microsoft.SqlServer.Server.SqlProcedure()> _
Public Shared Sub  usp_sysprocesses ()
    Using connection As New SqlConnection("context connection=true")
        connection.Open()

        Dim command As New SqlCommand("SELECT * FROM sys.sysprocesses", connection)
        SqlContext.Pipe.ExecuteAndSend(command)
    End Using
End Sub
End Class