Mass Updating Profile Object Permissions Via ANT Migration Tool


Hello, and welcome to Another Salesforce Blog!  Here I will be posting solutions to problems that I couldn’t find an answer to in hopes of helping those who find themselves stuck when using the Salesforce platform.

User Story

We have a new object in our organization. We must update our existing profiles to have appropriate permission sets for the object. Some profiles will have Read access, others will have Edit access. We want to automate this because we have dozens of profiles, and we have to make this change in a testing environment, a staging environment, and production.

Background

Unfortunately, updating profile object permission sets is a time consuming manual process. While you are able to edit multiple profiles with list views, you would have to set up the list view for each org that you want to make changes in. This is still a time consuming manual process, and likely to be error prone.

This tutorial assumes that you have the most recent version of Apache ANT installed, instructions for which can be found here. I have my ANT folder installed under my C:\ directory for ease of access.

If you are not familiar with ANT, you can refer to my previous post, Getting Started With ANT: Retrieving Metadata via ANT Migration Tool for Salesforce.

Solution

As in my previous post, we will start by retrieving the profiles using Apache Ant. We will need three files, build.properties, build.xml, and package.xml. The package.xml file will be contained within a folder called retrievepkg. Additionally, we will have a second folder called deploypkg, which we will populate with our changes. I have my files located in the folder C:\ant\UpdateCases for ease of access.

Step One – build the files.

build.properties

Today, we will make our build.properties file a little bit more suited to an enterprise org by creating parameters for two environments, Stage and Production. This will allow us to test our changes in a lower environment before applying them to the full organization. This is useful for automating lengthy deployments. If you are using a developer environment, you can specify sf.username and sf.password here.

Additionally, we will specify a retrieval package, retrievepkg, and a deployment package, deploypkg, which will allow us to easily copy our changes to multiple environments.

# build.properties
#

# Specify the login credentials for the desired Salesforce organization

sf.usernameStage = USERNAME
sf.passwordStage = PASSWORD

sf.usernameProd = USERNAME
sf.passwordProd = PASSWORD

#sf.pkgName = <Insert comma separated package names to be retrieved>

sf.pkgNameRetrieve = retrievepkg
sf.pkgNameDeploy = deploypkg

# Use 'https://login.salesforce.com' for production or developer edition (the default if not specified).
# Use 'https://test.salesforce.com for sandbox.
#sf.serverurl = https://test.salesforce.com

sf.testurl = https://test.salesforce.com
sf.loginurl = https://login.salesforce.com

sf.maxPoll = 20

# If your network requires an HTTP proxy, see http://ant.apache.org/manual/proxy.html for configuration.
#

package.xml

In order to retrieve the metadata for an object as it relates to a profile, we must retrieve the object as well as the profiles. We can specify this in our package.xml file according to the Salesforce documentation. In order to retrieve a standard or custom object, we will name the component using the CustomObject tag, and declare the specific object using the members tag. In order to retrieve a standard or custom field, we would name the component using the CustomField tag, and declare the field using the members tag.

The example given in the Salesforce documentation is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Case.EngineeringReqNumber__c</members>
        <name>CustomField</name>
    </types>
    <types>
        <members>Account</members>
        <name>CustomObject</name>
    </types>
    <version>47.0</version>
</Package>

This example is easily modified. For this tutorial, we will be retrieving the Case object metadata and the Profile metadata to modify CRUDE permissions on the Case object for each profile. Our package.xml file will be:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Case</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>*</members>
        <name>Profile</name>
    </types>
    <version>47.0</version>
</Package>

build.xml

Lastly, we will build our build.xml file. Similar to the last tutorial, we will have a retrieve action, but we will also have a deploy action so that we can deploy our changes. For a step by step walkthrough of each line of code, please see my previous tutorial here. Note that we are specifying the login parameters as sf.usernameStage and sf.passwordStage so that we can test this in a lower environment first. If you are using a developer org, you can use sf.username and sf.password here.

<project name="Another Salesforce Blog" default="test" basedir="." xmlns:sf="antlib:com.salesforce">

    <property file="build.properties"/>
    <property environment="env"/>
    <!-- Setting default value for username, password and session id properties to empty string 
         so unset values are treated as empty. Without this, ant expressions such as ${sf.username}
         will be treated literally.
    -->
    <condition property="sf.usernameStage" value=""> <not> <isset property="sf.usernameStage"/> </not> </condition>
    <condition property="sf.passwordStage" value=""> <not> <isset property="sf.passwordStage"/> </not> </condition>
    <condition property="sf.sessionId" value=""> <not> <isset property="sf.sessionId"/> </not> </condition>
    <taskdef resource="com/salesforce/antlib.xml" uri="antlib:com.salesforce">
        <classpath>
            <pathelement location="C:\ant\ant-salesforce.jar" />        	
        </classpath>
    </taskdef>
    <!-- Retrieve Profiles  -->
    <target name="retrieveProfiles">
      <mkdir dir="retrieveProfiles"/>
      <!-- Retrieve the contents into another directory -->
      <sf:retrieve username="${sf.usernameStage}"
                   password="${sf.passwordStage}"
                   sessionId="${sf.sessionId}"
                   serverurl="${sf.loginurl}"
                   maxPoll="${sf.maxPoll}"
                   retrieveTarget="retrieveProfiles"
                   unpackaged="retrievepkg/package.xml"/>
    </target>

    <!-- Deploy Profiles  -->
    <target name="deployProfiles">
      <!-- Upload the contents of the specified package -->
      <sf:deploy username="${sf.usernameStage}"
                 password="${sf.passwordStage}"
                 sessionId="${sf.sessionId}"
                 serverurl="${sf.loginurl}"
                 maxPoll="${sf.maxPoll}"
                 deployRoot="${sf.pkgNameDeploy}"
                 singlePackage="true"
                 rollbackOnError="true"/>
    </target>
