JPV*_*ogt 4 security sql-server stored-procedures permissions impersonation
我有一个存储过程,它为需要由我们的一位数据分析师每个月运行的特定项目创建一个数据库。问题是我如何构建它以使分析师能够在不授予他们创建数据库权限的情况下运行此存储过程。
我试过用 EXECUTE 作为 OWNER/USER_NAME
分析人员仍然收到以下错误:消息 262,级别 14,状态 1,第 67 行 CREATE 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];
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
,请参阅我的帖子: