ADD SIGNATURE(Transact-SQL)
적용 대상:SQL Server
Azure SQL 데이터베이스
Azure SQL Managed Instance
저장 프로시저, 함수, 어셈블리 또는 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(Binary Large Object)를 지정합니다. 이 절은 프라이빗 키를 포함하지 않고 모듈을 제공하려는 경우 유용합니다. 이 절을 사용할 때는 모듈, 서명 및 공개 키만 있으면 서명된 BLOB(Binary Large Object)을 데이터베이스에 추가할 수 있습니다. signed_blob은 16진수 형식의 BLOB 자체입니다.
ASYMMETRIC KEY Asym_Key_Name
저장 프로시저, 함수, 어셈블리 또는 트리거에 서명하거나 반대 서명할 비대칭 키의 이름입니다.
설명
서명하거나 연대 서명할 모듈과 모듈에 서명하는 데 사용되는 인증서 또는 비대칭 키가 있어야 합니다. 모듈의 모든 문자는 서명 계산에 포함됩니다. 여기에는 선행 캐리지 리턴과 줄 바꿈도 포함됩니다.
모듈에 서명하거나 연대 서명하는 데 사용되는 인증서와 비대칭 키의 수는 제한되지 않습니다.
모듈이 변경되면 모듈의 서명이 삭제됩니다.
모듈에 EXECUTE AS
절이 포함된 경우 보안 주체의 SID(보안 ID)도 서명 프로세스의 일부로 포함됩니다.
주의
모듈 서명은 사용 권한을 부여하는 용도로만 사용해야 하며 사용 권한을 거부하거나 취소하는 용도로 사용하면 안 됩니다.
DDL(데이터 정의 언어) 트리거 및 인라인 테이블 반환 함수는 서명할 수 없습니다.
서명에 대한 정보는 sys.crypt_properties
카탈로그 뷰에 표시됩니다.
경고
서명 프로시저를 다시 만들 때 원래 일괄 처리의 모든 문이 다시 생성된 일괄 처리와 일치해야 합니다. 배치의 일부가 공백이나 주석에서도 다른 경우 결과 서명은 다릅니다.
연대 서명
서명된 모듈을 실행하면 서명이 일시적으로 SQL 토큰에 추가되지만 모듈이 다른 모듈을 실행하거나 모듈이 실행을 종료하는 경우 서명이 손실됩니다. 서명 특별한 형태의 서명입니다. 그 자체로, 반대 서명은 어떤 권한도 부여하지 않습니다. 그러나 동일한 인증서 또는 비대칭 키로 만든 서명을 카운터 서명된 개체에 대한 호출 기간 동안 유지할 수 있습니다.
예를 들어 사용자 Alice
프로시저 ProcSelectT1
호출하는 프로시저 ProcForAlice
호출하고 테이블 T1
선택합니다. Alice는 ProcForAlice
대한 EXECUTE
권한을 가지고 있지만 T1
대한 ProcSelectT1
또는 SELECT
권한에 대한 EXECUTE
권한이 없으며 이 전체 체인에는 소유권 체인이 포함되지 않습니다. Alice는 직접 또는 ProcForAlice
및 ProcSelectT1
사용하여 테이블 T1
액세스할 수 없습니다. Alice는 항상 액세스에 ProcForAlice
사용하려고 하므로 ProcSelectT1
실행할 수 있는 권한을 부여하지 않습니다. 이 시나리오를 어떻게 수행할 수 있나요?
ProcSelectT1
T1
액세스할 수 있도록ProcSelectT1
서명하면 Alice는ProcSelectT1
직접 호출할 수 있으며ProcForAlice
호출할 필요가 없습니다.Alice에 대한
ProcSelectT1
대한EXECUTE
권한을 거부할 수 있지만 Alice는ProcForAlice
통해ProcSelectT1
호출할 수 없습니다.ProcSelectT1
호출에서 서명이 손실되기 때문에 서명ProcForAlice
그 자체로 작동하지 않습니다.
그러나 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;