I was looking for a way to move Privacy Center policies between Salesforce environments so I started looking at custom objects but nothing there really so it couldn’t be data. Next I looked at the installed packages in the org and there were 3 pieces of custom metadata listed. Maybe policies are custom metadata?
Next I created a SalesforceDX project and did a sfdx force:source:retrieve from the Privacy Center org and boy was there a lot of custom metadata records. So my best guess is that the policies are actually custom metadata meaning it could be deployed from org to org with the metadata API. Yay!
The records are split across 3 custom metadata types:
In order for Salesforce Security Center to access a child tenant and its data you need to have a user with the correct permissions in each child tenant. Many customers would want the users in the child tenants to have the fewest number of permissions possible. Based on my investigation the user in the child tenant needs to have the following permissions as a minimum:
Manage Security Center
View Roles and Role Hierarchy
View Setup and Configuration
I have successfully enabled these permissions for a new user by creating a new user in the child tenant using the “Salesforce” license and the “Minimum Access – Salesforce” profile. I then created a permission set with the above mentioned permissions and assigned that permission set to the user I’m going to use to access the child tenant from the parent tenant.
I was then able to authenticate as that user when connecting to the child tenant from the parent tenant.
I was doing some work with packaging on Salesforce and used the dreamhouse-lwc repo as a foundation. When I was building package versions the Apex unit tests were failing as the SOQL queries is using WITH SECURITY_ENFORCED and the user running the queries did not have the right access. The solution was to update the unit test to create a user and assign the dreamhouse Permission Set but to create a user you need to set a Profile. Which one to pick? Easy – use the “Standard User” Profile which is easily accessible by SOQL:
SELECT Id FROM Profile WHERE Name='Standard User' LIMIT 1
This code failed however as the Profile couldn’t be found. It turned out to be because the scratch org created was in Danish so the Profile is called “Standard Bruger” instead. This could be solved by setting the language of the scratch org by using the language key in config/project-scratch-def.json but the repo maintainers didn’t want that. A more flexible and still language agnostic way was to query more intelligently for the Profile. The below SOQL query achieves the same result as above but without setting the org language.
SELECT Name, Id FROM Profile WHERE UserType = 'Standard' AND PermissionsPrivacyDataAccess = false AND PermissionsSubmitMacrosAllowed = true AND PermissionsMassInlineEdit = true LIMIT 1
All my scratch orgs gets created with the user-language set to Danish which is a good guess but I cannot find anything in Setup that way. No Dev Hub setting I’ve found can change that but setting the language in the scratch org definition file will. That’s easily done from the terminal with jq.
By default when you create an Apex trigger in Salesforce to trigger on a Platform Event it will run as the Automated Process system user. This can cause problems when you want to access data or use features that require a “real” user like Chatter. Starting with Spring 21 this has been made a lot better as you can specify the running user and maximum batch size among other things. It’s done through the PlatformEventSubscriberConfig metadata element (or through the Tooling API) and you can read more in the Spring 21 release notes.
The actual configuration is easy enough but I did find one caveat in that it didn’t take effect when deploying a PlatformEventSubscriberConfig record for an existing trigger i.e. a trigger already in the org. The metadata deployed just fine but it didn’t take effect. To fix it I had to delete the trigger from the org and the redeploy the trigger and the PlatformEventSubscriberConfig configuration at the same time.
Based on a number of comments I’ve added a video walkthru for the Azure Client Credentials Auth. Provider I have available on Github. The video is hosted on Youtube and besides a description of the elements used shows pushing the source to Salesforce, configuring the Auth. Provider in Salesforce as well as configuring the App Registration on Microsoft Azure.
So this is finally happening. When I write finally it’s because I am sure this will lead to removing quite a lot of code in the Salesforce core application. With Summer 21 we are deprecating a bunch of API versions (see the release notes for more info) which means we will finally remove support for the API versions in Summer 22.
Below are the API versions that will be deprecated and ultimately removed:
When doing integrations from Salesforce you sometimes need to do this using single identity instead as in the context of the current user. Salesforce supports both through Named Credentials i.e. both working as the current user or as a Named Principal. Through the Named Credentials and Auth. Provider concepts from Salesforce you can setup a connection between Salesforce and an OAuth 2.0 enabled endpoint such as Microsoft Azure i.e. if needing the access the Microsoft Graph API. This can however be an issue as the target system (i.e. Microsoft Azure in this case) may not use a user that is able to login or you may not want to use a user license in the target system.
In this case you might want to use the client_credentials OAuth flow as that identifies the caller using a client_id and a client_secret instead of a user id. Unfortunately that OAuth flow type is not supported out-of-the-box with Salesforce. The reason is that the Auth. Providers in Salesforce usually deals with a user behind the keyboard. Due to this the OAuth 2.0 Auth. Provider flows was designed for a access_token / refresh_token World. This makes it impossible to use the built in capabilities for the client_credentials flow.
The solution is to write a custom Auth. Provider in Apex and use that from your Named Credential. To make this easier I’ve already implemented this for you. The code is available on Github in my salesforce-azure-clientcredentials-authprovider repo. This implementation just plays along with the access_token / refresh_token requirements and just requests a new access_token using the client_credentials flow whenever a (new) access_token is needed and hence do not need a user behind the keyboard.
The README.md in the repo has instructions for installing and configuring the code in the org. Once deployed you can create an Auth. Provider and a Named Credential. Please note you also need to create an App Registration in Azure Active Directory with the required Application Permissions.