Sql-Server
創建數據庫的儲存過程的執行權限
我有一個儲存過程,它為需要由我們的一位數據分析師每月執行的特定項目創建數據庫。問題是我如何建構它以使分析師能夠在不授予他們創建數據庫權限的情況下執行此儲存過程。
我嘗試使用 EXECUTE AS OWNER/USER_NAME
分析師仍然收到以下錯誤:Msg 262,Level 14,State 1,Line 67 CREATE DATABASE permission denied in database ‘master’。
有什麼建議嗎?
它不起作用,因為語句的
EXECUTE AS
子句CREATE {object}
只能引用一個使用者,這是一個數據庫級主體。CREATE DATABASE
是實例級權限,因此需要授予登錄名(實例級主體),而不是使用者。使用模組簽名很容易做到這一點:
設置
USE [tempdb]; CREATE LOGIN [DbCreator] WITH PASSWORD='create a DB'; CREATE USER [DbCreator] FOR LOGIN [DbCreator]; EXEC(N'CREATE PROCEDURE dbo.CreateDatabase ( @NewDatabaseName sysname ) AS SET NOCOUNT ON; DECLARE @SQL NVARCHAR(MAX); SET @SQL = N''CREATE DATABASE '' + QUOTENAME(@NewDatabaseName); EXEC(@SQL); '); GRANT EXECUTE ON dbo.[CreateDatabase] TO [DbCreator];
申請模組簽名
-- 1) Create the Certificate: CREATE CERTIFICATE [Permission$CreateDatabase] ENCRYPTION BY PASSWORD = 'UseBetterPassword!' WITH SUBJECT = 'CREATE DATABASE permission', EXPIRY_DATE = '2099-12-31'; -- 2) Sign the Module: ADD SIGNATURE TO [dbo].[CreateDatabase] BY CERTIFICATE [Permission$CreateDatabase] WITH PASSWORD = 'UseBetterPassword!'; -- 3) Backup the Private Key to a VARBINARY string -- to be copied and pasted somewhere safe (optional): SELECT CERTPRIVATEKEY(CERT_ID(N'Permission$CreateDatabase'), 'NewPassword!', 'UseBetterPassword!'); -- 4) Remove the Private Key (optional): ALTER CERTIFICATE [Permission$CreateDatabase] REMOVE PRIVATE KEY; -- 5) Copy Certificate to [master] (Public Key only): DECLARE @Cert NVARCHAR(4000) = CONVERT(NVARCHAR(4000), CERTENCODED(CERT_ID(N'Permission$CreateDatabase')), 1); EXEC (N'USE [master]; CREATE CERTIFICATE [Permission$CreateDatabase] FROM BINARY = ' + @Cert); -- 6) Create Login and Grant Permission: EXEC (N'USE [master]; CREATE LOGIN [Permission$CreateDatabase] FROM CERTIFICATE [Permission$CreateDatabase]; GRANT CREATE ANY DATABASE TO [Permission$CreateDatabase];');
測試
EXECUTE AS LOGIN = N'DbCreator'; SELECT SESSION_USER; -- DbCreator CREATE DATABASE [_TEST:FAIL]; /* Msg 262, Level 14, State 1, Line XXXXX CREATE DATABASE permission denied in database 'master'. */ EXEC dbo.[CreateDatabase] N'_TEST:PASS'; -- Success!! SELECT * FROM sys.databases WHERE [name] = N'_TEST:PASS'; REVERT; SELECT SESSION_USER; -- dbo DROP DATABASE [_TEST:PASS];
有關應用模組簽名所採取步驟的詳細說明,請參閱我的文章:
無需將高級權限授予任何人即可安全輕鬆地使用高級權限:伺服器級
有關一般模組簽名的更多資訊,以及為什麼應該使用它而不是更簡單但更危險的
SET TRUSTWORTHY ON
,請參閱我的文章: