Workaround: PnP Sites Core not provisioning Sub Web Security!
June 24, 2016 Leave a comment
Introduction
Let’s start by reminding ourselves how SharePoint groups work: when you add a SP group to a sub web, it is actually added to the Site Collection SharePoint groups. And when you assign some permissions (e.g. ‘Contribute’) to that group in the sub web, two things may happen, depending on whether the sub web inherits parent permissions or not:
- permissions are inherited – the group is given ‘Contribute’ permissions in the Site Collection and all sub webs receive it too, implicitly.
- permissions inheritance is broken – the group is given ‘Contribute’ permissions only on the Sub Web! In the Site Collection root you will still see the group under ‘People & Groups’ page (because as we said, the groups are provisioned on Site Collection level), but you will not see in the ‘Permissions’ page, because it is given permissions only in the sub web.
The issue
Ok, now consider the following scenario: you are provisioning a PnP Template against a sub web. e.g.:
<pnp:Provisioning xmlns:pnp="http://schemas.dev.office.com/PnP/2015/12/ProvisioningSchema">
<pnp:Preferences Generator="OfficeDevPnP.Core, Version=2.3.1604.0, Culture=neutral, PublicKeyToken=3751622786b357c2" />
<pnp:Templates ID="CONTAINER-TEMPLATE-XXX">
<pnp:ProvisioningTemplate ID="TEMPLATE-XXX" Version="1">
<pnp:Security>
<pnp:SiteGroups>
<pnp:SiteGroup Title="My Group" Owner="SHAREPOINT\system" AllowMembersEditMembership="false" AllowRequestToJoinLeave="false" AutoAcceptRequestToJoinLeave="false" OnlyAllowMembersViewMembership="true" />
</pnp:SiteGroups>
<pnp:Permissions>
<pnp:RoleAssignments>
<pnp:RoleAssignment Principal="My Group" RoleDefinition="Full Control" />
</pnp:RoleAssignments>
</pnp:Permissions>
</pnp:Security>
</pnp:ProvisioningTemplate>
</pnp:Templates>
</pnp:Provisioning>
what would you expect to happen when the PnP engine runs this? Personally, I would expect that the engine sees the ‘My Group’, creates it under the Site Collection and assigns ‘Full Control’ permission level to it on the Sub Web level. Now, as we explained, if the Sub Web permission inheritance is not broken, that would actually mean giving the ‘My Group’ ‘Full Control’ rights within the entire site collection. But this is the exact reason why the PnP provisioning engine ignores the Security element for sub webs! Because the PnP team has a principle of ‘provisioning a site can never change settings in other sites‘. Yes, PnP provisioning engine will simply ignore your Security instructions, when executed against a sub web.
However, in the case when the sub web has broken permission inheritance, I disagree! When the inheritance is broken, the Group will be created on the Site Collection level, but it will only be given rights on the sub web, hence – not actually changing anything in the other (parent) site!
Solution
To overcome this issue, I have created a PnP extension, which will perform the Security element provisioning on the sub web exactly the way I think it should be – if the web is a sub web and the permission inheritance is broken – go ahead with the Security provisioning, instead of ignoring it.
Template
First you have to change your template to:
<pnp:Provisioning xmlns:pnp="http://schemas.dev.office.com/PnP/2015/12/ProvisioningSchema">
<pnp:Preferences Generator="OfficeDevPnP.Core, Version=2.3.1604.0, Culture=neutral, PublicKeyToken=3751622786b357c2" />
<pnp:Templates ID="CONTAINER-TEMPLATE-XXX">
<pnp:ProvisioningTemplate ID="TEMPLATE-XXX" Version="1">
<pnp:Security>
<pnp:SiteGroups>
<pnp:SiteGroup Title="My Group" Owner="SHAREPOINT\system" AllowMembersEditMembership="false" AllowRequestToJoinLeave="false" AutoAcceptRequestToJoinLeave="false" OnlyAllowMembersViewMembership="true" />
</pnp:SiteGroups>
<pnp:Permissions>
<pnp:RoleAssignments>
<pnp:RoleAssignment Principal="My Group" RoleDefinition="Full Control" />
</pnp:RoleAssignments>
</pnp:Permissions>
</pnp:Security>
<pnp:Providers>
<pnp:Provider Enabled="true" HandlerType="My.Assembly.NameSpace.MyClassName, My.Assembly" />
</pnp:Providers>
</pnp:ProvisioningTemplate>
</pnp:Templates>
</pnp:Provisioning>
Which basically tells the PnP engine to search for the My.Assembly.dll and within it, it shall find My.Assembly.NameSpace.MyClassName class, which implements IProvisioningExtensibilityHandler interface. Search Google for more information on PnP extension engine.
Extension
Here is the C# code for your extension class, which is basically the original PnP method, but with modifications to provision Security against a sub web, when the sub web has broken inheritance.
Conclusion & Download
With this extension in place, you can now provision Security elements against a sub web, when the sub web has broken inheritance. It overrides the default PnP provisioning engine, which ignores the Security element, as soon as it sees that it’s a sub web.
Again, my opinion is that sub web Security should not be ignored, when the sub web has broken inheritance, because it doesn’t change in any way any other site, except adding the Group container on the Site Collection level (but without giving it any permissions!).
You can find the code samples as a here.
Cheers!