TLDR问题
用户可以通过在他拥有 CONTROL 权限的个人架构中创建禁止数据的视图来查看禁止的数据。
简介
我有一个带有两个数据库的 Azure SQL(托管实例)服务器:
sources
:包含数据的表格reports
:视图构建在 sources
在
reports
数据库中,数据分析师拥有自己的个人模式,有权创建视图和表。由于某些数据的性质,并非每个模式都允许向数据分析师公开。
问题
我拒绝/撤销对某些模式的访问,并且可以直接访问这些模式。但数据分析师仍然可以创建引用
sources
数据库中禁止的表的新视图,并仍然通过创建的视图查看数据。
问题
这应该是不可能的,因为数据分析师不应该能够访问
sources
数据库中的数据。但我似乎找不到办法来阻止这种情况。
设置
用户的帐户是在 Azure 的 AD 中创建的。我在
reports
数据库中为用户创建登录名。
CREATE USER [[email protected]] FOR LOGIN [[email protected]];
用他自己的模式:
USE [reports];
CREATE SCHEMA mypersonal;
-- Create a role
CREATE ROLE mypersonal_schema_creator;
-- Grant permissions to the role
GRANT CREATE TABLE TO mypersonal_schema_creator;
GRANT CREATE VIEW TO mypersonal_schema_creator;
-- Grant control on the schema to the role
GRANT CONTROL ON SCHEMA::mypersonal TO mypersonal_schema_creator;
-- Add the user to the role
ALTER ROLE mypersonal_schema_creator ADD MEMBER [[email protected]];
我授予用户访问
sources
数据库中模式的权限:
-- Connect to sqldb-ingestion01
CREATE USER [[email protected]] FOR LOGIN [[email protected]];
-- Grant SELECT permission on the ALLOWED schema
GRANT SELECT ON SCHEMA::allowed TO [[email protected]];
并且当用户访问
sources
数据库时,他看不到除 allowed
模式之外的其他模式。但是当他创建一个访问 forbidden
模式中的表的视图时,他仍然可以看到数据。
这既是预期行为,也是有记录的行为。您所经历的就是所谓的所有权链。
当调用某个对象(例如
VIEW
或 PROCEDURE
)时,如果 USER
有权使用该对象,那么它也会 隐式 被授予访问与该对象具有相同所有者的对象引用的任何对象的权限对象,而在该对象的范围内。在这种情况下,您有一个 USER
创建了一个 VIEW
,其中 SELECT
来自具有相同所有者的其他对象(大概是 dbo
或其他东西),所以即使 USER
不对基础表具有显式访问权限,VIEW
允许它们隐式权限。
虽然我很感激您为我们提供了一些细节,但我将使用对象 DDL 来设置我自己的示例。首先,我们创建一个测试数据库并
USER
CREATE DATABASE YourDB;
GO
USE YourDB;
GO
CREATE USER SomeUser WITHOUT LOGIN; --Example User
GO
CREATE SCHEMA SomeSchema; --Example schema
GO
GRANT CONTROL ON SCHEMA::SomeSchema TO SomeUser;
GRANT CREATE TABLE TO SomeUser;
GRANT CREATE VIEW TO SomeUser;
GRANT SELECT ON SCHEMA::SomeSchema TO SomeUser;
因此
USER
有权创建 VIEW
和 TABLE
,它们 CONTROL
“他们的”模式,并且他们也可以从他们的模式中 SELECT
。
现在让我们创建一些示例对象:
CREATE TABLE dbo.SomeTable (SomeID int);
CREATE TABLE dbo.AnotherTable (AnotherID int);
--We don't need any sample data, this is just permissions checking;
GO
GRANT SELECT ON dbo.SomeTable TO SomeUser;
注意,我授予
USER
对 SomeTable
的显式访问权限,但不授予 AnotherTable
。
现在,作为
USER
,我要CREATE
一些VIEW
,然后做一些测试SELECT
:
EXECUTE AS USER = 'SomeUser';
GO
SELECT SomeID
FROM dbo.SomeTable; --Works
GO
CREATE VIEW SomeSchema.SomeView AS
SELECT SomeID AS ID
FROM dbo.SomeTable;
GO
SELECT ID
FROM SomeSchema.SomeView; --Doesn't works.
GO
SELECT AnotherID
FROM dbo.AnotherTable; --Works
GO
CREATE VIEW SomeSchema.AnotherView AS
SELECT AnotherID AS ID
FROM dbo.AnotherTable;
GO
SELECT ID
FROM SomeSchema.AnotherView; --Does works, due to permission chaining
GO
GO
REVERT; --back to normal
正如我们所看到的,这正如我所预期的那样;唯一失败的
SELECT
是直接针对物体 dbo.AnotherTable
。
为了解决这个问题,正如我提到的,更改
USER
正在使用的架构的所有者:
--Let's change the owner of the schema
ALTER AUTHORIZATION ON SCHEMA::SomeSchema TO SomeUser;
现在我们可以再次测试,只需查询 2 个
VIEW
:
--Now let's try those VIEWs again
EXECUTE AS USER = 'SomeUser';
GO
SELECT SomeID
FROM dbo.SomeTable; --Works, we have explicit SELECT on the table
GO
SELECT ID
FROM SomeSchema.AnotherView; --Fails, we don't have explicit permission and ownership chaining fails
GO
REVERT;
这次针对
SomeSchema.AnotherView
also 的查询失败,与尝试直接查询 dbo.AnotherTable
时遇到的权限错误相同。
清理:
USE master;
GO
ALTER DATABASE YourDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
DROP DATABASE YourDB;