Zertifikate für die Ausführung von Prozeduren verwenden

Bein einem internationalen Unternehmen, für das ich häufiger tätig bin, wurde eine Anforderung gestellt, einem Team [sysadmin]-Berechtigungen zu erteilen. Auf die Frage nach dem Grund für diese weitreichenden Berechtigungen wurde uns mitgeteilt, dass man Informationen über Jobs und deren Ausführungen, Fehler, Ausführungsdauer, usw. benötige. Diese Informationen wolle man mittels Reporting Services verarbeiten und ausgeben. Wir waren gefordert, eine Lösung anzubieten, die mit dem "minimal rights Prinzip" vereinbar ist. Lesen Sie in diesem Artikel, wie Sie einen Zugriff auf Objekte kontrolliert einschränken können, ohne Benutzern weitreichende Berechtigungen zu erteilen.

Problemstellung

Der Kunde benötigt Daten über Aufträge des SQL Servers um diese Informationen weiterverarbeiten zu können. Jobs werden vom SQL Server Agent ausgeführt und protokolliert. Informationen zu den Aufträgen sowie deren Ausführungs- und Protokolldaten werden in der Systemdatenbank [msdb] gespeichert.

Um Jobdaten einzusehen, gibt es drei interne Datenbankrollen in der msdb, die für die Verwaltung von Jobs verwendet werden können.

Rolle Beschreibung
SQLAgentUserRole Die Mitglieder von SQLAgentUserRole haben lediglich Berechtigungen für lokale Aufträge und Auftragszeitpläne, deren Besitzer sie sind.

SQLAgentReaderRole

Die Mitglieder dieser Rolle können die Liste aller verfügbaren Aufträge und Auftragszeitpläne sowie ihre Eigenschaften anzeigen, nicht nur die Aufträge und Auftragszeitpläne, deren Besitzer sie sind.

SQLAgentOperatorRole Die Mitglieder dieser Rolle können alle lokalen Aufträge ausführen, beenden oder starten, und sie können den Auftragsverlauf eines lokalen Auftrags auf dem Server löschen. Sie können auch alle lokalen Aufträge und Zeitpläne auf dem Server aktivieren und deaktivieren.

Ein Zugriff über die Rolle [SQLAgentUserRole] konnte nicht in Betracht gezogen werden, da diese Rolle nicht nur die Einsicht in Protokolle der eigenen Jobs gewährt sondern auch die Änderung dieser Jobs. Änderungen an Produktivsystemen dürfen aber nur kontrolliert über ein "Changeverfahren" implementiert werden.

Ein weiterer Nachteil dieser Datenbankrolle besteht darin, dass nur auf Aufträge zugegriffen werden kann, die im Besitz der Anforderer sind. Hieraus ergeben sich zwei markante Problemstellungen:

  • Alle Mitarbeiter des Geschäftsbereichs müssen auf die Daten zugreifen
  • Der Eigentümer der Aufträge hat u. U. nicht so weitreichende Berechtigungen, die der Auftrag benötigt:
    (Beispiel: Im Job wird ein TRUNCATE TABLE ausgeführt, der Besitzer des Jobs hat aber keine DDL-Berechtigungen)

Eine Mitgliedschaft in der Rolle [SQLAgentReaderRole] ist auch nicht möglich. Diese Rolle gibt auch Zugriffsmöglichkeiten auf Jobs, die Aufgaben für andere Datenbanken ausführen. Des weiteren können damit auch administrative Jobs, die von den Administratoren erstellt wurden, eingesehen werden.

Die weitreichendsten Zugriffsmöglichkeiten ergeben sich aus der Mitgliedschaft in der Datenbankrolle [SQLAgentOperatorRole]. Damit wäre "Haus und Hof" geöffnet, um einen unkontrollierten Zugang zu system- und sicherheitsrelevanten Prozessen zu gewähren. Eine Mitgliedschaft in dieser Rolle war also ebenfalls unmöglich.

Lösungsansatz

