adding RLS

This commit is contained in:
Jos de Bruijn
2016-05-26 16:38:38 -07:00
parent c31fd952ff
commit 6024a9c315
3 changed files with 255 additions and 0 deletions
@@ -0,0 +1,33 @@
-- Demonstrate Row Level Security -- Window 2
-- Right-click this query window and change connection
-- Log on as SQL login Website with password SQLRocks!00
-- Ensure we are logged on as the website user
SELECT SUSER_SNAME();
GO
-- Note that no customers are visible as yet
SELECT * FROM Sales.Customers;
GO
-- Set the session context (the website would set this on behalf of the user)
EXEC sp_set_session_context N'SalesTerritory', N'Great Lakes', @read_only = 1;
GO
-- Check the value that was set
SELECT SESSION_CONTEXT(N'SalesTerritory');
GO
-- Note that the user can now access the users based upon the sales territory in the session_context
SELECT * FROM Sales.Customers;
GO
USE tempdb;
GO
-- Right-click this window and from the connection menu, disconnect
-- Switch back to the main window to tidy up
@@ -0,0 +1,156 @@
-- Demonstrate Row Level Security
USE master;
GO
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
IF NOT EXISTS (SELECT 1 FROM sys.server_principals WHERE name = N'Website')
BEGIN
CREATE LOGIN Website
WITH PASSWORD = N'SQLRocks!00',
CHECK_POLICY = OFF,
CHECK_EXPIRATION = OFF,
DEFAULT_DATABASE = WideWorldImporters;
END;
GO
USE WideWorldImporters;
GO
CREATE USER GreatLakesUser FOR LOGIN GreatLakesUser;
GO
CREATE USER Website FOR LOGIN Website;
GO
ALTER ROLE [Great Lakes Sales] ADD MEMBER GreatLakesUser;
GO
-- Ensure that the policy has been applied
EXEC [Application].Configuration_ApplyRowLevelSecurity;
GO
-- The function that has been applied is as follows:
--
-- CREATE FUNCTION [Application].DetermineCustomerAccess(@CityID int)
-- RETURNS TABLE
-- WITH SCHEMABINDING
-- AS
-- RETURN (SELECT 1 AS AccessResult
-- WHERE IS_ROLEMEMBER(N'db_owner') <> 0
-- OR IS_ROLEMEMBER((SELECT sp.SalesTerritory
-- FROM [Application].Cities AS c
-- INNER JOIN [Application].StateProvinces AS sp
-- ON c.StateProvinceID = sp.StateProvinceID
-- WHERE c.CityID = @CityID) + N' Sales') <> 0
-- OR (ORIGINAL_LOGIN() = N'Website'
-- AND EXISTS (SELECT 1
-- FROM [Application].Cities AS c
-- INNER JOIN [Application].StateProvinces AS sp
-- ON c.StateProvinceID = sp.StateProvinceID
-- WHERE c.CityID = @CityID
-- AND sp.SalesTerritory = SESSION_CONTEXT(N'SalesTerritory'))));
-- GO
-- The security policy that has been applied is as follows:
--
-- CREATE SECURITY POLICY [Application].FilterCustomersBySalesTerritoryRole
-- ADD FILTER PREDICATE [Application].DetermineCustomerAccess(DeliveryCityID)
-- ON Sales.Customers,
-- ADD BLOCK PREDICATE [Application].DetermineCustomerAccess(DeliveryCityID)
-- ON Sales.Customers AFTER UPDATE;
-- GO
SELECT * FROM sys.database_principals; -- not the role for Great Lakes and the user for Great Lakes
GO
SELECT * FROM Sales.Customers; -- and note count
GO
GRANT SELECT, UPDATE ON Sales.Customers TO [Great Lakes Sales];
GRANT SELECT ON [Application].Cities TO [Great Lakes Sales];
GRANT SELECT ON [Application].Countries TO [Great Lakes Sales];
GO
EXECUTE AS USER = 'GreatLakesUser';
GO
-- Now note the count and which rows are returned
-- even though we have not changed the command
SELECT * FROM Sales.Customers;
GO
-- where are those customers?
-- note the spatial results tab
SELECT c.Border
FROM [Application].Countries AS c
WHERE c.CountryName = N'United States'
UNION ALL
SELECT c.DeliveryLocation
FROM Sales.Customers AS c;
GO
-- updating rows that are accessible to a non-accessible row is blocked
UPDATE Sales.Customers -- Attempt to update
SET DeliveryCityID = 3 -- to a city that is not in the Great Lakes Sales Territory
WHERE DeliveryCityID = 32887; -- for a customer that is in the Great Lakes Sales Territory
REVERT;
GO
-- Remove the user from the role
ALTER ROLE [Great Lakes Sales] DROP MEMBER GreatLakesUser;
GO
-- Instead of permission for a role, let's give permissions to the website user
GRANT SELECT, UPDATE ON Sales.Customers TO [Website];
GRANT SELECT ON [Application].Cities TO [Website];
GRANT SELECT ON [Application].Countries TO [Website];
GO
-- Open the second RLS demo window and follow the instructions there
-- Finally, tidy up (optional)
REVOKE SELECT, UPDATE ON Sales.Customers FROM [Great Lakes Sales];
REVOKE SELECT ON [Application].Cities FROM [Great Lakes Sales];
REVOKE SELECT ON [Application].Countries FROM [Great Lakes Sales];
REVOKE SELECT, UPDATE ON Sales.Customers FROM [Website];
REVOKE SELECT ON [Application].Cities FROM [Website];
REVOKE SELECT ON [Application].Countries FROM [Website];
GO
EXEC [Application].Configuration_RemoveRowLevelSecurity;
GO
DROP USER GreatLakesUser;
GO
DROP USER Website;
GO
USE master;
GO
DROP LOGIN GreatLakesUser;
GO
DROP LOGIN Website;
GO
USE tempdb;
GO
@@ -0,0 +1,66 @@
# Sample for use of Row-Level Security in WideWorldImporters
This script demonstrates the use of Row-Level Security to restrict access to certains rows in the table to certain users.
### Contents
[About this sample](#about-this-sample)<br/>
[Before you begin](#before-you-begin)<br/>
[Running the sample](#run-this-sample)<br/>
[Sample details](#sample-details)<br/>
[Disclaimers](#disclaimers)<br/>
[Related links](#related-links)<br/>
<a name=about-this-sample></a>
## About this sample
<!-- Delete the ones that don't apply -->
1. **Applies to:** SQL Server 2016 (or higher), Azure SQL Database
1. **Key features:** Row-Level Security
1. **Workload:** OLTP
1. **Programming Language:** T-SQL
1. **Authors:** Greg Low, Jos de Bruijn
1. **Update history:** 26 May 2016 - initial revision
<a name=before-you-begin></a>
## Before you begin
To run this sample, you need the following prerequisites.
**Software prerequisites:**
<!-- Examples -->
1. SQL Server 2016 (or higher) or Azure SQL Database.
- With SQL Server, make sure SQL authentication is enabled.
2. SQL Server Management Studio
3. The WideWorldImporters database.
<a name=run-this-sample></a>
## Running the sample
1. Open both scripts in different windows or tabs in Management Studio.
2. Follow the instructions in the main script DemonstrateRLS.sql.
## Sample details
The sample adds a new table with sensitive data about suppliers. This sensitive data is always encrypted.
As part of the sample you create an encryption key that is saved locally (where you run SSMS). The client application inserts data into the table. With the sample scripts you will see how the data is encrypted in the table and cannot be viewed, even by a sysadmin, unless you have the encryption key.
<a name=disclaimers></a>
## Disclaimers
The code included in this sample is not intended to be used for production purposes.
<a name=related-links></a>
## Related Links
<!-- Links to more articles. Remember to delete "en-us" from the link path. -->
TBD