Tidying-up of authenticator and integeration tests.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/18598baf Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/18598baf Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/18598baf Branch: refs/heads/master Commit: 18598baff6039dd281bb18d42524c3f317d97218 Parents: 8453b61 Author: Matthew Allen <[email protected]> Authored: Wed Aug 1 20:30:13 2018 +0100 Committer: Matthew Allen <[email protected]> Committed: Thu Aug 23 06:39:29 2018 +0100 ---------------------------------------------------------------------- .../main/javascript/gremlin-javascript/index.js | 6 +- .../lib/driver/auth/authenticator.js | 19 +++++ .../auth/mechanisms/sasl-mechanism-base.js | 18 ++++- .../auth/mechanisms/sasl-mechanism-plain.js | 81 +++++++++++++++++--- .../lib/driver/auth/sasl-authenticator.js | 30 ++++++++ .../lib/driver/authenticator.js | 14 ---- .../lib/driver/sasl-authenticator.js | 30 -------- .../gremlin-javascript/test/helper.js | 4 +- .../integration/sasl-authentication-tests.js | 8 +- 9 files changed, 143 insertions(+), 67 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/18598baf/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js index 5ada391..d4c6d88 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/index.js @@ -31,17 +31,13 @@ const rc = require('./lib/driver/remote-connection'); const Bytecode = require('./lib/process/bytecode'); const utils = require('./lib/utils'); const DriverRemoteConnection = require('./lib/driver/driver-remote-connection'); -const Auth = require('./lib/driver/authenticator'); -const SaslAuth = require('./lib/driver/sasl-authenticator'); module.exports = { driver: { RemoteConnection: rc.RemoteConnection, RemoteStrategy: rc.RemoteStrategy, RemoteTraversal: rc.RemoteTraversal, - DriverRemoteConnection: DriverRemoteConnection, - Authenticator: Auth, - SaslAuthenticator: SaslAuth + DriverRemoteConnection: DriverRemoteConnection }, process: { Bytecode: Bytecode, http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/18598baf/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/authenticator.js ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/authenticator.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/authenticator.js new file mode 100644 index 0000000..b57e385 --- /dev/null +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/authenticator.js @@ -0,0 +1,19 @@ +'use strict'; + +/** @abstract */ +class Authenticator { + constructor(options) { + this._options = options; + } + + /** + * @abstract + * Evaluates the challenge from the server and returns appropriate response. + * @param {String} challenge Challenge string presented by the server. + */ + evaluateChallenge(challenge) { + throw new Error("evaluateChallenge should be implemented"); + } +} + +module.exports = Authenticator; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/18598baf/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/mechanisms/sasl-mechanism-base.js ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/mechanisms/sasl-mechanism-base.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/mechanisms/sasl-mechanism-base.js index 4b75778..b909cc8 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/mechanisms/sasl-mechanism-base.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/mechanisms/sasl-mechanism-base.js @@ -20,17 +20,33 @@ /** @abstract */ class SaslMechanismBase { + constructor(options) { + this.setopts(options); + } + + /** + * Returns the name of the mechanism + */ get name() { return null; } + /** + * Set the options for the mechanism + * @param {object} options Options specific to the mechanism + */ setopts(options) { this._options = options; } + /** + * @abstract + * Evaluates the challenge from the server and returns appropriate response + * @param {String} challenge Challenge string presented by the server + */ evaluateChallenge(challenge) { throw new Error("evaluateChallenge should be implemented"); } } -module.exports = SaslMechanismBase; \ No newline at end of file +module.exports = SaslMechanismBase; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/18598baf/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/mechanisms/sasl-mechanism-plain.js ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/mechanisms/sasl-mechanism-plain.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/mechanisms/sasl-mechanism-plain.js index be418be..597a929 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/mechanisms/sasl-mechanism-plain.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/mechanisms/sasl-mechanism-plain.js @@ -1,31 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ 'use strict'; const SaslMechanismBase = require('./sasl-mechanism-base'); class SaslMechanismPlain extends SaslMechanismBase { + /** + * Creates a new instance of SaslMechanismPlain. + * @param {Object} [options] The mechanism options. + * @param {String} [options.authzid] The identity of the client. + * @param {String} [options.username] The identity of user with access to server. + * @param {String} [options.password] The password of user with access to server. + * @constructor + */ + constructor(options) { + super(options); + + if (this._options.username === undefined + || this._options.username === null + || this._options.username.length == 0 + || this._options.password === undefined + || this._options.password === null + || this._options.password.length == 0 + ) { + throw new Error('Missing credentials for SASL PLAIN mechanism'); + } + } + + /** + * Returns the name of the mechanism + */ get name() { return 'PLAIN'; } + /** + * Evaluates the challenge from the server and returns appropriate response. + * @param {String} challenge Challenge string presented by the server. + * @return {Object} A Promise that resolves to a valid sasl response object. + */ evaluateChallenge(challenge) { if (this._hasInitialResponse(challenge)) { - return Promise.resolve({ 'saslMechanism': this.name, 'sasl': this._saslArgument() }); + return Promise.resolve({ + 'saslMechanism': this.name, + 'sasl': this._saslArgument(this._options.authzid, this._options.username, this._options.password) + }); } - return Promise.resolve({ 'sasl': this._saslArgument() }); + return Promise.resolve({ 'sasl': this._saslArgument(this._options.authzid, this._options.username, this._options.password) }); } - _saslArgument() { - if (this._options.username === undefined || this._options.username.length === 0 - || this._options.password === undefined || this._options.password.length === 0 ) { - throw new Error('No Credentials Supplied'); - } + /** + * Generates a base64 encoded sasl argument based on the given parameters. + * @param {String} authzid Identitiy of the client. + * @param {String} username The identity of user with access to server. + * @param {String} password The password of user with access to server. + */ + _saslArgument(authzid, username, password) { + if (authzid === undefined || authzid === null) authzid = ''; + if (username === undefined || username === null) username = ''; + if (password === undefined || password.length === null) password = ''; - const authstr = ((this._options.authId !== undefined && this._options.authId.length) ? this._options.authId : '') - + `\0${this._options.username}\0${this._options.password}`; - return new Buffer(authstr).toString('base64'); + return new Buffer(`${authzid}\0${username}\0${password}`).toString('base64'); } + /** + * Checks challenge to see if we have the initial sasl response from the server. + * @param {String} challenge The challenge string from the server. + * @return {Boolean} + */ _hasInitialResponse(challenge) { if (challenge === undefined || challenge === null) { return false; @@ -34,4 +93,4 @@ class SaslMechanismPlain extends SaslMechanismBase { } } -module.exports = SaslMechanismPlain; \ No newline at end of file +module.exports = SaslMechanismPlain; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/18598baf/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/sasl-authenticator.js ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/sasl-authenticator.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/sasl-authenticator.js new file mode 100644 index 0000000..eb1fbe8 --- /dev/null +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/auth/sasl-authenticator.js @@ -0,0 +1,30 @@ +'use strict'; + +const Authenticator = require('./authenticator'); + +class SaslAuthenticator extends Authenticator { + /** + * Creates a new instance of SaslAuthenticator. + * @param {Object} [options] The authentication options. + * @param {Object} [options.mechanism] The mechanism to be used for authentication. + * @constructor + */ + constructor(options) { + super(options); + + if (options.mechanism === null || options.mechanism === undefined) { + throw new Error('No Sasl Mechanism Specified'); + } + } + + /** + * Evaluates the challenge from the server and returns appropriate response. + * @param {String} challenge Challenge string presented by the server. + * @return {Object} A Promise that resolves to a valid sasl response object. + */ + evaluateChallenge(challenge) { + return Promise.resolve(this._options.mechanism.evaluateChallenge(challenge)); + } +} + +module.exports = SaslAuthenticator; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/18598baf/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/authenticator.js ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/authenticator.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/authenticator.js deleted file mode 100644 index c57cec5..0000000 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/authenticator.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -/** @abstract */ -class Authenticator { - constructor(credentials) { - this._credentials = credentials; - } - - evaluateChallenge(challenge) { - throw new Error("evaluateChallenge should be implemented"); - } -} - -module.exports = Authenticator; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/18598baf/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/sasl-authenticator.js ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/sasl-authenticator.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/sasl-authenticator.js deleted file mode 100644 index 4b63ab5..0000000 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/sasl-authenticator.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -const Authenticator = require('./authenticator'); - -class SaslAuthenticator extends Authenticator { - /** - * Creates a new instance of SaslAuthenticator. - * @param {Object} [options] The authentication options. - * @param {Object} [options.mechanism] The mechanism to be used for authentication. - * @param {String} [options.hostname] The hostname of the client. - * @param {*} [options] Other mechanism specific options. - * @constructor - */ - constructor(options) { - super(options); - - if (options.mechanism === null || options.mechanism === undefined) { - throw new Error('No Sasl Mechanism Specified'); - } - - this._options = options; - this._options.mechanism.setopts(this._options); - } - - evaluateChallenge(challenge) { - return Promise.resolve(this._options.mechanism.evaluateChallenge(challenge)); - } -} - -module.exports = SaslAuthenticator; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/18598baf/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js index e1c24a3..82c47be 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js @@ -24,7 +24,7 @@ const os = require('os'); const DriverRemoteConnection = require('../lib/driver/driver-remote-connection'); -const SaslAuthenticator = require('../lib/driver/sasl-authenticator'); +const SaslAuthenticator = require('../lib/driver/auth/sasl-authenticator'); const SaslMechanismPlain = require('../lib/driver/auth/mechanisms/sasl-mechanism-plain'); exports.getConnection = function getConnection(traversalSource) { @@ -32,7 +32,7 @@ exports.getConnection = function getConnection(traversalSource) { }; exports.getSecureConnectionWithAuthenticator = function getConnection(traversalSource) { - const authenticator = new SaslAuthenticator({ mechanism: new SaslMechanismPlain(), username: 'stephen', password: 'password', authId: os.hostname() }); + const authenticator = new SaslAuthenticator({ mechanism: new SaslMechanismPlain({ username: 'stephen', password: 'password', authzid: os.hostname() }) }); return new DriverRemoteConnection('ws://localhost:45941/gremlin', { traversalSource: traversalSource, authenticator: authenticator, http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/18598baf/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/sasl-authentication-tests.js ---------------------------------------------------------------------- diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/sasl-authentication-tests.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/sasl-authentication-tests.js index f38d087..c9450f8 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/sasl-authentication-tests.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/sasl-authentication-tests.js @@ -49,16 +49,16 @@ describe('DriverRemoteConnectionWithSaslAuthenticator', function () { }); }); it('should send the request with invalid credentials and parse the response error', function () { - connection._authenticator.username = 'Bob'; + connection._authenticator._options.mechanism._options.username = 'Bob'; return connection.submit(new Bytecode().addStep('V', []).addStep('tail', [])) .catch(function (err) { assert.ok(err); assert.ok(err.message.indexOf('401') > 0); }); }); - it('should send incorrect conifugration to the authenticator and parse the response error', function () { - delete connection._authenticator.username; - delete connection._authenticator.password; + it('should send incorrect configuration to the authenticator and parse the response error', function () { + delete connection._authenticator._options.mechanism._options.username; + delete connection._authenticator._options.mechanism._options.password; return connection.submit(new Bytecode().addStep('V', []).addStep('tail', [])) .catch(function (err) { assert.ok(err);