Zunächst haben wir uns überlegt, der Benutzergruppe des Anforderers SELECT-Berechtigungen auf die benötigten Tabellen in der msdb zu geben. Hieraus ergibt sich aber das Problem, dass wiederum Informationen zu ALLEN Jobs und deren Eigenschaften ausgelesen werden können.

Ein weiteres Problem ergibt sich aus der Konsequenz eines datenbankübergreifenden Berechtigungsmodells; wenn ein Benutzer aus einer Datenbank auf die Objekte einer weiteren Datenbank zugreifen möchte, muss die Benutzerdatenbank nach außen als vertrauenswürdig (TRUSTWORTHY) eingestuft werden. Dies ist aber mit weitreichenden Sicherheitsbedenken verbunden und stand nicht zur Diskussion.

Die Möglichkeit, eine Prozedur mit der Option [WITH EXECUTE AS 'User'] zu erstellen, wurde ebenfalls verworfen. Folgende Gründe sprachen gegen diese Lösung:

  • Die Datenbankoption TRUSTWORTHY muss aktiviert (ON) sein
  • Es muss ein personenbezogener Serverbenutzer erstellt werden, der Zugriff auf die Benutzerdatenbank sowie auf die [msdb] Datenbank besitzt

Die Option [EXECUTE AS] brachte uns dann aber einen entscheidenden Punkt weiter; verwenden wir statt eines benutzerbezogenen Logins ein Zertifikat! Dadurch ist ein unmittelbarer Zugang zu den Ressourcen nicht mehr möglich. Gedacht ist dieses Konzept für Szenarien, in denen Berechtigungen nicht über die Besitzverkettung geerbt werden können oder in denen die Besitzkette unterbrochen ist, wie bei dynamischem SQL. Bei der Ausführung einer gespeicherten Prozedur mit Signatur kombiniert SQL Server die Berechtigungen des Zertifikatsbenutzers mit den Berechtigungen des Aufrufers. Im Gegensatz zur EXECUTE AS-Klausel ändert sich der Ausführungskontext der Prozedur nicht.

Implementierung

Nachfolgend werden die einzelnen Lösungsschritte durchgeführt und erläutert. Für das nachfolgende Szenario werden die nachfolgenden Objekte verwendet:

msdb Systemdatenbank des Microsoft SQL Servers
mydb Benutzerdatenbank des Kunden
temp_user1 Server- und Datenbankbenutzer, der das Ausführungskonto des Kunden repräsentiert. Dieses Benutzerkonto existiert bereits in der Datenbank [myDB].
cert_JobHistory Zertifikat für die Signierung der Prozedur
login_JobHistory Serverbenutzer, der das Zertifikat [cert_JobHistory] repräsentiert

Erstellen der Prozedur für die Ermittlung der Auftragsinformationen

Zunächst wird die eigentliche Prozedur für die Ermittlung der benötigten Daten erstellt. Hierbei handelt es sich um ein SELECT-Statement, dass auf die erforderlichen Objekte in der msdb Datenbank zugreift.

USE myDB
GO

IF OBJECT_ID('dbo.proc_app_Get_JobHistory', 'P') IS NOT NULL
    DROP PROCEDURE dbo.proc_app_Get_JobHistory;
    GO

CREATE PROCEDURE dbo.proc_app_Get_JobHistory
WITH EXECUTE AS OWNER
AS
BEGIN
    SET NOCOUNT ON;

    SELECT  c.name,
            j.name,
            j.enabled,
            j.description,
            js.*,
            jh.*
    FROM    msdb.dbo.sysjobs j
            LEFT JOIN msdb.dbo.sysjobsteps js ON (j.job_id = js.job_id)
            LEFT JOIN msdb.dbo.sysjobhistory jh ON (j.job_id = jh.job_id)
            LEFT JOIN msdb.dbo.syscategories c ON (j.category_id = c.category_id)
    WHERE    c.name != 'DBA - Maintenance'

    SET NOCOUNT OFF;
END
GO

