Han*_*non 3 security sql-server sql-server-2008-r2
我正在尝试创建一个存储过程,该过程可用作创建数据库的代理,而用户无权创建数据库。请参阅限制用户组访问数据库/功能?欲了解更多信息
当我尝试执行存储过程时,SQL Server 生成一个安全错误:
Msg 262, Level 14, State 1, Line 1
CREATE DATABASE permission denied in database 'master'.
Run Code Online (Sandbox Code Playgroud)
这是代码:
CREATE LOGIN DatabaseCreator WITH PASSWORD='Pa$$w0rd'; /* REPLACE WITH A SECURE PASSWORD! */
GO
CREATE USER DatabaseCreator FOR LOGIN DatabaseCreator;
GO
EXEC sys.sp_addsrvrolemember 'DatabaseCreator','sysadmin';
GO
CREATE PROCEDURE dbo.CreateDatabase
(
@DatabaseName SYSNAME
)
WITH EXECUTE AS 'DatabaseCreator'
AS
BEGIN
SET NOCOUNT ON;
DECLARE @cmd NVARCHAR(max);
IF COALESCE(@DatabaseName,'') <> ''
BEGIN
SET @cmd = 'CREATE DATABASE ' + QUOTENAME(@DatabaseName) + ';'
EXEC sys.sp_executesql @cmd;
END
ELSE
BEGIN
SET @cmd = 'INVALID DATABASE NAME';
RAISERROR (@cmd, 0, 1);
END
END;
GO
EXEC master.dbo.CreateDatabase 'MyDatabaseName';
Run Code Online (Sandbox Code Playgroud)
msg 262
似乎是一条通用的 Permission Denied 消息。既然DatabaseCreator
有sysadmin
特权,这不应该发生。除非我遗漏了什么。
所述EXECUTE AS
的子句CREATE PROCEDURE
只能用于模拟用户(不是登录)和模拟的范围被限制为当前数据库。该sysadmin
权限与登录,而不是用户相关联,因此您收到一个权限错误。
正确的授予方式 CREATE DATABASE
这里是签署程序。该过程有点复杂,因为我们希望签署该过程以授予服务器级权限,但该过程的每个步骤都相当简单:
首先,创建一个证书并master
使用CREATE ANY DATABASE
权限登录。该证书稍后将被复制到目标数据库以允许过程签名。
USE master;
GO
CREATE CERTIFICATE CreateDatabaseCert
ENCRYPTION BY PASSWORD = 'password'
WITH SUBJECT = 'Create Database',
START_DATE = '20140101',
EXPIRY_DATE = '20141231';
GO
CREATE LOGIN CreateDatabaseLogin
FROM CERTIFICATE CreateDatabaseCert;
GO
DENY CONNECT SQL TO CreateDatabaseLogin;
GO
GRANT CREATE ANY DATABASE
TO CreateDatabaseLogin;
Run Code Online (Sandbox Code Playgroud)
我们现在需要将证书复制到将运行该过程的数据库中。有几种方法可以做到这一点,但最兼容的是通过文件读取和写入证书。下一步编写证书:
BACKUP CERTIFICATE CreateDatabaseCert
TO FILE = 'C:\Temp\CreateDatabase.cer'
WITH PRIVATE KEY
(
FILE = 'C:\Temp\CreateDatabase.pvk',
ENCRYPTION BY PASSWORD = 'password',
DECRYPTION BY PASSWORD = 'password'
);
Run Code Online (Sandbox Code Playgroud)
现在我们切换到目标数据库,恢复证书,并删除临时文件:
USE Sandpit;
GO
CREATE CERTIFICATE CreateDatabaseCert
FROM FILE = 'C:\Temp\CreateDatabase.cer'
WITH PRIVATE KEY
(
FILE = 'C:\Temp\CreateDatabase.pvk',
ENCRYPTION BY PASSWORD = 'password',
DECRYPTION BY PASSWORD = 'password'
);
GO
--EXECUTE sys.sp_configure 'show advanced options', 1;
--RECONFIGURE;
--EXECUTE sys.sp_configure 'xp_cmdshell', 1;
--RECONFIGURE;
EXECUTE sys.xp_cmdshell 'ERASE C:\Temp\CreateDatabase.*';
Run Code Online (Sandbox Code Playgroud)
现在创建过程,并使用证书对其进行签名:
CREATE PROCEDURE dbo.CreateDatabase
(
@DatabaseName SYSNAME
)
WITH EXECUTE AS CALLER
AS
BEGIN
SET NOCOUNT ON;
DECLARE @cmd NVARCHAR(max);
IF COALESCE(@DatabaseName,'') <> ''
BEGIN
SET @cmd = 'CREATE DATABASE ' + QUOTENAME(@DatabaseName) + ';'
EXEC sys.sp_executesql @cmd;
END
ELSE
BEGIN
SET @cmd = 'INVALID DATABASE NAME';
RAISERROR (@cmd, 0, 1);
END
END;
GO
ADD SIGNATURE TO dbo.CreateDatabase
BY CERTIFICATE CreateDatabaseCert
WITH PASSWORD = 'password';
Run Code Online (Sandbox Code Playgroud)
为了测试这是否有效,我们创建了一个新的登录名和仅具有执行该过程权限的用户:
CREATE LOGIN test WITH PASSWORD = 'password';
CREATE USER test FROM LOGIN test;
GRANT EXECUTE ON dbo.CreateDatabase TO test;
Run Code Online (Sandbox Code Playgroud)
测试本身:
EXECUTE AS LOGIN = 'test';
EXECUTE dbo.CreateDatabase @DatabaseName = 'NewDB';
REVERT;
Run Code Online (Sandbox Code Playgroud)
数据库创建成功。要清理,请运行以下命令:
DROP DATABASE NewDB;
DROP USER test;
DROP LOGIN test;
DROP PROCEDURE dbo.CreateDatabase;
DROP CERTIFICATE CreateDatabaseCert;
GO
USE master;
DROP LOGIN CreateDatabaseLogin;
DROP CERTIFICATE CreateDatabaseCert;
Run Code Online (Sandbox Code Playgroud)
有关权限的更多信息,请参阅Erland Sommarskog 的优秀文章。
归档时间: |
|
查看次数: |
10420 次 |
最近记录: |