Freigeben über


ADD SIGNATURE (Transact-SQL)

Gilt für:SQL ServerAzure SQL-DatenbankAzure SQL Managed Instance

Fügt einer gespeicherten Prozedur, einer Funktion, einer Assembly oder einem DML-Trigger eine digitale Signatur hinzu. Fügt einer gespeicherten Prozedur, einer Funktion, einer Assembly oder einem DML-Trigger außerdem eine Gegensignatur hinzu.

Transact-SQL-Syntaxkonventionen

Syntax

ADD [ COUNTER ] SIGNATURE TO module_class::module_name
    BY <crypto_list> [ , ...n ]

<crypto_list> ::=
    CERTIFICATE cert_name
    | CERTIFICATE cert_name [ WITH PASSWORD = 'password' ]
    | CERTIFICATE cert_name WITH SIGNATURE = signed_blob
    | ASYMMETRIC KEY Asym_Key_Name
    | ASYMMETRIC KEY Asym_Key_Name [ WITH PASSWORD = 'password' ]
    | ASYMMETRIC KEY Asym_Key_Name WITH SIGNATURE = signed_blob

Argumente

module_class

Die Klasse des Moduls, dem die Signatur hinzugefügt wird. Die Standardeinstellung für Schema-bezogene Module ist OBJECT.

module_name

Der Name einer gespeicherten Prozedur, Funktion, Assembly oder Trigger, die signiert oder gegensigniert werden soll.

CERTIFICATE cert_name

Der Name eines Zertifikats, mit dem die gespeicherte Prozedur, Funktion, Assembly oder Trigger signiert oder gegensigniert werden soll.

WITH PASSWORD = 'Kennwort'

Das Kennwort, das zum Entschlüsseln des privaten Schlüssels des Zertifikats oder asymmetrischen Schlüssels erforderlich ist. Diese Klausel ist nur erforderlich, wenn der private Schlüssel nicht durch den Hauptschlüssel für die Datenbank geschützt ist.

SIGNATUR = signed_blob

Gibt das signierte BLOB-Element des Moduls an. Diese Klausel ist hilfreich, wenn Sie ein Modul ohne den privaten Schlüssel versenden möchten. Bei Verwendung dieser Klausel sind nur das Modul, die Signatur und der öffentliche Schlüssel erforderlich, um das signierte BLOB-Element für eine Datenbank zu signieren. Bei signed_blob handelt es sich um das BLOB-Element im Hexadezimalformat.

ASYMMETRIC KEY Asym_Key_Name

Der Name eines asymmetrischen Schlüssels, mit dem die gespeicherte Prozedur, Funktion, Assembly oder Trigger signiert oder gegen signieren soll.

Bemerkungen

Das Modul, das signiert oder gegensigniert wird, und das Zertifikat oder der asymmetrische Schlüssel, das bzw. der zum Signieren verwendet wird, müssen bereits vorhanden sein. Jedes Zeichen im Modul ist in der Signaturberechnung enthalten. Hierzu gehören auch führende Wagenrückläufe und Zeilenvorschübe.

Ein Modul kann mit einer beliebigen Anzahl von Zertifikaten und asymmetrischen Schlüsseln signiert oder gegensigniert werden.

Die Signatur eines Moduls wird bei Änderung des Moduls gelöscht.

Wenn ein Modul eine EXECUTE AS-Klausel enthält, wird auch die Sicherheits-ID (SID) des Prinzipals als Teil des Signierungsprozesses eingeschlossen.

Achtung

Module dürfen nur beim Erteilen von Berechtigungen signiert werden, nie beim Verweigern oder Aufheben von Berechtigungen.

DDL-Trigger (Data Definition Language) und Inlinetabellenwertfunktionen können nicht signiert werden.

Informationen zu Signaturen sind in der sys.crypt_properties Katalogansicht sichtbar.

Warnung

Wenn Sie eine Prozedur für die Signatur neu erstellen, müssen alle Anweisungen im ursprünglichen Batch mit dem neu erstellten Batch übereinstimmen. Wenn sich ein Teil des Batches unterscheidet, auch in Leerzeichen oder Kommentaren, ist die resultierende Signatur unterschiedlich.

Gegensignaturen

Wenn Sie ein signiertes Modul ausführen, werden die Signaturen vorübergehend zum SQL-Token hinzugefügt, aber die Signaturen gehen verloren, wenn das Modul ein anderes Modul ausführt oder wenn das Modul die Ausführung beendet. Eine Gegensignatur ist eine spezielle Signaturform. Selbst gewährt eine Gegensignatur keine Berechtigungen. Sie ermöglicht jedoch, dass Signaturen, die von demselben Zertifikat oder asymmetrischen Schlüssel vorgenommen wurden, für die Dauer des Aufrufs an das gegensignierte Objekt aufbewahrt werden.

