SharePoint Account Management using SPUserUtil - Part 4 - Replaying Permissions and Moving Webs

SharePoint Account Management using SPUserUtil - Part 4 - Replaying Permissions and Moving Webs

Originally posted as: Moving a web and preserving permissions using SPUserUtil . Because of a ton of recent queries on this exact subject, I'm re-posting it but also re-titling it to include it in the "SharePoint Account Management using SPUserUtil series.

Aside from user migrations, another issue where the SPUserUtil tools come in handy is with site relocations. I don’t mean Site Collection relocations, as you can easily use STSADM backup and restore for this, but rather “Web” site relocations within the Site Collection hierarchy, or to another server in general. You can't use STSADM backup/restore to accomplish this task, as STSADM does not allow granular level web relocations. (This applies to Windows SharePoint Services 2.0 and SharePoint Portal Server 2003. Windows SharePoint Services 3.0 and Microsoft Office SharePoint Server 2007 allow you to do this with STSADM, so there's some improvements with the next version :))

Consider the following two requirements:

  • In your organization, it is deemed that a particular sub-web of a site collection is growing beyond the quota or scalability limits imposed by the site collection it belongs in. The sub-web needs to be placed into it’s own site collection. 
  • Based on corporate needs, a sub-web needs to be moved into a different location within the URL namespace of a SharePoint server. 

In order to accomplish those goals, you have to use SMIGRATE to export the data, and then import the data in a different location. When using SMIGRATE to export/import site data, the security information is not captured and is lost. But, using SPUserUtil, you can preserve and re-play the security information after the move has occurred.

You can also use this same method to just replay a set of permissions onto a new web or entire site collection.

The steps to accomplish this are broken down as follows:

  1. Collect the webs current security map
  2. Export the web data to disk
  3. Provision space for a new site collection or new web location
  4. Import the web data into the new location
  5. Prepare updated security map
  6. Reapply permissions
  7. Remove the previous web.

The following sections will detail the steps above as an aid to help you in preparing your site relocation plan. Since we’re speaking of Team Sites, we’ll be using WSSUserUtil. In our theoretical scenario, the HR sub web of our divisions site collection on our SharePoint site at https://server/divisions/hr has grown beyond it’s previous requirements, and it was deemed necessary to move it into it’s own “Human Resources” site collection. We’ll create the new site collection at https://server/sites/hr

Collect the webs current security map

When an SPUserUtil analyze operation is run, there are actually two files generated, the user map and the webs manifest file. (See the SPUserUtil documentations description for the analyze operation.) The Webs Manifest file is the key file used for re-applying permissions on a web. If you do not specify the name of the web manifest, one will automatically be created for you using the name portion of the User Manifest File, and appended with “-webs”. For example, if you specify –usermap c:\portalusers.xml, a file named c:\portalusers-webs.xml will be created for the webs manifest.

The first step to perform is generating a webs manifest file using the analyze operation such as the following:

WSSUserUtil -o analyze -url https://localhost/divisions/hr -r -usermap c:\hr.xml

This creates two files, the hr.xml file which contains our user map of unique users found on the site, and the hr-webs.xml file which contains our Web Manifest file. We used the -r switch to analyze recursively down the web heirarchy from the point of the hr web. The end result in our test case looks something similar to the following:

<?xml version="1.0" standalone="no"?>

<!DOCTYPE SPUserUtilWebFile>

<!--This file represents the web information generated and used by SPUserUtil-->

