Advertisement
Guest User

Untitled

a guest
Jul 24th, 2017
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.67 KB | None | 0 0
  1. ---------------------------------------------------------------
  2. -- PART 2: How to configure RLS
  3. ----------------------------------------------------------------
  4. -- Let's change the security policy to support a common scenario for web applications. In this scenario,
  5. -- Sales Persons connect to the database through a middle-tier application using a shared SQL login. To
  6. -- identify the current application user in the database, the application will store the current user name
  7. -- in the SESSION_CONTEXT immediately after opening a connection. This way, the RLS policy can filter rows
  8. -- based on the user name stored in SESSION_CONTEXT.
  9.  
  10. -- First, create a shared SQL login for the application's connection string
  11. CREATE LOGIN ApplicationServiceAccount WITH PASSWORD = 'pass@word1'
  12. CREATE USER ApplicationServiceAccount FOR LOGIN ApplicationServiceAccount
  13. GRANT SELECT, INSERT, UPDATE, DELETE ON Sales.CustomerPII TO ApplicationServiceAccount
  14. go
  15.  
  16. -- To set the SESSION_CONTEXT, the application will execute the following each time a connection is opened:
  17. EXEC sp_set_session_context @key=N'user_name', @value=N'michael9' -- for example, the Sales Person from above
  18. go
  19.  
  20. -- Now, this user name is stored in the SESSION_CONTEXT for the rest of the session (it will be reset when the
  21. -- connection is closed and returned to the connection pool).
  22. SELECT SESSION_CONTEXT(N'user_name')
  23. go
  24.  
  25. -- Reset for now
  26. EXEC sp_set_session_context @key=N'user_name', @value=NULL
  27. go
  28.  
  29. -- We need to change our security policy to filter based on the user_name stored in SESSION_CONTEXT. To do this,
  30. -- create a new predicate function that adds the new access logic. As a best practice, we'll put the function in a
  31. -- separate 'Security' schema that we've already created.
  32. CREATE FUNCTION Security.customerAccessPredicate_v2(@TerritoryID int)
  33. RETURNS TABLE
  34. WITH SCHEMABINDING
  35. AS
  36. RETURN SELECT 1 AS accessResult
  37. FROM HumanResources.Employee e
  38. INNER JOIN Sales.SalesPerson sp ON sp.BusinessEntityID = e.BusinessEntityID
  39. WHERE
  40. -- SalesPersons can only access customers in assigned territory
  41. ( IS_MEMBER('SalesPersons') = 1
  42. AND RIGHT(e.LoginID, LEN(e.LoginID) - LEN('adventure-works\')) = USER_NAME()
  43. AND sp.TerritoryID = @TerritoryID )
  44.  
  45. -- SalesManagers and database administrators can access all customers
  46. OR IS_MEMBER('SalesManagers') = 1
  47. OR IS_MEMBER('db_owner') = 1
  48.  
  49. -- NEW: Use the user_name stored in SESSION_CONTEXT if ApplicationServiceAccount is connected
  50. OR ( USER_NAME() = 'ApplicationServiceAccount'
  51. AND RIGHT(e.LoginID, LEN(e.LoginID) - LEN('adventure-works\')) = CAST(SESSION_CONTEXT(N'user_name') AS sysname)
  52. AND sp.TerritoryID = @TerritoryID )
  53. go
  54.  
  55. -- Swap this new function into the existing security policy. The FILTER predicate filters which rows
  56. -- are accessible via SELECT, UPDATE, and DELETE. The BLOCK predicate will prevent users from INSERT-ing or
  57. -- UPDATE-ing rows such that they violate the predicate.
  58. ALTER SECURITY POLICY Security.customerPolicy
  59. ALTER FILTER PREDICATE Security.customerAccessPredicate_v2(TerritoryID) ON Sales.CustomerPII,
  60. ALTER BLOCK PREDICATE Security.customerAccessPredicate_v2(TerritoryID) ON Sales.CustomerPII
  61. go
  62.  
  63. -- To simulate the application, impersonate ApplicationServiceAccount
  64. EXECUTE AS USER = 'ApplicationServiceAccount'
  65. go
  66.  
  67. -- If the application has not set the user_name key in SESSION_CONTEXT (i.e. it's NULL), then all rows are filtered:
  68. SELECT * FROM Sales.CustomerPII -- 0 rows
  69. go
  70.  
  71. -- So the application should set the current user_name in SESSION_CONTEXT immediately after opening a connection:
  72. EXEC sp_set_session_context @key=N'user_name', @value=N'michael9' -- assume 'michael9' is logged in to the application
  73. go
  74.  
  75. -- Only customers for Territory 2 are visible
  76. SELECT * FROM Sales.CustomerPII
  77. go
  78.  
  79. -- Application is blocked from inserting a new customer in a territory not assigned to the current user...
  80. INSERT INTO Sales.CustomerPII (CustomerID, FirstName, LastName, TerritoryID)
  81. VALUES (0, 'Bad', 'Customer', 10) -- operation failed, block predicate conflicts
  82. go
  83.  
  84. REVERT
  85. go
  86.  
  87. -- Reset the changes
  88. EXEC sp_set_session_context @key=N'user_name', @value=NULL
  89. go
  90.  
  91. ALTER SECURITY POLICY Security.customerPolicy
  92. ALTER FILTER PREDICATE Security.customerAccessPredicate(TerritoryID) ON Sales.CustomerPII,
  93. ALTER BLOCK PREDICATE Security.customerAccessPredicate(TerritoryID) ON Sales.CustomerPII
  94. go
  95.  
  96. DROP FUNCTION Security.customerAccessPredicate_v2
  97. DROP USER ApplicationServiceAccount
  98. DROP LOGIN ApplicationServiceAccount
  99. go
  100.  
  101.  
  102. -- Final note: Use these system views to monitor and manage security policies and predicates
  103. SELECT * FROM sys.security_policies
  104. SELECT * FROM sys.security_predicates
  105. go
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement