Authentication in JanusGraph Server


grahamwallis.dev@...
 

Thanks for looking at it Marc, and for raising the issue.

As you say, we can work around the issue by using a different persistent store, but I must admit to being intrigued as to why it seems to not work with berkeleydb. If I get time I will do some more digging - and will add any comments to the above issue.

Thanks again
  Graham


hadoopmarc@...
 


hadoopmarc@...
 

Hi Graham,

This was certainly one to investigate for the weekend. Where you started investigating from the inside of janusgraph, I started from the user perspective and this is what I did:
  1. I replicated your steps on janusgraph-full-0.5.3 and hit the same issue (incorrect username/password)
  2. I also replicated your steps on janusgraph-0.3.2 to be sure no bugs were introduced in later versions, but still the same issue
  3. I checked the old user list and found https://groups.google.com/g/janusgraph-users/c/iVqlUS2zQbc/m/vmf8PgEQBAAJ  This was interesting: someone had problems with the credentialsDb and only got it working after switching from a Berkeleyje backend to an HBase backend. This was a pattern: your issue also was with Berkeleyje
  4. In the authentication section of the gremlin-server.yaml I changed the properties file for the credentialsDb to one using cql-es with a keyspace "credentials" and... remote authentication worked
This was a nasty one, but the effort you had already taken inspired me to do my part. I will make an issue report for this on github.

Best wishes,   Marc


grahamwallis.dev@...
 

Hi @hadoopmarc,

Thanks for replying and no apology needed - it's a good question. Although I failed to mention it in my question, I did set the credentials to ('graham','sass-password') in the sasl-remote.yaml file when testing with the JanusGraph as credentials store.

Setting a breakpoint in the server I could see the correct credentials being received, and the credentials store traversal looked fine; but no vertex is returned.

All the best
  Graham


hadoopmarc@...
 

Sorry for asking, but you did not state it explicitly: you did modify your sasl-remote.yaml file to reflect the new ('graham', 'sasl-password') credentials, did you?

Marc


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