问题描述
我正在使用一个具有restore命令来还原MSsql数据库的工具。到现在为止,该工具正在使用sysadmin特权还原数据库。但是,根据新要求,我想最小化此命令的访问权限,即还原应使用dbcreator角色而不是sysadmin完成。使用 dbcreator ,我可以还原数据库,但是此命令还对还原的数据库执行一些后操作,即更新表中的某些值。由于缺少此用户,
解决方法
遵循最小特权和基于角色的访问控制的安全原理的一种方法是将需要提升权限的T-SQL命令封装在存储过程中。然后,可以使用证书对proc进行签名,以授予其他权限,而无需直接将这些权限授予用户。仅需要对签名存储过程具有执行权限,授权用户只能使用封装的功能。
以下是使用此技术创建存储过程和DBRestore
角色的示例脚本。如果您实际的RESTORE
命令包含无法参数化的选项(例如WITH MOVE
文件位置),则需要在proc中使用动态SQL并格外小心,以确保值经过验证和/或从可信来源获得(例如,配置表而不是临时参数值)。
USE master
GO
--create certificate in master database
CREATE CERTIFICATE sysadmin_cert_login_cert
ENCRYPTION BY PASSWORD = '<cert-password>'
WITH SUBJECT = 'For sysadmin privileges';
GO
--create login from certificate
CREATE LOGIN sysadmin_cert_login FROM CERTIFICATE sysadmin_cert_login_cert;
--confer sysadmin permissions to certificate login
ALTER SERVER ROLE sysadmin
ADD MEMBER sysadmin_cert_login;
GO
--create role for restore user(s)
CREATE ROLE DBRestoreRole;
GO
--create restore proc in master database
CREATE PROC dbo.usp_RestoreDatabase
@DatabaseName sysname,@BackupFilePath varchar(255)
AS
BEGIN TRY
RESTORE DATABASE @DatabaseName FROM DISK=@BackupFilePath WITH REPLACE;
--after restore,set database owner as desired
ALTER AUTHORIZATION ON DATABASE::RestoreTest TO sa;
--execute post restore DML
UPDATE RestoreTest.dbo.SomeTable
SET SomeColumn = 1;
END TRY
BEGIN CATCH
THROW;
END CATCH;
GO
--grant execute permission to DBRestoreRole
GRANT EXECUTE ON dbo.usp_RestoreDatabase TO DBRestoreRole;
--sign proc with sysadmin certificate
ADD SIGNATURE TO dbo.usp_RestoreDatabase BY CERTIFICATE sysadmin_cert_login_cert WITH PASSWORD='<cert-password>';
--optionally,remove ephemoral private key after signing
ALTER CERTIFICATE sysadmin_cert_login_cert REMOVE PRIVATE KEY;
GO
--create example DBRestoreRole login/user
CREATE LOGIN RestoreTestLogin WITH PASSWORD = '<login-password>';
CREATE USER RestoreTestLogin;
ALTER ROLE DBRestoreRole
ADD MEMBER RestoreTestLogin;
GO
--test execution
EXECUTE AS LOGIN = 'RestoreTestLogin';
GO
EXEC dbo.usp_RestoreDatabase
@DatabaseName = N'RestoreExample',@BackupFilePath = 'E:\BackupFiles\RestoreExample.bak';
GO
REVERT;
GO