DCL (Data Control Language) commands manage database security by controlling access to database objects through permissions and roles.
-- Create a SQL Server login
CREATE LOGIN [SalesManager]
WITH PASSWORD = 'Str0ngP@ssw0rd!',
DEFAULT_DATABASE = [OrderDB],
CHECK_EXPIRATION = ON,
CHECK_POLICY = ON;
GO
-- Create a database user mapped to login
USE [OrderDB];
CREATE USER [SalesManager_User] FOR LOGIN [SalesManager];
GO
-- Create a user without login (for application use)
CREATE USER [App_Service_Account] WITHOUT LOGIN;
GO
-- Change user name
ALTER USER [SalesManager_User] WITH NAME = [SalesAdmin_User];
GO
-- Change default schema
ALTER USER [SalesAdmin_User] WITH DEFAULT_SCHEMA = [Sales];
GO
-- Map user to different login
ALTER USER [SalesAdmin_User] WITH LOGIN = [NewSalesLogin];
GO
-- Drop database user
DROP USER [App_Service_Account];
GO
-- Drop server login
DROP LOGIN [SalesManager];
GO
-- Add login to fixed server role
ALTER SERVER ROLE [sysadmin] ADD MEMBER [SalesManager];
GO
-- Create custom server role
CREATE SERVER ROLE [OrderDB_Admin];
GO
GRANT CONTROL SERVER TO [OrderDB_Admin];
GO
-- Add user to fixed database role
ALTER ROLE [db_datareader] ADD MEMBER [SalesAdmin_User];
GO
-- Create custom database role
CREATE ROLE [Sales_Team];
GO
-- Grant role to another role
ALTER ROLE [Sales_Team] ADD MEMBER [Marketing_Team];
GO
-- Drop role
DROP ROLE [Sales_Team];
GO
-- Basic permissions
GRANT SELECT ON [Sales].[Customers] TO [Sales_Team];
GRANT INSERT, UPDATE ON [Sales].[Orders] TO [SalesAdmin_User];
GRANT EXECUTE ON [Sales].[PlaceOrder] TO [Sales_Team];
-- Schema-level permissions
GRANT SELECT, INSERT ON SCHEMA::[Sales] TO [Sales_Team];
GRANT ALTER ON SCHEMA::[Sales] TO [SalesAdmin_User];
-- Database-level permissions
GRANT CREATE TABLE TO [SalesAdmin_User];
GRANT SHOWPLAN TO [Reporting_User];
-- Explicit deny overrides grants
DENY DELETE ON [Sales].[Customers] TO [Sales_Team];
DENY ALTER ON SCHEMA::[Finance] TO [SalesAdmin_User];
-- Remove specific permissions
REVOKE SELECT ON [Sales].[Customers] FROM [Sales_Team];
REVOKE CREATE TABLE FROM [SalesAdmin_User];
-- Remove all permissions
REVOKE ALL ON [Sales].[Orders] FROM [Sales_Team];
-- Create predicate function
CREATE FUNCTION [Sales].[fn_SecurityPredicate](@SalesRepID INT)
RETURNS TABLE
WITH SCHEMABINDING
AS RETURN
SELECT 1 AS [result]
WHERE @SalesRepID = USER_ID()
OR USER_NAME() = 'SalesManager';
GO
-- Apply security policy
CREATE SECURITY POLICY [Sales].[CustomerAccessPolicy]
ADD FILTER PREDICATE [Sales].[fn_SecurityPredicate](SalesRepID)
ON [Sales].[Customers];
GO
-- Alter security policy
ALTER SECURITY POLICY [Sales].[CustomerAccessPolicy]
ADD BLOCK PREDICATE [Sales].[fn_SecurityPredicate](SalesRepID)
ON [Sales].[Customers] AFTER INSERT;
GO
-- Disable policy
ALTER SECURITY POLICY [Sales].[CustomerAccessPolicy] WITH (STATE = OFF);
GO
-- Drop policy
DROP SECURITY POLICY [Sales].[CustomerAccessPolicy];
GO
-- Add masking to existing column
ALTER TABLE [Sales].[Customers]
ALTER COLUMN [Email] ADD MASKED WITH (FUNCTION = 'email()');
GO
-- Full masking options
ALTER TABLE [HR].[Employees]
ALTER COLUMN [Salary] ADD MASKED WITH (FUNCTION = 'random(10000, 50000)');
GO
ALTER TABLE [Sales].[Customers]
ALTER COLUMN [CreditCard] ADD MASKED WITH (FUNCTION = 'partial(0, "XXXX-XXXX-XXXX-", 4)');
GO
-- Grant unmask permission
GRANT UNMASK TO [Finance_Team];
GO
-- Remove masking
ALTER TABLE [Sales].[Customers]
ALTER COLUMN [Email] DROP MASKED;
GO
-- Create audit destination
CREATE SERVER AUDIT [OrderDB_Audit]
TO FILE (FILEPATH = 'C:\Audits\', MAXSIZE = 1 GB)
WITH (QUEUE_DELAY = 1000, ON_FAILURE = CONTINUE);
GO
-- Enable audit
ALTER SERVER AUDIT [OrderDB_Audit] WITH (STATE = ON);
GO
-- Track DDL changes
CREATE DATABASE AUDIT SPECIFICATION [OrderDB_DDL_Audit]
FOR SERVER AUDIT [OrderDB_Audit]
ADD (SCHEMA_OBJECT_CHANGE_GROUP),
ADD (DATABASE_PRINCIPAL_CHANGE_GROUP);
GO
-- Track sensitive data access
ALTER DATABASE AUDIT SPECIFICATION [OrderDB_DDL_Audit]
ADD (SELECT, INSERT, UPDATE, DELETE ON [Sales].[Customers] BY [public]);
GO
-- 1. Create login and user
CREATE LOGIN [Audit_Admin] WITH PASSWORD = 'Aud1tP@ss!';
GO
USE [OrderDB];
CREATE USER [Audit_Admin] FOR LOGIN [Audit_Admin];
GO
-- 2. Create custom role
CREATE ROLE [Data_Stewards];
GO
-- 3. Assign permissions
GRANT SELECT ON SCHEMA::[Sales] TO [Data_Stewards];
GRANT INSERT ON [Sales].[Customers] TO [Data_Stewards];
DENY DELETE ON SCHEMA::[Sales] TO [Data_Stewards];
GO
-- 4. Add user to role
ALTER ROLE [Data_Stewards] ADD MEMBER [Audit_Admin];
GO
-- 5. Implement row-level security
CREATE FUNCTION [Sales].[fn_RegionSecurity](@RegionID INT)
RETURNS TABLE WITH SCHEMABINDING
AS RETURN (SELECT 1 AS [access]
WHERE @RegionID = (SELECT RegionID FROM [emp].[RegionMap]
WHERE UserID = USER_ID()));
GO
CREATE SECURITY POLICY [Sales].[RegionPolicy]
ADD FILTER PREDICATE [Sales].[fn_RegionSecurity](RegionID) ON [Sales].[Orders];
GO
-- 6. Set up auditing
CREATE SERVER AUDIT [SensitiveData_Access]
TO APPLICATION_LOG
WITH (QUEUE_DELAY = 1000);
GO
CREATE DATABASE AUDIT SPECIFICATION [CustomerData_Access]
FOR SERVER AUDIT [SensitiveData_Access]
ADD (SELECT, UPDATE ON [Sales].[Customers] BY [public]);
GO