<webs>

  <web url="https://localhost/divisions/hr" title="Human Resources" description="" lcid="1033" template="STS" uniqueperms="True">

    <user loginname="NA\johndoe" displayname="John Doe" email="johndoe@yourcompany.com" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

      <crosssitegroups />

      <sitegroups>

        <group name="Contributor" />

      </sitegroups>

      <listpermissions />

    </user>

    <user loginname="NA\dwild" displayname="Don Wild" email="dwild@yourcompany.com" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

      <crosssitegroups />

      <sitegroups>

        <group name="Contributor" />

      </sitegroups>

      <listpermissions />

    </user>

    <user loginname="NA\krichie" displayname="Keith Richie" email="krichie@yourcompany.com" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

      <crosssitegroups />

      <sitegroups>

        <group name="Administrator" />

      </sitegroups>

      <listpermissions />

    </user>

    <user loginname="NA\EditorGroup" displayname="NA\EditorGroup" email="" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

      <crosssitegroups />

      <sitegroups>

        <group name="Reader" />

      </sitegroups>

      <listpermissions />

    </user>

    <user loginname="NA\nander" displayname="Neo Anderson" email="nander@yourcompany.com" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

      <crosssitegroups />

      <sitegroups>

        <group name="Contributor" />

      </sitegroups>

      <listpermissions />

    </user>

    <web url="https://localhost/divisions/hr/benefits" title="Benefits" description="" lcid="1033" template="STS" uniqueperms="False">

      <user loginname="NA\johndoe" displayname="John Doe" email="johndoe@yourcompany.com" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

        <crosssitegroups />

        <sitegroups>

          <group name="Contributor" />

        </sitegroups>

        <listpermissions />

      </user>

      <user loginname="NA\dwild" displayname="Don Wild" email="dwild@yourcompany.com" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

        <crosssitegroups />

        <sitegroups>

          <group name="Contributor" />

        </sitegroups>

        <listpermissions />

      </user>

      <user loginname="NA\krichie" displayname="Keith Richie" email="krichie@yourcompany.com" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

        <crosssitegroups />

        <sitegroups>

          <group name="Administrator" />

        </sitegroups>

        <listpermissions />

      </user>

      <user loginname="NA\EditorGroup" displayname="NA\EditorGroup" email="" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

        <crosssitegroups />

        <sitegroups>

          <group name="Reader" />

        </sitegroups>

        <listpermissions />

      </user>

      <user loginname="NA\nander" displayname="Neo Anderson" email="nander@yourcompany.com" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

        <crosssitegroups />

        <sitegroups>

          <group name="Contributor" />

        </sitegroups>

        <listpermissions />

      </user>

    </web>

    <web url="https://localhost/divisions/hr/legal" title="Legal" description="" lcid="1033" template="STS" uniqueperms="True">

      <user loginname="NA\johndoe" displayname="John Doe" email="johndoe@yourcompany.com" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

        <crosssitegroups />

        <sitegroups>

          <group name="Contributor" />

        </sitegroups>

        <listpermissions />

      </user>

      <user loginname="NA\dwild" displayname="Don Wild" email="dwild@yourcompany.com" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

        <crosssitegroups />

        <sitegroups>

          <group name="Contributor" />

        </sitegroups>

        <listpermissions />

      </user>

      <user loginname="NA\krichie" displayname="Keith Richie" email="krichie@yourcompany.com" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

        <crosssitegroups />

        <sitegroups>

          <group name="Administrator" />

        </sitegroups>

        <listpermissions />

      </user>

      <user loginname="NA\EditorGroup" displayname="NA\EditorGroup" email="" notes="" sid="S-1-5-xx-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxx">

        <crosssitegroups />

        <sitegroups>

          <group name="Reader" />

        </sitegroups>

        <listpermissions />

      </user>

    </web>

  </web>

</webs>

Something to consider in a later step, is that from reviewing the data above, note that there are actually two sub-webs underneath the /hr/ web. One of the sub-webs is named Benefits, the other named Legal. If you look closer you’ll notice that the Legal sub-web is using unique permissions, but the Benefits sub-web is not, thus inheriting it's permissions from the /hr/ web. SPUserUtil currently just writes out the permission set it finds for the web, regardless if it is inheriting or not. This gives you a complete XML section for that web, and it's security, in case you have to strip it out and re-use it later.

Also take note, that the current version of the SPUserUtil tools does not differentiate between a User Account, and a Group Account. The NA\EditorGroup in the above XML actually refers to a Security Group. A later version of SPUserUtil will help differentiate the difference.

Export the web data to disk

Once you have preserved your current security map, the next step is to actually export the data using the SMIGRATE tool.

smigrate -w https://localhost/divisions/hr -f f:\moveweb\hr.mig

This creates an export of your webs data. Since we did not specify the –e option, this export file contains the hr web and all of its sub-webs. For more information on the SMIGRATE tool, please refer to the Windows SharePoint Services documentation.

Provision space for a new site collection or web location

You can use either the Windows SharePoint Services Central Administration UI pages, or STSADM to provision a new site collection or provision a new web in an existing site collection. In our example, we’ll use STSADM as follows:

stsadm -o createsite -url https://localhost/sites/hr -ownerlogin YOURDOMAIN\YOUROWNER -owneremail yourowner@yourdomain.com

This command provisions new space for a site collection and creates a top level site, yet no template is currently chosen for the site. Choosing a template is not needed for this process. For more information on the STSADM tool, please refer to the Windows SharePoint Services documentation.

If instead, you need to move a web to a new location within the same site collection, use STSADM in the following fashion

stsadm -o createweb -url https://localhost/divisions/newlocation/hr

Import the web data into the new location

We’ll use the SMIGRATE tool once again to import the saved data into the new site collection

smigrate -r -w https://localhost/sites/hr -f f:\moveweb\hr.mig

This imports the web data contained in the hr.mig file into the site collection at web location provided. For more information on the SMIGRATE tool, please refer to the Windows SharePoint Services documentation.

Prepare updated security map

