在資料庫層級具有 CONTROL SERVER 或 CONTROL 權限的使用者可以檢視其原始格式的遮罩資料。 這包括系統管理員使用者或角色,例如系統管理員、db_owner等。
PolyBase 外部資料表中的資料行。
對於不具 UNMASK 權限的使用者,已遭取代的 READTEXT、 UPDATETEXT和 WRITETEXT 陳述式在為「動態資料遮罩」設定的資料行上無法正常作用。
新增動態資料遮罩會實作為基礎資料表上的結構描述變更,因此無法在具有相依性的資料行上執行 (例如,計算資料行參考的資料行)。 試著針對具有相依性的資料行新增動態資料遮罩會導致錯誤 ALTER TABLE ALTER COLUMN _columnname_ failed because one or more objects access this column
。 若要暫時解決這項限制,您可以先移除相依性,並新增動態資料遮罩,然後重新建立相依性。 例如,如果相依性是基於相依於該資料行索引,則您可以卸除索引,並新增遮罩,然後重新建立相依索引。
每當您計畫參考定義了資料遮罩函式的資料行的運算式時,也會遮蔽該運算式。 不論用來遮蔽參考資料行的函式 (預設、電子郵件、隨機、自訂字串) 為何,產生的運算式一律會以預設函式加以遮蔽。
跨資料庫查詢跨越兩個不同的 Azure SQL 資料庫或裝載在不同 SQL Server 實例上的資料庫,且牽涉到 MASKED 數據行上任何類型的比較或聯結作業,都未提供正確的結果。 從遠端伺服器傳回的結果已採用 MASKED 格式,並且不適合在本端進行任何類型的比較或聯結作業。
在索引檢視中參考基礎表時,不支援動態資料遮罩。
安全性注意事項:使用推斷或暴力破解方法略過遮罩
動態資料遮罩的設計是要藉由限制應用程式所使用之預先定義查詢集的資料曝光,簡化應用程式開發。 雖然動態資料遮罩也可以用來避免在直接存取生產資料庫時意外洩露機密資料,您必須特別注意具有特定查詢權限的無特殊權限使用者,可以套用技術以存取實際的資料。 如果需要授與這類特定存取權,應該使用稽核來監視所有的資料庫活動,並減輕這種情況。
例如,請考慮資料庫主體具有足夠的權限對資料庫執行特定查詢,並嘗試猜測基礎資料,最終推斷實際的值。 假設我們在 [Employee].[Salary]
資料行上定義了遮罩,而這位使用者直接連接到資料庫並開始猜測值,最後推斷出 [Salary]
資料表中的 Employees
值:
SELECT ID, Name, Salary FROM Employees
WHERE Salary > 99999 and Salary < 100001;
這示範了動態資料遮罩不應該單獨用來完全保護機密資料不受對資料庫執行特定查詢的使用者存取。 它適於防止機密資料不慎洩露,但無法防止惡意推斷基礎資料。
請務必適當地管理資料庫的權限,並隨時遵守最小必要權限的原則。 此外,請記得啟用稽核來追蹤資料庫上發生的所有活動。
SQL Server 2022 中引進的細微權限
從 SQL Server 2022 (16.x) 開始,您可以防止未經授權存取敏感性的資料,並透過在不同的資料庫層級中對未經授權的使用者將它遮蔽起來以獲得控制權。 您可以將資料庫層級、架構層級、數據表層級或數據行層級的 UNMASK 許可權授與或撤銷使用者、資料庫角色、Microsoft Entra 身分識別,或Microsoft Entra 群組。 此增強功能可提供更細微的方式來控制及限制未經授權存取資料庫中所儲存的資料,並改善資料安全性管理。
建立動態資料遮罩
下列範例將建立有三種不同動態資料遮罩類型的資料表。 範例會填入資料表,並選擇顯示結果。
-- schema to contain user tables
CREATE SCHEMA Data;
-- table with masked columns
CREATE TABLE Data.Membership (
MemberID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED,
FirstName VARCHAR(100) MASKED WITH (FUNCTION = 'partial(1, "xxxxx", 1)') NULL,
LastName VARCHAR(100) NOT NULL,
Phone VARCHAR(12) MASKED WITH (FUNCTION = 'default()') NULL,
Email VARCHAR(100) MASKED WITH (FUNCTION = 'email()') NOT NULL,
DiscountCode SMALLINT MASKED WITH (FUNCTION = 'random(1, 100)') NULL
-- inserting sample data
INSERT INTO Data.Membership (FirstName, LastName, Phone, Email, DiscountCode)
VALUES
('Roberto', 'Tamburello', '555.123.4567', '[email protected]', 10),
('Janice', 'Galvin', '555.123.4568', '[email protected]', 5),
('Shakti', 'Menon', '555.123.4570', '[email protected]', 50),
('Zheng', 'Mu', '555.123.4569', '[email protected]', 40);
會建立新的使用者,並在資料表所在的結構描述上授與 SELECT 權限。 在 MaskingTestUser
檢視遮罩資料時執行了查詢。
CREATE USER MaskingTestUser WITHOUT LOGIN;
GRANT SELECT ON SCHEMA::Data TO MaskingTestUser;
-- impersonate for testing:
EXECUTE AS USER = 'MaskingTestUser';
SELECT * FROM Data.Membership;
REVERT;
結果會顯示遮罩,方法是將資料從:
1 Roberto Tamburello 555.123.4567 [email protected] 10
1 Rxxxxxo Tamburello xxxx [email protected] 91
DiscountCode
中的數字在每一次查詢結果中都是隨機的。
在現有的資料行上新增或編輯遮罩
使用 ALTER TABLE
陳述式將遮罩加入資料表的現有資料行中,或在該資料行編輯遮罩。
下列範例會將遮罩函數新增至 LastName
資料行:
ALTER TABLE Data.Membership
ALTER COLUMN LastName ADD MASKED WITH (FUNCTION = 'partial(2,"xxxx",0)');
以下範例會變更 LastName
資料行的遮罩函數:
ALTER TABLE Data.Membership
ALTER COLUMN LastName VARCHAR(100) MASKED WITH (FUNCTION = 'default()');
授與權限以檢視未遮蔽的資料
授與 UNMASK 權限可讓 MaskingTestUser
看見未遮罩的資料。
GRANT UNMASK TO MaskingTestUser;
EXECUTE AS USER = 'MaskingTestUser';
SELECT * FROM Data.Membership;
REVERT;
-- Removing the UNMASK permission
REVOKE UNMASK TO MaskingTestUser;
捨棄動態資料遮罩
以下陳述式會卸除先前範例中在 LastName
資料行建立的遮罩:
ALTER TABLE Data.Membership
ALTER COLUMN LastName DROP MASKED;
細微權限範例
建立結構描述以包含使用者資料表:
CREATE SCHEMA Data;
建立具有遮罩資料行的資料表:
CREATE TABLE Data.Membership (
MemberID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED,
FirstName VARCHAR(100) MASKED WITH (FUNCTION = 'partial(1, "xxxxx", 1)') NULL,
LastName VARCHAR(100) NOT NULL,
Phone VARCHAR(12) MASKED WITH (FUNCTION = 'default()') NULL,
Email VARCHAR(100) MASKED WITH (FUNCTION = 'email()') NOT NULL,
DiscountCode SMALLINT MASKED WITH (FUNCTION = 'random(1, 100)') NULL,
BirthDay DATETIME MASKED WITH (FUNCTION = 'default()') NULL
插入範例資料:
INSERT INTO Data.Membership (FirstName, LastName, Phone, Email, DiscountCode, BirthDay)
VALUES
('Roberto', 'Tamburello', '555.123.4567', '[email protected]', 10, '1985-01-25 03:25:05'),
('Janice', 'Galvin', '555.123.4568', '[email protected]', 5, '1990-05-14 11:30:00'),
('Shakti', 'Menon', '555.123.4570', '[email protected]', 50, '2004-02-29 14:20:10'),
('Zheng', 'Mu', '555.123.4569', '[email protected]', 40, '1990-03-01 06:00:00');
建立結構描述以包含服務資料表:
CREATE SCHEMA Service;
建立具有遮罩資料行的服務資料表:
CREATE TABLE Service.Feedback (
MemberID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED,
Feedback VARCHAR(100) MASKED WITH (FUNCTION = 'default()') NULL,
Rating INT MASKED WITH (FUNCTION = 'default()'),
Received_On DATETIME
插入範例資料:
INSERT INTO Service.Feedback(Feedback, Rating, Received_On)
VALUES
('Good', 4, '2022-01-25 11:25:05'),
('Excellent', 5, '2021-12-22 08:10:07'),
('Average', 3, '2021-09-15 09:00:00');
在資料庫中建立不同的使用者:
CREATE USER ServiceAttendant WITHOUT LOGIN;
CREATE USER ServiceLead WITHOUT LOGIN;
CREATE USER ServiceManager WITHOUT LOGIN;
CREATE USER ServiceHead WITHOUT LOGIN;
授與讀取權限給資料庫中的使用者:
ALTER ROLE db_datareader ADD MEMBER ServiceAttendant;
ALTER ROLE db_datareader ADD MEMBER ServiceLead;
ALTER ROLE db_datareader ADD MEMBER ServiceManager;
ALTER ROLE db_datareader ADD MEMBER ServiceHead;
授與不同的 UNMASK 權限給使用者:
--Grant column level UNMASK permission to ServiceAttendant
GRANT UNMASK ON Data.Membership(FirstName) TO ServiceAttendant;
-- Grant table level UNMASK permission to ServiceLead
GRANT UNMASK ON Data.Membership TO ServiceLead;
-- Grant schema level UNMASK permission to ServiceManager
GRANT UNMASK ON SCHEMA::Data TO ServiceManager;
GRANT UNMASK ON SCHEMA::Service TO ServiceManager;
--Grant database level UNMASK permission to ServiceHead;
GRANT UNMASK TO ServiceHead;
在使用者 ServiceAttendant
的內容下查詢資料:
EXECUTE AS USER = 'ServiceAttendant';
SELECT MemberID, FirstName, LastName, Phone, Email, BirthDay
FROM Data.Membership;
SELECT MemberID, Feedback, Rating
FROM Service.Feedback;
REVERT;
在使用者 ServiceLead
的內容下查詢資料:
EXECUTE AS USER = 'ServiceLead';
SELECT MemberID, FirstName, LastName, Phone, Email, BirthDay
FROM Data.Membership;
SELECT MemberID, Feedback, Rating
FROM Service.Feedback;
REVERT;
在使用者 ServiceManager
的內容下查詢資料:
EXECUTE AS USER = 'ServiceManager';
SELECT MemberID, FirstName, LastName, Phone, Email, BirthDay
FROM Data.Membership;
SELECT MemberID, Feedback, Rating
FROM Service.Feedback;
REVERT;
在使用者 ServiceHead
的內容下查詢資料
EXECUTE AS USER = 'ServiceHead';
SELECT MemberID, FirstName, LastName, Phone, Email, BirthDay
FROM Data.Membership;
SELECT MemberID, Feedback, Rating
FROM Service.Feedback;
REVERT;
若要撤銷 UNMASK 權限,請使用下列 T-SQL 陳述式:
REVOKE UNMASK ON Data.Membership(FirstName) FROM ServiceAttendant;
REVOKE UNMASK ON Data.Membership FROM ServiceLead;
REVOKE UNMASK ON SCHEMA::Data FROM ServiceManager;
REVOKE UNMASK ON SCHEMA::Service FROM ServiceManager;
REVOKE UNMASK FROM ServiceHead;
CREATE TABLE (Transact-SQL)
ALTER TABLE (Transact-SQL)
column_definition (Transact-SQL)
sys.masked_columns (Transact-SQL)
開始使用 SQL 資料庫動態資料遮罩 (Azure 入口網站)
Fabric 資料倉儲中的動態資料遮罩