Tuesday, February 21, 2017

SQL Server Dynamic Data Masking SQL Server 2016

 This is one of the cool feature that introduced in SQL Server 2016, which can enable DBAs to mask data while database is in test\QA stage for testing. It limits the data exposure to the developers, testers and other unintended users, though it has it limitations and restrictions.

Types of Masking: 

Default Masking: Also known as full masking according to the data types of the designated fields.
  • For char, nchar, varchar, nvarchar, text, ntext uses XXXX or Fewer Xs depending on the field size.
  • For Date types uses 01.01.1900 00:00:00.0000000.
  • For bigint, bit, decimal, int, money, numeric, smallint, smallmoney, tinyint, float, real uses a zero value.
  • For Binary varbinary and image uses a Single byte of ASCII value 0.
Syntax:  Phone# varchar(12) MASKED WITH (FUNCTION = 'default()') NULL
               Alter syntax: ALTER COLUMN Gender ADD MASKED WITH (FUNCTION = 'default()')


Email Masking: This masking method which exposes the first letter of an email address and the constant suffix ".com", in the form of an email address.
e.g.: It Shows email addresses like aXXX@XXXX.com.
Syntax: Email varchar(100) MASKED WITH (FUNCTION = 'email()') NULL
              Alter syntax: ALTER COLUMN Email ADD MASKED WITH (FUNCTION = 'email()')


Random Masking: This masking function can be used on any numeric type to mask the original value with a random value within a specified range.
Syntax: Account_Number bigint MASKED WITH (FUNCTION = 'random([start range], [end range])')
              Alter syntax: ALTER COLUMN [Month] ADD MASKED WITH (FUNCTION = 'random(1, 12)')


Custom Masking: This masking method which exposes the first and last letters and adds a custom padding string in the middle.
Syntax: FirstName varchar(100) MASKED WITH (FUNCTION = 'partial(prefix,[padding],suffix)') NULL
            ALTER COLUMN [Phone Number] ADD MASKED WITH (FUNCTION = 'partial(1,"XXXXXXX",0)')

Masking Hands On:
-- Create a Demo database for Masking
CREATE DATABASE [Masking]
GO

-- Create a Demo table for masking
USE [Masking]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Masking_Demo](
 [ID] [int] NOT NULL,
 [Name] [nvarchar](10) NULL,
 [DateOfBirth] [date] NULL,
 [AccNum] [numeric](18, 0) NULL,
 [Gender] [varchar](50) NULL,
 [EMailID] VARCHAR(50) NULL,
 [City] [nchar](10) NULL,
 [State] [nchar](10) NULL
) ON [PRIMARY]
GO

-- Inserting data into the above table
INSERT INTO dbo.Masking_Demo
        ( ID ,Name ,DateOfBirth ,AccNum ,Gender ,EMailID , City ,State)
VALUES  ( '1','Sri','1987-2-2','757676567','Male','Sri.anu@soandso.com', 'Florence','KY'),
        ( '2','Jer','1967-3-3','764900097','Male', 'Jer.cole@soandso.com', 'Hamilton','OH'),
  ( '3','Don','1990-4-4','780090909','Male','Don.sl@soandso.com', 'Newyork','NY')

-- Select Data from above table
SELECT * FROM [Masking].[dbo].[Masking_Demo]







Apply Masking to above table:
-- Create a Demo database for Masking
-- Alter table to mask each column with different masking functions
SET ANSI_PADDING OFF
GO

  Alter Table [Masking].[Masking_Demo] ALTER COLUMN [ID] ADD MASKED WITH (FUNCTION = 'default()')
  Alter Table [Masking].[Masking_Demo] ALTER COLUMN [Name] ADD MASKED WITH (FUNCTION = 'default()')
  Alter Table [Masking].[Masking_Demo] ALTER COLUMN [DateOfBirth] ADD MASKED WITH (FUNCTION = 'default()')
  Alter Table [Masking].[Masking_Demo] ALTER COLUMN [AccNum] ADD MASKED WITH (FUNCTION = 'random(1, 12000)')
  Alter Table [Masking].[Masking_Demo] ALTER COLUMN [Gender] ADD MASKED WITH (FUNCTION = 'default()')
  Alter Table [Masking].[Masking_Demo] ALTER COLUMN [EMailID] ADD MASKED WITH (FUNCTION = 'email()')
  Alter Table [Masking].[Masking_Demo] ALTER COLUMN [City] ADD MASKED WITH (FUNCTION = 'partial(3,"XXXX",2)')
  Alter Table [Masking].[Masking_Demo] ALTER COLUMN [State] ADD MASKED WITH (FUNCTION = 'partial(1,"XXXXXXX",0)')

-- Select Data from table after masking
SELECT * FROM [Masking].[dbo].[Masking_Demo]




Permissions:
  • Permissions required to create table with dynamic data mask are: CREATE TABLE and ALTER schema.
  • Adding, replacing, or removing the mask of a column, requires the ALTER ANY MASK permission and ALTER permission on the table.
  • SELECT permission on a table will view masked data only.
  • UNMASK permission are needed to retrieve unmasked data from the columns for which masking is defined. e.g.: GRANT UNMASK TO
  • The CONTROL permission on the database includes both the ALTER ANY MASK and UNMASK permission.

Best Practices and Common Use Cases:
  • Creating a mask on a column does not prevent updates to that column. So users receive masked data when querying the masked column, the same users can update the data if they have write permissions. A proper access control policy should still be used to limit update permissions.
  • Using SELECT INTO or INSERT INTO to copy data from a masked column into another table results in masked data in the target table.
  • Dynamic Data Masking is applied when running SQL Server Import and Export. A database containing masked columns will result in a backup file with masked data (assuming it is exported by a user without UNMASK privileges), and the imported database will contain statically masked data
Limitations and Restrictions:
A masking rule cannot be defined for the following column types:
  • Encrypted columns (Always Encrypted)
  • FILESTREAM
  • COLUMN_SET or a sparse column that is part of a column set.
  • A mask cannot be configured on a computed column, but if the computed column depends on a column with a MASK, then the computed column will return masked data.
  • A column with data masking cannot be a key for a FULLTEXT index.
  • For users without the UNMASK permission, the deprecated READTEXT, UPDATETEXT, and WRITETEXT statements do not function properly on a column configured for Dynamic Data Masking.

Security Note:
Bypassing masking using inference or brute-force techniques:
Dynamic Data Masking is designed to simplify application development by limiting data exposure in a set of pre-defined queries used by the application. While Dynamic Data Masking can also be useful to prevent accidental exposure of sensitive data when accessing a production database directly, it is important to note that unprivileged users with ad-hoc query permissions can apply techniques to gain access to the actual data. If there is a need to grant such ad-hoc access, Auditing should be used to monitor all database activity and mitigate this scenario.




Note to DBAs and Developers:
Don’t use the design mode to alter any column or table that is participating in Dynamic Data Masking, Design mode force the table to drop and recreate which results in masking to get removed.




Additional Readings: