On the Question of Data Separation...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-24-2014 01:21 PM
The need to securely segment data between groups, departments, or even locations is constant, even within IT organizations. What organization doesn't have a particular group that is subject to extenuating compliance requirements that necessitate that their data remain hidden from the rest of the organization? As we delve deeper into the world of Enterprise Service Management, this need only grows. I have yet to find an HR organization that doesn't wish to keep their data separate from IT. Additional requirements for the financial department, medical organizations, etc only add to the complexity!
Historically, there have been 3 methods by which to attack this:
- Access Control Rules - These make sense at first glance, but can be a real drag on performance. For simple needs, field level security, and role-based security, you're all good! For complex scripted conditions, you'd best keep these at arm's length. Remember, that script with 2 GlideRecord queries that you built into that ACL is going to run for every single record on that 1.2 million record Incident table at Acme Corp, and every single time you view the table - that's potentially 2.4 million queries needed for a simple table list! Not to mention that your users will see that annoying "XX rows removed by security" message every time they view that list.
- Domain Separation - Pure power! Domain separation is a wonderful thing - separated and secured data between every domain; not to mention the ability to have separate processes for each domain - business rules, client scripts, and now even workflows that are unique to each domain in your instance! Sounds great, but make sure you know what you're getting into. The maintenance and testing requirements on a domain separated instance are far larger than a typical instance, and there is a financial uptick that comes with a license to use domain separation. If you need separated processes between domains, go for it! If you only need separated data, then this may be a hammer too big for the nail.
- Before Query Business Rules - These are en vogue these days, and for good reason! But, they can sound a bit intimidating. What exactly do they do? Well, before query business rules allow you to inject custom queries onto the front of every database access, so that you may limit the data returned according to whatever custom requirements you may have - these rules can be specific to particular tables and user sessions, providing a great deal of flexibility. The best part? Before query business rules only run once for each table access. So, compared to option 1 above (with the 2.4 million queries), this option only requires a single query - quite a bit more efficient, eh?
Note that each of the methods above apply to every database access - meaning that simple lists will be affected, but so will data returned in your CMS pages, your knowledge base, reference fields, etc. Each of these methods is equally secure and should be functionally identical to the end user. And each one has it's own valid use cases. So, which should you choose? Whenever I'm approached with this question, I generally have 3 golden rules:
- Are you segmenting data at the field level? In other words, do you want group A and group B to both have access to a given record, but only group B should be able to see field XYZ? If so, then Access Control Rules are your only option - the other options segment data at the record level.
- Do you require significantly different processes between group A and group B, as well as segmented data? Are there many such groups that each require their own processes and own data? If so, Domain Separation is your baby. There is some gray area here, as small levels of process differentiation are possible via simple code. But, for significant variations, DS all the way.
- In almost all other cases, go with Before Query Business Rules. They're relatively cheap, both financially and computationally, and they get the job done.
Disclaimer: Promotional Material Below...
Understanding that Golden Rule 3 will apply to most folks, and understanding that configuring before query business rules can be onerous, I've put together an application to simplify the process of building the most efficient business rules with the least amount of effort and time. This solution is available on ServiceNow Share currently, and has been road-tested heavily. Check out the video below, try it out in your dev instance, and see if it works for you!
Simple Record Separation on Share
For the latest supported release, visit Simple Separation on the ServiceNow Store
- Labels:
-
Multiple Versions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-24-2016 01:02 PM
Ben,
I wrote an onBefore Query business rule from scratch and got it to work. HOWEVER, I'd like to use your tool with this code, but I can't get it to work if I customize the query via the cool tool.
function onBefore(current, previous) {
var group = new GlideRecord('sys_user_group');
group.addQuery('name','EMS');
group.query();
if(group.next()){
if(gs.hasRoleInGroup('ncpi',group)){
gs.log('has role');
}
else{
gs.log(gs.getUser()+' does not have ncpi role');
var qc = current.addQuery('assignment_group',gs.getUser());
qc.addOrCondition('assignment_group','NOT IN','6297e1416f630100244eeef11c3ee4b8'); //EMS
qc.addOrCondition('assignment_group','');//not blank
}
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-24-2016 01:11 PM
I FIGURED IT OUT!!!!!
Really, the key was to remove "getMyGroups()" from the addQuery, and test for the role before calling the sepRecs() function. Can't figure out why I can't get the nice code editor to work on this thread. Please excuse how icky this looks.
//Only run group queries if user does not have ncpi role
var group = new GlideRecord('sys_user_group');
group.addQuery('name','EMS');
group.query();
if(group.next()){
if(gs.hasRoleInGroup('ncpi',group)){
//gs.log('has role');
}
else{
sepRecs();
}
}
sepRecs();
}
}
function sepRecs(){
//Basic data separation query
var qc = current.addQuery('assignment_group', gs.getUser());
//Selective application queries
qc.addOrCondition('assignment_group', 'NOT IN', '6297e1416f630100244eeef11c3ee4b8');
qc.addOrCondition('assignment_group', '');
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-24-2016 01:33 PM
Great work, Laurie - glad you were able to make it work!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-24-2016 01:39 PM
Um...slight bug...now no one can see the records. I think I'm close!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-24-2016 02:38 PM
Hey Ben,
I got the code to work, but via a business rule I wrote. Do you think at some point in time you might update your tool to include separation by role as an extra layer of protection? Here's our scenario. We are a a power company and regulated by NERC-CIP.
The NERC CIP (North American Electric Reliability Corporation critical infrastructure protection) plan is a set of requirements designed to secure the assets required for operating North America's bulk electric system.
Employees that require the ability to view NERC-CIP information must go through training and a background check. This information could be things like an IP address of an energy management system (EMS) server. If records are separated based on assignment group only, then someone might enter a change/incident/problem ticket with sensitive information and accidentally assign it to the wrong group (the non-EMS group). Additionally, it might be possible that someone is a member of the EMS group, but has not yet completed their training and background check. So the EMS group does not grant the role called 'ncpi' (nerc cip protected information). The ncpi role is granted to the person once they completed training and background check. So it's really an extra layer of protection. On the other hand, people with the ncpi role need the ability to see all other records in the system, so a read ACL would not work on the table.
We wanted our ncpi roled people to be able to use existing processes, forms, etc., and NOT use domain separation due to admin overhead, etc.
Here is my solution. If you see anything I'm missing, please point it out. I am merely a humble grasshopper...
var role = new GlideRecord('sys_user_role');
role.addQuery('name','ncpi');
role.setLimit(1); //only want to check for current user
role.query();
if(role.next()){
if(gs.hasRole('ncpi')){
//gs.log(gs.getUserDisplayName()+' has role');
}
else{
//gs.log(gs.getUserDisplayName()+' does not have ncpi role');
var qc = current.addQuery('assignment_group',gs.getUser());
qc.addOrCondition('assignment_group','NOT IN','6297e1416f630100244eeef11c3ee4b8'); //EMS Group
qc.addOrCondition('assignment_group','');//not blank
}
}