Before re-applying permissions, it’s important to understand that when using the add operation, we key off of the url attribute for each web element in the webs manifest file in order to apply permissions. In other words, this is the URL used to open a web context to, to then apply the permissions. In it’s current state, the add operation would try to open the previous locations of the webs and try to re-add the permissions, which of course would not have the desired results J. So, we need to update hr-webs.xml to match the new location for the webs.

Notice in the copy of hr-webs.xml above, the url attribute of each web element points to https://localhost/divisions/hr/... The easiest way to update this file, is simply change all references of https://localhost/divisions/hr/ to https://localhost/sites/hr/. Since we’re not going to modify any of the permissions themselves, and just re-play the permission map onto the webs, we’re ALMOST ready to go.

SPUserUtil currently has one limitation that requires you to make a slight change to your imported webs in the site collection. When running SMIGRATE to import web site data, each subweb is set to re-inherit permissions from each parent, thus any webs which had the “Use unique permissions” flag set, are set back to always inherit. SPUserUtil currently does not care if the web inherits permissions or not when using the add operation, so it’s necessary to either:

  • Remove the <web> element for the sub-web that is going to inherit from it’s parent, or
  • change the web site to use unique permissions.

Refer to the Windows SharePoint Services documentation for the steps to disable security inheritance.

Which ever choice you decide to make, is up to you. A future version of SPUserUtil will have options to “Re-set” inheritance etc based on the uniqueperms attribute in the manifest file.

You could also use this time to make adjustments to the user elements for each web, but that is beyond the scope of this tutorial.

Reapply permissions

With our updated hr-webs.xml manifest file in hand, let’s now run WSSUserUtil using the add operation to re-apply the permissions back onto our migrated web hierarchy.

wssuserutil -o add -url https://localhost/sites/hr -webfile f:\moveweb\hr-webs.xml

The above command will enumerate over each <web> element found in the manifest file, and apply the permissions as noted in the file.

Remove the previous web

After you have re-applied permissions, validate everything is correct and then remove the old webs from their current site collection

If the web you are deleting did not have sub-webs, you could easily use STSADM to accomplish this task using the following command line:

stsadm -o deleteweb -url https://localhost/divisions/hr

The problem with this, is that it will error out, as you cannot delete a web which currently has sub-webs. You would have to issue the command for each sub-web, then finally remove the parent web, such as:

stsadm -o deleteweb -url https://localhost/divisions/hr/Benefits

stsadm -o deleteweb -url https://localhost/divisions/hr/Legal

stsadm -o deleteweb -url https://localhost/divisions/hr

If you have a lot of nested sub-webs, it could be fairly time consuming.

The SharePoint Utility Suite at https://www.microsoft.com/sharepoint/downloads/components/detail.asp?a=724 has a tool call SPPruneWeb that was designed just for this purpose. It will traverse a web hierarchy and remove all child webs from the specified parent then remove the parent web you specified. More information on SPPruneWeb can be found in the SharePoint Utility Suite documentation included in the package above.

Hope this helps!

- Keith Richie


Previous posts in this series:

SharePoint Account Management using SPUserUtil - Part 0 - Removing Accounts
https://blogs.msdn.com/krichie/archive/2006/05/17/600040.aspx

SharePoint Account Management using SPUserUtil - Part 1 - Cloning Accounts
https://blogs.msdn.com/krichie/archive/2006/05/17/600218.aspx

SharePoint Account Management using SPUserUtil - Part 2 - Adding Accounts
https://blogs.msdn.com/krichie/archive/2006/05/19/602057.aspx

SharePoint Account Management using SPUserUtil - Part 3 - Auditing Accounts
https://blogs.msdn.com/krichie/archive/2006/05/22/604021.aspx

Additional Reference Material:

For more information in regards to the Schema of the Various SharePoint Tables, see the Databases section in the SharePoint Products and Technologies SDK at:
https://msdn.microsoft.com/library/default.asp?url=/library/en-us/spptsdk/html/SPPTWSSDatabases_SV01072208.asp

For more information in regards to Managing Users and Cross Site Groups in SharePoint
https://office.microsoft.com/en-us/assistance/HA011608091033.aspx

SPUserUtil is contained in the The SharePoint Utility Suite at:
https://www.microsoft.com/sharepoint/downloads/components/detail.asp?a1=724

For More information on the Windows SharePoint Services MigrateUserAccount() API:
https://msdn.microsoft.com/library/default.asp?url=/library/en-us/spptsdk/html/tsamSPGlobalAdminMigrateUserAccount_SV01234066.asp

For More information on the SharePoint Portal Server MigrateAccount() API:
https://msdn.microsoft.com/library/default.asp?url=/library/en-us/spptsdk/html/mPortalAccountMigManagerMigrateAccount2_SV01187841.asp

For more information on Windows SharePoint Services and SharePoint Portal Server 2003:
https://www.microsoft.com/sharepoint