【问题标题】:View and table security conflict resolution视图和表安全冲突解决
【发布时间】:2019-10-31 22:41:52
【问题描述】:

我有一个 SQL Server 2017 实例,上面有 5 个数据库。 A、B、C、D、E。数据库 A 只包含模式和视图。实例上的每个后续数据库(A、B、C、D、E)都有一个架构,每个架构拥有 50 - 150 个视图。

我需要能够授予用户对数据库 A 中所有视图的选择权限,但直接拒绝对所有表的选择权限。

测试条件应如下所示。

SELECT * FROM [B].dbo.[any_table] (DENIED)
SELECT * FROM [A].[B].some_view (WORKS)

由于架构 A - E 都归 dbo 所有,我认为我可以执行以下操作:

USE A
GO

CREATE ROLE db_viewreader
GO

GRANT SELECT ON SCHEMA::A TO db_viewreader (repeat for b, c, d, e)
GO

CREATE USER testuser WITHOUT LOGIN
GO
ALTER ROLE db_viewreader ADD MEMBER testuser
GO

EXECUTE AS USER = 'testuser'

SELECT *
FROM [A].[B].some_view

我无法从视图或表格中获取结果。我想我明白为什么我没有得到查询表的结果,因为我创建的用户在数据库 B - E 中不存在。这是否与我不能调用访问这些基础表中数据的视图的原因相同?如果是这样,我有什么方法可以创建一个可以利用视图但不能利用它们所在的表的用户?

【问题讨论】:

  • 1) 在所有 5 个数据库中创建 testuser。 2) 在所有 5 个数据库中启用DB_CHAINING。 3) 确保所有 5 个数据库都归同一个用户所有。 4)在数据库A视图上授予SELECT(不需要DENY)。

标签: sql sql-server database-security


【解决方案1】:

可以通过ownership chaining 允许SELECT 对基础表没有权限的视图。只要涉及的所有对象都归同一个安全主体所有,所有权链接将允许授予视图权限的用户使用它,而不管视图引用的表的权限如何。

对不同数据库中的对象使用所有权链接还有其他注意事项。

  • 必须为所涉及的数据库打开DB_CHAINING 选项 或打开服务器级cross db ownership chaining 选项:

    ALTER DATABASE A SET DB_CHAINING ON;
    ALTER DATABASE B SET DB_CHAINING ON;
    ALTER DATABASE C SET DB_CHAINING ON;
    ALTER DATABASE D SET DB_CHAINING ON;
    ALTER DATABASE E SET DB_CHAINING ON;
    
  • 用户必须是服务器级别的主体并添加到每个数据库(或在其他数据库中启用的访客用户):

    CREATE LOGIN testuser WITH PASSWORD = 'n3$(s(+#BB4--';
    USE A;CREATE USER testuser;ALTER ROLE db_viewreader ADD MEMBER testuser;
    USE B;CREATE USER testuser;
    USE C;CREATE USER testuser;
    USE D;CREATE USER testuser;
    USE E;CREATE USER testuser;
    
  • 对象所有者,通常继承自对象的架构 AUTHORIZATION,对于所有涉及的对象,必须是相同的安全主体。对于dbo 用户,这是数据库所有者登录:

    ALTER AUTHORIZATION ON DATABASE::A TO DatabaseOwnerLogin;
    ALTER AUTHORIZATION ON DATABASE::B TO DatabaseOwnerLogin;
    ALTER AUTHORIZATION ON DATABASE::C TO DatabaseOwnerLogin;
    ALTER AUTHORIZATION ON DATABASE::D TO DatabaseOwnerLogin;
    ALTER AUTHORIZATION ON DATABASE::E TO DatabaseOwnerLogin;
    

请注意,除非您直接或通过角色成员身份授予用户对表的权限,否则不需要对表使用显式 DENY。除非被授予,否则用户默认没有对象权限。

要测试权限,您需要模拟服务器级别的主体而不是数据库用户,否则 db 用户将在上下文数据库中被沙盒化(除非数据库是 TRUSTWORTHY):

USE A;
GO
EXECUTE AS LOGIN = 'testuser';
GO
SELECT *
FROM [A].[B].some_view;
GO
REVERT;
GO

请注意,由于以下文档摘录中所述的原因,默认情况下会关闭跨数据库的所有权链接。当只有sysadmin 角色成员可以在生产数据库中创建数据库对象时,这可能不是问题,当然,在部署之前检查代码。

数据库所有者和 db_ddladmin 或 db_owners 的成员 数据库角色可以创建其他用户拥有的对象。这些 对象可以潜在地以其他数据库中的对象为目标。这表示 如果启用跨数据库所有权链接,则必须完全 使用所有数据库中的数据信任这些用户。

【讨论】:

  • 这就像一个魅力,只有系统管理员角色成员才能创建对象,我们在部署之前审查所有代码。非常感谢丹!
猜你喜欢
  • 2023-03-10
  • 1970-01-01
  • 2012-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多