As has been the case since the first TrailheaDX in 2016, the stars didn't align so that I could attend in person. Luckily a lot of the content is already up on Salesforce+, including a very interesting session on the Apex roadmap from Daniel Ballinger and Chris Peterson. One feature that is currently in development really stood out for me - User Mode with Permission Sets.
User Mode
User Mode went GA in the Spring 23 release of Salesforce, and is a real benefit for those of us with app exchange packages containing Apex code. For those who haven't attempted this and the associated security review, here's a brief summary of what you are up against with the previous tooling:
- You need to respect the CRUD and FLS permissions set by the subscriber org (the Salesforce instance into which the package has been installed) administrator. This is of course quite right, otherwise your package could just help itself to confidential information that it has no business accessing.
- There isn't much support in the platform for this, so you need to either create your own methods to check this for each object and field, or use one of the myriad third party offerings.
I've always been in agreement with this governance being enforced in the
security review, and also of the strong opinion that if this is a requirement
it should be baked into the platform, rather than pushed back on everyone that
is developing a package with code. There must be tens of thousands of lines of
code in all the packages out there, all re-solving the same problem.
There were previous attempts to solve this, but they all had compromises. User
Mode genuinely takes the transaction out of system mode so that all configured
permissions apply for the database operation. If the database operation
attempts to use fields or objects that aren't accessible, errors are returned
for every disallowed item.
All well and good when you are respecting the admin's decision about access,
but what happens if access to objects and fields managed by the package is
required in order for the package to function correctly? You could put the
user through death by a thousand cuts, allowing them to get slightly further
each time before an error is thrown and they request additional permissions
from their admin, or you can execute your database operations in System
Mode. This is quite the nuclear option though, as it opens up access to
every object and field in the instance. If all you need is to get at the value
for a single checkbox, it's an extremely large hammer to crack a small nut.
User Mode with Permission Sets
User Mode with Permission Sets allows you to select an appropriate sized
hammer for the nut in question. Rather than elevating the user's access to
everything, everywhere, you can give them the minimal amount of additional
privilege required for your package to function correctly, just for the
database operations that it is needed. To continue the example of needing
access to a single checkbox value, you'd also package a permission set that
grants access to just that field and execute the database operation in user
mode plus that permission set. Much better from a security and governance
perspective.
Here's a code snippet snatched from the session - note that as this is still
in development the syntax is likely to change, but it gives a sense of the
direction of travel:
Packages aren't the only use case for this though, limiting the data that your
Apex code has access to is good practice regardless of whether it's going into
a package or being deployed directly to an org. Sadly it wouldn't stop my Evil
Co-Worker, as when they have access to the code they can simply change it to
run in System Mode in all cases. It will limit the impact of simple mistakes
though, and keep your Information Security department a little happier.
I wonder if a mode which allows system access to package owned fields would help. A package would tend to want system mode to maintain internal state or access internal control information. This will involve fields and objects that are in its own namespace. It may not always be desirable to all the user direct access to that state - a fundamental flaw I think with the model that requires the user to be granted granular permission to every object touched on their behalf.
ReplyDeleteA risk with system mode READ is information becoming available to the end user that they should not see. I can imagine many packages needing a mix - "I need to restrict records here by Sharing so the user can only interact with what they are allowed to see, but I need these fields that the user cannot see". Maybe a useful thing for security scanning would be to trace data from the database to the UI or other system boundary to make sure information does not leak.
At the moment you'd need to perform two queries, using precious SOQL limit. One query works out the sharing situation, the other pulls in the system level fields. The UserAccess special fields seem to always return true when you perform a system mode query, so rendering them useless. The proposed permission set solution would help here.