Implicit Shares in Microsoft CRM 2011

Microsoft CRM has a security model feature which is not well documented but can be of use when designing the security for your CRM implementation.   The concept is that with CRM configured a certain way you can ensure that child records created in CRM are automatically shared to the owner of the parent record.    A common place you might want to do this is with customer records (Contacts and Accounts) – where you might like any child records added to these records by other users to be always visible to the owner of that Customer record.   CRM utilizes Shares for this but these are hidden shares that you will not see in the CRM UI.   They do exist in the PrincipalObjectAccess (POA) table though.   Because Sharing is used, users are able to see records above and beyond what their security role permits.  i.e. A user’s security role may grant them Read access to only the Activity records they own but if another user adds an Activity to one of their Contacts and implicit sharing is enabled then the user will be able to see this Activity, even if they are not the owner of the record.

There are some peculiarities related to implicit shares that you need to understand if you want this to be a key part of your security design.  

Firstly, the settings that drive this behavior are the Cascade settings on your entity relationships:

image

To have an implicit share created when a child record is added to a parent you need to have the Reparent option set to the Cascade.   This cascade is triggered when the lookup field on the child record changes from one parent to another.   This trigger also fires when a child record is first created under a parent record as the lookup field goes from NULL to a non-NULL value.    Now, there is a caveat here, the share will only be created if the owner of the child record differs from the owner of the parent record.   But then if the records share the same owner there is no need to share access.

Here’s how this looks.  I have these Cascade settings between Contact and Task:

image

I have a Contact owned by CRM Admin and another user, Ken Mallit has created a Task against this Contact:

image

On the Task record there is no visible Share:

image

But in the PrincipalObjectAccess table you will see a Share has been created against the Task, sharing access to the CRM Admin user:

image

And if I log in as CRM Admin I can see the Task owned by Ken, even when my security role only grants user-level read access to Tasks.

Now, if Ken moves the Task from the original Contact to a different Contact (re-parenting the record) that too fires the Re-parent event and the implicit share is updated.   After this change I see 2 records in the POA table:

image

The original share sharing the Task to CRM Admin is still there but the InheritedAccessRightsMark value is now 0.  This is what CRM does, it zero’s out the permissions shared rather than deleting the record.  I believe I heard from a Microsoft colleague that a maintenance job purges these eventually.   We also see a new share, sharing the Task to Jill Frank who is the owner of the Contact I moved the Task to.   This sharing change means CRM Admin loses visibility of this Task (which is good as the Task no longer relates to one of their Contacts) and Jill gains visibility of the Task.

Let’s now look at what happens during an Assign event.  Currently, we have a Task owned by Ken that is parented by a Contact owned by Jill.  An implicit share provides Jill access to the Task.   If we now reassign the Contact record from Jill to Mark let’s see what happens to the implicit share:

image

You will see that no new Share has been created for Mark.  And the existing Share for Jill has been zeroed out (InheritedAccessRightsMark value is now 0).   This caught me by surprise when I first hit this.  This feels like a functional gap to me.   Now there is another Cascade setting we can fiddle with here to alter the behavior, but you may not like what it does.   The above tests were done with the Cascade Assign setting set to None.   If we flick  that over to Cascade All and then repeat the test we see the same result with the implicit shares but the reassignment of the Contact will cascade down and the Task record will get reassigned as well.   This will give Mark access to the Task attached to his Contact (he will now be the Owner of the Task) but Ken, the original Owner of the Task, will lose access. Which may well be an undesirable behavior.  I found this behavior quite problematic on my last project as I was using Teams to manage access to Contacts and whenever the Team changed on the Contact I had to make sure Tasks were not reassigned but still needed access to the Task to be adjusted to the new Team.  End up creating a custom “Assigned To” field and some other bits and pieces to address that.

Hope this helps someone out there. Implicit shares are an interesting feature.  It feels a little incomplete to me.  It is important you are aware of it so understand why users see what they see.  But if you want to build it into your security design you need to be very careful.

Advertisements

14 thoughts on “Implicit Shares in Microsoft CRM 2011

  1. Aaron Carpenter

    Glad to see you are posting again. Your posts have come in very handy many times in the past. Welcome back!

    Reply
  2. Adam Vero

    Thanks for this article Gareth, this is an area which I find loads of long time CRM consultants and admins have no idea about, let alone understand fully.

    The way I always describe how this works (when I teach the 80294B customisation course) is that the Reparent cascade enables the owner of the parent record to act on the child record *as if they actually owned it* to whatever level of access their security roles gives them.

    If they have the right to only read their user-owned [Task|Opportunity|whatever] records (which would be unusual), then that is all they can do on that type of child record of a record they own, but if the they have write, delete or assign privs on their own records (of the same entity as the child in question), they now have that right on the child record in question.
    This means a key account manager can act on all Opportunities for their client as if they owned them, even if the Opps are owned by other members of their sales team or internal sales. This is usually a good thing – as long as people expect it to work like this.

    So you are right that it makes the child record visible to the parent owner, which is almost always desirable, but the fact they can now edit, re-assign or even delete the child record is non-obvious to users and even admins, and needs to be carefully considered.
    Also bear in mind that Reparent = Cascade All is the *default* behaviour for lots of relationships out-of-the-box. And if there is a Reparent cascade relationship behaviour from the child to a grandchild record this is honoured too – so the owner of an Account will be able to act on Activities regarding an Opportunity or Case for that Account as if they owned the activities (although of course they do not show up in “My Activities” since they don’t actually own them).

    As to the “gap”, yes, it is frustrating but you can see why it arises – the cascade is triggered by a reparent, not by a re-assign of the parent. This gap should probably be closed, but then might need a new setting to be available – when I re-assign the parent and it gives an implicit access to the new owner, should it leave the original owner with any access or not? Arguably not, but I can imagine some people might want it to remain, so a setting (using OrgDBOrgSettings tool) to control this would be helpful.

    Reply
  3. Renan Albuquerque

    Gareth,

    How can i retrieve data from this table PrincipalObjectAccess by javascript?? using oData json?? Could you help me ?

    Reply
    1. Gareth Tucker Post author

      I am not sure that table is surfaced through the entity framework and made available through the odata service. You will likely need to create your own service.

      Reply
      1. Renan Albuquerque

        thanks for your answer,

        So is there another way to retrieve data using javascript ?

        I have the id of Team (TeamId) = PrincipalId (from POA) retrieving this i can catch the queueId = ObjectId (from POA), that’s why i want to retrieve on this table, to get the queue shared to a team.

  4. Chalky

    Gareth/Adam, there is a setting in CRM 4 and CRM 2011 named ‘share reassigned records with original owner’. It is independent of cascading.

    Reply
    1. ukcrmguru

      Chalky, yes, you are right, there is a horrible setting to share records with the original owner, which has nothing to do with cascading and does a different job, that setting would mean that when I reassign an Account from me to you, it is also shared back with me to make sure I don’t suddenly lose visibility of this. That might in turn, through cascading of the new share, mean that I also have all the child records shared with me.

      And the original assignment might also, through cascading, mean that all the child records are assigned to you, and that all of those get shared back with the previous owner, and their grandchildren likewise and so on.

      BUT! Most people turn off or tune “cascade assign” so that not all child records get reassigned – especially not closed records, and in some situations simply none at all (maybe the owners are in sales, so why would we reassign Cases for this Account at all?)

      “Share records with original owner” is completely indiscriminate – it will share the record back with me even if I have global access and can still see it anyway. There is only one setting for the whole Org, so while it might be useful in environments with extremely tight security roles, it is creating potentially thousands of shares on Accounts and Contact, and Case, and Opportunity, and Activities – just because you reassigned one Account. All these shares add up to a huge POA table. In an environment with very open security roles, this should not affect performance too much as it may not need to be read at all (eg if the user has global read on Contacts, their views will be displayed without ever referencing the POA table). With tight security roles, the POA table will be accessed all the time to evaluate records for views, forms, ribbon controls etc and performance can head downhill very fast.

      Use this setting with extreme caution. Or better still, never.

      Cascade reparent, on the other hand, does not share the original “parent” reassigned record at all. When I reassign that Account over to you, it adds / changes implicit shares on the child records so that you can now access them even if they have not been assigned to you through cascading or any other means, and again this trickles down to grandchildren etc. It does not give me (the original owner) any more access, in fact rather less as any original implicit shares I had will disappear.

      Reply
  5. Pingback: Rahul Desai's Blog » Implicit Shares in Microsoft CRM 2011 | GT // CRM

  6. Pingback: CRM 2013 New Features: Access Teams | GT // CRM

  7. Pingback: Implicit Shares in Microsoft CRM 2011 | Dynamics CRM on the Road

  8. Darwich

    Gareth, thanks a lot for your useful posts.

    Dear, I have a case in my company regarding Business Units and Territories security.
    I have a matrix across Business Units and Territories, i.e. [Sales Reps & Managers] security is by BU, [Branch & Area Managers] is by territory, and also I have [Product Managers & Specialists] is per Business Unit & Territory.

    Please advise if you have any idea.

    Best Regards,
    Darwich

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s