System security is probably one of the more challenging things to implement in Service-now.com.  While an out-of-box ServiceNow instance comes with the core security built-in, any implementation will inevitably have customizations in this area.  At some point, I plan on writing a basic security guide to help administrators and consultants make informed decisions about how security should be implemented in their systems.

I’ve now added the security guide I promised! Check out the ‘What Everybody Should Know about ServiceNow Security‘ article for more details!

One little-known, but extremely useful access control method is to use business rules to restrict record access in your system.  You can do this by creating what I call a ‘Before Query’ business rule.  These business rules have a ‘When’ value of ‘Before’ and also have the ‘Query’ checkbox selected.  ‘Before Query’ business rules are only used when you need to restrict access to certain rows within a table for certain groups of individuals.  Because the security is controlled by a script, the restriction can be applied based on roles, group membership, company or department information from the user record, or pretty much anything else that you can derive about the user trying to access a set of records.  There are a few of these business rules out-of-box that serve as great examples of how to implement security in this way.  When I need to implement security with a ‘Before Query’ business rule, I usually start with the ‘incident query’ business rule as my template.

The purpose of the ‘incident query’ business rule is to limit the access of records (rows) on the ‘Incident’ table.  Specifically, it says that you need to have the ‘itil’ role to access incident records unless you are the person listed as the Caller or Opened by on the Incident.  It is because of this business rule that your end-users can only see their own incident records in the system!  Below is the script (along with comments explaining exactly how it works).

if (!gs.hasRole('itil') && gs.getSession().isInteractive()) { //Check if the user has the 'itil' role and if the session is an actual user session
   //If they DON'T have the 'itil' role then do the following...
   var u = gs.getUserID(); //Get the sys_id value of the current user
   var q = current.addQuery('caller_id', u); //Modify the current query on the incident table so that if the user is listed in the 'caller_id' field they can see the record
   q.addOrCondition('opened_by', u); //Also allow the user access if they are the one who opened the incident (even if they aren't the caller)
   gs.print('query restricted to user: ' + u);
}

Here’s another example. This time we will restrict visibility to records if the user is a member of the current assignment group.

if (gs.getSession().isInteractive()) {          
   //Restrict to caller or members of assigned group...
   var u = gs.getUserID(); //Get the sys_id value of the current user
   var g = getMyGroups(); //Get the list of the current user groups
   var q = current.addQuery('caller_id', u).addOrCondition('assignment_group', getMyGroups()); //Modify the current query on the incident table
}
Any time you’re working with ‘Before Query’ business rules you’ll want to be sure you account for a specific scenario you may encounter when you’re referencing the records you’re limiting access to. Setting things up incorrectly may mean that you end up with blank reference fields!