30 April 2013

How to Test & Migrate Profiles and Permission Sets Using Workbench

I spend a fair amount of time working with customers and partners to understand how to migrate profiles and permission sets from one environment to another.

Migrating metadata between sandbox and production orgs enables customers to create and test org changes without impacting production users. Independent software vendors (ISVs) create customizations like profile settings and permission sets that can be packaged from a developer edition org and distributed to subscriber's sandbox or production orgs.

The good news here is that there is a powerful metadata API (mdAPI) that serves as the backbone for helping you manage these kinds of migration.

The not so good news here is that this API, while powerful, has a lot of flexibility built into it resulting in some behaviors that may seem confusing, especially when it is consumed by different applications.

There are many applications that use the mdAPI to migrate metadata from one environment to another:

  1. Changes sets enables admins to declaratively migrate metadata from sandbox to production and vice-versa. 
  2. The Force.com (ANT) migration tool enables IT and developers to programmatic migrate metadata from sandbox to production and vice-versa.
  3. Force.com IDE enables developers to create and migrate metadata declaratively
  4. Packaging enables ISVs to create custom metadata in a Developer Edition org and allow customer admins to install it in a their sandbox or production org.

Because there is always a chance that any one of these tools will insert their own pre-defiend set of assumptions, I will often test any migration use case using a simple flow that eliminates any specialized behaviors created by an application, allowing me to focus on what is possible using the mdAPI that all of these applications use. This ensures that I can eliminate some of the confusion that may result in migrating my metadata using one of these applications.

Below are some simple steps to try out pretty much any use case that may come up when migrating either profiles or permission sets. If you have any questions why something is behaving the way it is, I would highly recommend trying out a retrieve and deploy using the mdAPI directly using this technique. Once you know how it works with the mdAPI, you can troubleshoot the behavior you may be experiencing in any one of the client applications I mentioned above.


How to retrieve a profile or permission set using the mdAPI:


1. Create your package.xml that will define the metadata types you want to retrieve in a payload and save it somewhere on your computer. I typically start with the following XML that I save in an .xml file. Depending on the use case I'm working on, I hide the metadata I don't want to retrieve yet behind HTML comment tags (e.g. <!-- everything between these tags are hidden -->). For instance, when I want to retrieve object and field permissions, I'll move the CustomObject type below the commented XML with the Profile and PermissionSet types. The following package.xml example will only retrieve the bare minimum Profile and PermissionSet metadata:

<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<!-- **************************  
    <types>
    <members>*</members>
    <name>CustomObject</name>
    </types> 
    <types>
        <members>*</members>
        <name>Layout</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomApplication</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomTab</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexPage</name>
    </types> 
    <types>
        <members>*</members>
        <name>ApexClass</name>
    </types>
************************** -->  
    <types>
    <members>PermissionSetName</members>
    <name>PermissionSet</name>
    </types>     
    <types>
    <members>ProfileName</members>
    <name>Profile</name>
    </types>
    <version>27.0</version>
</Package>

2. Log in to your source org that you want to retrieve metadata from.
3. I like to use the workbench tool created by Ryan Brainard by entering the following URL into my browser: https://workbench.developerforce.com/login.php. This tool allows you to focus on the core metadata API.

4. Navigate to migration > Retrieve.
5. Select the 'Choose File' button and navigate in your file system to the package.xml file you created in the first step.
6. Select the 'Single Package' checkbox.
7. Select 'Next' button.

8. Select 'Retrieve' button.

9. After the retrieval is finished, right click on the 'Download ZIP File' link to save the zip file with your metadata.

10. Unzip the ZIP file and start working with each individual metadata file. When you open a .profile file, you can now make changes to specific permissions like loginHours or loginIpRanges. For instance, I might change a loginHours start or end time to reflect a new set of hours when users with this particular profile can login and work.

How to deploy a profile or permission set using the mdAPI:


1. After making changes to metadata in the .profile or .permissionset files, I'm ready to zip and deploy changes to my target org.
2. You will need to zip the directory that you downloaded when you retrieved your metadata. It's important to zip the package.xml file in this directory since it provides the basic set of instructions used in the deployment. Because I use Mac OSX, I typically use the terminal app to zip up my contents rather than rely on the operating system's native compression functionality. One reason I don't zip using the native OSX functionality is that the package.xml file, which is necessary for the deployment, doesn't always register properly unless I use the terminal to zip it with the rest of the metadata files and directories. Open your terminal or command shell application and change the directory (e.g. cd /Users/me/mdapi) where your metadata directory structure exists.

3. Zip the directory using the following terminal command: "zip -r d2.zip r2" where r2 is the source directory with metadata, d2.zip is the target zip file, and -r will ensure that all subdirectories will also be zipped as well.
4. Log in to your target org that you where you want to deploy metadata.
5. Use the workbench tool by entering the following URL in the browser: https://workbench.developerforce.com/login.php
6. Navigate to migration > Deploy.
7. Select 'Choose File' button and find the ZIP file you just compressed.
8. Select the 'Allow Missing Files' checkbox.
9. Select the 'Next' button.

10. Select the 'Deploy' button.

11. When the deployment is finished, you can expand any of the nodes to find and resolve any errors or check your target org to ensure that the deployment was successful.

This tutorial is really only meant to enable testing profile and permission set migration use cases. It can be very powerful when troubleshooting different behaviors you may be experiencing and can even be used to manage your migrations without relying on tools like the Force.com Migration Tool (ANT) or Change Sets.

3 comments:

  1. Thank you for this useful post. I'm trying to export a profile that pertains to an ISV installed package so that I can migrate it from a Salesforce Platform License to a Salesforce License. The documentation on creating a manifest package file for this case is very terse and hard to follow (http://www.salesforce.com/us/developer/docs/api_meta/index_Left.htm#StartTopic=Content/manifest_samples.htm). I've tried different tweaks to the package.xml file, but I'm not able to export the permissions on the objects that belong to this installed package. Any tips on how I can move an existing profile from one license type to another? I actually started out with a more ambitious goal of taking the exported profile tweaking it to look like a permission set and then importing it into the new license type, but even the first step of migrating the profile as-is is turning out to be more difficult than expected.

    ReplyDelete
    Replies
    1. Hi Arvind,

      This issue comes up quite a bit. The MdAPI is probably the best way to handle it, but it's not as simple as just changing a license element in a profile file. You have to first create an empty shell of a profile in your target org using the license type that you want to migrate to. Then you can retrieve the original licensed profile or permission set and start migrating sections of permissions into that target shell.

      The reason why this isn't simple is that a license defines the max value or boundary of what is allowable in a profile or permission set. Simply trying to change the license element doesn't take into consideration that there may be a needle in the haystack (e.g. one permission that is *not* allowed on the new license) that you need to resolve.

      Migrating by chunks of permissions will help you to identify that needle and build the migrated profile or permission set a section at a time. Hope this helps.

      Delete
  2. If it still valid? I am following all the steps, but when I download zipped file, it contains package.xml file which has same info as in my initial package.xml file.

    ReplyDelete

Note: Only a member of this blog may post a comment.