创建数据库的存储过程的执行权限

JPV*_*ogt 4 security sql-server stored-procedures permissions impersonation

我有一个存储过程,它为需要由我们的一位数据分析师每个月运行的特定项目创建一个数据库。问题是我如何构建它以使分析师能够在不授予他们创建数据库权限的情况下运行此存储过程。

我试过用 EXECUTE 作为 OWNER/USER_NAME

分析人员仍然收到以下错误:消息 262,级别 14,状态 1,第 67 行 CREATE DATABASE 权限在数据库“master”中被拒绝。

有什么建议吗?

Sol*_*zky 8

它不起作用,因为语句的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];
Run Code Online (Sandbox Code Playgroud)

应用模块签名

-- 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];');
Run Code Online (Sandbox Code Playgroud)

测试

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];
Run Code Online (Sandbox Code Playgroud)

有关应用模块签名所采取步骤的详细说明,请参阅我的帖子:

安全、轻松地使用高级权限,无需授予任何人:服务器级

有关模块签名的更多信息,以及为什么应该使用它而不是更简单但更危险的方法SET TRUSTWORTHY ON,请参阅我的帖子:

请,请,请停止使用假冒、可信和跨数据库所有权链接