如何将db_owner
固定数据库角色的所有权利和特权授予应用程序角色?
命令:
GRANT CONTROL ON [DatabaseName] TO [ApplicationRoleName];
将是我想要的,但是失败了:
Msg 15151, Level 16, State 1, Line 23
Cannot find the object 'DatabaseName', because it does not exist or you do not have permission.
我正在使用SQL Server 应用程序角色进行调查。
连接到服务器后,您的应用程序将运行存储过程以“登录” 本身作为应用程序:
EXECUTE sp_SetAppRole @rolename='Contoso.exe', @password='Tm8gaSBkaWRuJ3QganVzdCBiYXNlNjQgZW5jb2RlIGEgcGFzc3dvcmQuIEl0J3Mgb25seSBhbiBleGFtcGxlIQ=='
通常,应用程序以固定身份db_owner成员的用户身份登录。 db_owner
角色具有权限:
同时:
您不能将应用程序角色放入数据库角色
接下来的问题是如何授予我的应用程序角色所有权限,以执行所有操作。
现在是时候为该角色授予权限了。遵循此页面的建议:] 2
GRANT SELECT, INSERT, UPDATE, DELETE ON Users TO "Contoso.exe";
这很有趣,但它并没有授予所有特权-它仅授予SELECT
,INSERT
,UPDATE
和DELETE
。我想授予 一切 -特别是当我不知道(或可能是)所有特权时。
我盲目尝试:
GRANT ALL ON Users to "Contoso.exe";
The ALL permission is deprecated and maintained only for compatibility. It DOES NOT imply ALL permissions defined on the entity.
好,因此授予ALL不会授予ALL。太恐怖了
所以我回到:
GRANT SELECT, INSERT, UPDATE, DELETE ON Users TO "Contoso.exe";
除了不能授予一切。例如,我碰巧知道有一种能力可以继续将特权授予其他人(db_owner
拥有的特权)。所以我必须将我的东西更改为:
GRANT SELECT, INSERT, UPDATE, DELETE ON Users TO "Contoso.exe" WITH GRANT OPTION;
好的,这更近了,但它仅适用于一张桌子。
我需要适用于所有表的内容:
EXECUTE sp_msForEachTable 'GRANT SELECT, INSERT, UPDATE, DELETE ON ? TO "Contoso.exe" WITH GRANT OPTION;'
尽管事实证明我错过了一些特权:
确定我可以更新我的脚本:
EXECUTE sp_msForEachTable 'GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES, ALTER ON ? TO "Contoso.exe" WITH GRANT OPTION;'
但不是这个猫捉老鼠的猜谜游戏:我想授予 ALL 权限。
在上面的警告中,SQL Server指出 ALL 不会授予全部权限。但是他们确实document what all does grant:
| Permission | Table | View | SP | Scalar UDF | Table UDF |
|------------|-------|------|----|------------|-----------|
| SELECT | ✔️ | ✔️ | | | ✔️ |
| INSERT | ✔️ | ✔️ | | | ✔️ |
| UPDATE | ✔️ | ✔️ | | | ✔️ |
| DELETE | ✔️ | ✔️ | | | ✔️ |
| REFERENCES | ✔️ | ✔️ | | ✔️ | ✔️ |
| EXECUTE | | | ✔️ | ✔️ | |
| ALTER | ❌ | ❌ | ❌ | ❌ | ❌ |
原来,他们都是被欺骗的。对于另一个权限已创建。一个permission to rule them all:
- 控制
赋予被授予者类似所有权的功能。被授予者实际上对安全对象具有所有定义的权限。已被授予CONTROL权限的主体也可以授予对安全对象的权限。由于SQL Server安全模型是分层的,因此特定范围内的CONTROL隐式包含该范围下所有可安全对象的CONTROL。例如,对数据库的CONTROL意味着对数据库的所有权限,对数据库中所有程序集的所有权限,对数据库中所有模式的所有权限以及对数据库内所有模式中的对象的所有权限。
它们继续枚举您具有 CONTROL 时隐含的权限:
那好多了。不必知道所有权限,我只授予一个即可。我不知道哪种权限适用于哪种对象,而是只授予一种。并且由于这一行:
已被授予CONTROL权限的主体也可以授予对安全对象的权限。
我不必GRANT
WITH GRANT
:
EXECUTE sp_msForEachTable 'GRANT CONTROL ON ? TO [Contoso.exe];' --when you have CONTROL you also get WITH GRANT for free
我的问题是我需要对数据库中的每个对象赋予CONTROL权限。每当添加任何新对象时,我都必须确保返回并将其添加到应用程序角色中。
我需要的是向我的微软提示的东西:
例如,对数据库的CONTROL意味着对数据库的所有权限,对数据库中所有程序集的所有权限,对数据库中所有模式的所有权限以及对数据库内所有模式中的对象的所有权限。
要重述,如果您在数据库上授予CONTROL
,则您将拥有所有权限:
那是我想要的。我想将Grobber
数据库的控制权授予[Contoso.exe]
应用程序角色:
GRANT CONTROL ON Grobber TO "Contoso.exe";
Msg 15151, Level 16, State 1, Line 23
Cannot find the object 'Grobber ', because it does not exist or you do not have permission.
我可能几乎已经解决了我的问题,只是被停在了1码线上。
或者我可能不在附近。所以我问:
如何向其他角色授予db_owner权限?
当客户端登录到应用程序角色时,该身份是该连接的持久属性。并且启用了连接池(这是ADO.net,ADO和ODBC中的首选和默认选项),即使关闭连接后,连接也会保持打开状态很长。
当您的应用程序(即网络服务器)尝试打开新连接时,它会从连接池中获取一个连接。 SqlConnection 要做的第一件事是尝试将连接状态重置为默认状态(使用sp_reset_connection
)。
sp_reset_connection
试图做的一件事是撤消您是应用角色用户的事实。这是不允许的(因为服务器不知道您以前是谁)。因此,使用应用程序角色,当您尝试连接到服务器时会突然出现错误。
“修复” 的唯一方法是禁用连接池。
您不想想要做的事情。
因此解决方案是不在生产设置中使用应用程序角色。
答案 0 :(得分:2)
“您不能将应用程序角色放入数据库角色”似乎是不正确的部分。可以将(应用程序)角色添加为另一个角色的成员:
EXEC sp_addrolemember 'db_owner', 'ApplicationRoleName';
(从2012年起,不推荐使用此过程,而采用了新的ALTER ROLE .. ADD MEMBER
语法。)
要在整个数据库上GRANT CONTROL
扮演某个角色,请执行以下操作:
USE [DatabaseName];
GRANT CONTROL ON DATABASE::[DatabaseName] TO [ApplicationRoleName];
USE
对于将角色纳入范围是必不可少的;引用数据库时,DATABASE::
范围限定符始终是必需的。
说了这么多,应用程序角色可能不是授予最广泛权限的理想人选。除非小心加密连接本身,否则密码将以纯文本形式传递,否则监视和审核可能会忽略它,并且当不再需要权限时,很容易忘记还原。最后一部分是特别隐蔽的,因为未还原的应用程序角色激活将在池连接中持续存在,从而使连接“卡在”管理模式中。替代方法包括使用新凭证打开单独的连接以执行任意操作,并使用存储过程与EXECUTE AS
来获得无法有效GRANT
的权限。
答案 1 :(得分:1)
sp_reset_connection
试图做的一件事是撤消您是应用角色用户的事实。不允许这样做(因为服务器不知道您以前是谁)。
...
“修复”的唯一方法是禁用连接池。
sp_reset_connection
不能自动完成撤消应用程序角色的任务,但可以 完成(从SQL Server 2005开始)。只需通过sp_unsetapprole手动完成即可。这需要指示sp_setapprole
生成cookie(VARBINARY
值),在执行该系统proc时捕获它,并将其存储在某个地方(通过CONTEXT_INFO
或更新的{{1 }},或在应用程序层中)。然后,您只需要在关闭SESSION_CONTEXT
之前将该值传回sp_unsetapprole
(即将该连接返回到池中)。
从理论上讲,使用SqlConnection
来切换安全上下文是有可能EXECUTE AS
可以撤消的,因为它只需要在T-SQL中执行sp_reset_connection
(不需要cookie值),并且如果没有要还原的上下文切换,则不会出错({REVERT
仅在活动数据库与执行REVERT
时不同的情况下调用时才引发错误)。但是,我没有时间进行测试(无论如何也不建议这样做)。
通常,应用程序以用户身份登录,该用户是
EXECUTE AS
固定角色的成员。
现在,这当然不是理想的选择(尤其是拥有数据库的登录名具有任何管理员权限时)。是的,当您有效地禁用所有安全性以至于您永远不会遇到权限错误时,它的确确实使某些任务变得更容易,但是即使您确实添加了密码的额外步骤,此方法也是高度不安全的需要设置应用角色。
首选方法(非常精细且非常安全)是使用Module Signing。通过对模块进行签名(存储过程,标量函数,多语句TVF和触发器),可以为它们(模块)提供执行封装的代码所必需的任何权限,而不必担心有人会获得这些权限并执行某些操作他们意想不到的。通过这种方法,您将授予代码权限,而不是用户权限(即人员/应用程序登录名)。关于您为什么要离开应用程序角色和db_owner
,而转向模块签名:PLEASE, Please, please Stop Using Impersonation, TRUSTWORTHY, and Cross-DB Ownership Chaining,我有更多详细信息。有关具体示例,请参见: