26 March 2013

What can View All Data do?

I hear this question quite a bit: "We have over one hundred people with View All Data which is too many. How can I reduce this number to reduce the risk that people can view more than they should be able to?"

Before you can reduce the list of who has View All Data, you may need to determine if any of those users have this permission for one of the following ten reasons listed below. If they don't need to accomplish one of these tasks, it's a good idea to change their profile or permission sets over to something that doesn't have View All Data. 

  1. You need Read on all objects (Sharing is ignored in this case) - this is the primary use case for granting View All Data and what View All Records was meant to solve for by ignoring sharing on an object basis rather than across all objects.
  2. You need to set the Running User of a dashboard to someone other than yourself (requires Manage Dashboards permission as well)
  3. Anyone with Modify All Data, Author Apex, Download AppExchange Packages or Create AppExchange Packages will also get View All Data (it's required).
  4. The "big deal alert" user on opportunities needs to have view all data
  5. You need to view private attachments, notes, and Google docs from other users will be displayed in the related list and in the API
  6. You need to view private events and tasks owned by other people are available in the calendar and API.
  7. You need API Access to Forecasting
  8. You need to do an API Upsert on a non unique fields
  9. You need to use the System (Apex) system log (in the header)
  10. You need to view private chatter groups
For more ideas on what to do when you have too many people with View All Data, check out this previous salesforce hacker post.

25 March 2013

How Not To Give Out Modify All Data

Have you ever given Modify All Data to a user but didn't really want to?

If so, you're not alone.  There are several permissions that may be used to define an administrator. Modify All Data is the single best way to do it - it gives the user full access to all org data and about thirty other magical powers that clear their path to getting their job done. It is the ultimate power in the permission universe. After all, isn't that what it's really about, making it easy for a user to do their job?  Maybe it is, but it wouldn't it be great if you didn't have to give out full access to everything just to allow a user to download the data loader or empty the recycle bin?

It is possible to ween your users off their addiction to Modify All Data.  The key to properly enabling your users is to begin identifying the tasks that they perform that might require a permission like Modify All Data.  In some cases, those tasks are fairly straight forward and can be remedied.  For instance, I used to hear a great deal that Modify All Data had to be given out in order for someone to manage all of the data related to a custom object.  This didn't make much sense why we gave a bazooka to do a fly swatter's job, so we created the Modify All object permissions. Now a user may be granted Modify All records instead of Modify All Data in order to manage the data related to that one object and business process. This is an example of an easy decision to make.

But there are some requirements in the system such as the requirement for the automated case creator user to have Modify All Data. This isn't something that is easily remedied. 

And then there are some tasks that really can be remedied through creative solutions and features that you may have long forgotten about from the ADM 201 Admin training you took four years ago.  For instance, the ability to Login-As is granted for all users with Modify All Data.  But if your requirement is to enable users to Login-As a group of users, you can use the Delegated Administration feature found under Setup | Administration Setup | Security Controls | Delegated Administration to create a group and assign them Login-As rights to a role and/or subordinate roles worth of users.  In this case, all that would be required of the user is to have View Setup and Configuration.

In this post, we looked at a couple of specific examples how to remove Modify All Data from users who don't need it by giving them an alternative permission.  In future posts, we'll continue to examine creative ways to enable users with only the tasks they need to do rather than give them the easy way out by giving them the reins to the Death Star.

18 March 2013

API Usage Notification, Who Knew?

I've been at salesforce.com almost eight years and I love the fact that I'm still finding new things to dig about the service. I found this gem of a feature last week. What surprised me was not discovering this feature, or the fact that it has been there for about two years, but that everyone I told about it was also amazed that it existed. I was so excited about my find that I wanted to share it with the world.

This feature solves a common problem for developers and system administrators. Over half of all salesforce.com transactions are API based. At a billion transactions per day, that's a lot of API calls. As with most things that voluminous, there are limits to help protect the service for everyone. If you run into one of these limits, you may be prevented from continuing, which can be a problem if you're in the middle of a nightly data load or are using a mission critical application that relies on the API.

API usage notifications sends an email when you have hit a configurable threshold. For instance, you might want to know when you are 50% of your API limit threshold and again when you are 80% of your threshold. This information can help you prevent a work stoppage, develop some simple forecast capacity planning, and react if you're about to hit a limit.

Monitoring usage is critical to the health of your business applications. This is just another way you can get what you need to keep your mission critical apps running.

11 March 2013

Permission Set Best Practice: Reduce Risk through Re-Certification

'Re-certification' is the term I've been hearing information security teams throw around when discussing high risk permissions. Re-certification is the process of verifying the permissions a user needs by taking risky permissions away from all users in the organization and then granting them back on an individual basis through a permission set instead of the user's profile.

For instance, an organization I was working with recently realized that more people had View All Data than desired. There are many legitimate reasons why someone might have View All Data but in some cases, users have it because they share a profile with another user or because of legacy reasons that no longer apply.

To reduce risk, the organization removed View All Data from all but the System Administrator profile. As individuals realized that they needed View All Data to do their job (for example to configure the running user in a dashboard), they filed an IT help desk ticket with a reason to have their access re-instated. IT then reviewed the request and granted the permission through a permission set to those invidividual users who actually needed it.

As a result, the organization was able to reduce the number of users who didn't really need View All Data and moving forward, were able to better control who received View All Data using permission sets rather than profiles.

04 March 2013

Maker Checker (Segregation of Duties)

Every now and then, I get asked about segregation of duties - in particular how to separate out the ability to create users versus the ability to activate them. Affectionately called maker-checker, this ability prevents a user with the Manage Users permission from escalating their own rights by creating a user that has more access than what they already have.

If you're interested, check out my previous blog posting for more detail on what Manage Users permission controls - it's a lot of stuff. As a result, I often recommend that an organization not have more than one or two users with this permission. However, you do need at least one user to have Manage Users permission which will give them the ability to not only create and edit users, but also to activate them and modify either their profiles or sharing settings. In other words, the keys to the kingdom.

This creates a scenario where a single individual within an organization can become, or enable others to become, the most powerful users in the org.  There are many issues that arise from providing this level of power including the ability to export any/all data or delete any/all data from an org without any appropriate organizational checks in place to prevent this type of behavior.

Below is a workaround designed to prevent any one person from having the ability to both create a user and make them active.  The theory here is that if a ‘Maker’ Administrator may not activate a user, they can't complete the act of creating a user without a second ‘Checker’ Administrator providing activation status. 

The solution below is based on a prototype that will meet most of these requirements.  The sample code should be used as an example of what is possible and not added to an org without fully understanding and testing the consequences that come with someone like me, a non-programmer, creating code.

To try this out, I suggest first creating a trial org or trying this in your sandbox; otherwise, you run the risk of locking yourself out of the user provisioning process by accident.

  1. As the Uber Admin (original System Administrator) create a new Profile: Maker Administrator.
    1. Enable Manage Users – to create users and assign profiles
    2. Enable API Enabled – to mass create and edit user records
    3. Enable Modify All Data – to change user profiles if the original profile already has Modify All Data (system requirement)
  2. As the Uber Admin (original System Administrator) create a new Profile: Checker Administrator.
    1. Enable Manage Users – to create users and assign profiles
    2. Enable API Enabled – to mass create and edit user records
    3. Enable View Setup and Configuration – for navigating to the users screen
  3. As the Uber Admin (original System Administrator) create a new Profile: Builder Administrator.
    1. Enable Customize Application – to create and edit validation rules
    2. Enable Author Apex – to create and edit Apex Triggers
    3. Enable View Setup and Configuration – for navigating the setup tree
  4. As the Uber Admin (original System Administrator) create a new User Validation Rule to prevent the Maker Administrator from changing the User Active Status
    1. Name: isActive
    2. Error Condition: AND( $Profile.Name = "Maker Administrator" , ISCHANGED( IsActive ))
    3. Error Message: You are not authorized to change the user activation status.
  5. As the Uber Admin (original System Administrator) create a new User Validation Rule to prevent the Checker Administrator from creating new user records
    1. Name: isNew
    2. Error Condition: IF( $Profile.Name = "Checker Administrator", ISNEW(),null)
    3. Error Message: You are not authorized to create new user records.
  6. As the Uber Admin (original System Administrator) create a new User Apex Trigger to change the isActive Boolean to false upon creation (overriding current behavior)

    trigger deactivateUserOnCreate on User (before insert) {
    for (User usr : Trigger.new){
    usr.isActive = false;

  7. As the Uber Admin (original System Administrator) create a new User Apex Trigger to prevent the Checker Administrator from changing any field EXCEPT the Active field.  Important Notes:
    1. Change the Profile ID to whatever the current org ID is for the newly created Checker Profile
    2. This won’t have an impact on User Related Lists
    3. Custom Fields may be restricted to read only through FLS rather than hard coding into the Trigger Below
    4. Additional Standard Fields created with each major release would have to be added into the code below
    5. Code may be found below:

    trigger preventCheckerUpdate on User (before update) {

    //User oldUsr : Trigger.old;

    for(User newUsr : Trigger.new){

    for (User oldUsr : Trigger.old){


    // Substitute the Checker Administrator ID below:
    (UserInfo.getProfileId() == '00e30000000vfwXAAQ') &&
    (oldUsr.Alias != newUsr.Alias) ||
    (oldUsr.CallCenterId != newUsr.CallCenterId) ||
    (oldUsr.City != newUsr.City) ||
    (oldUsr.CompanyName != newUsr.CompanyName) ||
    (oldUsr.ContactId != newUsr.ContactId) ||
    (oldUsr.Country != newUsr.Country) ||
    // (oldUsr.CurrencyIsoCode != newUsr.CurrencyIsoCode) ||
    // (oldUsr.DefaultCurrencyIsoCode != newUsr.DefaultCurrencyIsoCode) ||
    // (oldUsr.DefaultDivision != newUsr.DefaultDivision) ||
    (oldUsr.DelegatedApproverId != newUsr.DelegatedApproverId) ||
    (oldUsr.Department != newUsr.Department) ||
    (oldUsr.Division != newUsr.Division) ||
    (oldUsr.Email != newUsr.Email) ||
    (oldUsr.EmailEncodingKey != newUsr.EmailEncodingKey) ||
    (oldUsr.EmployeeNumber != newUsr.EmployeeNumber) ||
    (oldUsr.Extension != newUsr.Extension) ||
    (oldUsr.Fax != newUsr.Fax) ||
    (oldUsr.FirstName != newUsr.FirstName) ||
    (oldUsr.ForecastEnabled != newUsr.ForecastEnabled) ||
    (oldUsr.IsPortalSelfRegistered != newUsr.IsPortalSelfRegistered) ||
    (oldUsr.LanguageLocaleKey != newUsr.LanguageLocaleKey) ||
    (oldUsr.LocaleSidKey != newUsr.LocaleSidKey) ||
    (oldUsr.LastName != newUsr.LastName) ||
    (oldUsr.ManagerId != newUsr.ManagerId) ||
    (oldUsr.MobilePhone != newUsr.MobilePhone) ||
    (oldUsr.Name != newUsr.Name) ||
    (oldUsr.OfflinePdaTrialExpirationDate != newUsr.OfflinePdaTrialExpirationDate) ||
    (oldUsr.OfflineTrialExpirationDate != newUsr.OfflineTrialExpirationDate) ||
    (oldUsr.Phone != newUsr.Phone) ||
    (oldUsr.PortalRole != newUsr.PortalRole) ||
    (oldUsr.PostalCode != newUsr.PostalCode) ||
    (oldUsr.ProfileId != newUsr.ProfileId) ||
    (oldUsr.ReceivesAdminInfoEmails != newUsr.ReceivesAdminInfoEmails) ||
    (oldUsr.ReceivesInfoEmails != newUsr.ReceivesInfoEmails) ||
    (oldUsr.State != newUsr.State) ||
    (oldUsr.Street != newUsr.Street) ||
    (oldUsr.TimeZoneSidKey != newUsr.TimeZoneSidKey) ||
    (oldUsr.Title != newUsr.Title) ||
    (oldUsr.UserPermissionsAvantgoUser != newUsr.UserPermissionsAvantgoUser) ||
    (oldUsr.UserPermissionsCallCenterAutoLogin != newUsr.UserPermissionsCallCenterAutoLogin) ||
    (oldUsr.UserPermissionsMarketingUser != newUsr.UserPermissionsMarketingUser) ||
    (oldUsr.UserPermissionsMobileUser != newUsr.UserPermissionsMobileUser) ||
    (oldUsr.UserPermissionsOfflineUser != newUsr.UserPermissionsOfflineUser) ||
    (oldUsr.UserPreferencesActivityRemindersPopup != newUsr.UserPreferencesActivityRemindersPopup) ||
    (oldUsr.UserPreferencesApexPagesDeveloperMode != newUsr.UserPreferencesApexPagesDeveloperMode) ||
    (oldUsr.UserPreferencesEventRemindersCheckboxDefault != newUsr.UserPreferencesEventRemindersCheckboxDefault) ||
    (oldUsr.UserPreferencesReminderSoundOff != newUsr.UserPreferencesReminderSoundOff) ||
    (oldUsr.UserPreferencesTaskRemindersCheckboxDefault != newUsr.UserPreferencesTaskRemindersCheckboxDefault) ||
    (oldUsr.UserRoleId != newUsr.UserRoleId) ||
    (oldUsr.UserType != newUsr.UserType) ||
    (oldUsr.Username != newUsr.Username)))

    newUsr.addError('Trigger Err 1001 - You are not authorized to change anything except for the active state');
    // newUsr.addError('\nYour Profile: ' + UserInfo.getProfileId() + ' and Active is: ' + newUsr.isActive);

  8. As the Uber Admin (original System Administrator) create three new users and assign to the three new profiles: Maker, Checker, and Builder Administrators
  9. Modify any references to the Uber Admin in the org 
    1. Default Workflow User
    2. Case Assignment Rule Entries
    3. Case Escalation Rule Entries 
    4. Lead Assignment Rule Entries
    5. Default Lead Creator
    6. Google Apps Admin
    7. Portal Admins for customer and partner portals
    8. Workflow Tasks
    9. Workflow Alerts
  10. Have the Maker Administrator login and change the profile of the Uber Admin to Standard User
  11. Have the Checker Administrator login and deactivate the Uber Admin
  12. If the Uber Admin needs to be resurrected,  have the Maker Administrator change the profile of the Uber Admin back to System Administrator and have the Checker Administrator reactivate the Uber Admin User record.

Keep in mind:
1. Because both the Maker Administrator has both Manage Users and Modify All Data, they may use the Grant Login Access functionality to login as the Builder Administrator and deactivate or modify both the Validation rules and User Apex Triggers.  This risk may be mitigated by explicitly telling the Builder Administrator (or anyone with Customize Application permissions) not to grant login access.
2. The Builder Administrator in this scenario may be the only person to configure delegated Administration since Customize Application is required. However, anyone with Delegated Administrator access may potentially change user access, profiles, or login as an administrator. This risk may be mitigated by explicitly defining separate roles for the Administrators at the top of the hierarchy or defining no roles for the Administrators in a public share model.

One final note on this topic, any time we discuss segregation of duties and escalation of privileges, we get into a fundamental conundrum - if you need more than one person to perform some sensitive task productivity may ultimately be sacrificed to the audit gods. Creating users can be a very regular occurrence, but ensuring that you have maker-checker segregation of duties ensures that if one person is out of the commission, you have stopped what may be a critical day-to-day process. It's a slippery, though sometimes necessary, slope on the road to preventing escalation of privileges.