DEV Community

loading...

Help: Security per record - is it possible to make optimal solution ?

Haris Secic
software developer doing some architecture
・2 min read

So I have a case where data structure looks more like a graph so lets say (object)->(another one)->(yes, antoher)->(even more). And this is stored in graph DB but there's "piled" data which is stored in different engine as pile of things referenced by some filed to vertex/node in graph one.

My problem is that I need security "user per object" where each user can have different access rights, and no role will help in this case as most of the users have different access rights even when they work at same position. So this is what I would call access grant per record or per object.

Now if someone has access to particular object he automatically has access to parent objects. But for example lets say I have (A)->(B) and (A)->(C). If I can access B I should be able to get A but not necessarily C.

I do plan to integrate something like HashiCorp Consul or if there's another similar thing which is easy to use but I don't think this can help at all. I also do have SSO but as any other it mainly relies on roles and such.

BTW, system is multi tenant so adding a new record to a specific user should be visible only for that particular client users, and Admin should decide who get's to see what.

So couple of ways to do it:

  1. Have enormous amount of custom queries which filter out data - slow, hard to maintain and possible to leak data when new features are added or changes are introduced.
  2. Middleware that handles access per object only - also slow due to a lot of network calls like Client -> load balancer -> API -> DB -> API -> middleware -> DB of the middleware -> middleware -> API -> load balancer -> Client. This could be used with some form of in memory cache which would speed up thing to some extent.
  3. Have in-memory filter where each record stored and modified by admin has it's access towards each user cached - extra expensive to have huge amounts of RAM for such a cache
  4. Have SSO deal with it through roles - now I have no idea how would I automate adding roles for each new object inserted to the system, and why would I have so much roles. Users have single access for SSO, so the actual roles would have to spill all over place as there's things like user from one tenant can be added to access some of the data of another tenant...

Anyone have ideas on how to deal with this in optimal way? I really do need help, maybe some software for this I didn't know exits or using SSO or Consul properly somehow for this?

Discussion (7)

Collapse
phlash909 profile image
Phil Ashby

This feels like your "requirement" is actually a work around or poorly expressed business need?

If your business really needs fine-grained per-user access controls, then people are going to be spending most of their time managing those rules, never mind coding a system that can apply them.

I would strongly urge you to have conversation with the requirement owner(s) and get a broader understanding of their needs, which may resolve into something your chosen graphDB can do already (many have RBAC built in), if the existing/incoming data can appropriately classified and can be assigned to appropriate consumer roles?

We have similar challenges in my world (identity verification), where we have large graphs of relationships between people / things, but not all our customers can know what we know, due to various constraints from supplier contract, legal jurisdictions and customer licences - thus we use data source identifiers to classify data, and can map each of our customer organisations, through their licence and location (jurisdiction) to roles that permit appropriate access.

Collapse
greenroommate profile image
Haris Secic Author

Thanks a lot for the answer. I do have a problem where this is actually a requirement and people will be spending a lot of time managing access control through out the system.

I remembered one real world example on small scale. Let's say you have a building and it has floors and rooms on it. Now you wan't some users to access some rooms. But not all. So if you give user access to room 2001 on floor 2, it means that user has to have access to a building because he cannot access floor unless he access room. But on the other hand he doesn't have to have access to floor 1, he can use elevator directly to floor 2, and have a key or a card for specific room.

Now my problem in comparison to example would be I have customers owning thousands of buildings. And I have a lot of customers. And some of them want to offer access to users belonging to a different client BUT only for SPECIFIC buildings :D

I tried to push something which most people hate me for and that is "tell clients this cannot work good and let's have access per parent". I'm not sure will it work (will sales accept the suggestion and will clients agree on it as reasonable approach) but if so I still need to have access per building and you if you have 1 user with access to buildings A,B,C another one can have access to C,D and third one to B,D,N,L,M. So I would have to do all permutations of it to make roles or have role per object in database which still brings me to I need access control inside of my own graph database and roles don't help at all as in this case it's much easier to have users have access to different parts.

Your example sounds interesting but I have no idea where to start with it so I'll start searching for "data source identifiers" and check if something pops up.

Again, thanks a lot for the answer.

Collapse
phlash909 profile image
Phil Ashby

Nice analogy - thanks, and glad you aren't trying to solve a non-existent problem :)

As @tonymet suggests, this does feel like a file system in some ways. Perhaps you can use the graphDB primarily as the permissions management system though appropriate use of relationships from a node to nodes that represent users, so you can express the 'room access' you describe and build searches that apply the stated permissions (by requiring the edges back to the user(s)), then collecting related attributes from the 'pile' once you have filtered down the nodes?

Thread Thread
greenroommate profile image
Haris Secic Author

I'm actually working towards it. Thanks. Also the thing with this one was performance concern, where I have additional call to access management API, or even if I kind of "monolith it" I still need that extra call to filter out data not allowed for specific users. I'll look into options for my framework and how not to redesign whole architecture because of this but still maintain some performance. Anyways I think it's safe to say I'm using Neo4j sa graph db and Spring (for now) as framework so there might be a way. Just not here yet.

But more importantly I value your answer as it gave me some encouragement that there's just no way around "user per resource" as it's a requirement, but it might be not that bad as I think.

Just want to share latest experiment in Cypher

RETURN EXISTS((s)-[*0..]->()<-[:HAS_ACCESS]-()<-[:HAS_ROLE*0..1]-(u))

So this would work for both User having direct access to a certain object or Role having access to it. It's also relying on a fact that only parents point to children not the other way around. So if I have two options:
(SuperParent)->(Parent)->(Child)->(Edge)
(SuperParent)->(Parent2)->(Child2)
where User - has access -> child2 but Role -> has access -> child 1
I can get true for

MATCH (c:Child) WHERE c.name = 'Child' OR c.name = 'Child2'
MATCH (u:User {name: "user1"})
RETURN EXISTS((s)-[*0..]->()<-[:HAS_ACCESS]-()<-[:HAS_ROLE*0..1]-(u))

so it either uses Role if it can or ignores it. And it's quite fast to my surprise, however it's just a sample cypher on sample DB. But also I can ask for Super parent in same query and get true. But it does go through Role as it's using most of the relationships or it might be that role access relationship was made first so it hits it first.

So I discovered that I can have optional relationships and mandatory ones in query with Neo4j. Might write post about this one as I find it interesting what can you do with cypher regardless of what I use in the project.

Collapse
tonymet profile image
Tony Metzidis

Sounds just like a filesystem. put the objects on disk, protect them with ACLs (eg chmod)

Collapse
greenroommate profile image
Haris Secic Author

Good point, however I need it in DB for many other things. But I could investigate on how to "mimic" this approach. Had stuff on file storage previously but searching was not so optimal and projections were hard, although it was cloud storage so no ACL was possible without having users as part of the cloud provider user system which was not an option at that point.

Collapse
tonymet profile image
Tony Metzidis

no reason not to use both