Gehen Sie beispielsweise davon aus, dass der Benutzer Alice Prozedur ProcForAliceaufruft, die Prozedur ProcSelectT1aufruft, die aus der Tabelle T1auswählt. Alice verfügt über EXECUTE Berechtigung für ProcForAlice, verfügt jedoch nicht über EXECUTE Berechtigungen für ProcSelectT1 oder SELECT Berechtigung für T1, und es ist keine Verkettung des Besitzes an dieser gesamten Kette beteiligt. Alice kann nicht direkt oder mithilfe von ProcForAlice und ProcSelectT1auf Tabellen-T1zugreifen. Da Alice immer ProcForAlice für den Zugriff verwenden soll, möchten wir ihr nicht die Berechtigung erteilen, ProcSelectT1auszuführen. Wie können wir dieses Szenario erreichen?

  • Wenn wir ProcSelectT1signieren, sodass ProcSelectT1 auf T1zugreifen können, kann Alice ProcSelectT1 direkt aufrufen und muss nicht ProcForAliceanrufen.

  • Wir konnten EXECUTE Erlaubnis für ProcSelectT1 an Alice verweigern, aber dann kann Alice ProcSelectT1 nicht über ProcForAliceanrufen.

  • Das Signieren ProcForAlice würde nicht allein funktionieren, da die Signatur im Aufruf von ProcSelectT1verloren geht.

Durch die Gegensignierung von ProcSelectT1 mit demselben Zertifikat, das zum Signieren von ProcForAliceverwendet wird, wird die Signatur jedoch über die Anrufkette hinweg beibehalten und kann auf T1zugreifen. Wenn Alice versucht, ProcSelectT1 direkt aufzurufen, kann sie nicht auf T1zugreifen, da die Gegensignatur keine Rechte gewährt. Beispiel C zeigt die Transact-SQL für dieses Beispiel an.

Screenshot des Signaturbeispiels.

Berechtigungen

Erfordert ALTER Berechtigung für das Objekt und CONTROL Berechtigung für das Zertifikat oder den asymmetrischen Schlüssel. Falls ein zugeordneter privater Schlüssel mit einem Kennwort geschützt ist, muss der Benutzer zudem das Kennwort kennen.

Beispiele

A. Signieren einer gespeicherten Prozedur mithilfe eines Zertifikats

Im folgenden Beispiel wird die gespeicherte Prozedur HumanResources.uspUpdateEmployeeLogin mit dem Zertifikat HumanResourcesDP signiert.

USE AdventureWorks2022;

ADD SIGNATURE TO HumanResources.uspUpdateEmployeeLogin
    BY CERTIFICATE HumanResourcesDP;
GO

B. Signieren einer gespeicherten Prozedur mithilfe eines signierten BLOB

Im folgenden Beispiel werden eine neue Datenbank und ein Zertifikat erstellt, die im Beispiel verwendet werden sollen. Im Beispiel wird eine grundlegende gespeicherte Prozedur erstellt und signiert und die Signatur-BLOB aus sys.crypt_propertiesabgerufen. Die Signatur wird dann gelöscht und erneut hinzugefügt. Im Beispiel wird die Prozedur mithilfe der WITH SIGNATURE-Syntax signiert.

CREATE DATABASE TestSignature;
GO

USE TestSignature;
GO

-- Create a CERTIFICATE to sign the procedure.
CREATE CERTIFICATE cert_signature_demo
    ENCRYPTION BY PASSWORD = 'pGFD4bb925DGvbd2439587y'
    WITH SUBJECT = 'ADD SIGNATURE demo';
GO

-- Create a basic procedure.
CREATE PROCEDURE [sp_signature_demo]
AS
PRINT 'This is the content of the procedure.';
GO

-- Sign the procedure.
ADD SIGNATURE TO [sp_signature_demo]
    BY CERTIFICATE [cert_signature_demo] WITH PASSWORD = 'pGFD4bb925DGvbd2439587y';
GO

-- Get the signature binary BLOB for the sp_signature_demo procedure.
SELECT cp.crypt_property
FROM sys.crypt_properties AS cp
     INNER JOIN sys.certificates AS cer
         ON cp.thumbprint = cer.thumbprint
WHERE cer.name = 'cert_signature_demo';
GO

Die von dieser Anweisung zurückgegebene crypt_property Signatur unterscheidet sich jedes Mal, wenn Sie eine Prozedur erstellen. Notieren Sie sich das Ergebnis, um es später in diesem Beispiel zu verwenden. In diesem fall ist das gezeigte Ergebnis 0x831F5530C86CC8ED606E5BC2720DA835351E46219A6D5DE9CE546297B88AEF3B6A7051891AF3EE7A68EAB37CD8380988B4C3F7469C8EABDD9579A2A5C507A4482905C2F24024FFB2F9BD7A953DD5E98470C4AA90CE83237739BB5FAE7BAC796E7710BDE291B03C43582F6F2D3B381F2102EEF8407731E01A51E24D808D54B373.

-- Drop the signature so that it can be signed again.
DROP SIGNATURE FROM [sp_signature_demo]
    BY CERTIFICATE [cert_signature_demo];
GO

-- Add the signature. Use the signature BLOB obtained earlier.
ADD SIGNATURE TO [sp_signature_demo]
    BY CERTIFICATE [cert_signature_demo] WITH SIGNATURE = 0x831F5530C86CC8ED606E5BC2720DA835351E46219A6D5DE9CE546297B88AEF3B6A7051891AF3EE7A68EAB37CD8380988B4C3F7469C8EABDD9579A2A5C507A4482905C2F24024FFB2F9BD7A953DD5E98470C4AA90CE83237739BB5FAE7BAC796E7710BDE291B03C43582F6F2D3B381F2102EEF8407731E01A51E24D808D54B373;
GO

C. Zugreifen auf eine Prozedur mithilfe einer Gegensignatur

Im folgenden Beispiel wird gezeigt, wie durch das Gegensignieren der Zugriff auf ein Objekt gesteuert wird. Sie müssen <password> durch ein entsprechendes Kennwort ersetzen.

-- Create tesT1 database
CREATE DATABASE testDB;
GO

USE testDB;
GO

-- Create table T1
CREATE TABLE T1 (c VARCHAR (11));
INSERT INTO T1 VALUES ('This is T1.');

-- Create a TestUser user to own table T1
CREATE USER TestUser WITHOUT LOGIN;
ALTER AUTHORIZATION ON T1 TO TestUser;

-- Create a certificate for signing
CREATE CERTIFICATE csSelectT
    ENCRYPTION BY PASSWORD = '<password>'
    WITH SUBJECT = 'Certificate used to grant SELECT on T1';

CREATE USER ucsSelectT1 FOR CERTIFICATE csSelectT;
GRANT SELECT ON T1 TO ucsSelectT1;

-- Create a principal with low privileges
CREATE LOGIN Alice WITH PASSWORD = '<password>';
CREATE USER Alice;

-- Verify Alice cannoT1 access T1;
EXECUTE AS LOGIN = 'Alice';
SELECT * FROM T1;
REVERT;
GO

-- Create a procedure that directly accesses T1
CREATE PROCEDURE procSelectT1
AS
BEGIN
    PRINT 'Now selecting from T1...';
    SELECT *
    FROM T1;
END
GO

GRANT EXECUTE ON ProcSelectT1 TO PUBLIC;
GO

-- Create special procedure for accessing T1
CREATE PROCEDURE ProcForAlice
AS
BEGIN
    IF USER_ID() <> USER_ID('Alice')
        BEGIN
            PRINT 'Only Alice can use this.';
            RETURN;
        END
    EXECUTE ProcSelectT1;
END
GO

GRANT EXECUTE ON ProcForAlice TO PUBLIC;

-- Verify procedure works for a sysadmin user
EXECUTE ProcForAlice;

-- Alice still can't use the procedure yet
EXECUTE AS LOGIN = 'Alice';
EXECUTE ProcForAlice;
REVERT;

-- Sign procedure to grant it SELECT permission
ADD SIGNATURE TO ProcForAlice
BY CERTIFICATE csSelectT WITH PASSWORD = '<password>';

ADD COUNTER SIGNATURE TO ProcSelectT1
BY CERTIFICATE csSelectT WITH PASSWORD = '<password>';

-- Now the stored procedure works.   
-- Note that calling ProcSelectT1 directly still doesn't work.
EXECUTE AS LOGIN = 'Alice';
EXECUTE ProcForAlice;
EXECUTE ProcSelectT1;
REVERT;

-- Cleanup
USE master;
GO

DROP DATABASE testDB;
DROP LOGIN Alice;