我创建了一个testuser
登录集,设置为sysdamin
,并将其用于在execute as
以外的测试数据库中创建的以下函数中的子句msdb
。
CREATE FUNCTION [dbo].[MyTestFunction]
(@job_name SYSNAME)
RETURNS INT
WITH EXECUTE AS 'TestUser'
AS
BEGIN
DECLARE @id INT
SELECT TOP 1 @id = schedule_id
FROM msdb.dbo.sysjobschedules
RETURN @id
END
执行MyTestFunction
时出现以下错误:
对对象'sysjobschedules',数据库'msdb',模式'dbo'的SELECT权限被拒绝。
作为更改,如果我直接使用TestUser
登录名并使用测试数据库直接执行SELECT
语句,它将正常工作。
用户TestUser
可以直接从测试数据库访问msdb
,但是如果在测试数据库功能的msdb
子句中使用,则不能访问execute as
。
如何从另一个数据库中创建的函数访问msdb
数据库?
预先感谢
Ignacio
答案 0 :(得分:0)
已将EXECUTE AS
模拟的安全上下文沙箱化到当前数据库。除非数据库为TRUSTWORTHY
,否则您将无法访问函数中的其他数据库,这通常不是一个好习惯。
对于最低特权用户的跨数据库访问,请考虑使用module signing。这使您可以在模块执行上下文中授予对其他数据库和对象的访问权限,而无需授予最终用户直接权限。用户只需要对该功能的权限。
下面是从参考文章中收集的示例脚本,可满足您的特定需求。尽管可以扩展此基本技术以提供sysadmin
权限,但是最佳实践是使用最低特权帐户。
-- Create a certificate in msdb
USE msdb;
CREATE CERTIFICATE msdb_certificate
ENCRYPTION BY PASSWORD = 'p@Ss0RDforTheceRT1cate'
WITH SUBJECT = 'For cross-database access to msdb database';
-- create a user from certification with needed permissions
CREATE USER msdb_certificate_user FROM CERTIFICATE msdb_certificate;
GRANT SELECT ON msdb.dbo.sysjobschedules TO msdb_certificate_user;
-- Copy certificate to user database (Example)
DECLARE @cert_id int = cert_id('msdb_certificate');
DECLARE @public_key varbinary(MAX) = certencoded(@cert_id),
@private_key varbinary(MAX) =
certprivatekey(@cert_id,
'p@Ss0RDforTheceRT1cate',
'p@Ss0RDforTheceRT1cate');
DECLARE @sql nvarchar(MAX) =
'CREATE CERTIFICATE msdb_certificate
FROM BINARY = ' + convert(varchar(MAX), @public_key, 1) + '
WITH PRIVATE KEY (BINARY = ' +
convert(varchar(MAX), @private_key, 1) + ',
DECRYPTION BY PASSWORD = ''p@Ss0RDforTheceRT1cate'',
ENCRYPTION BY PASSWORD = ''p@Ss0RDforTheceRT1cate'')';
EXEC YourDatabase.sys.sp_executesql @sql;
ALTER CERTIFICATE msdb_certificate REMOVE PRIVATE KEY; --remove ephemeral private key
GO
--sign module with certificate
USE YourDatabase;
ADD SIGNATURE TO dbo.MyTestFunction BY CERTIFICATE msdb_certificate
WITH PASSWORD = 'p@Ss0RDforTheceRT1cate';
ALTER CERTIFICATE msdb_certificate REMOVE PRIVATE KEY; --remove ephemeral private key
GO
--users only need permissions on directly invoked module
GRANT EXECUTE ON dbo.MyTestFunction TO YourUser;
GO