</project>

Step two – retrieve metadata.

Next, we will retrieve the metadata for our Profiles and the Case object.

We do this by opening a command prompt, navigating to the folder our build.xml file is contained in, and calling our action in ANT using the command ant retrieveProfiles.

Command Line Interface showing a successful retrieve request.

We will now have a directory, retrieveProfiles, that is populated with the metadata from our organization’s profiles and the Case object, as well as a copy of our package.xml:

It is important to note that if there are special characters in any of your organization’s profile names, they will need to be manually updated in your filenames before they can be deployed back into Salesforce.

Step three – modify profile metadata.

Next, we must modify the Profile metadata to update the object permissions. We will not be modifying the Case object metadata.

Best practice dictates that we keep a copy of our original data in case we mess anything up, so what we are going to do is copy the contents of our retrieveProfiles folder into our deploypkg folder. That way, our originals are in the retrieveProfiles folder, and the files we are modifying are in the deploypkg folder.

Now, our deploypkg folder should look like this:

We need all three pieces in order to modify our CRUDE permissions for our profiles.

When we open up our profiles folder, we see a list of .profile files, which look like this when you open them up:

Most of them go on for about 800 lines of code (or more, depending on how many objects you pulled). In these files are all of the User Permissions in our organization, each of the Field permissions for each object, and the Object Permissions for each object specified.

The nice thing about deploying with metadata is that the only changes that will occur is what we specify, so we can delete everything we don’t want to change. The easiest way to do this is to search for objectPermissions, delete everything before the section we want using Ctrl+Shift+Home while deselecting the first three lines, and delete everything after using Ctrl+Shift+End while deselecting the last line.

After removing the unnecessary metadata, our metadata is down to a much more readable 13 lines:

You’ll notice that the name of the profile is not specified in the metadata, just the file name, so if you have a number of profiles that require the same object settings, you can modify one profile and either Save As the other profiles or copy paste into the .profile files. It is important, however, to note that the custom tags denoting whether a profile is Standard or Custom to the org must be included, so I prefer to copy paste.

Say I want to make the Case object read only for all profiles. I would update the allowCreate, allowDelete, allowEdit, and modifyAllRecords permissions to false, and then update the allowRead and viewAllRecords permissions to true:

<?xml version="1.0" encoding="UTF-8"?>
<Profile xmlns="http://soap.sforce.com/2006/04/metadata">
    <custom>false</custom>
    <objectPermissions>
        <allowCreate>false</allowCreate>
        <allowDelete>false</allowDelete>
        <allowEdit>false</allowEdit>
        <allowRead>true</allowRead>
        <modifyAllRecords>false</modifyAllRecords>
        <object>Case</object>
        <viewAllRecords>true</viewAllRecords>
    </objectPermissions>
</Profile>

I would copy the objectPermissions tags into all of the profiles I wanted to modify and save each file, being careful to leave the custom tags for Standard profiles set to false, and for Custom profiles set to true.

Step four – deploy profile metadata.

After all of our profiles are modified, we will deploy our updated metadata.

Open a command line window, navigate to the directory containing your build.xml file, and issue the command ant deployProfiles.

Command Line Interface showing a successful deployment.

(Optional) Step five – roll back changes.

In case you need to roll back your changes, whether due to human error or due to locking out users during a deployment, we can once again copy the contents of our retrieveProfile folder into our deploypkg folder.

Again, open a command line window, navigate to the directory containing your build.xml file, and issue the command ant deployProfiles.

Command Line Interface showing a successful deployment.

Post-mortem

There you have it. A way to automate updating Object Permissions for multiple Profiles. It takes a minute to set up, but once you’ve done it, you can reuse and easily modify your data for multiple deployments across multiple staging, testing, and production environments.

Thanks for reading, let me know if you have any comments or questions!

Evelyn Maguire

Another Salesforce Blog

One-Time
Monthly
Yearly

Make a one-time donation

Make a monthly donation

Make a yearly donation

Choose an amount

$5.00
$15.00
$50.00
$5.00
$15.00
$50.00
$5.00
$15.00
$50.00

Or enter a custom amount

$

Help keep Another Salesforce Blog on the internet by donating today!

Your contribution is appreciated.

Your contribution is appreciated.

DonateDonate monthlyDonate yearly

3 responses to “Mass Updating Profile Object Permissions Via ANT Migration Tool”

  1. Thank you very much for this tutorial, it is really helpful for those like me that are starting to use ANT.

    I have an small question, if we deploy only the permissions for the case object, and the profiles i the destination org have permissions for also (let’s say) Account, Opportunity and others, would this remove their permissions on the Account and Opportunity objects because we are not mentioning these two objects in the package as well? or Salesforce will keep all the existing permissions and only add this one of the Case object?

    Thank you very much!, you’re exellent at explaining this things.

    • Hello! As long as the permissions are not specified (eg, ONLY the case permissions are deployed, no others), the permissions for other objects will not be affected. I hope this helps!

Leave a Reply

Discover more from Another Salesforce Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading