Skip to content

Commit

Permalink
Support for SASL (revisiting PR jbmusso#78) (jbmusso#83)
Browse files Browse the repository at this point in the history
* SSL and SASL support.

* Updating README to show how to use SASL Authentication.

* Update, adding user and password to options list.
Additionally, updating SASL auth example to remove session option, and adding ssl option.

* Changed ordering of options.

* -Moved utf8 importing to the top, to avoid reloading each time. (Also changed the pattern to follow standard javascript importing)
-Added an example for gremlin client with SASL. (username and pwd have to be set accordingly based on your gremlin server)
  • Loading branch information
vivekr20 authored and jbmusso committed Aug 29, 2017
1 parent 9387ae9 commit 747c080
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 2 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,26 @@ The `options` object currently allows you to set the following options:
* `path`: a custom URL connection path if connecting to a Gremlin server behind a WebSocket proxy
* `ssl`: whether to use secure WebSockets or not (default: `false`)
$ `rejectUnauthorized`: when using ssl, whether to reject self-signed certificates or not (default: `true`). Useful in development mode when using gremlin-server self signed certificates. Do NOT use self-signed certificates with this option in production.
* `user` : username to use for SASL authentication
* `password` : password to use for SASL authentication

## Using SASL Authentication

If you want to use [SASL Authentication] (http:https://tinkerpop.apache.org/docs/3.2.5/dev/provider/#_authentication) with your gremlin server:

```javascript
import { createClient } from 'gremlin';

const client = Gremlin.createClient(8182, 'localhost', { ssl:true, user:'user', password:'password' });

client.execute('g.V()', { }, (err, results) => {
if (err) {
return console.error(err)
}

console.log(results);
});
```

### Executing Gremlin queries

Expand Down
29 changes: 29 additions & 0 deletions examples/node-sasl-example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
var gremlin = require('../src');

var client = gremlin.createClient(51549, 'localhost', {
session: false,
ssl:true,
user:'username',
password:'password' });

var script = 'g.V()';

// Callback style
client.execute(script, function(err, res) {
console.log(err, res);
});

// Stream style
var s = client.stream(script);

s.on('data', function(result) {
console.log(result);
});

s.on('end', function() {
console.log("All results fetched");
});

s.on('error', function(e) {
console.log(e);
});
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"node-uuid": "^1.4.3",
"readable-stream": "^2.0.2",
"ws": "^2.3.1",
"zer": "^0.1.0"
"zer": "^0.1.0",
"utf8": "^2.0.0"
},
"devDependencies": {
"babel-cli": "^6.4.5",
Expand Down
25 changes: 24 additions & 1 deletion src/GremlinClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import uuid from 'node-uuid';
import _ from 'lodash';
import highland from 'highland';
import { gremlin, renderChain } from 'zer';
import utf8 from 'utf8';

import WebSocketGremlinConnection from './WebSocketGremlinConnection';
import MessageStream from './MessageStream';
Expand Down Expand Up @@ -33,11 +34,15 @@ class GremlinClient extends EventEmitter {
executeHandler,
ssl: false,
rejectUnauthorized: true,
user: '',
password: '',
...options,
path: path.length && !path.startsWith('/') ? `/${path}` : path
path: path && path.length && !path.startsWith('/') ? `/${path}` : path
}

this.useSession = this.options.session;
this.user = this.options.user;
this.password = this.options.password;

if (this.useSession) {
this.sessionId = uuid.v1();
Expand Down Expand Up @@ -128,6 +133,10 @@ class GremlinClient extends EventEmitter {
case 206: // PARTIAL_CONTENT
messageStream.push(rawMessage);
break;
case 407: // AUTHENTICATE CHALLANGE
const challengeResponse = this.buildChallengeResponse(requestId);
this.sendMessage(challengeResponse);
break;
default:
delete this.commands[requestId];
messageStream.emit('error', new Error(statusMessage + ' (Error '+ statusCode +')'));
Expand Down Expand Up @@ -218,6 +227,20 @@ class GremlinClient extends EventEmitter {
return message;
};

buildChallengeResponse(requestId) {
const { processor, op, accept, language, aliases } = this.options;
var args = { SASL: utf8.encode('\0' + this.user + '\0' + this.password) };

const message = {
requestId: requestId,
processor,
op: 'authentication',
args
};

return message;
};

sendMessage(message) {
let serializedMessage = this.options.accept + JSON.stringify(message);
serializedMessage = unescape(encodeURIComponent(serializedMessage));
Expand Down

0 comments on commit 747c080

Please sign in to comment.