12 December 2013

Using the Force.com Command Line Interface


Tools, tips, and tricks are the lifeblood of a salesforce hacker.

At Dreamforce 2013, Dave Carroll announced a fantastic new Command Line Interface (CLI) tool that administrators can use when managing their organization.

Some of you are probably thinking, 'how cool!'. But for others, a CLI is not usually thought of as a 'cool' administrative tool outside of managing a Unix server or as a developer tool for uploading code to GitHub.

However, a CLI is a fantastic tool for going bare metal when it comes to managing your organization. You can do truly amazing things when you combine the power of querying the platform with many of the MacOSX terminal commands like 'grep'.

For instance, I can quickly query all of the permission sets assigned to a specific user:


Using standard terminal commands helps me more easily navigate data I want to review. For instance, if I want to check just the name of the user who is currently logged into to CLI, I can filter any field with 'Name' in it using grep:


However, if I just want to know the actual name of the user, I can add the regular expression '^' caret to mark the beginning of a string, in this case the 'Name' field:


Now I've combined the power of the force.com platform with terminal commands and regular expressions, all in one easy to use tool. This translates as more power than what I have with other tools in a much simpler format than other user interfaces I'm used to using. 

You can download the Force.com CLI from https://force-cli.heroku.com/. There's also a fantastic blog posting from Wade Wegner to help get you started.


16 November 2013

#Where is the Salesforce Hacker at Dreamforce 2013?

I can't believe Dreamforce 2013 is here! This will be my ninth year presenting at the conference. It's incredible to see how it's changed from a small user conference that took place over two and one half days in Moscone West to now taking over most of San Francisco for four whole days.

With 120,000 people from 65 countries expected to register to attend, this year's user conference is definitely lining up to be the largest and most transformational event in history of cloud computing. I've been preparing to meet as many people as I can, present at as many sessions as I can squeeze in, and take in the experience of being with over one hundred thousand people who share my wonderment of what is possible with cloud computing.

This year, I am presenting at seven breakout sessions, four executive briefing center visits, one salesforce community podcast, attending the True to the Core session, and having as much fun as is legally allowed.

I hope to see you at one of these sessions and if you get a chance, please come up and say hi after the presentation. It would be fantastic to meet you!

Session
Location
Date
Time
Community Live Podcast
Hilton Ballroom Union Square
Monday, November 18th
11:00 AM - 11:30 AM
Keeping it Simple with Permission Sets
San Francisco Marriott Marquis, Nob Hill A - D
Monday, November 18th
1:00 PM - 2:00 PM
Administrator Tools for the Future - Platform Roadmap
San Francisco Marriott Marquis, Yerba Buena - Salons 4, 5, 6
Monday, November 18th
4:00 PM - 5:00 PM
Five Developer Tips Every Admin Needs To Know
Moscone Center West, 2006 / 2008
Tuesday, November 19th
5:15 PM - 6:00 PM
Administrator Tools for the Future - Platform Roadmap (Mach 2)
InterContinental San Francisco, Grand Ballroom ABC
Wednesday, November 20th
12:00 PM - 1:00 PM
Case Study: How Security Improves Collaboration for the Social Enterprise
Partner Theater West Cloud Expo
Wednesday, November 20th
2:30 PM - 2:45 PM
Understand Force.com in 60 Minutes or Less
Moscone Center West, 3022
Wednesday, November 20th
4:00 PM - 5:00 PM
Phoenix - A High Performance Open Source SQL Layer over HBase
Moscone Center West, 2009
Thursday, November 21st
8:30 AM - 9:15 AM
Parker Harris's True to the Core: What’s Next for Our Core Products
YBCA - Lam Research Theater
Thursday, November 21st
11:30 AM - 12:30 AM

28 October 2013

A drag-and-drop tool for comparing profiles, permission sets, and users



Comparing profiles, permission sets, and users in an easy to use, intuitive, drag-and-drop user interface, is a difficult usability problem to solve. It's difficult because each user, permission set, and profile may have thousands if not millions of permissions associated with them. Therefore, when comparing users, profiles, and permission sets together, the number of questions you can ask are several orders of magnitude. Basically, instead of looking for a needle in a haystack, it's like comparing multiple haystacks looking for multiple needles of varying size, color, and material.

John Brock created such an app for a Dreamforce 2012 presentation. He set out to demonstrate what could be accomplished with the permission set and user API.  Built on Heroku and the Salesforce platform using OAuth2, ExtJS4, and Java with the Play! framework, the PermComparator, provides a simple drag-and-drop user interface that allows an administrator to drag and drop users, permission sets, and profiles into a series of columns to compare and contrast their individual settings.

With each user, permission set, or profile, the administrator can compare user, object, and setup entity access permissions through a series of collapsible, accordion style lists. Within each set of permissions, the administrator can compare common, unique, and differing permissions. The easiest way to understand how to use the PermComparator is through the concept of a Venn Diagram.


Assuming A, B, and C are any combination of users, profiles, and permission sets that an administrator would compare:

  • Common permissions (111) help answer the question, "How are these users, profiles, or permission sets the same as one another." This helps determine where there are redundant profiles or permission sets that could potentially be merged or deleted. This also helps when determining why one user has access that another doesn't. Since all comparisons share these permissions in common, these permission can be ruled out as creating the additional access.
  • Unique permissions (001, 100, 010) help answer the question, "What does this user, profile, or permission set have that none of other ones have." This can help troubleshoot why one user, profile, or permission set has access to something where none of the others do and is a likely candidate for determining what additional access has been granted.
  • Differing permissions are everything but what is common (100, 110, 010, 011, 001, 101 which is really everything in the diagram but 111). This matters most when you have more than two things you are comparing. Differing permissions answers the question, "What permissions are assigned and shared with some but not shared with everything being compared." This can help isolate potential differences which may result in discovering that a user should have a slightly different profile or permission set to get the job done. 

Recently, there was a lot of buzz in the Salesforce community about this tool. It was great to hear members of the community sing John Brock's praises for the PermComparator. He was called a 'crazy genius' whose tool was 'life changing'. One thing for sure, John solved a difficult problem and created an incredible visualization tool for understanding access controls in a complex system by making it drag-and-drop simple.

The PermComparator is open source and available on GitHub to be downloaded, forked, or contributed to should you need access to the actual source code.

21 October 2013

Visualizing Identity Fraud Using Login History



I love the cool data visualizations that I find on the web. I spend hours upon hours perusing great visualizations and infographics on sites like visual.ly, flowingdata.com, and Information is Beautiful. It's amazing how much I have learned about the US debt ceiling, the complete history of coffee, or ten things I never knew about Disneyland.

While these sites visualize great esoteric knowledge, I'm always amazed at the lack of great, easy to use data visualization tools within the enterprise to understand common problems like discovering when a user's credentials have been compromised.

In salesforce.com, administrators can use login history to help solve the problem of discovering identity fraud. Administrators can download the last six months of login data including who logged in, how they are did it, and from where. This is incredibly valuable data but is also a sea of information that only grows with the number of users and the adoption of the platform.

Yesterday, I came across a great new app that makes visualizing data sets like this incredibly easy.

The site is called Raw from Density Designs. It allows you to drop data into a free form text box and declaratively drag-and-drop from any number of easy to use vector graphics including treemaps, bubble charts, dendrograms, alluvial diagrams, circle packings, and scatterplots.

To try this, use workbench to first download your login history.
You should also download your users so that you can transform the user id in login history into user name which will make it easier to visualize your data.
To transform your user ids to user names, use the VLOOKUP function. You don't have to do this but it really will make your visualization easier to understand.

Once you have your complete login history data, copy and drop it into the Raw free form text box.
One of the great features of this app is that it automatically understands the data and gives you options. I kept it simple and decided I wanted to understand the relationship of users and how they logged into my organization so I used an alluvial diagram and compared the username, platform, sourceip, browser, and application attributes.
This gave me a great visualization of how these attributes relate to one another.

It also gave me the ability to export the resulting visualization to SVG, PNG, or JSON so I could use them. The first image in this blog post came from the PNG export.
With this visualization, I can now look for anomalies where a user may log in from an unknown IP, browser, application, or computing platform. These anomalies help me understand whether a user has had their account compromised and whether identity fraud has taken place within my organization.

Visualization of large data sets is all over the internet and there are great tools to help explore the data. Why shouldn't we be able to use them to solve our everyday enterprise sized problems?

07 October 2013

Visualizing User's Permissions Across Profiles and Permission Sets


Matt Lamb, a salesforce.com MVP at Appirio, responded to a question about whether it's worth just using profiles or if administrators should also use permission sets when assigning permissions to users. 

