Поделиться через


ADD SIGNATURE (Transact-SQL)

Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure

Добавляет цифровую подпись для хранимой процедуры, функции, сборки или DML-триггера. Добавляет также подпись другой стороны для хранимой процедуры, функции, сборки или DML-триггера.

Соглашения о синтаксисе Transact-SQL

Синтаксис

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

Аргументы

module_class

Класс модуля, в который добавляется подпись. По умолчанию для модулей с областью схемы используется OBJECT.

module_name

Имя хранимой процедуры, функции, сборки или триггера для подписи или счетчика.

CERTIFICATE cert_name

Имя сертификата, с помощью которого следует подписывать хранимую процедуру, функцию, сборку или триггер.

WITH PASSWORD = 'пароля'

Пароль, необходимый для расшифровки закрытого ключа сертификата или асимметричного ключа. Это предложение необходимо, только когда закрытый ключ не защищен главным ключом базы данных.

SIGNATURE = signed_blob

Указывает подписанный большой двоичный объект (BLOB) модуля. Это предложение полезно, если нужно передать модуль без передачи закрытого ключа. При использовании этого предложения необходимы только модуль, подпись и открытый ключ, чтобы добавить подписанный большой двоичный объект в базу данных. Аргумент signed_blob является самым большим двоичным объектом в шестнадцатеричном формате.

ASYMMETRIC KEY Asym_Key_Name

Имя асимметричного ключа, с помощью которого необходимо подписать или подписать хранимую процедуру, функцию, сборку или триггер.

Замечания

Подписываемый модуль или модуль, на который ставится скрепляющая подпись, а также сертификат или асимметричный ключ, используемые для подписания, должны существовать. Каждый символ в модуле включен в вычисление подписи. Сюда включены начальные символы возврата каретки и перевода строки.

Подписи и скрепляющие подписи для модуля могут добавляться любым числом сертификатов и асимметричных ключей.

Подпись модуля удаляется при изменении модуля.

Если модуль содержит предложение EXECUTE AS, идентификатор безопасности субъекта также включается в процесс подписывания.

Внимание

Подписывание модуля следует использовать только для предоставления разрешений, но не для их запрещения или отмены.

Триггеры языка определения данных (DDL) и встроенные табличные функции не могут быть подписаны.

Сведения о подписях отображаются в представлении каталога sys.crypt_properties.

Предупреждение

При повторном создании процедуры для подписи все инструкции в исходном пакете должны соответствовать повторно созданному пакету. Если любая часть пакета отличается даже в пробелах или примечаниях, результирующая подпись отличается.

Скрепляющая подпись

При выполнении подписанного модуля подписи подписи временно добавляются в маркер SQL, но подписи теряются, если модуль выполняет другой модуль, или если модуль завершает выполнение. — это специальная форма подписи. По себе контрназначение не предоставляет никаких разрешений. Однако он позволяет подписям, сделанным тем же сертификатом или асимметричным ключом, храниться в течение длительности вызова, выполненного в объект с контрназначениями.

Например, предположим, что пользователь Alice вызывает процедуру ProcForAlice, которая вызывает процедуру ProcSelectT1, которая выбирается из таблицы T1. Алиса имеет EXECUTE разрешение на ProcForAlice, но не имеет EXECUTE разрешений на ProcSelectT1 или SELECT разрешение на T1, а цепочка владения не участвует в этой всей цепочке. Алиса не может получить доступ к таблице T1напрямую или с помощью ProcForAlice и ProcSelectT1. Так как мы хотим, чтобы Алиса всегда использовала ProcForAlice для доступа, мы не хотим предоставить ей разрешение на выполнение ProcSelectT1. Как мы можем выполнить этот сценарий?

  • Если мы подписываем ProcSelectT1, таким образом, что ProcSelectT1 может получить доступ к T1, то Алиса может вызвать ProcSelectT1 напрямую, и ей не нужно вызывать ProcForAlice.

  • Мы могли бы запретить EXECUTE разрешение на ProcSelectT1 в Алису, но тогда Алиса не может вызывать ProcSelectT1 через ProcForAlice.

  • Подписывание ProcForAlice не будет работать самостоятельно, так как подпись теряется в вызове ProcSelectT1.

Однако путем счетчика ProcSelectT1 с тем же сертификатом, используемым для подписи ProcForAlice, подпись хранится в цепочке вызовов и разрешен доступ к T1. Если Алиса пытается вызвать ProcSelectT1 напрямую, она не может получить доступ к T1, так как контрназначение не предоставляет никаких прав. пример C показывает Transact-SQL для этого примера.

снимок экрана: пример подписи.

Разрешения

Требуется ALTER разрешение на объект и разрешение CONTROL для сертификата или асимметричного ключа. Если соответствующий закрытый ключ защищен паролем, то у пользователя также должен быть этот пароль.

Примеры

А. Подписыв хранимую процедуру с помощью сертификата

В следующем примере хранимая процедура HumanResources.uspUpdateEmployeeLogin подписывается сертификатом HumanResourcesDP.

USE AdventureWorks2022;

ADD SIGNATURE TO HumanResources.uspUpdateEmployeeLogin
    BY CERTIFICATE HumanResourcesDP;
GO

B. Подписывай хранимую процедуру с помощью подписанного BLOB-объекта

В следующем примере создается новая база данных и сертификат для использования в примере. В примере создаются и подписывается базовая хранимая процедура и извлекается сигнатура BLOB из sys.crypt_properties. Подпись удаляется, затем добавляется еще раз. Пример подписывает процедуру с помощью синтаксиса WITH SIGNATURE.

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

Подпись crypt_property, возвращаемая этим оператором, отличается при каждом создании процедуры. Запишите результат для использования далее в ходе примера. В этом случае показан результат 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

В. Доступ к процедуре с помощью счетчика

В следующем примере показано, как скрепляющая подпись помогает контролировать доступ к объекту. Необходимо заменить <password> соответствующим паролем.

-- 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;