ADD SIGNATURE (Transact-SQL)
適用対象:SQL Server
Azure SQL Database
Azure SQL Managed Instance
ストアド プロシージャ、関数、アセンブリ、または DML トリガーにデジタル署名を追加します。 また、ストアド プロシージャ、関数、アセンブリ、または DML トリガーに副署名を追加します。
構文
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 = 'password'
証明書または非対称キーの秘密キーの暗号化を解除するために必要なパスワード。 この句は、秘密キーがデータベースのマスター キーで保護されていない場合にのみ必要です。
SIGNATURE = signed_blob
モジュールの署名付きバイナリ ラージ オブジェクト (BLOB) を指定します。 この句は、秘密キーを配布せずにモジュールを配布する場合に便利です。 この句を使用する場合、署名付きバイナリ ラージ オブジェクトをデータベースに追加するときに必要となるのは、モジュール、署名、公開キーだけです。 signed_blob はそれ自体 16 進数形式の BLOB です。
ASYMMETRIC KEY Asym_Key_Name
ストアド プロシージャ、関数、アセンブリ、またはトリガーに署名またはカウンター署名する非対称キーの名前。
解説
署名または副署名されるモジュールと、署名に使用する証明書または非対称キーは、あらかじめ存在している必要があります。 署名の確認で、モジュールのすべての文字が確認されます。 これには、先頭のキャリッジ リターンとライン フィードも含まれます。
モジュールには、任意の数の証明書と非対称キーを使用して署名や副署名を行うことができます。
モジュールが変更された場合、モジュールの署名は削除されます。
モジュールに EXECUTE AS
句が含まれている場合、プリンシパルのセキュリティ ID (SID) も署名プロセスの一部として含まれます。
注意事項
モジュールの署名は権限の許可のみに使用し、権限の拒否または取り消しには使用しないでください。
データ定義言語 (DDL) トリガーとインライン テーブル値関数は署名できません。
署名に関する情報は、sys.crypt_properties
カタログ ビューに表示されます。
警告
署名のプロシージャを再作成する場合、元のバッチ内のすべてのステートメントが再作成されたバッチと一致する必要があります。 バッチの一部がスペースやコメントでも異なる場合、結果のシグネチャは異なります。
副署名
署名付きモジュールを実行すると、署名は一時的に SQL トークンに追加されますが、モジュールが別のモジュールを実行した場合、またはモジュールが実行を終了した場合、署名は失われます。 の署名 は、特殊な形式の署名です。 それ自体では、カウンター署名ではアクセス許可は付与されません。 ただし、同じ証明書または非対称キーによって作成された署名は、署名されたオブジェクトに対する呼び出しの間保持できます。
たとえば、ユーザー Alice
がプロシージャ ProcForAlice
を呼び出し、プロシージャ ProcSelectT1
を呼び出し、テーブル T1
から選択するとします。 Alice には ProcForAlice
に対する EXECUTE
アクセス許可がありますが、ProcSelectT1
に対する EXECUTE
アクセス許可も、T1
に対する SELECT
アクセス許可もありません。また、このチェーン全体に所有権は関係ありません。 Alice は、テーブル T1
に直接アクセスすることも、ProcForAlice
と ProcSelectT1
を使用してアクセスすることもできません。 Alice は常にアクセスに ProcForAlice
を使用する必要があるため、ProcSelectT1
を実行するアクセス許可を与える必要はありません。 このシナリオを実現する方法
ProcSelectT1
がT1
にアクセスできるように、ProcSelectT1
に署名すると、Alice はProcSelectT1
を直接呼び出すことができるので、ProcForAlice
を呼び出す必要はありません。Alice への
ProcSelectT1
に対するアクセス許可EXECUTE
拒否できますが、Alice はProcForAlice
を介してProcSelectT1
を呼び出すことはできません。署名
ProcForAlice
は、ProcSelectT1
の呼び出しで署名が失われるため、単独では機能しません。
ただし、ProcForAlice
の署名に使用したのと同じ証明書で ProcSelectT1
に署名することで、署名は呼び出しチェーン全体に保持され、T1
へのアクセスが許可されます。 Alice が ProcSelectT1
を直接呼び出そうとすると、反署名で権限が付与されないため、T1
にアクセスできません。 例 C 、この例の Transact-SQL を示します。
アクセス許可
オブジェクト ALTER
アクセス許可と、証明書または非対称キーに対する CONTROL
アクセス許可が必要です。 関連付けられている秘密キーがパスワードで保護されている場合、ユーザーはそのパスワードも保持している必要があります。
例
A. 証明書を使用してストアド プロシージャに署名する
次の例では、ストアド プロシージャ HumanResources.uspUpdateEmployeeLogin
に対して、証明書 HumanResourcesDP
を使用して署名を行います。
USE AdventureWorks2022;
ADD SIGNATURE TO HumanResources.uspUpdateEmployeeLogin
BY CERTIFICATE HumanResourcesDP;
GO
B. 署名付き BLOB を使用してストアド プロシージャに署名する
次の例では、新しいデータベースを作成し、この例で使用する証明書を作成します。 この例では、基本的なストアド プロシージャを作成して署名し、sys.crypt_properties
から署名 BLOB を取得します。 その後、署名は削除され、再度追加されます。 この例では、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
C. カウンター署名を使用してプロシージャにアクセスする
次の例では、副署名によってオブジェクトへのアクセスを制御する方法を示します。
<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;