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;