I’ve seen this question come up on the newsgroups, as well as internally. A user will have access to some particular Account, Contact, etc. when their role doesn’t allow it and neither they nor a team of which they’re a member is listed in the sharing dialog. How can this happen?
Well, it’s not a hole in the security model. This can happen when the reason the user has access to the object is because of cascaded security rights. Scott Colson has an overview of cascading in this blog post: http://blogs.msdn.com/crm/archive/2007/01/17/cascaded-security-privileges-and-sharing.aspx.
In a nutshell, cascading is a property of entity relationships. Cascading shows up in the customization UI on the relationship form:
When an operation, such as Assign or Share is marked as something other than “Cascade None”, it means that in addition to applying to the object on which the action was taken, it will apply to the object’s child objects as well, and the children’s children, etc. – basically the whole object hierarchy. In CRM 3.0, we added more ability to control over which specific child objects get cascaded to. This feature, called Configurable Cascading, is described in this blog post from Naveen Garg: http://blogs.msdn.com/crm/archive/2006/08/01/685573.aspx.
Let’s take a look at an example. Say you have the following simple object hierarchy:
Let’s assume the default cascading options for sharing for the Account-Account relationship, which is “Cascade All”. Now let’s say Accounts A and B are both owned by Phil Richardson, who shares A to me with “Read” permissions. Let’s say by default I only have “User” level access, which means I can only see accounts that I own or are shared to me or a team of which I’m a member. After Account A is shared, I can see Account A, of course. In the sharing dialog for Account A, you’d see something like this:
Because the share was cascaded, I can also see Sub-Account B, but the sharing dialog is empty:
The sharing dialog (obviously) only displays the explicit shares, not the inherited ones. Why is that? One part of the answer is that we store explicit and inherited access information differently. In my last post, I mentioned that the table in which we store all our information about sharing, both explicit and inherited, is called the PrincipalObjectAccess table. The structure of this table has two columns per entry that track sharing rights: “AccessRightsMask” and “InheritedAccessRightsMask”. Based on the names, it should be obvious that “AccessRightsMask” tracks the explicit shares and is what shows up in the sharing dialog for Account A. “InheritedAccessRightsMask” tracks inherited/cascaded rights, which can come from sharing, parenting, or assignment (depending on whether your org setting for “Share to Previous Owner on Assign” is set to true or not). The sharing dialog does not look at this column.
But other than just some limitation of the sharing dialog, there is a reason to not show it: inherited rights can’t be changed. Cascading behavior is defined at the relationship level by the administrator as an organization-wide business rule and should not be overridden by individual users. Additionally, if individual links in an object hierarchy changed their cascading rights, the objects below them would not inherit their rights properly and things could get very out of sync.
Of course, one option would be to do what Windows security dialogs do, which is show inherited rights in a read-only form. What do you think: useful or more confusing?