Vertexium Security Model With Code Examples

Note: The code for these examples is available at github

At work, I use Vertexium day-to-day. Not only is it a graph database that can scale well to large sizes of data, but it has cell-level and element-level security which is useful in situations where certain people are not allowed to see certain parts of the the graph.
Let’s say that you are developing an application for a call center and when a customer calls in, their personal information will appear in front of whoever answered. Due to some reason, regular call center employees who answer the phones are not allowed to see all of the information about a person, but their manager is. Since Vertexium is a graph database, the data will probably be stored in a vertex like this:

VertexId = PersonVertex

Property Value
FirstName John
LastName Johnson
SSN 123-45-6789

In order to store and retrieve that data, you can use the following code for Vertexium (look at the repository if you want to run the code yourself):

Storing Vertices and Properties

Example in the Example Repository in src/main/java/com/rgimmy/vertexiumsecurityexamples/Example1.java

Map<String, Object> config = new HashMap<>();
InMemoryGraphConfiguration configuration = new InMemoryGraphConfiguration(config);
InMemoryGraph inMemoryGraph = InMemoryGraph.create(configuration);
Authorizations authorizations = inMemoryGraph.createAuthorizations();
Visibility visibility = Visibility.EMPTY;

//create vertex
Vertex vertex = inMemoryGraph.addVertex("PersonVertex", visibility, authorizations);
vertex.setProperty("FirstName", "John", visibility, authorizations);
vertex.setProperty("LastName", "Johnson", visibility, authorizations);
vertex.setProperty("SSN", "123-45-6789", visibility, authorizations);
inMemoryGraph.flush();

Reading Vertices and Properties

//read vertex
Vertex readVertex = inMemoryGraph.getVertex("PersonVertex", authorizations);
System.out.println("ID: " + readVertex.getId());
System.out.println("FirstName: " + readVertex.getPropertyValue("FirstName"));
System.out.println("LastName: " + readVertex.getPropertyValue("LastName"));
System.out.println("SSN: " + readVertex.getPropertyValue("SSN"));

Output:

ID: PersonVertex
FirstName: John
LastName: Johnson
SSN: 123-45-6789

We expect to get all of the data back since since we haven’t used any special authorizations and/or visibilities.

Authorizations and Visibilities

Now, you may have noticed that there is both Authorizations and Visibility in those code snippets. What is the difference between the two? The short answer right now is that you use visibilities while writing data while you use authorizations while reading data. The API calls that we use here require both since it does a little bit of both, but if you use more advanced parts of the Vertexium API, you can use them individually and will need to know what they do.

Now, back to our original problem, you want to develop a way for managers to see more data than the regular people in the call center. In order to do that, we must tag the restricted data with a visibility so that it will not be visible to people without the authorization to see that data. To do that, we will modify the previous example with the following:

Store with different authorizations

Example in the Example Repository in src/main/java/com/rgimmy/vertexiumsecurityexamples/Example2.java

Map<String, Object> config = new HashMap<>();
InMemoryGraphConfiguration configuration = new InMemoryGraphConfiguration(config);
InMemoryGraph inMemoryGraph = InMemoryGraph.create(configuration);

String securityTag = "manager";
Authorizations noAuthorizations = inMemoryGraph.createAuthorizations();
Authorizations higherLevelAuthorizations = inMemoryGraph.createAuthorizations(securityTag);
Visibility visibility = Visibility.EMPTY;
Visibility highLevelVisibility = new Visibility(securityTag);

//create vertex
Vertex vertex = inMemoryGraph.addVertex("PersonVertex", visibility, higherLevelAuthorizations);
vertex.setProperty("FirstName", "John", visibility, noAuthorizations);
vertex.setProperty("LastName", "Johnson", visibility, noAuthorizations);
vertex.setProperty("SSN", "123-45-6789", highLevelVisibility, higherLevelAuthorizations);
inMemoryGraph.flush();

Retrieve with different authorizations

//read vertex as no authorization user
System.out.println("=====reading vertex as regular user======");
Vertex readVertex = inMemoryGraph.getVertex("PersonVertex", noAuthorizations);
System.out.println("ID: " + readVertex.getId());
System.out.println("FirstName: " + readVertex.getPropertyValue("FirstName"));
System.out.println("LastName: " + readVertex.getPropertyValue("LastName"));
System.out.println("SSN: " + readVertex.getPropertyValue("SSN")); // this will be null

//read vertex as elevated user
System.out.println("=====reading vertex as elevated user======");
readVertex = inMemoryGraph.getVertex("PersonVertex", higherLevelAuthorizations);
System.out.println("ID: " + readVertex.getId());
System.out.println("FirstName: " + readVertex.getPropertyValue("FirstName"));
System.out.println("LastName: " + readVertex.getPropertyValue("LastName"));
System.out.println("SSN: " + readVertex.getPropertyValue("SSN"));

Output

=====reading vertex as regular user======
ID: PersonVertex
FirstName: John
LastName: Johnson
SSN: null
=====reading vertex as elevated user======
ID: PersonVertex
FirstName: John
LastName: Johnson
SSN: 123-45-6789

So you can see that if you are not correctly authorized, you can’t see the properties. In this example, when we tried to pull back the SSN property, there was no value at all that came back. When we refer to cell-level security, the cells are represented as properties in the vertex. This extends to properties on both edges and vertices, but the whole concept applies to vertex and edges themselves through the concept of vertex-level security. Going back to our example if the call center worker tries to pull up data that they don’t have access to, or shouldn’t even know about (maybe you have a celebrity as a person in your database and your corporate policy doesn’t allow regular workers to see that they are in the system.) For example, if you don’t have the correct authorizations, you will be unable to pull back a vertex you don’t have access to in the following code:

Store different authorizations on vertices

Example in the Example Repository in src/main/java/com/rgimmy/vertexiumsecurityexamples/Example3.java

Map<String, Object> config = new HashMap<>();
InMemoryGraphConfiguration configuration = new InMemoryGraphConfiguration(config);
InMemoryGraph inMemoryGraph = InMemoryGraph.create(configuration);

String securityTag = "manager";
Authorizations noAuthorizations = inMemoryGraph.createAuthorizations();
Authorizations higherLevelAuthorizations = inMemoryGraph.createAuthorizations(securityTag);
Visibility visibility = Visibility.EMPTY;
Visibility highLevelVisibility = new Visibility(securityTag);

//create vertex
inMemoryGraph.addVertex("PersonVertex1", visibility, noAuthorizations);
inMemoryGraph.addVertex("PersonVertex2", highLevelVisibility, higherLevelAuthorizations);
inMemoryGraph.flush();

Retrieve vertices with different authorizations

System.out.println("=====reading all vertices as regular user======");
Iterable<Vertex> vertices = inMemoryGraph.getVertices(noAuthorizations);
for(Vertex vertex : vertices){
    System.out.println(vertex.getId());
}

System.out.println("=====reading all vertices as elevated user======");
vertices = inMemoryGraph.getVertices(higherLevelAuthorizations);
for(Vertex vertex : vertices){
    System.out.println(vertex.getId());
}

Output

=====reading all vertices as regular user======
PersonVertex1
=====reading all vertices as elevated user======
PersonVertex1
PersonVertex2

If you don’t have the security tag (also called Authorizations in the vertexium world) you are unable to retrieve the properties with those tags. This is pretty powerful for a couple of reasons:

  1. Security is stored alongside the data so your app doesn’t have to deal with complicated
  2. It is relatively easy from an administrative perspective to add/remove security tags from individual users
  3. It is more difficult to leak data to unprivileged people

1. Security alongside the data

We have probably all developed on platforms that, if you have access to the database, you have the full reign of all of the data. There are plenty of ways to mitigate that threat, but Vertexium typically uses an Accumulo so we can go a step further and make sure that each user needs the correct authorizations as well as the correct credentials to go a step further and ensure that no one can see anything that they are not authorized to see

2. Easy administration

Is your user getting promoted to another position in which they need more access to the data? Simply add the correct authorizations and you will get all of the new data by default in your application. No muss, no fuss, except for adding the authorizations to your users of course.

3. No data leaks

If your user doesn’t have the correct authorizations, the data isn’t even brought back from Accumulo. That means that there isn’t any filtering that needs to be done client-side, which is not typically the case for other graph databases. Vertexium was designed on top of Accumulo with their security model in mind. These examples only use the inmemory implementation of Vertexium and do not use Accumulo, but these are illustrative examples only. The simple concept of tagging the data and storing the security information with it leads to a very robust and secure platform on which to develop apps, which is what I do every day at Visallo. If you are interested in working at Visallo, chatting about security models, or anything else, drop me a line at ryan@visallo.com.