Authentication in JanusGraph Server


Graham Wallis <grahamwallis.dev@...>
 

Hi, 

I've been trying to use authentication over a websocket connection to a JanusGraph Server. 

If I configure the server to use a SimpleAuthenticator and a TinkerGraph for the credentials, as described in the Tinkerpop documentation, it works. 

In this mode, my gremlin-server.yaml is configured for authentication as follows: 

authentication: { 
  authenticator: org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator, 
  authenticationHandler: org.apache.tinkerpop.gremlin.server.handler.SaslAuthenticationHandler, 
  config: { 
    credentialsDb: conf/tinkergraph-credentials.properties 
  } 

where the tinkergraph-credentials.properties file is the same as the example from Tinkerpop:

gremlin.graph=org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph 
gremlin.tinkergraph.vertexIdManager=LONG 
gremlin.tinkergraph.graphLocation=data/credentials.kryo 
gremlin.tinkergraph.graphFormat=gryo 

My gremlin-server.yaml also has the following SSL configuration: 

ssl: { 
  enabled: true, 
  sslEnabledProtocols: [TLSv1.2], 
  keyStore: server.jks, 
  keyStorePassword: mykeystore 

I've created a self-signed certificate for localhost, added it to the server.jks keystore (with the key password the same as the store password). 
Because my client (console) is on the same machine as the server, I used the server.jks keystore as the truststore for the client, and created 
a sasl-remote.yaml file for the client, with the following: 

hosts: [localhost] 
port: 8182 
serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }} 
username: stephen 
password: password 
connectionPool: { 
  enableSsl: true, 
  sslEnabledProtocols: [TLSv1.2], 
  trustStore: server.jks, 
  trustStorePassword: mykeystore 
} 
I can start a gremlin-console and connect to the server, using the credentials ("stephen", "password"). 

:remote connect tinkerpop.server conf/sasl-remote.yaml session 

and subsequent remote operations against my (real) graph succeed. 

The above all works nicely. I can step through the invocation of SimpleAuthenticator's authenticate() method in the server in the debugger and it does exactly what you'd expect. 


If I try to do the same using a JanusGraph DB to store the credentials I can't get the client to authenticate. 

I tried using the following janusgraph-credentials-server.properties file for my credentials store: 

gremlin.graph=org.janusgraph.core.JanusGraphFactory 
storage.backend=berkeleyje 
storage.directory=../cred/berkeley 

And changed my gremlin-server yaml as follows: 

authentication: { 
  authenticator: org.janusgraph.graphdb.tinkerpop.gremlin.server.auth.JanusGraphSimpleAuthenticator, 
  authenticationHandler: org.apache.tinkerpop.gremlin.server.handler.SaslAuthenticationHandler, 
  config: { 
    defaultUsername: graham, 
    defaultPassword: sasl-password, 
    credentialsDb: conf/janusgraph-credentials-server.properties 
  } 

The ../cred/berkeley database is created during start of the gremlin-server. If I subsequeently stop the server and open the credentials database using a gremlin-console (locally) I can see that the default user has been added to it, the vertex is correctly labelled (as 'user') and the username and (hashed) password match. So the credentials store looks OK. 

However, if I now create a connection to the server and try to perform an remote operation, it doesn't authenticate and always results in "Username and/or password are incorrect". 

Stepping through the server code in the debugger, I noticed that the JanusGraphSimpleAuthenticator authenticate() method is never called, because the handler calls the SimpleAuthenticator's authenticate() method directly. This is probably fine as the former delegates to the latter anyway. But when the SimpleAuthenticator's authenticate() actually performs the credentials traversal, it does not find the user. 

I wondered whether I shuold be using a JanusGraph specific authentication handler, but that doesn't look like it would help; for a websocket connection the SaslAndHMACAuthentiucationHandler will delegate to the channelRead method of its superclass, i.e. SaslAuthenticationHandler, which is the same as the above. The only difference I can see in the code is that the SimpleAuthenticator is using a Tinkerpop generic Graph to create its CredentialTraversalSource, whereas the JanusGraphSimpleAuthenticaor uses a JanusGraph. 

Please can anyone can see what I'm doing wrong? 


Best regards,
 Graham

Linux Foundation LFAIData
Project: Egeria

Join {janusgraph-users@lists.lfaidata.foundation to automatically receive all group messages.