explore
engage
elevate
Dynamics CRM Security Modelling: Performance Considerations
“How to get 1.21 Gigawatts out of CRM”
Adam Vero, MVP, MCT
Co-Founder of CRMMasters
explore engage elevate
Adam Vero
Freelance Consultant, MVP and Microsoft Certified Trainer
Co-Founder of CRMMasters
Working with CRM >7 years
@AdamVero
blog.crmguru.co.uk
Getting “under the hood” of CRM
explore engage elevate
Topics
Quick revision
Overview of POA table
Cascading behaviours
How security is evaluated
Hierarchical security model
Flux capacitor optimisation
General security design tips for best performance
explore
engage
elevate
Security Model Design Quick Revision
explore engage elevate
Assigning Security Roles
Users can be assigned Security Roles directly, or indirectly via Team membership
This is not a straightforward “inheritance”, it is more complex: http://wp.me/p2I5L-ip
User needs to be directly assigned at least one Security Role directly in order to use CRM http://wp.me/p2I5L-l2
Users typically have many Security Roles, and the system calculates their resulting privileges
This privilege information is cached on every front-end web server that a user connects to
explore engage elevate
Sharing Records
Records can be shared with any Users or Teams Sharing a record with a Team is exactly equivalent to sharing it with members of the Team
Rights are determined by the sharing user
Privileges limit those shared rights
Access Teams use exactly the same sharing mechanism There is no special “magic” to how Access Teams work
Rights are determined by Access Team Template
Team membership determined by users
Sharing should be used to provide granular record access Use for entities where sharing is the model that is the best fit for purpose, rather than broad access for all users
explore
engage
elevate
Overview of POA Table
explore engage elevate
Overview of the POA table
• Who: usually User or Team
• Can also be Organization or BU Principal
• Which record
• Entity type code also stored Object
• Bit mask of privileges
• Shared and inherited separate Access
explore engage elevate
POA table considerations
Stores information about shares Explicit shares in AccessRightsMask column
Inherited and implicit shares in InheritedAccessRightsMask
Can grow very large Shared records x Users or Teams sharing
Even larger with cascading shares in 1:N relationships
Performance impact depends on other aspects of security model
Later versions of CRM (>2011) on later SQL server versions (>2008) significantly reduce bottlenecks and improve performance
Access Teams use POA table just like any other shares Use SQL queries to investigate http://wp.me/p2I5L-mx
explore
engage
elevate
Cascading Behaviors
explore engage elevate
Cascading Behaviors
Affect 1:N relationship “child” records
Can be configured, but often overlooked
Can add considerably to POA table
Work in some unexpected ways
Provide more access than you intend
Can drive a wrecking ball through your carefully planned security model
explore engage elevate
Example record hierarchy Account
Contact
Case
Activity
Opp.
Activity
Project
Milestone
Actions can be cascaded to tens, hundreds or even thousands of child records very easily
explore engage elevate
Relationship Behaviour Configuration
explore engage elevate
Assign, Share, Unshare
Rule Result for related entities in this relationship
Cascade All Perform the action on all related entity records.
Cascade
Active
Perform the action on all related entity records
that are Active (or Open, or equivalent Status).
Cascade
User-Owned
Perform the action on all related records owned by
the same user as the primary entity record.
Cascade
None Related entity records are not affected.
explore engage elevate
Effects of Assign, Share, Unshare
Assign modifies the child records This alters the Modified By / On fields on the records
It might also trigger workflows, plugins or auditing when the Owner field changes
Share / Unshare actions do not modify records Actions “only” update or insert rows in the POA table
explore engage elevate
Delete
Rule Result for related entities in this relationship
Cascade All Delete all related (child) entity records, even if
the user has no rights to delete them normally.
Remove Link
Clear the lookup field for this relationship, so the
related (child) record remains in the system but
could become an orphan.
Restrict Prevents the primary (parent) record from being
deleted if any related entity records exist.
Intended to help control “orphan” records (an “orphan” is a record without a parent)
explore engage elevate
Cascade Delete scenario
Account
Case
Task Delete:Restrict
Delete:All Account cannot be deleted
if one or more Tasks exist
Cases will be deleted if no Tasks
exist, even if user has delete
privileges on Cases set to “none”
explore engage elevate
Reparent
Triggered when a child record lookup field is filled in for the first time or changed later
Existing records unaffected if this setting is turned on
Grants access to the child record for Users or Teams who have access to the parent
Owner of the parent record can act on the child record as if they own it, even though they do not
Uses POA table to store “implicit” and “inherited” shares These shares cannot be seen, queried, or reported on in the UI
explore engage elevate
Re-Parent Shares in the POA table
Shares are recorded in the POA table in the InheritedAccessRightsMask column
Owner Owner of the parent record gets a POA row with InheritedAccessRightsMask value of 135,069,719.
This is “all (relevant) bits on”, granting all rights implicitly.
The Owner can therefore do any action to the child record, for which they have at least User level privilege on the entity.
CRM works as if they own the record (but they do not)
Shares on the parent record are inherited at same value plus 134,217,728
explore engage elevate
Assigning or Updating later
No implicit share is added if the parent and child have the same owner. Assigning the child later does not add a row for the parent record owner.
If the parent record is reassigned, Owner implicit share value is set to zero, but no rows are added for new Owner so they might not have access.
Inherited shares are updated if parent record sharing is changed and Share cascading is on
explore
engage
elevate
Security Evaluation
explore engage elevate
How security is evaluated in CRM
Scalable security whitepapers http://bit.ly/CRM2013ScalableSecurity
http://bit.ly/CRM2015ScalabilityDocs
Evaluation includes: User’s Security Roles and privileges
Team’s Security Roles and privileges
User’s Business Unit, and their Teams’ BUs (for Teams that have Roles with access level of BU or PC:BU)
Records Owned by User, or User’s Teams
Records in BUs accessible by User, or User’s Teams
Records explicitly or implicitly shared with User, or User’s Teams
explore engage elevate
Retrieve Multiple
Display a View or fetch records from custom code
Read privilege for the entity filters the record set
Global (=Organisation) access level is most efficient
Any other level of read privilege must check several possibly complex queries to find records for the user:
Records Owned by the User or by any Team the User is in
Records in any BU the User or their Teams are in (BU aka “local”)
Records in child BUs of those BUs (Parent:Child aka “deep” level)
Records shared with the User or any Team the User is in
Then intersect results with the filters defined in the view / request
explore engage elevate
SystemUserPrincipal table
Table that maintains list of IDs for Users for different security principals they can “impersonate”
Columns for UserID and (other) PrincipalID
Row for User + their own ID (in both columns in other words)
Rows for User + every Team they are a member of
Row for User + BU they are in
Row for each Team + BU it is in
Used as an intermediate table in joins For example, to find records shared with a User or any of their Teams: query requesting user in SystemUserPrincipal joined to PrincipalObjectAccess to include User + Team shares in one query.
explore engage elevate
Command bar / other UI elements
Privileges (eg delete, assign) above level of “none” from anywhere will display buttons for a view
Uses cached “deepest privilege” for maximum efficiency
Single record in a form will display buttons when user has: Global access to a privilege for the User or any Team
Record is owned by the User or a Team the User is in, and that principal has a privilege at least at “owner” level
Record is in a Business Unit the User or one of their Teams has access to via a Security Role with that privilege
Record is shared with that privilege (in the AccessRightsMask) to the User/Team and the User has that privilege at least at User level
explore engage elevate
Web Application Server caching
Some security data cached on each web server to avoid having to query SQL for every action (20 minutes TTL)
User’s memberships of Owner Teams Flushed if User added to/removed from Owner Team
Access Teams are ignored and not cached
Users’ and Owner Teams’ BUs and privileges Calculates “deepest” access level for every privilege and caches it
Flushed if Security Roles are assigned to User or Team
User cache is flushed if User record is modified in any way
Privileges in each Security Role Flushed if Security Role is modified
explore
engage
elevate
What about the new Hierarchical Security Modelling?
explore engage elevate
Hierarchical Security Modelling (HSM)
Intended use: Replace code that automates sharing records with managers for reporting purposes, or creating Teams on the fly to achieve this
Choose to use Manager or Position hierarchy
Choose how many levels down the “tree” to consider
Managers Manager must be in same BU or a BU above the one the User is in
Might already be configured and ready to use
Positions Can cut across BUs
Need to configure from scratch
explore engage elevate
Hierarchical Security Model Performance
SystemUserManagerMap table allows simple evaluation of which users report to a manager, at which level
Records owned by the User or their Teams are available to the immediate manager to work on, and further up the hierarchy on a read-only basis
Combination of SystemUserManagerMap and SystemUserPrincipal enables simple queries through a couple of joins
Records shared explicitly with User or their Teams as well Combination of SystemUserManagerMap, SystemUserPrincipal and POA table enables simple queries through a few joins
In the end, HSM mainly uses existing mechanisms
explore
engage
elevate
General Design Guidelines
explore engage elevate
General Principles for Security Sanity
To grant access to records in “foreign” business units Use Teams as record owners (often less preferred by management who want accountability)
Assign Teams to Security Roles with Business Unit level privileges
Use Hierarchical Security and configure Positions
Make sure you review and configure cascading behaviours Avoid unexpected security holes, and reduce unnecessary rows in the POA table that do not help you achieve security objectives
Not retro-active, so you might need to clean up POA table if users have access that they should not (rather than to reduce the size)
Use Teams with no security roles to grant access to Forms, Dashboards and Field Security Profiles
explore engage elevate
General Principles for Performance
“Organization” (“Global”) read is ideal If you have performance issues and suspect security, temporarily grant global read for a user and test again. If performance improves, security might be a factor. If not, focus elsewhere.
Having lots of BUs and Teams in the system is OK Users being a member of many Owner Teams, and/or Teams from many BUs: slower
Update User record or Owner Team memberships: slower Due to cache flushing (Note: Access Teams are not cached)
Use manually-created Access Teams for non-security things such as segmentation in views / charts / reports
Read the scalability white papers!
Adam Vero
blog.CRMguru.co.uk
@AdamVero