-- Berechtigungen für Temp_User1 erteilen
GRANT EXECUTE ON dbo.proc_app_Get_JobHistory TO Temp_User1;
GO

Erstellen des Zertifikats für den Zugriff auf die Auftragsobjekte

Nachdem die eigentliche Prozedur erstellt wurde, kann im zweiten Schritt das Zertifikat erstellt werden, mit dem die Prozedur später signiert wird. Dieses Zertifikat wird unter anderem dazu benutzt, die Prozedur zu signieren als auch einen Serverbenutzer zu erstellen, der das Zertifikat repräsentiert.

-- Erstellung eines Zertifikats für die gemeinsame Verwendung;
IF EXISTS (SELECT * FROM sys.certificates WHERE name = 'cert_JobHistory')
    DROP CERTIFICATE cert_JobHistory;
    GO

CREATE CERTIFICATE cert_JobHistory
ENCRYPTION BY PASSWORD = 'myUltracomplexPassword'
WITH SUBJECT = 'Zertificate für JobHistory',
START_DATE = '20120101',
EXPIRY_DATE = '29991231'
GO

-- Sicherung des Zertifikats für die Implementierung in MASTER
EXEC xp_cmdshell 'DEL C:\temp\cert_JobHistory.* /q', no_output;
BACKUP CERTIFICATE cert_JobHistory TO FILE = 'C:\temp\cert_JobHistory.cer';
GO

-- Zertifikat nun in der master-Datenbank installieren
USE master
GO

-- Löschen eines möglichen Logins für das Zertifikat
IF EXISTS (SELECT * FROM sys.server_principals WHERE name = 'login_JobHistory')
    DROP LOGIN login_JobHistory;
    GO

IF EXISTS (SELECT * FROM sys.certificates WHERE name = 'cert_JobHistory')
    DROP CERTIFICATE cert_JobHistory;
    GO

CREATE CERTIFICATE cert_JobHistory FROM FILE = 'C:\temp\cert_JobHistory.cer';
GO

Zunächst wird das Zertifikat mit dem Namen [cert_JobHistory] in der Benutzerdatenbank angelegt. Anschließend muss das Zertifikat natürlich auch in der master Datenbank angelegt werden, da dieses Zertifikat als Grundlage für den Serverbenutzer dient. Damit die Zertifikate identisch sind, wird -  nach der Erstellung des Zertifikats in der Benutzerdatenbank - eine Sicherung des Zertifikats gemacht und anschließend diese Sicherung in der master-Datenbank wiederhergestellt. Das gesicherte Zertifikat kann man jederzeit durch einen Doppelklick öffnen und die gesetzten Eigenschaften anzeigen lassen.

  Die Eigenschaften des Zertifikats, die bei der Erstellung gesetzt wurden, sind deutlich zu erkennen.
So repräsentiert z. B. das Attribut [Aussteller] die Option [Subject] der Methode CREATE CERTIFICATE.
Auch das Gültigkeitsdatum sowie das Ablaufdatum des Zertifikats ist deutlich zu erkennen.

Erstellen eines Serverbenutzers auf Basis des erstellten Zertifikats

Nachdem Prozedur und Zertifikat erstellt wurden, muss im nächsten Schritt für das Zertifikat ein Login erstellt werden. Dies ist notwendig, da einem Zertifikat selbst keine Berechtigungen auf Objekte in Datenbanken erteilt werden können. Der zu erstellende Serverbenutzer repräsentiert das Zertifikat.

-- Erstellen eines Logins basierend auf dem Zertifikat
CREATE LOGIN login_JobHistory FROM CERTIFICATE [cert_JobHistory];
GRANT AUTHENTICATE SERVER TO [login_JobHistory];
GO

-- Benutzer in Datenbank msdb anlegen und für die Objekte berechtigen
USE msdb
GO

IF EXISTS (SELECT * FROM sys.database_principals WHERE name = 'login_JobHistory')
    DROP USER login_JobHistory;
    GO

CREATE USER login_JobHistory FROM LOGIN [login_JobHistory];
GRANT SELECT ON dbo.sysJobs TO login_JobHistory;
GRANT SELECT ON dbo.sysJobSteps TO login_JobHistory;
GRANT SELECT ON dbo.sysJobHistory TO login_JobHistory;
GRANT SELECT ON dbo.syscategories TO login_JobHistory;
GO

Der wohl wichtigste Punkt bei der Erstellung des Serverbenutzers ist es, dem Login die Berechtigung [AUTHENTICATE SERVER] zu gewähren. Das Recht [AUTHENTICATE SERVER] berechtigt, eine Signatur in allen Datenbanken anzuwenden, wenn ein Benutzerwechsel (IMPERSONATION) stattfindet.

Nachdem der Serverbenutzer angelegt worden ist, wird er als Datenbankbenutzer in der Systemdatenbank msdn erstellt und die erforderlichen Berechtigungen auf die Objekte erteilt, die in der Prozedur verwendet werden.

Signieren der auszuführenden Prozedur

Die zuvor erstellte Prozedur muss zu guter Letzt noch signiert werden. Dies bedeutet, dass bei der Ausführung der gespeicherten Prozedur SQL Server die Berechtigungen des Zertifikatsbenutzers mit den Berechtigungen des Aufrufers kombiniert . Im Gegensatz zur EXECUTE AS-Klausel ändert sich der Ausführungskontext der Prozedur nicht. Integrierte Funktionen, die Anmelde- und Benutzernamen zurückgeben, geben den Namen des Aufrufers, und nicht den Namen des Zertifikatsbenutzers zurück.

USE myDB;
GO

ADD SIGNATURE TO OBJECT::dbo.proc_app_Get_JobHistory
BY CERTIFICATE [cert_JobHistory]
WITH Password = ''myUltracomplexPassword';

Mit der Signatur der Prozedur ist der Prozess abgeschlossen und die Prozedur kann nun von den berechtigten Benutzern der Datenbank myDB verwendet werden. Der abschließende Test simuliert diesen Zugriff. In einem neuen Abfragefenster wird die folgende Befehlssequenz ausgeführt:

USE MCM2008;
GO

EXECUTE AS User = 'temp_user1'
    EXEC dbo.proc_app_Get_JobHistory;
REVERT;

Fazit

Das Signieren einer gespeicherten Prozedur mit einem Zertifikat bietet sich an, wenn Berechtigungen für die gespeicherte Prozedur erforderlich sein sollen, Sie einem Benutzer diese Berechtigungen aber nicht explizit erteilen möchten. Zwar gibt es für das Ausführen dieser Aufgabe mehrere Möglichkeiten (z. B. können Sie die EXECUTE AS-Anweisung verwenden), das Verwenden eines Zertifikats ermöglicht aber das Verwenden einer Ablaufverfolgung, um die Person ausfindig zu machen, von der die gespeicherte Prozedur ursprünglich aufgerufen wurde. Auf diese Weise erreichen Sie ein hohes Maß an Überwachung, insbesondere bei der Sicherheit von DDL-Vorgängen (Data Definition Language, Datendefinitionssprache).

Herzlichen Dank für's Lesen

 

Datebankrollen des SQL Agenten http://msdn.microsoft.com/de-de/library/ms188283.aspx
TRUSTWORTHY-Eigenschaft http://msdn.microsoft.com/de-de/library/ms187861.aspx
Signieren von Prozeduren http://msdn.microsoft.com/de-de/library/vstudio/bb669102.aspx
http://msdn.microsoft.com/de-de/library/bb283630.aspx
CREATE CERTIFICATE http://msdn.microsoft.com/de-de/library/ms187798.aspx
CREATE LOGIN http://msdn.microsoft.com/de-de/library/ms189751.aspx
SERVER PERMISSIONS http://msdn.microsoft.com/de-de/library/ms191291.aspx
Impersonation http://msdn.microsoft.com/de-de/library/ms188304(v=sql.105).aspx
ADD SIGNATURE http://msdn.microsoft.com/de-de/library/ms181700.aspx