我需要建立一个允许开发人员为数据库请求紧急ID的系统。他们将被分配到一个名为“分析师”的角色,该角色将为他们提供一个下拉框,其中包含他们可以访问的数据库。他们将提交请求,并将生成临时SQL登录并显示在屏幕上。登录将有一些提升的权限。登录将在12小时后删除。
我已经把自己作为一个SA在ASP.net上工作了,但现在我正在修改程序,使用应用程序连接字符串中的SQL登录工作。
我已经尝试了一些方法来实现它,但遇到了障碍。
这是我完成实际工作的程序。
USE [SQLEmergencyLoginRequest]
GO
/****** Object: StoredProcedure [dbo].[SQLELR_Login_CREATE] Script Date: 12/08/2009 14:48:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SQLELR_Login_CREATE]
@SERVER VARCHAR(50),
@DATABASE VARCHAR(50),
@NTLOGIN VARCHAR(50),
@IR INT,
@LOGIN VARCHAR(50) OUTPUT,
@PWD VARCHAR(20) OUTPUT,
@NotifyDBA INT
WITH EXECUTE AS OWNER
AS
/*
Emergency_Access_Login_CREATE: Create Login/PWD, Create User, Create Role, Add User to Role, return Login/PWD.
*/
DECLARE @Random_Login_Extension VARCHAR(20)
DECLARE @sql VARCHAR(1000)
SET @Database = QUOTENAME(@Database);
BEGIN TRANSACTION
--CREATE LOGIN/PWD
EXEC dbo.random_password @Random_Login_Extension OUTPUT;
EXEC dbo.random_password @PWD OUTPUT;
SET @LOGIN = 'Emergency_Login_' + @Random_Login_Extension;
SET @sql= 'CREATE LOGIN [' + @LOGIN + ']' +
'WITH PASSWORD= ''' + @PWD + ''', DEFAULT_DATABASE=[master], ' +
'CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF';
EXEC(@sql);
--CREATE USER
DECLARE @User_Cmd VARCHAR(1000);
SET @User_Cmd = 'USE ' + @DATABASE + ';' +
'CREATE USER [' + @LOGIN + '] FOR LOGIN [' + @LOGIN + '];' +
'EXEC sp_addrolemember N''db_datareader'',''' + @LOGIN + ''';' +
'EXEC sp_addrolemember N''db_datawriter'',''' + @LOGIN + ''';' +
'EXEC sp_addrolemember N''db_ddladmin'',''' + @LOGIN + ''';';
EXEC (@User_Cmd);
INSERT INTO dbo.SQLELR_Emergency_Logins
([CreationTime]
,[NTLogin]
,[IR]
,[SERVER]
,[DATABASE]
,SQLLoginCreated)
VALUES
(GETDATE()
,@NTLOGIN
,@IR
,@SERVER
,@DATABASE
,@LOGIN)
DECLARE @MYBODY VARCHAR(500)
SET @MYBODY = @NTLOGIN + ' has created a temporary login in the ' + @Database + ' Database. The login name is ' + @LOGIN;
DECLARE @MYSUBJECT VARCHAR(500)
SET @MYSUBJECT = 'Emergency Login Creation ON server ' + @@SERVERNAME;
IF @NotifyDBA = 1
BEGIN
EXEC msdb.dbo.sp_notify_operator
@profile_name = 'SQLDBA',
@name = 'SQLDBA',
@subject = @MYSUBJECT,
@body = @MYBODY;
END
COMMIT TRANSACTION
我不希望应用程序帐户在每个数据库中都具有高权限,因此我创建了另一个帐户,该帐户将进入每个数据库并拥有db_owner
。显然,使用固定数据库角色的sp_addrolemember
需要db_owner才能工作,这就是acct为db_owner
的原因。我更喜欢安全管理员,但似乎不可能。
回到问题 - 使用EXECUTE AS和动态代码不起作用。
通过在创建用户的每个数据库中创建存储过程来实现此目的的唯一方法是什么?
我们之所以这样做,是因为我们希望在此服务器上降低安全性,并从开发人员手中夺走db_owner,这已经成为多年来的常态。创建此机制将满足他们唯一仍然无法访问的投诉。他们害怕我们不会回答一个页面,他们将无法解决问题,所以这将解决这个问题。
当然,任何有关安全漏洞的建议也会受到赞赏。
答案 0 :(得分:1)
关于工作程序的EXECUTE AS子句将您带入“执行为”笼子,请参阅Extending Database Impersonation by Using EXECUTE AS。由于该过程的EXECUTE AS是数据库主体,因此只在数据库内部才会信任执行上下文。
有两种解决方法,ALTER DATABASE [SQLEmergencyLoginRequest] SET TRUSTWORTHY ON
的500磅大锤或代码签名的手术切割工具,请参阅Call a procedure in another database from an activated procedure的示例。我强烈推荐代码签名方法:
这将确保该程序具有在任何数据库中完成其工作所需的所有特权。每次更改时都必须重做整个签名过程。