Matt tweeted, "The modularity [of permission sets] is awesome. In practice I've found they make auditing (e.g. "Who can Delete Accounts?") very difficult."

It's true that auditing can be difficult. I'd like to show you some simple steps that make the process much easier.

Permission sets were created to enable the layering of permissions. This allows administrators to meet use cases where profiles alone cannot go. Permission sets' modularity provides everything from the ability to layer a single permission to providing access to whole applications across different regions and lines of business.

Adopting permission sets introduces an auditing challenge. Now that permissions span a user's profile and all of their permission sets, it's challenging to determine why a user has access (e.g. "Who can delete accounts?").

I don't buy the argument that an administrator should rely solely on a profile because it's somehow more auditable than permission sets. I've even heard that 'CTRL-F' on a profile is a best practice when determining what a user has access to.

Some people may have seen me roll the Standard User profile out on over forty feet of paper in past Dreamforce sessions.

But what many admins may forget is that there's more than forty feet of permissions there. To view page layout assignments, record type settings, and field level security, you need to click into other pages. So even if you constrain yourself to only using profiles, they are still fundamentally not self-auditing.

Ultimately, what we all want is a visualization and reporting tool that allows us to audit what a user has been assigned. While we don't have a declarative reporting interface to display this information, we do have a robust API that allows a developer to build administrative tools to visualize and report on a user's permissions.

Last year, Doug Bitting created exactly that. His tool allows you to easily audit a user's permissions across both their profile and all of their permission sets in a highly visual manner.

As an example, Shawna Wolverton as a user in my org has one profile and many permission sets assigned to her.


When I click on the 'Display Perms' custom link on her user page, I can visualize the permissions assigned her.  I also start to get some sense of exactly how many permissions can be assigned a single user.



We can also report on the object and field permissions that the user has.


Finally, we can report on setup entity access permissions such as Apex Class and Apex Page access.


Doug made it very easy to download and configure my organization with this functionality.

