次の方法で共有


ADD SIGNATURE (Transact-SQL)

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

ストアド プロシージャ、関数、アセンブリ、または 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 = '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に直接アクセスすることも、ProcForAliceProcSelectT1を使用してアクセスすることもできません。 Alice は常にアクセスに ProcForAlice を使用する必要があるため、ProcSelectT1を実行するアクセス許可を与える必要はありません。 このシナリオを実現する方法

  • ProcSelectT1T1にアクセスできるように、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;