Share
Embed
[dreamOle26] How we handle Profiles and User Access deployment
You’ve heard that you should ditch Profiles and move to Permission Set? Great. And then you start doing and you discover that all these nice theoretical blog articles only cover a part of a real life implementation. How to actually migrate? Retrieve and deploy what’s still only on Profiles? Create new Profiles with just the needed rights ? Clean Profiles from access that are now on Permission Set? Come and see how we handle these.
Fabien Taillon
March 27, 2026
Transcript
28 slides
-
Fabien Taillon Paris Developer Group leader French Touch Dreamin team
https://www.salesforce.com/trailblazer/fabien https://www.fabientaillon.com https://www.texei.com /in/fabientaillon @FabienTaillon Partner & CTO Texeï -
What do we want ? A reliable solution for managing
and deploying user access rights -
Salesforce recommendations • Move away from Profiles • Use Permission
Sets and Permission Set Groups -
Permission Set + Profiles Permission Sets are working fine BUT
Profiles are still needed - Page Layout Assignments - Default Record Types - Default Custom App… And no one tells you how to handle that part -
We want to be clear that we won’t be making
any improvements to profiles going forward. All of our efforts will be focused on permission sets, permission set groups, and related features Cheryl Feldman Senior Director of Product Management at Salesforce https://admin.salesforce.com/blog/2023/permissions-updates-learn-moar-spring-23 -
Profile Retrieve Retrieving a Profile is an inconsistent operation •
Depends on what you retrieve at the same time • Don’t behave the same between orgs with/without Source Tracking Without Source Tracking - Only package.xml content With Source Tracking - package.xml content - any metadata tracked by Source Tracking (SourceMember table) -
Profile Retrieve <?xml version="1.0" encoding="UTF-8"?> <Package xmlns="http://soap.sforce.com/2006/04/metadata"> <types> <members>Account.MyFirstField__c</members> <name>CustomField</name>
</types> <types> <members>My Profile</members> <name>Profile</name> </types> <version>66.0</version> </Package> <?xml version="1.0" encoding="UTF-8"?> <Profile xmlns="http://soap.sforce.com/2006/04/metadata"> <custom>true</custom> <fieldPermissions> <editable>true</editable> <field>Account.MyFirstField__c</field> <readable>true</readable> </fieldPermissions> </Profile> package.xml retrieved profile -
Profile Retrieve <?xml version="1.0" encoding="UTF-8"?> <Package xmlns="http://soap.sforce.com/2006/04/metadata"> <types> <members>Account.MySecondField__c</members> <name>CustomField</name>
</types> <types> <members>My Profile</members> <name>Profile</name> </types> <version>66.0</version> </Package> <?xml version="1.0" encoding="UTF-8"?> <Profile xmlns="http://soap.sforce.com/2006/04/metadata"> <custom>true</custom> <fieldPermissions> <editable>true</editable> <field>Account.MySecondField__c</field> <readable>true</readable> </fieldPermissions> </Profile> package.xml retrieved profile -
Profile Retrieve <?xml version="1.0" encoding="UTF-8"?> <Package xmlns="http://soap.sforce.com/2006/04/metadata"> <types> <members>Account.MySecondField__c</members> <name>CustomField</name>
</types> <types> <members>My Profile</members> <name>Profile</name> </types> <version>66.0</version> </Package> <?xml version="1.0" encoding="UTF-8"?> <Profile xmlns="http://soap.sforce.com/2006/04/metadata"> <custom>true</custom> <fieldPermissions> <editable>true</editable> <field>Account.MySecondField__c</field> <readable>true</readable> </fieldPermissions> </Profile> package.xml retrieved profile • MyFirstField__c is not there anymore • Different behavior for Source Tracking -
Profile Deployment - Creation Deploying an empty Profile on creation
gives a few extra access rights <?xml version="1.0" encoding="UTF-8"?> <Profile xmlns="http://soap.sforce.com/2006/04/metadata"> <custom>true</custom> <userLicense>Salesforce</userLicense> <userPermissions> <enabled>true</enabled> <name>ActivitiesAccess</name> </userPermissions> <userPermissions> <enabled>true</enabled> <name>AllowViewKnowledge</name> </userPermissions> <userPermissions> <enabled>true</enabled> <name>ChatterInternalUser</name> </userPermissions> <userPermissions> <enabled>true</enabled> <name>LightningConsoleAllowedForUser</name> </userPermissions> <userPermissions> <enabled>true</enabled> <name>ViewHelpLink</name> </userPermissions> </Profile> Still, much much better than before cf. https://texei.com/conseils/create-empty-profiles-automatically-to-fearlessly-deploy-all-your-access-rights-in-salesforce/ -
Profile Deployment - Update <?xml version="1.0" encoding="UTF-8"?> <Profile xmlns="http://soap.sforce.com/2006/04/metadata"> <custom>true</custom>
<userLicense>Salesforce</userLicense> … <userPermissions> <enabled>true</enabled> <name>CustomizeApplication</name> </userPermissions> … </Profile> <?xml version="1.0" encoding="UTF-8"?> <Profile xmlns="http://soap.sforce.com/2006/04/metadata"> <custom>true</custom> <userLicense>Salesforce</userLicense> … … </Profile> Removing a permission in the UI removes it in the Metadata -
Profile Deployment - Update <?xml version="1.0" encoding="UTF-8"?> <Profile xmlns="http://soap.sforce.com/2006/04/metadata"> <custom>true</custom>
<userLicense>Salesforce</userLicense> … <userPermissions> <enabled>false</enabled> <name>CustomizeApplication</name> </userPermissions> … </Profile> Deploying as is doesn’t remove permission in org • just skips it • should be explicitly set to false (not done by the API on retrieve) • permission sets are working correctly to remove permissions, use them instead ! -
Theory is simple: Use Permission Sets and Permission Set Groups
Keep only on Profiles permissions that can’t be on a Permission Set Then what ? -
Then what ? 1. Even without doing anything, knowing how
it works may help you to be careful 2. Move Profile permissions to Permission Sets (as some things that don’t work on Profiles do work on Permission Sets) 3. Then fix the underlying issues with extra tooling Our take on the tooling: Texeï SFDX Plugin, free, open source https://github.com/texei Documentation: https://texei.github.io/texei-sfdx-plugin/ (thank you Nicolas Vuillamy 💙) -
Migration to Permission Set • Migrating Profile to Permission Set
• Use User Access Policy to assign Profile - Permission Set 1-1 ◦ Doesn’t cover removing old permset • Emptying Profile • Refreshing sandboxes Moving to Permission Sets could require a whole refactoring, have a look to Louise Lockie’s session -
Migration to Permission Set Migrating Profile to Permission Set •
Some existing solutions, good with some flaws • Not open source, so nothing you can do about it → sf texei profile convert --profile-name “Sales User” -
Migration to Permission Set Use User Access Policy to assign
Profile - Permission Set 1-1 -
Migration to Permission Set Emptying Profile → sf texei profile
empty --profile-name “Sales User” --target-org “My Org” Will remove from Profile all Permissions that could be on a Profile. Still Beta, because permissions need to be set to false, and no API is returning all available permissions (or I couldn’t find it) -
Skinny Profiles Basically: A Profile containing only what can’t be
on a Permission Set 3 commands to help: Creating an empty Profile on a target org: → sf texei skinnyprofile create Retrieving a Profile, based on local’s project content: → sf texei skinnyprofile retrieve Additional check for CI: → sf texei skinnyprofile check -
Resources https://admin.salesforce.com/blog/2023/permissions-updates- learn-moar-spring-23 https://github.com/texei Applying a Permission Set-Led Security Model:
https://drive.google.com/file/d/1XRjHPIUUzKkePSsFklbrZqlZ0F _H5OG5/view