I went to github (https://github.com/forcedotcom/user-access-visualization) and followed his directions in the Readme file. 

I first downloaded a ZIP of the repository. 

Then I used workbench to deploy a ZIP of the 'src' directory to my organization. (I could have used the force.com IDE to deploy the files as well; workbench is just my tool of choice.)

Last, I created a custom link on the user object. This link redirects an administrator to the visualforce page that will display the user's permissions. It knows who the user is because the page passes in the user id in the parameters of the URL (e.g. /apex/UserAccessDetails?uid={!User.Id}).


And there you have it. Using these methods, you can setup and audit a user's access across their profile and permission sets in around ten minutes.

30 September 2013

Build Your Own Custom Sharing Button

Judi Sohn gave me a great use case last Friday on twitter. While discussing the issue of whether to use only profiles or also use permission sets, the question of why a user has access to a record came up.

This is an interesting question because there is a sharing button on every record designed to provide this information. However, there are two shortcomings with using this button:

  1. The sharing button is disabled if org wide defaults are set to public read/write for an object
  2. It only tells you about sharing rows, not the object permissions contained in a user's profile or permission sets


As a result, it's possible to use this button to see which users have access to a record, only to find out that the user lacked the object permissions necessary to work with this record.

However, there is a workaround for these issues. You can create your own custom sharing button that will take both sharing and profile or permission set permissions into consideration, regardless of the sharing settings on the object.

For instance, we have a user, Doug Bitting. His profile grants him View Setup and Configuration permission and nothing else.



While on an account record, we can click on the sharing button to view which users have access to the record as long as accounts do not have their org wide default set to public read/write.



Viewing this sharing page tells us that our user, Doug Bitting, has access to the record even though he doesn't actually have the object permissions necessary to read the record.



By clicking on a custom button that I added called 'User Access', I can look up more information on what level of access a user like Doug actually has. This button launches a visualforce page with a custom apex controller in a new window.



In this case, when I look up Doug Bitting, I find out that he doesn't have access to the record.



I can add access to accounts through an accountRead permission set that has read on accounts.



Now when I use the custom 'User Access' button, I find that Doug actually has the read access I need him to have.



I built this solution with a custom button, visualforce page, and custom apex controller.

The button can be applied to any object where sharing and custom buttons are supported. Here's an example of the account button that I created. All that is required is to pass in the record Id in the URL when the page is called.



The apex code is pretty simple. The first part enables you to find a user using SOQL.


    // query user from the User's Name input Text
   public void queryUserName() {
       
    // prevent SOQL Injection - oh no Mr. Bill!
    String queryU = '%' + uName + '%'; 
     
    // create query passing in queryLabel from input text in page
    // this can easily be changed with other search parameters 
    // only return one user,may require narrowing search results
    queryUser = 
   [SELECT Id, Username, Name, Title, Profile.Name, UserRole.Name
    FROM User
    WHERE Name like :queryU
    OR Title like :queryU
    OR Profile.Name like :queryU 
    ORDER By Name
    LIMIT 1];
   }




The second part enables you to use the user Id from the SOQL query and the record Id from the URL in the UserRecordAccess where clause to determine the user's actual access.


   // Determine User Access based on the queryUser  
  // and the Id passed in through page reference in the URL 
   
   public void queryAccess()
   {
       // Store queryUser results in a new object
       User u = [SELECT Id 
                 FROM User 
                 WHERE Id = :queryUser];
       
       // Extract the Id from the user results
       String uId = u.Id;     
       
       // UserRecordAccess using the userId and recordId 
       ura = [SELECT MaxAccessLevel,RecordId
              FROM UserRecordAccess 
              WHERE RecordId =      :ApexPages.currentPage().getParameters().get('Id') 
                    AND UserId = :uId];
   } 


This solution works because the UserRecordAccess sObject which is available in the API. If you haven't seen this before, it's a great way to determine who has access to any record by combining profiles, permission sets, and sharing together.

The source code for the apex page and controller can be found on my github page: https://github.com/atorman/CustomSharingButton. Feel free to use it although there is some more work that I am planning to do so keep in mind that there is more to come.

While this doesn't address the original intent of the twitter conversation, it does address a couple of shortcomings with the Sharing button in particular.



23 September 2013

Master Record Types with Permission Sets

I had an interesting question come up the other day about permission sets and record types.

The customer wanted to remove all record type assignments from their user's profiles and configure record type assignments on two different permission sets. Unfortunately, that's not possible since, unlike other settings on permission sets, record types have a default setting and the profile is the only place where we can set that default. In addition, the 'Master' or 'null' record type simply means we won't set any record type when a record is created or edited.

For example, if I have a profile called 'Account Only' with the Master record type defaulted:

and I assign it to John Doe user with no permission sets:

when I Login-As John Doe and create a new Account, the Master record type (null) is automatically selected and I do not get a jump screen where I can choose a different record type:

I log out from John Doe and create a permission set with one of five record types selected:

and another permission set with the rest of the record types selected:

Now when I assign the single record type permission set to the John Doe user:


and login as John Doe to create a new Account record, I still skip the jump screen and the one custom record type (note Master is ignored in the single record type case) is added to the newly created record:


I log out from John Doe user and change his permission set assignment to grant access to the remaining record types:



Now when I log in as John Doe user, I get the jump screen and can select from a list of different custom record types:

This behavior is unlike any other setting that we've migrated to permission sets from profile in that it has a default that remains on the profile and it's possible to have that default set to a 'null' value called Master.

As a guideline for using the Master and default record types with permission sets, if I have:
  1. Only Master [default on profile and no permission sets] - the user will skip the jump screen and the Master (null) record type will automatically be set on the newly created record
  2. Master defaulted on the profile + only 1 custom record type on a permission set - the user will skip the jump screen and the custom record type will automatically be set on the newly created record
  3. Master defaulted on the profile + > 1 custom record type on one or more permission sets -  the user will get the jump screen every time in order to choose which custom record type they want to assign to the record they are creating

16 September 2013

What's in a profile name? Well, apparently a lot! Migrating standard profiles using the MdAPI

I had an interesting scenario come up the other day while trying to migrate some permissions on both standard and custom profiles using the Metadata API (MdAPI).

It turns out that what we call the 'System Administrator' standard profile actually maps to the Admin.profile file in the MdAPI. This means, when retrieving the System Administrator profile, you'll find all of the permissions and settings in the Admin.profile file in the profile directory.

Here's where it goes a little sideways. If you create a custom profile called 'Admin', there's some ambiguity when you try to migrate permissions for the 'System Administrator' standard profile which goes by the same name.

As a result, given the right order of operations, the System Administrator profile will be ignored when migrating permissions for the custom Admin profile using the MdAPI.

The same is true for any of the standard profiles:

Standard Profile Name in the User InterfaceStandard Profile File Name in the MdAPI
System AdministratorAdmin.profile
Standard UserStandard.profile
Marketing UserMarketingProfile.profile
Contract ManagerContractManager.profile
Solution ManagerSolutionManager.profile
Read OnlyReadOnly.profile
Customer Portal ManagerCustomerManager.profile
Customer Portal UserCustomerUser.profile
High Volume Customer PortalHighVolumePortal.profile
Partner UserPartner.profile
Authenticated WebsitePlatformPortal.profile
Standard Platform UserStandardAul.profile

Give it a try - steps to reproduce:
  1. retrieve 'Admin' profile in MdAPI which retrieves the 'System Administrator' profile
  2. add an assigned app visibility to the .Admin profile file and deploy
  3. System Administrator profile updates with additional app visibility
  4. clone System Administrator profile and call it 'Admin'
  5. retrieve 'Admin' profile in MdAPI which retrieves the cloned/custom 'Admin' profile thereby ignoring the 'System Administrator' profile
  6. add an assigned app visibility to the .Admin profile file and deploy
  7. custom Admin profile updates with additional app visibility, System Administrator profile is ignored
Use the following steps to find out if you already have any custom profiles with one of these names and rename them:
  1. log into workbench
  2. add the ability to query parent relationships by going to Workbench > Settings and enabling 'Allows SOQL Parent Relationship Queries' before selecting 'Apply Settings' button at the top of the screen 
  3. run the following query by going to queries > SOQL Query:

SELECT Profile.Id, Profile.Name FROM PermissionSet WHERE
(Profile.Name = 'Admin' OR
 Profile.Name = 'Standard' OR
 Profile.Name = 'MarketingProfile' OR
 Profile.Name = 'ContractManager' OR
 Profile.Name = 'SolutionManager' OR
 Profile.Name = 'ReadOnly' OR
 Profile.Name = 'CustomerManager' OR
 Profile.Name = 'CustomerUser' OR
 Profile.Name = 'HighVolumePortal' OR
 Profile.Name = 'Partner' OR
 Profile.Name = 'PlatformPortal' OR
 Profile.Name = 'StandardAul')

As a result of this edge case, the best practice is to name custom profiles something different from what the MdAPI understands as a standard profile name in order to effectively migrate permissions between environments.

20 August 2013

A funny thing happened while uninstalling a package...

David Schach contacted me late last week with a problem - when trying to uninstall a package, he kept getting an error that permission sets from the package were assigned to a user. What was strange was that he had unassigned all of the users from the permission set. It was pretty easy to determine this, all you had to do was go to a permission set and click the Assigned Users button.

We met outside Starbucks this afternoon and worked together to see what was going on with the particular package. By using my favorite API tool, workbench, we were able to run the following SOQL query:

SELECT Assignee.Name, PermissionSet.Id, PermissionSet.Name
FROM PermissionSetAssignment

From this query, we found that there were actually some hidden permission set assignments. In this case, the packaged permission set had been assigned to a guest site user. Using workbench we deleted these assignments and tried the package uninstall process again. This time, it worked.

I dig connections like this because not only was I able to help, but now I have a fun use case to discuss with the packaging team around the uninstall process.

05 August 2013

Reduce Users with Too Many Administrative Rights



Giving out Modify All Data, Customize App, or Manage Users to other users is like giving the ultimate power in the salesforce.com universe.  And with total power comes... a lot of risk.

Ultimately, as organizations segment and divide into multiple organizations housed in a single org, the need to grant more delegated administrative rights grows exponentially.

There are options that you can explore:

  1. Modify All Records or View All Records instead of Modify All Data or View All Data
  2. Sharing instead of Modify All Data or View All Data
  3. Delegated Administration instead of Manage Users for specific roles or Customize Application for Custom Objects

The best way to proceed is to take away any of these administrative permissions from your users and let them try to perform their daily tasks.  You will quickly find where these permissions were needed and where you can compensate by providing alternative permissions or configurations.

For instance, one customer I worked with recently removed Modify All Data from a group of delegated admins.

One issue that came up was the need to use the data loader.  They solved this by downloading the client to a shared directory.

Another instance came up where delegated administrators needed to login as end-users; however, these admins could not have the Manage Users permission.  Using Delegated Administration groups, these admins were able to login and manage users for a role and the role's subordinates without requiring Manage Users (only View Setup and Configuration was required).

Ultimately, some tasks must still be performed by a System Administrator, but at least you can begin to whittle down the number of administrators who have too much access.

08 July 2013

Troubleshoot Profile and Permission Set Changes with the Setup Audit Trail


For many organizations, auditability is treated in a similar way to keeping tax records around for the past ten years;  you know that you need it, but you're not sure you'll ever use it unless you are audited.  As a result, it's not typically the first tool that admins will use when troubleshooting a user's access.  Many admins I talk to never even realize that this feature exists.  If you haven't seen it before, go to:
Setup | Administer | Security Controls | View Setup Audit Trail  

The setup audit trail is designed to capture many of the common changes that take place under Setup.

The advantages to the setup audit trail include:


  • Easy to determine who made a change to setup and when it was made
  • Easy to troubleshoot a granular change that was made to a profile since we now track both the old and new values of the change
  • Easy to download detail to a spreadsheet in order to filter and sort the data by user, time, or action
  • Easy to track Login-As Delegate User actions when users are logged in as another user


We track the last 20 changes on the screen and for any changes beyond that, you can download a CSV for the past 6 months of changes. I find it helpful to filter by time when troubleshooting a change, since I usually know about when the change took place.  Most recently, I helped with a customer case where I was able to recreate the timeline of events related to how the customer moved profile and tab changes between sandbox and production instances.

An audit is rarely fun, but having an audit trail can be more than just a way to protect yourself, it can be an invaluable tool for you to troubleshoot a user's access as well as changes to your profiles.

24 June 2013

Mass Assign Permission Sets and other cool things using the API


The Salesforce sObject API is an important part of permission sets, allowing you to perform tasks that you cannot perform through the permission set UIs.  Some administrators may already be comfortable with the salesforce.com sObject API, but for those who are not, it is possible to use the API without writing a bunch of source code by using the Workbench tool at http://workbench.developerforce.com/.  While Workbench has a great query builder interface, below are some example queries.


Users with a Permission like Modify All Data


Because a user’s effective permissions are determined by both their profile and all assigned permission sets, it actually requires two queries to determine which users have a particular permission.  The query asks the question what users are assigned to a profile or permission set that contains Modify All Data.

SELECT AssigneeId, Assignee.Name, PermissionSet.Label, PermissionSet.isOwnedByProfile
FROM PermissionSetAssignment
WHERE PermissionSet.PermissionsModifyAllData = true


Permission Sets Assigned to a User


SELECT PermissionSet.Id, PermissionSet.Name
FROM PermissionSetAssignment
WHERE Assignee.Username = 'admin@my.org' AND
PermissionSet.isOwnedByProfile = false


Permission Sets with a Particular Token


In a previous section, it was suggested that adding tokens to your permission set names or descriptions may be useful.  Here is a query that looks for a token within a permission set description:

SELECT Id, Name, Description
FROM PermissionSet
WHERE Description Like '%#salesrep#%'
Mass Assign Permission Sets to Users

Mass Assign Permission Sets to Users


It is possible to perform mass assignment of permission sets via the sObject API.  This is performed by inserting PermissionSetAssignment records (unassigning is nothing more than deleting the PermissionSetAssignment records).  To perform this operation with a spreadsheet and the Workbench, follow these instructions:

  1. Select “Insert” from the “Data” menu at the top of your browser window.
  2. Select PermissionSetAssignment from the ObjectType menu
  3. Select the “From File” radio button and choose your CSV-formatted spreadsheet.
  4. Click “Next”
  5. Map the columns from your spreadsheet as appropriate.
  6. Click “Map Fields”
  7. Choose whether you wish to process the request asynchronously
  8. Click “Confirm Insert”

17 June 2013

Phasing in Permission Sets



Permission sets represent a fundamental shift in enabling a user's access. As a result, you should have a release strategy before rolling out new permission sets to users in your org.

As with other important changes made to an org, you should first create permission sets within a Sandbox environment and test them with actual users.  This will enable you to effectively test a user's access prior to rolling it out to production but it will also give you an opportunity to discuss with other Admins the use cases which will make sense for your deployment. And because permission sets are supported in Change Sets, it's easy to move them from sandbox to production.

Instead of fixing existing profiles and their clones, consider preventing one-off profiles being created from this point forward as a good first step in phasing in permission sets.

If you do choose to remove permissions from your profiles and migrate them to your permission sets, consider doing the following:

  1. For any group of users, select/ask for 3-5 ‘volunteers’ to participate in a control group.  Make sure they have the time and willingness to give you feedback, and allot time for yourself to make corrections as they use the app.
  2. Do not delete existing profile.
  3. Create a baseline profile that represents all of the layout, field permissions, and other configurations necessary for this small group to get their job done. Keep in mind that this profile should be designed as a reusable set of baseline configurations (will be usable by more than this control group’s functional role).
  4. Create the additional permission sets consisting of user and object perms necessary for them to do their job.
  5. Add on other control groups to the profile, differentiating the users by the permissions in their specific permission sets.

As an example, you may have created a one-off profile in the past that represents all users who have read access to the app but a couple of additional permissions that make them different like the ability to single sign-on or use the API. Design a profile that removes these different permissions but establishes a baseline set of field permissions, layout assignments, etc that is a simple user.  For these users, add the permission sets that set them apart from this baseline profile including the necessary read permissions on objects. As other groups need to have some read access to the app, create different permission sets that represent that grouping but assign them the same profile that is shared by the original control group.

As with other org changes, implementing permission sets in phases using sandbox deployments and isolated use cases is the best practice for managing changes in a user's access rights.

07 June 2013

Why CIOs Shouldn't be Afraid of Shadow IT Organizations


I heard a little story the other day. Let me run it by you to see if you've ever come across this.

A small group of people with a big problem signed up for salesforce.com. They became proficient using and administering it. It was a huge productivity boost to one of their critical business process. Things were going so well that they flew too close to the sun. The CIO and the corporate IT organization discovered that there was a shadow IT organization within their walls.

One of the greatest fears of a CIO or VP of IT is when a shadow IT organization purchases, implements, and starts using a system that they have little knowledge or control of. Movement of mission critical apps to the cloud has made this more challenging for CIOs and is often discussed as the 'Consumerization of IT'.

Now the CIO and IT organization are playing catch-up; trying to gain oversight over the shadow IT group to ensure that they follow best practices and official security policies defined by the company. This is where terms like 'segregation of duties', 'least privilege', and 'escalated rights' get thrown around in the game of buzzword bingo. The scary part for the CIO and IT is that they not only need to get up to speed on salesforce.com, but they need to be smarter than the shadow IT organization that has a head start using it.

From my standpoint, this is where understanding how salesforce.com's access management is critical to the success of both groups. You neither want to limit the productivity of the shadow IT group too much, nor escalate their privileges within the corporate IT organization above what is appropriate.

From a process standpoint, there are really five critical steps get control of this situation:
  1. Identify user rights that may violate a security policy if mis-assigned or mis-used. This may vary by organization; however, I typically sum this up in four sensitive security permissions: Manage Users, Modify All Data, View All Data, and Customize Application.
  2. Determine which users have access to these permissions by checking their profiles and permission set assignments. These are the users you will need to monitor.
  3. Reduce your risk by segregating duties where applicable so that users have only what they need to perform a task and nothing more. There are a lot of different ways to do this in salesforce.com. I've blogged a couple different ways worth checking out such as: How Not to Give Out Modify All Data, Reduce Risk Through Re-Certification, and Maker-Checker. I'm also always amazed how few people I talk with know about the Delegated Administration feature.
  4. Create a governance policy that downloads and checks the Setup Audit Trail once per month. Look for patterns that may indicate a compromised security policy. For the most part, this pattern involves either changing the permissions in a profile/permission set or the assignment of any profiles/permission sets that have been identified as a potential security risk. Whenever a questionable activity is identified, flag the user and time in the audit trail.
  5. Finally, check the Login History to determine if the user performing questionable changes is actually a single user or multiple users sharing the same user account. This is easily done by viewing the history of logins for a user and correlating the Source IP, Browser, and Application fields. If there is a lot of variance, they have given their credentials out to other people. Once a user voluntarily gives out their user credentials, you lose the ability to audit their actions. Plus, it's actually a violation of the terms of service.
Most of the conversations I have with CIOs and VPs of IT start from a place of fear but in reality, there are a lot of proactive and reactive ways in which they can limit their risk. 

As Sun-Tzu once said, "If you know the enemy and know yourself, you need not fear the result of a hundred battles."