【问题标题】:Masking column in stored procedure存储过程中的屏蔽列
【发布时间】:2020-12-10 14:56:40
【问题描述】:

首先,作为 SQL Server 的管理员,我正在尝试使用标准数据库来屏蔽列。

CREATE TABLE [Person].[MyEmailAddress]
(
    [MyBusinessEntityID] [int] NOT NULL,
    [MyEmailAddressID] [int] IDENTITY(1,1) NOT NULL,
    [EmailAddress] [nvarchar](50) MASKED WITH (FUNCTION = 'email()') NULL, --<== masked
    [rowguid] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
    [ModifiedDate] [datetime] NOT NULL,
    CONSTRAINT [PK_MyEmailAddress_BusinessEntityID_EmailAddressID] PRIMARY KEY CLUSTERED (
        [MyBusinessEntityID] ASC,
        [MyEmailAddressID] ASC
    )
) ON [PRIMARY]
GO

然后,我创建了一个新的存储过程

CREATE PROCEDURE [Person].[Email_Address]
AS
BEGIN
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    SELECT * from [Person].[EmailAddress]
END
GO

然后,我创建了一个新的登录用户

create login AdvUserTest004
with password = 'Test123'

create user User004
for login AdvUserTest004

-- add user to the database owner role
exec sp_addrolemember N'db_owner', N'User004'

通过将此link 引用到db_datawriterdb_datareader 来设置用户角色。没有这两个成员资格,表格就不会出现。

然后,我尝试使用 SQL Server 身份验证模式使用“AdvUserTest004”登录。尝试执行select语句

select * from [Person].[EmailAddress]

输出结果看起来不错,被屏蔽了。

但是上面的存储过程没有出现。所以,通过引用这个document,授予执行权限。

现在,存储过程照常出现。然后,执行存储过程

exec [Person].[Email_Address]

结果如下:

所以问题是,

  1. 为什么电子邮件列在存储过程中执行时未屏蔽,但在 select 语句中被屏蔽?
  2. 在存储过程中执行时,email列应该如何掩码?

【问题讨论】:

    标签: sql sql-server permissions data-masking


    【解决方案1】:

    我刚刚从这个link得到了例子

    -- Demonstrate Dynamic Data Masking
    -- 
    -- Make sure to connect using a privileged user such as the database owner or sysadmin
    
    IF NOT EXISTS (SELECT 1 FROM sys.server_principals WHERE name = N'GreatLakesUser')
    BEGIN
        CREATE LOGIN GreatLakesUser 
        WITH PASSWORD = N'SQLRocks!00',
             CHECK_POLICY = OFF,
             CHECK_EXPIRATION = OFF,
             DEFAULT_DATABASE = WideWorldImporters;
    END;
    GO
    
    USE WideWorldImporters;
    GO
    
    IF NOT EXISTS(SELECT * FROM sys.database_principals WHERE name = N'GreatLakesUser')
    BEGIN
        CREATE USER GreatLakesUser FOR LOGIN GreatLakesUser;
    END;
    GO
    
    ALTER ROLE [Great Lakes Sales] ADD MEMBER GreatLakesUser;
    GO
    
    -- grant SELECT rights to role principal
    GRANT SELECT ON Purchasing.Suppliers TO [Great Lakes Sales];
    GO
    
    -- select with current UNMASK rights (NOTE row count and data values), assuming you are connected using a privileged user
    SELECT SupplierID, SupplierName, BankAccountName, BankAccountBranch, BankAccountCode, BankAccountNumber FROM Purchasing.Suppliers;
    
    -- impersonate the user GreatLakesUser
    EXECUTE AS USER = 'GreatLakesUser';
    GO
    
    -- select with impersonated MASKED rights (NOTE row count and data values)
    SELECT SupplierID, SupplierName, BankAccountName, BankAccountBranch, BankAccountCode, BankAccountNumber FROM Purchasing.Suppliers;
    GO
    
    REVERT;
    GO
    
    -- Clean-up (optional)
    /*
    REVOKE SELECT ON Purchasing.Suppliers TO [Great Lakes Sales];
    GO
    DROP USER GreatLakesUser;
    GO
    DROP LOGIN GreatLakesUser;
    GO
    */
    

    【讨论】:

      【解决方案2】:

      您正在使您的用户成为db_owner。如果你检查Chart of SQL Server Permissions

      你可以看到这个角色的成员可以UNMASK任何数据。这可以通过以下代码轻松检查:

      DROP TABLE IF EXISTS [dbo].[StackOverflow];
      
      CREATE TABLE [dbo].[StackOverflow]
      (
          [email] NVARCHAR(128) MASKED WITH (FUNCTION = 'email()')
      );
      
      INSERT INTO [dbo].[StackOverflow] ([email])
      VALUES ('text1@gmail.bg')
            ,('text2@gmail.bg')
            ,('text3@gmail.bg');
      
      SELECT [email]
      FROM [dbo].[StackOverflow];
      
      GO
      
      DROP USER IF EXISTS [Daleman];
      
      CREATE USER [Daleman] WITHOUT LOGIN;  
      GRANT SELECT ON [dbo].[StackOverflow] TO [Daleman];  
      
      GO
      
      EXECUTE AS USER = 'Daleman'; 
      
      SELECT [email]
      FROM [dbo].[StackOverflow];
      REVERT;
      
      GO
      
      EXEC sp_addrolemember N'db_owner', N'Daleman';
      
      
      EXECUTE AS USER = 'Daleman'; 
      
      SELECT [email]
      FROM [dbo].[StackOverflow];
      REVERT;
      

      我在哪里:

      • 创建一个新表并查询它(我是sys.admin我可以unmask
      • 创建一个有权查询表的新用户(谁不能unmask 并看到被屏蔽的数据)
      • 将用户设为db_owner 并显示现在用户可以看到原始数据

      这里是执行代码的输出:

      所以,我猜你没有正确测试你看到数据被屏蔽的情况。

      【讨论】:

      • 感谢您的代码和解释。问,为什么你创建没有登录的用户?我理解了其余的代码。
      • @Daleman 为简单起见,因为无需连接它 :-) 您可以使用 EXECUTE AS 进行测试以测试代码。此外,当使用EXECUTE AS 时,请使用REVERT 以确保您在测试运行后使用原始安全上下文。
      • 你们俩都应该使用 ALTER ROLE 而不是已弃用的 sp_addrolemember。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-23
      • 1970-01-01
      • 2018-10-03
      • 2020-02-29
      • 1970-01-01
      • 2015-10-02
      • 1970-01-01
      相关资源
      最近更新 更多