07 May 2013

Dude, where's my permission?


When working with profiles and permission sets in the Metadata API (MdAPI) have you ever wondered why a permission didn't migrate as expected? Maybe this happened when you were using a client app built on top of the MdAPI—like the Force.com IDE, Force.com Migration Tool, or Change Sets—instead of using the MdAPI directly, but regardless, you thought the permission would be there in the target organization and it wasn't.

This issue comes up quite a bit. Our documentation explains what is and isn't supported in the MdAPI, but it doesn't account for what happens when you try migrating permissions and settings. And regardless of how it happened, you're left confused and with the time-consuming task of manually configuring permissions or settings in your target organization.

There is some good and some bad news when working with any of the client apps that are built on top of the MdAPI. The good news is that they typically handle the creation of any necessary MdAPI elements so you don't have to worry about missing an XML element or a metadata entry. The bad news is that they can hide the MdAPI implementation. However, you can access the MdAPI directly with the Workbench tool, which helps to eliminate much of the mystery.

Here are some basic rules of thumb when migrating permissions using Workbench or any other tool:

1. Focus on the permission rather than the container.

Working with profiles and permission sets is unlike any other metadata type in the MdAPI. First of all, profiles and permission sets may consist of up to 12 different sets of overlapping permissions and settings—some of which are only found in profiles, some only in permission sets, and some in both.

Rather than thinking of migrating permissions as two metadata objects, profiles and permission sets, think of it as 12 different metadata objects. For example, think about migrating user permissions or tab settings rather than the standard user profile or the API-enabled permission set.

The permissions or settings that can be migrated include:
1.  overview information
2.  user permissions
3.  object permissions
4.  field permissions
5.  page layout access
6.  record type access
7.  custom tabs access
8.  custom apps access (tabset)
9.  apex classes access
10. apex pages (Visualforce) access
11. IP ranges
12. login hours

2.  Each permission or setting may have individualized behaviors when migrating.

In other words, expect the unexpected. In general these behaviors are coupled into similar settings.

As a general rule, behaviors can be grouped:

1.  record types are similar and dependent on page layouts
2.  object permissions are similar and dependent on field permissions
3.  IP ranges are similar to login hours
4.  apex access, Visualforce page access, and user permissions are similar
5.  app (tabset) access and tab settings are similar

3. When retrieving permissions (such as in an Inbound Change Set), in some cases only ‘enabled’ permissions are retrieved, and in other cases *both* ‘enabled’ and ‘disabled’ permissions are retrieved.

This is important because retrieving disabled permissions provide some discoverability with the definitions but it also creates additional metadata for you to keep track of when deploying.

Both enabled and disabled permissions are retrieved for:

1.  user permissions
2.  object permissions (when at least read access is enabled)
3.  field permissions
4.  assigned apps
5.  apex class access
6.  Visualforce page access

Only enabled permissions are retrieved for:

1.  IP ranges
2.  login hours
3.  tab settings
4.  record type visibilities
5.  page layout assignments

4. Including only profile or permission sets in the package.xml retrieves standard permissions only.

Example of package.xml that includes only a permission set and profile:

     <types>
       <members>Basic</members>
       <name>Profile</name>
    </types>
    <types>
       <members>Simple</members>
       <name>PermissionSet</name>
    </types>

This retrieves the following permissions every time regardless of what else is defined in package.xml:

1.     user permissions (Permission Set Only)
2.     IP ranges and login hours (Profile Only)

5. To migrate a permission that’s tied to a custom piece of metadata (such as a custom object, custom field, or apex class) include the component in the payload (package.xml) along with the profile or permission sets.

Example: to migrate custom object (CRUD) permissions, you must include CustomObject in package.xml and by using the wildcard (*), you will receive all custom objects in the payload.

    <types>
        <members>*</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>Basic</members>
        <name>Profile</name>
    </types>

6. Including custom components in your package.xml, the retrieval will include all the metadata, plus permissions or settings, you need.

You will be able to retrieve:

  • all object permissions with at least read access enabled
  • all field permissions
  • some record type visibilities
  • some tab visibilities  

7. Some profile settings won't be retrieved unless you include additional metadata in your package.xml.

1.  To get all tab visibilities instead of just some, you need to include the CustomTab type
2.  To get all record type visibilities including their layout mappings, you need to include the Layout type
For example, the following package.xml ties everything to CustomObject:

    <types>
         <members>Basic</members>
         <name>Profile</name>
    </types>
    <types>
         <members>Account</members>
         <members>Foo__c</members>
         <name>CustomObject</name>
    </types>  
    <types>
        <members>*</members>
        <name>Layout</name>
    </types>
    <types>
        <members>Foo__c</members>
        <name>CustomTab</name>
    </types>

8. To migrate a permission tied to standard schema metadata (such as Account object, Account.Number field), you still need to include CustomObject type in your payload (package.xml) but you need to explicitly specify the standard object as a member. The wild card (*) on CustomObject does not include standard objects.

For example, to migrate standard Account object (CRUD) permissions, include a standard object explicitly defined as a member of CustomObject in package.xml.

As a result, to get standard object permissions and settings, you will need the following package.xml:

         <types>
        <members>Account</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>Basic</members>
        <name>Profile</name>
    </types>

9. Permissions may be dependent on other permissions or your deployment will fail with an error.

Object permissions may:

  • require other permissions within the same object (for example, edit requires read).
  • require permissions across objects (for example, read on Assets requires read on Accounts).
  • be required by user permissions (for example, Edit Case Comments requires edit on Cases). 

10. It's possible to use the MdAPI directly to retrieve and deploy metadata.

You can change metadata entries with more precision by changing actual MdAPI element values (for example, <enabled>true</enabled>) or by omitting elements from deployment.

You may encounter different behaviors depending on what you, or a MdAPI enabled tool like Force.com IDE, omit or leave out from your payload (package.xml).

11. Unlike retrieval, deployment of permissions should only require that the payload (package.xml) has both the profile and/or permission sets defined and the actual permission values from the .profile and/or .permissionset files in the payload.

To deploy explicitly enabled permissions, the actual custom metadata doesn't need to be in the zipped payload, nor the custom metadata defined in the package.xml. This may seem strange since you must include a custom object in package.xml when retrieving object permissions, but not when deploying them.

The primary exception to this rule is if the custom metadata doesn't already exist in the target organization. For example, if you try to migrate object permissions on the Foo__c object and the Foo__c object doesn't exist in your target organization, your deployment will fail.

12. If you omit an entire entry, Salesforce ignores that particular entry during deployment and retains the original value of that entry in the target organization.

For example, if you omit

   <userPermissions>
      <enabled>false</enabled>
      <name>ApiEnabled</name>
   </userPermissions>

from a .permissionset file, the deployment ignores the API Enabled permission and retains whatever the original value is in the target organization.

13. If you omit all of the permissions or settings but not the header (where header is defined as the permission metadata type without any permission values), we disable that particular permission or setting, overwriting the value in the target organization.

For example, when if you omit

         <enabled>false</enabled>

from

     <userPermissions>
     <enabled>false</enabled>
     <name>ApiEnabled</name>
  </userPermissions>

the deployment assumes that the API Enabled permission should be revoked or set to false in the target organization.

14. If more than one type of permission is contained (for example, field permissions have both read and edit), when you omit any one of the permissions or settings but leave others including the permission header, then the deployment disables that particular permission or setting.

For example, if you omit

        <editable>true</editable>
from

   <fieldPermissions>
      <editable>true</editable>
      <readable>true</readable>
      <field>Foo__c.Bar__c</field>
   </fieldPermissions>

the deployment assumes the edit field permission should be revoked or set to false in the target organization.

The exception to this is if it depends on another permission that is included (for example, omit read but leave edit enabled).

15. There are some notable exceptions to these deployment rules.


  • Defaults: exist in <applicationVisibilities> and <recordTypeVisibilities> and are ignored when omitted unless a different application or record type becomes default in the same deployment.
  • <tabVisibilities>: are ignored during deployment and the original value is retained in the target organization if you omit the <visibility> element.
  • <recordTypeVisibilities>: are ignored during deployment and the original value is retained in the target organization if you omit the <visible> element where the record type is the default.
  • Omission of the entire <recordTypeVisibilities> entry where <layoutAssignments> are included in the .profile file during deployment results in the <layoutAssignments> overwriting the target values but the <recordTypeVisibilities> entry being ignored on the target. 


As this blog posting illustrates, migrating permissions using the MdAPI isn't as straightforward as migrating an object or a field. Following these guidelines will hopefully help clarify why a permission may or may not have migrated successfully.

