Neo4J Multi Tenancy and Role Based Access to Nodes - neo4j

I am trying to define a user management and permissions model for Neo4j. I have a web application (Angular 2) that connects to Neo4j via an API (KOANEO4J). Neo4j is the only database or persistent storage that the application uses. Through the application a user can add/edit/delete content which uses the API to carry out these instructions in Neo4j by running Cypher Statements. Up to now I have not worried about supporting multiple users but as a next step I am starting to think about this.
The product will be used by multiple different companies and each company will have multiple users so I need some way to support this. The model I am considering in Neo4J is as follows:
An "Orgaization" is represented by a node and it can have 1 or more "Organization Catalogs". All of the nodes belonging to that catalog will be children of one of the "Organization Catalogs".
Each user will also be represented by a node in the database. They will belong to an Organisation. They will have certain access permissions on an Organization Catalog identified by a an edge.
I am looking for some advice on whether or not this is an appropriate model to follow or if there are any examples or documents that describe how to achieve this in Neo4j.
If I do implement this model then would it be better to model the permissions as seperate nodes so a user is connected to a permission node (e.g. Read Only Access) that is then connected to the Organization Catalog.
Any suggestions on how I would actually get the API to work with this type of model. I'm sure I can pass the User Id to Neo4j as part of each query and then filter the results to show only nodes the user has access to but this doesn't seem like a very elegant solution - it also means that all of the security would be dependant on carefully written Cypher queries that don't leak data that a user isnt supposed to access.
Thanks a lot

I am looking for some advice on whether or not this is an appropriate
model to follow or if there are any examples or documents that
describe how to achieve this in Neo4j.
The answer for this question is: it depends. Remember that when modelling a graph database you should consider the queries that are asked to the database. If this model fits the queries that you are asking to the database then this model is appropriated, otherwise, not. Take a look in the Chapter 5 (Graphs in the Real World) of the book Graph Databases (by Ian Robison, Jim Webber and Emil Eifrem. Available for download here). This chapter shows the modelling process of an Authorization and Access Control system in Neo4j. Can be enlightening and helpful to you.
If I do implement this model then would it be better to model the
permissions as seperate nodes so a user is connected to a permission
node (e.g. Read Only Access) that is then connected to the
Organization Catalog.
Again, it depends. Do it if the Permission entity has connection to others entities of your application besides an User and an Organization Catalog. Otherwise I believe that your permission can be modeled as a relationship between an user and an organization catalog.
Any suggestions on how I would actually get the API to work with this
type of model. I'm sure I can pass the User Id to Neo4j as part of
each query and then filter the results to show only nodes the user has
access to but this doesn't seem like a very elegant solution - it also
means that all of the security would be dependant on carefully written
Cypher queries that don't leak data that a user isnt supposed to
access.
Maybe is a good idea add another layer of software between your AngularJS client app and the Neo4j database. This way in this new layer of software (a Node.js application, for example) you can implement a access control system, then verifiy if the authenticated user can access the resource that is being requested.

Related

Can neo4j 3.* enterprise edition can control user data's access permission?

I'm using neo4j enterprise edition, and I found neo4j have no user data access control strategy, such as on user can grant some data's read/write permission to other user?
I found this: https://neo4j.com/docs/operations-manual/3.4-preview/security/authentication-authorization/subgraph-access-control/
The title is "Subgraph access control" but the content is control procedure's execution permission. It look likes have no relation with subgraph's access control...
I also found some people said that writing code to implement interface SecurityRole can resolve the problem, I can't found more information about this, is this right?
Thanks!
Subgraph access control is about restricting a user's ability to access the graph so that they can only go through the procedures granted to them. The code in the procedures should encapsulate the kind of queries you want them to be able to use, so either the procedures contain the queries in full, or it allows queries but performs filtering at some level.
While this can work, it may not have the right granularity for what you're trying to do, and it is a somewhat clunky approach.
Additional work is being done to fill in those gaps.
In the upcoming Neo4j 3.4, you will have the ability to restrict access to properties of nodes, though this is across all nodes, not just nodes of certain labels, and it will rely on a blacklist that is defined in the neo4j.conf file, so (at this point) requiring a restart to change which roles are blacklisted from accessing certain properties (though you should be able to grant roles to users through procs as usual, no restart needed).
There's more work to be done on this of course, it's just a matter of feature prioritization, so richer options are likely to be introduced in later releases.

Subgraph access control

In the official Documentation (3.1: http://neo4j.com/docs/operations-manual/current/security/authentication-authorization/subgraph-access-control/)
It is said
"For example, a user can be allowed to read, but not write, nodes labelled with Employee and relationships of type REPORTS_TO"
But nowhere it's written in this page and others how to do it.
With the "call dbms.procedures()" we can see many more function in the enterprise edition but nothing about defining this Subgraph control
We think on changing the an enterprise edition, but if we are sure to be able to do that.
Can anyone explain me or gives me the address of the relevant documentation
Thanks
The documentation is all right there. Note the first sentence:
Through the use of user-defined procedures and custom roles, an
administrator may restrict a user’s access and subsequent actions to
specified portions of the graph.
The approach seems to be, for users without write permission, create roles for them as appropriate, then create (or use existing) user-defined procedures to do what operations they are allowed to do. Then configure the permissions of the procedures to the appropriate level, and associate the roles of the procedures (by modifying dbms.security.procedures.roles) with the roles you previously created. This allows the procedures you created to be executed by the roles you associated it with.
For example, given an HR user, who does not have write permissions, you could create a procedure to create or delete a :REPORTS_TO relationship between :Employee nodes. The procedure would need to be set to mode=WRITE since it needs write access. This would normally not be executable by this HR user, since they don't have write permissions.
But if you created a role, say 'hr', and added that role to this user, and set the procedure to be accessible by the hr role in dbms.security.procedures.roles, then the hr user could execute this procedure, and it would perform the necessary write operations.
In summary, Neo4j's subgraph access control isn't defined on the nodes or labels themselves, nor does it apply when executing write statements in Cypher. This access control is specific to user-defined procedures, and allows users with certain roles (where that role is associated with those procedures) to execute those procedures even if they normally would not be able to due to their access level.
EDIT
One final thing that could work for you...Neo4j has a means of registering transaction event handlers that can perform checking and logic on a transaction in progress, and reject if some criteria are not met. I would assume you could get a user's roles here, and probably check the transaction for writer operations on certain labels. Odd that this wasn't referenced in the securing the subgraph section of the documentation. I haven't tried this approach myself (I'll try my own testing later) so I'm not sure if it will fulfill what you need, but it's worth a look.
UPDATE:
It's been awhile, but we do have a more comprehensive means of access control coming to the upcoming Neo4j 4.0.
4.0 will include schema-based security, full ability to define, per user and role, the ability to grant or deny various levels of permissions (read, write, traverse, and more) for nodes and relationships of specific types. So for example you can have various roles that only have visibility on certain kinds of nodes, or are specifically denied visibility on others. You can also restrict whether certain nodes can be traversed through at all.
This should fulfill the needs of everyone who has been waiting for a more comprehensive security and access solution in Neo4j.
Here's the Neo4j 4.0 MR2 documentation, more to come as we approach the official 4.0 release!

Neo4j data modeling query

I am working on a project (platform) where I am using neo4j to make connections between users. There are following different ways where user can connect to other users on the platform.
When a user logs in with Facebook, I get his mutual friends who are already using our platform. There I make a connection in my graph database by creating a new node (current user) and make connections with all existing nodes whom he knows through facebook.
One user also connects with other user if both are staying in same society/community. So the use case is, once a user updates his residential address (society name, city) than I make a query in graph db and get all nodes who also stay in the same society and create this new user with those nodes with relationship name "Same society".
Same was user might be connected with other user if both users study in same college or school. I make a connection between two nodes with relationship "Same college/school".
What is the best way to model the above problem in neo4j? If I do a query in DB to get all the relationship types and shortest path of all the relationships between given two nodes, which model will be optimized for this type of query?
Simply create a relationship between users
(user)-[:FRIEND_OF]-(user)
Relationships in neo4j are always directional, but you can ignore the direction because, in this case, it doesn't make much sense. There is no performance penalty for traversing a relationship "backwards".
Create a node representing your society/community and link all users living there to that node. This has several benefits:
when you add new user to a community you only create one relationship (compared to linking the user directly to all users, which is N relationships), same goes for removing user from community.
you can create different relationships between the user and community
(user)-[:LIVES]-(community1)
(user)-[:WORKS]-(community2)
This is essentially the same as no. 2. You can differentiate between types of communities (schools, etc..) by having different labels/properties.
Finding a shortest path between two nodes in this model will give you their closest connection, the kind of "know via something". You may limit the path by relationship type/community type etc.

Deploying Neo4j database

so I developed a small Neo4j database with the aim of providing users with path-related information (shortest path from A to B and properties of individual sections of the path). My programming skills are very basic, but I want to make the database very user-friendly.
Basically, I would like to have a screen where users can choose start location and end location from dropdown lists, click a button, and the results (shortest path, distance of the path, properties of the path segments) will appear. For example, if this database had been made in MS Access, I would have made a form, where users could choose the locations, then click a control button which would have executed a query and produced results on a nice report.
Please note that all the nodes, relationships and queries are already in place. All I am looking for are some tips regarding the most user-friendly way of making the information accessible to the users.
Currently, all I can do is make the users install neo4j, run neo4j every time they need it, open the browser, run the cypher script and then edit the cypher script (write down strings as locations) and then execute the query. This makes it rather impractical for users and also I am worried that some user might corrupt the data,
I'd suggest making a web application using a web framework like Rails, especially if you're new to programming. You can use the neo4j gem for that to connect to your database and create models to access the data in a friendly way:
https://github.com/neo4jrb/neo4j
I'm one of the maintainers of that gem, so feel free to contact us if you have any questions:
neo4jrb#googlegroups.com
http://twitter.com/neo4jrb
Also, you might be interested in look at my newest project called meta model:
https://github.com/neo4jrb/meta_model
It's a Rails app that lets you define via the web app UI your database model (or at least part of it) and then browse/edit the objects via the web app. It's still very much preliminary, but I'd like to be able to things like what you're talking about (letting users examing data and the relationships between them in a user friendly way)
I general you would write an tiny (web/desktop/forms-)application that contains the form, takes the form values and issues the cypher requests with the form values as parameters.
The results can then be rendered as a table or chart or whatever.
You could even run this from Excel or Access with a Macro (using the Neo4j http endpoint).
Depending on your programming skills (which programming language can you write in) it can be anything. There is also a Neo4j .Net client (see http://neo4j.com/developer/dotnet).
And it's author Tatham Oddie showed a while ago how to do that with Excel

Documents as nodes and Security Mechanism

I'm very new using either neo4jDatabase or neo4jclient driver, I'm trying to create a proof-of-concept to understand if make sense to use this technology and I've the following doubts, (I tried to search over the web but no answers...).
I have some entities that have Documents associated with them, (PDFs, DOCx ...), is it possible to have a Node property pointing to those documents? or Can documents be added as a Graph Node with a Lucene index so that a search could return document node and related relationships?
How does the Security works? is it possible to the users have access to the nodes taking in consideration their profile? Imagine that the nodes represent documents how can be implemented a security mechanism that the users only access their nodes (Documents)?
Q1: You can simply add a node property with a URI referencing the document of choice. That could be pointing to blob storage, local disk, wherever you store your documents. You could add binary objects in a node's property (by using a byte array) but I wouldn't advise doing that, since that just adds bulk to the database footprint. For reference, here are all the node property types supported.
Q2: Security is going to be on the database itself, not on nodes. Node-level (or document-level in your case) security would need to be implemented in your application. To keep data secure, you should consider hiding your Neo4j server (and related endpoint) behind a firewall and not expose it to the web. For example, in Windows Azure, you'd deploy it to a Virtual Machine without any Input Endpoints, and just connect via an internal connection. For all the details around neo4j security, take a look at this page.
1) What David said.
2) For resource level security, you need to model this in to your graph. There's an example at http://docs.neo4j.org/chunked/milestone/examples-acl-structures-in-graphs.html

Resources