21 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Really interesting, thanks Adam !

    ReplyDelete
    Replies
    1. Thanks for visiting my blog! Please let me know if there are other topics or areas of interest you'd like to see postings for!

      Delete
  3. Hi Adam

    Very helpful post. Still have not figured out how to deploy Tab Permissions for our new HRIS App, which is built on force.com, since I cant hit anything that references the managed packages.

    I managed to migrate the field permissions and object permissions as a data job, but cant seem to do so for Tab Settings. Seems like I might need to go the Ant route, but not ready to dive off that cliff yet.

    ReplyDelete
    Replies
    1. Hi Gorav - I'm glad you found the post useful! I'm curious your use case - are you just trying to refer to components from another managed package or is there something specific about the tabs you're trying to migrate?

      Delete
    2. Thanks Adam,

      We are rolling out FinancialForce HCM, and have configured it in a Sandbox. All permissions are configured in 3 (custom, not managed) permission sets: Admin, Manager, and Employee.

      I migrated the 3 perm sets to production via change sets, but nothing really came over b/c I cant include the objects or fields in the change sets, since they are part of the managed package, and without including the managed objects none of the object, field or tab permissions for those objects were included.

      Thus began the long and winding road that led me to your door.

      I discovered some interesting things along the way. I managed to extract and insert field and object permissions using data loader. Therefore, I was only left w/ Tab Visibility to migrate. So I'm really trying to figure out how we will manage future development without manually re-configuring the permission sets in production, but focused on Tab visibility settings in the perm set as I have an acceptable solution for the other components.

      I tried the mdAPI and was able to retrieve Object, Field, and Tab settings in the permission set for a single object by explicitly including the object, with the namespace prefix, in the package.xml file. I was not able to deploy this package, as I get an error regarding fields not existing, even though the fields are included in the zip file.

      Hope that helps provide context. I feel like there must be a solution, otherwise migration is a very error-prone process, which is not what you want in any system, let alone a HR system with highly sensitive data!

      Any and all help is greatly appreciated!

      Delete
    3. Hi Adam

      Just wanted to drop a quick update - in browsing elsewhere on your blog, I realized there was an option when deploying metadata for "Allow Missing Files"

      I finally tested that option, and it turns out that it helps quite a bit. So I've managed to successfully deploy field permission and object permissions, and I believe I can get the Tab permissions w/ some additional tinkering.

      As this is a managed package, it requires me to provide the full API name including the namespace prefix of every object. Wildcards wont work. But, that is still a lot easier (will need to look for a way to easily extract that info and build the package files, etc), and its not a manual, error-prong process.

      Delete
    4. Yeah - it's interesting how much of a difference it makes when you check that option. Glad it worked out!!

      Delete
  4. Hi Adam Torman,

    Using metadata api i created field .How to give created field related pagelayout visible permission in salesforce through coding?

    help me...........

    ReplyDelete
    Replies
    1. Sorry for the delayed response. Can you provide additional information about your request? Thanks!

      Delete
  5. Hi Adam,
    When deploying new Profiles from one distinct Org to another (i.e. two Production Orgs), I've noticed that if I don't explicitly describe all FLS some Fields (both standard & custom) default to readable/editable and others are not accessible. In the UI one is forced to choose an existing Profile to serve as the basis for a new Profile, is there some default behavior for assigning new Profiles' FLS created via the Migration Tool and mdAPI?

    For my test I used a very limited sample .profile as can be seen below. The relevance is to understand how FLS for a field unique to the target org will be configured if the deploy from the source org does not define its FLS in a .profile.

    Thanks


    true
    Account.AccountSource
    true


    false
    Account.Admissions_Counselor__c
    false


    false
    ApiEnabled


    true
    ViewSetup

    ReplyDelete
    Replies
    1. (looks like the XML was stripped from my comment). Those are two (FieldPermissions) and (UserPermissions) entries.

      Delete
  6. Thanks Adam for the nice Post. really helpful.
    we were facing issue while deploying only permission sets - ofcourse this permission set was having permissions for some custom objects. in Package.xml we didnt include any of those custom objects - since the same objects were already in our destination Org. when we deployed permission sets using package.xml we got no errors, at the same time the permissions for cutom objects were not enabled as expected. later we included the custom objects, classes, and VF pages in the package.xml while deploying permission sets ... this went fine.

    Thanks

    ReplyDelete
    Replies
    1. Thanks @Thejasvi N for the comment. Not surprised and glad it was resolved adding the rest of the definitions into the package.xml.

      Delete
  7. Thanks Adam for this post. While working on a project where we needed to copy/deploy the permission set, I created a Java Utility to copy/deploy the permissions access settings for Apex Classes, Apex Pages, ObjectPermissions, and FieldPermissions using just the DML operation on ObjectPermissions, FieldPermissions, and SetupEntityAccess which is possible for the Permission Sets.

    Here is the code for anyone that need to use: https://github.com/thaka/SFDC-CopyPermissionSet

    For the Profiles related permissions and access settings the DML are not allowed on the ObjectPermissions, FieldPermissions, and SetupEntityAccess. The only way is to use the Metadata APIs. Working to create the Java Utility and open source it.

    Taulant

    ReplyDelete
    Replies
    1. Taulant - thanks for sharing! This is an awesome utility! I dig it!! Everyone in the community should check it out! I just shared it with the Admin team responsible for permission sets. Thanks!!

      Delete
  8. Adam, I read this post a few times now but am still confused. What items on profiles and permission sets don't deploy with MdAPI? Is permission set deployment as equally challenging as profile?

    ReplyDelete
    Replies
    1. Hi Jo,

      It's been a while since I played with profiles in the MdAPI so my information may be a bit out of date. But if I remember, some add-ons like org wide email addresses weren't exposed and there may be some limitations around standard metadata like required fields where we don't add FLS rows.

      Delete
  9. Hi Adam , how to get administrative permissions for profile and permission set

    ReplyDelete
    Replies
    1. You just need Manage Profiles and Permission Sets user permission granted.

      Delete
  10. I am dealing with this right now and pretty new to Ant deployments. How can I stop Ant from building the entire object when I need to add it to a package for a permission?

    ReplyDelete

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