1
0
Fork 0

Moving out more from #5066 (#5124)

This commit is contained in:
Simon 2018-04-17 16:55:19 +02:00 committed by Jan
parent a6ddeb3782
commit fad4c0f9f4
5 changed files with 144 additions and 147 deletions

View File

@ -54,7 +54,7 @@ typedef std::unordered_map<std::string, auth::User> UserMap;
/// stored in `_system/_users` as well as in external authentication
/// systems like LDAP. The permissions are cached locally if possible,
/// to avoid unnecessary disk access. An instance of this should only
/// exist on Coordinators and single servers.
/// exist on coordinators and single servers.
class UserManager {
public:
explicit UserManager();

View File

@ -29,31 +29,32 @@
const _ = require('lodash');
const fs = require('fs');
const yaml = require('js-yaml');
const toArgv = require('internal').toArgv;
const internal = require('internal');
const toArgv = internal.toArgv;
const crashUtils = require('@arangodb/crash-utils');
const crypto = require('@arangodb/crypto');
/* Functions: */
const executeExternal = require('internal').executeExternal;
const executeExternalAndWait = require('internal').executeExternalAndWait;
const killExternal = require('internal').killExternal;
const statusExternal = require('internal').statusExternal;
const base64Encode = require('internal').base64Encode;
const testPort = require('internal').testPort;
const download = require('internal').download;
const time = require('internal').time;
const wait = require('internal').wait;
const sleep = require('internal').sleep;
const executeExternal = internal.executeExternal;
const executeExternalAndWait = internal.executeExternalAndWait;
const killExternal = internal.killExternal;
const statusExternal = internal.statusExternal;
const base64Encode = internal.base64Encode;
const testPort = internal.testPort;
const download = internal.download;
const time = internal.time;
const wait = internal.wait;
const sleep = internal.sleep;
/* Constants: */
// const BLUE = require('internal').COLORS.COLOR_BLUE;
const CYAN = require('internal').COLORS.COLOR_CYAN;
const GREEN = require('internal').COLORS.COLOR_GREEN;
const RED = require('internal').COLORS.COLOR_RED;
const RESET = require('internal').COLORS.COLOR_RESET;
// const YELLOW = require('internal').COLORS.COLOR_YELLOW;
// const BLUE = internal.COLORS.COLOR_BLUE;
const CYAN = internal.COLORS.COLOR_CYAN;
const GREEN = internal.COLORS.COLOR_GREEN;
const RED = internal.COLORS.COLOR_RED;
const RESET = internal.COLORS.COLOR_RESET;
// const YELLOW = internal.COLORS.COLOR_YELLOW;
const platform = require('internal').platform;
const platform = internal.platform;
const abortSignal = 6;
@ -192,7 +193,7 @@ function findFreePort (minPort, maxPort, usedPorts) {
return port;
}
require('internal').wait(0.1);
internal.wait(0.1);
}
}
@ -523,7 +524,7 @@ function runArangoshCmd (options, instanceInfo, addArgs, cmds) {
args = Object.assign(args, addArgs);
}
require('internal').env.INSTANCEINFO = JSON.stringify(instanceInfo);
internal.env.INSTANCEINFO = JSON.stringify(instanceInfo);
const argv = toArgv(args).concat(cmds);
return executeAndWait(ARANGOSH_BIN, argv, options, 'arangoshcmd', instanceInfo.rootDir);
}
@ -842,7 +843,7 @@ function shutdownInstance (instanceInfo, options, forceTerminate) {
timeout *= 2;
}
var shutdownTime = require('internal').time();
var shutdownTime = internal.time();
let toShutdown = instanceInfo.arangods.slice();
while (toShutdown.length > 0) {
@ -863,7 +864,7 @@ function shutdownInstance (instanceInfo, options, forceTerminate) {
if (arangod.role === 'agent') {
localTimeout = localTimeout + 60;
}
if ((require('internal').time() - shutdownTime) > localTimeout) {
if ((internal.time() - shutdownTime) > localTimeout) {
print('forcefully terminating ' + yaml.safeDump(arangod.pid) +
' after ' + timeout + 's grace period; marking crashy.');
serverCrashed = true;
@ -920,8 +921,8 @@ function shutdownInstance (instanceInfo, options, forceTerminate) {
function startInstanceCluster (instanceInfo, protocol, options,
addArgs, rootDir) {
if (options.cluster && options.resilientsingle ||
!options.cluster && !options.resilientsingle) {
if (options.cluster && options.activefailover ||
!options.cluster && !options.activefailover) {
throw "invalid call to startInstanceCluster";
}
@ -945,7 +946,7 @@ function startInstanceCluster (instanceInfo, protocol, options,
startInstanceAgency(instanceInfo, protocol, options, ...makeArgs('agency', 'agency', {}));
let agencyEndpoint = instanceInfo.endpoint;
let agencyUrl = instanceInfo.url;
if (!checkInstanceAlive(instanceInfo, options)) {
throw new Error('startup of agency failed! bailing out!');
}
@ -977,9 +978,8 @@ function startInstanceCluster (instanceInfo, protocol, options,
startInstanceSingleServer(instanceInfo, protocol, options, ...makeArgs('coordinator' + i, 'coordinator', coordinatorArgs), 'coordinator');
}
} else if (options.resilientsingle) {
// for now start just two (TODO config parameter)
for (i = 0; i < 2; i++) {
} else if (options.activefailover) {
for (i = 0; i < options.singles; i++) {
let port = findFreePort(options.minPort, options.maxPort, usedPorts);
usedPorts.push(port);
let endpoint = protocol + '://127.0.0.1:' + port;
@ -988,7 +988,7 @@ function startInstanceCluster (instanceInfo, protocol, options,
singleArgs['cluster.my-address'] = endpoint;
singleArgs['cluster.my-role'] = 'SINGLE';
singleArgs['cluster.agency-endpoint'] = agencyEndpoint;
singleArgs['replication.automatic-failover'] = true;
singleArgs['replication.active-failover'] = true;
startInstanceSingleServer(instanceInfo, protocol, options, ...makeArgs('single' + i, 'single', singleArgs), 'single');
sleep(1.0);
}
@ -1051,20 +1051,33 @@ function startInstanceCluster (instanceInfo, protocol, options,
}
// we need to find the leading server
if (options.resilientsingle) {
const internal = require('internal');
const reply = download(instanceInfo.url + '/_api/cluster/endpoints', '', makeAuthorizationHeaders(authOpts));
if (options.activefailover) {
internal.wait(5.0);
let opts = makeAuthorizationHeaders(authOpts);
opts['headers']['content-type'] = 'application/json';
opts['method'] = 'POST';
let reply = download(agencyUrl + '/_api/agency/read',
'[["/arango/Plan/AsyncReplication/Leader"]]', opts);
if (!reply.error && reply.code === 200) {
let res = JSON.parse(reply.body);
internal.print("Response ====> " + reply.body);
let leader = res.endpoints[0].endpoint;
instanceInfo.arangods.forEach(d => {
if (d.endpoint === leader) {
instanceInfo.endpoint = d.endpoint;
instanceInfo.url = d.url;
}
});
let leader = res[0].arango.Plan.AsyncReplication.Leader;
if (!leader) {
throw "Leader is not selected";
}
}
opts['method'] = 'GET';
reply = download(instanceInfo.url + '/_api/cluster/endpoints', '', opts);
let res = JSON.parse(reply.body);
let leader = res.endpoints[0].endpoint;
instanceInfo.arangods.forEach(d => {
if (d.endpoint === leader) {
instanceInfo.endpoint = d.endpoint;
instanceInfo.url = d.url;
}
});
}
arango.reconnect(instanceInfo.endpoint, '_system', 'root', '');
@ -1248,7 +1261,7 @@ function startInstance (protocol, options, addArgs, testname, tmpDir) {
};
arango.reconnect(rc.endpoint, '_system', 'root', '');
return rc;
} else if (options.cluster || options.resilientsingle) {
} else if (options.cluster || options.activefailover) {
startInstanceCluster(instanceInfo, protocol, options,
addArgs, rootDir);
} else if (options.agency) {

View File

@ -82,7 +82,7 @@ let optionsDocumentation = [
' - `sanitizer`: if set the programs are run with enabled sanitizer',
' and need longer timeouts',
'',
' - `singleresilient` starts resilient single server setup (active/passive)',
' - `activefailover` starts active failover single server setup (active/passive)',
'',
' - `valgrind`: if set the programs are run with the valgrind',
' memory checker; should point to the valgrind executable',
@ -131,7 +131,7 @@ const optionsDefaults = {
'replication': false,
'rr': false,
'sanitizer': false,
'singleresilient': false,
'activefailover': false,
'skipLogAnalysis': true,
'skipMemoryIntense': false,
'skipNightly': true,

View File

@ -28,19 +28,19 @@
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
var arango = require("@arangodb").arango;
var db = require("internal").db;
var users = require("@arangodb/users");
var request = require('@arangodb/request');
var crypto = require('@arangodb/crypto');
const jsunity = require("jsunity");
const arango = require("@arangodb").arango;
const db = require("internal").db;
const users = require("@arangodb/users");
const request = require('@arangodb/request');
const crypto = require('@arangodb/crypto');
const expect = require('chai').expect;
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function AuthSuite () {
function AuthSuite() {
'use strict';
var baseUrl = function () {
return arango.getEndpoint().replace(/^tcp:/, 'http:').replace(/^ssl:/, 'https:');
@ -50,11 +50,11 @@ function AuthSuite () {
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
setUp: function () {
arango.reconnect(arango.getEndpoint(), db._name(), "root", "");
try {
@ -64,11 +64,11 @@ function AuthSuite () {
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
tearDown: function () {
try {
users.remove("hackers@arangodb.com");
}
@ -76,11 +76,11 @@ function AuthSuite () {
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test creating a new user
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief test creating a new user
////////////////////////////////////////////////////////////////////////////////
testNewUser : function () {
testNewUser: function () {
users.save("hackers@arangodb.com", "foobar");
users.grantDatabase('hackers@arangodb.com', db._name());
users.grantCollection('hackers@arangodb.com', db._name(), "*");
@ -110,11 +110,11 @@ function AuthSuite () {
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test creating a new user with empty password
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief test creating a new user with empty password
////////////////////////////////////////////////////////////////////////////////
testEmptyPassword : function () {
testEmptyPassword: function () {
users.save("hackers@arangodb.com", "");
users.grantDatabase('hackers@arangodb.com', db._name());
users.grantCollection('hackers@arangodb.com', db._name(), "*");
@ -136,7 +136,7 @@ function AuthSuite () {
}
},
testPasswordChange : function () {
testPasswordChange: function () {
users.save("hackers@arangodb.com", "");
users.grantDatabase('hackers@arangodb.com', db._name());
users.grantCollection('hackers@arangodb.com', db._name(), "*");
@ -155,11 +155,11 @@ function AuthSuite () {
assertTrue(db._collections().length > 0);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test creating a new user with case sensitive password
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief test creating a new user with case sensitive password
////////////////////////////////////////////////////////////////////////////////
testPasswordCase : function () {
testPasswordCase: function () {
users.save("hackers@arangodb.com", "FooBar");
users.grantDatabase('hackers@arangodb.com', db._name());
users.grantCollection('hackers@arangodb.com', db._name(), "*", "ro");
@ -207,11 +207,11 @@ function AuthSuite () {
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test creating a new user with colon in password
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief test creating a new user with colon in password
////////////////////////////////////////////////////////////////////////////////
testColon : function () {
testColon: function () {
users.save("hackers@arangodb.com", "fuxx::bar");
users.grantDatabase('hackers@arangodb.com', db._name());
users.grantCollection('hackers@arangodb.com', db._name(), "*", "ro");
@ -258,11 +258,11 @@ function AuthSuite () {
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test creating a new user with special chars in password
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief test creating a new user with special chars in password
////////////////////////////////////////////////////////////////////////////////
testSpecialChars : function () {
testSpecialChars: function () {
users.save("hackers@arangodb.com", ":\\abc'def:foobar@04. x-a");
users.grantDatabase('hackers@arangodb.com', db._name());
users.grantCollection('hackers@arangodb.com', db._name(), "*", "ro");
@ -308,18 +308,18 @@ function AuthSuite () {
fail();
}
},
testAuthOpen: function() {
testAuthOpen: function () {
var res = request(baseUrl() + "/_open/auth");
expect(res).to.be.an.instanceof(request.Response);
// mop: GET is an unsupported method, but it is skipping auth
expect(res).to.have.property('statusCode', 405);
},
testAuth: function() {
testAuth: function () {
var res = request.post({
url: baseUrl() + "/_open/auth",
body: JSON.stringify({"username": "root", "password": ""})
body: JSON.stringify({ "username": "root", "password": "" })
});
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 200);
@ -330,14 +330,14 @@ function AuthSuite () {
expect(obj.jwt).to.be.a('string');
expect(obj.jwt.split('.').length).to.be.equal(3);
},
testAuthNewUser: function() {
testAuthNewUser: function () {
users.save("hackers@arangodb.com", "foobar");
users.reload();
var res = request.post({
url: baseUrl() + "/_open/auth",
body: JSON.stringify({"username": "hackers@arangodb.com", "password": "foobar"})
body: JSON.stringify({ "username": "hackers@arangodb.com", "password": "foobar" })
});
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 200);
@ -347,47 +347,47 @@ function AuthSuite () {
expect(obj.jwt).to.be.a('string');
expect(obj.jwt.split('.').length).to.be.equal(3);
},
testAuthNewWrongPassword: function() {
testAuthNewWrongPassword: function () {
users.save("hackers@arangodb.com", "foobarJAJA");
users.reload();
var res = request.post({
url: baseUrl() + "/_open/auth",
body: JSON.stringify({"username": "hackers@arangodb.com", "password": "foobar"})
body: JSON.stringify({ "username": "hackers@arangodb.com", "password": "foobar" })
});
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 401);
},
testAuthNoPassword: function() {
testAuthNoPassword: function () {
var res = request.post({
url: baseUrl() + "/_open/auth",
body: JSON.stringify({"username": "hackers@arangodb.com", "passwordaa": "foobar"}),
});
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 400);
},
testAuthNoUsername: function() {
var res = request.post({
url: baseUrl() + "/_open/auth",
body: JSON.stringify({"usern": "hackers@arangodb.com", "password": "foobar"}),
body: JSON.stringify({ "username": "hackers@arangodb.com", "passwordaa": "foobar" }),
});
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 400);
},
testAuthRequired: function() {
testAuthNoUsername: function () {
var res = request.post({
url: baseUrl() + "/_open/auth",
body: JSON.stringify({ "usern": "hackers@arangodb.com", "password": "foobar" }),
});
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 400);
},
testAuthRequired: function () {
var res = request.get(baseUrl() + "/_api/version");
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 401);
},
testFullAuthWorkflow: function() {
testFullAuthWorkflow: function () {
var res = request.post({
url: baseUrl() + "/_open/auth",
body: JSON.stringify({"username": "root", "password": ""}),
body: JSON.stringify({ "username": "root", "password": "" }),
});
var jwt = JSON.parse(res.body).jwt;
@ -401,9 +401,12 @@ function AuthSuite () {
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 200);
},
testViaJS: function() {
var jwt = crypto.jwtEncode(jwtSecret, {"preferred_username": "root", "iss": "arangodb", "exp": Math.floor(Date.now() / 1000) + 3600}, 'HS256');
testViaJS: function () {
var jwt = crypto.jwtEncode(jwtSecret, {
"preferred_username": "root",
"iss": "arangodb", "exp": Math.floor(Date.now() / 1000) + 3600
}, 'HS256');
var res = request.get({
url: baseUrl() + "/_api/version",
@ -414,9 +417,9 @@ function AuthSuite () {
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 200);
},
testNoneAlgDisabled: function() {
var jwt = (new Buffer(JSON.stringify({"typ": "JWT","alg": "none"})).toString('base64')) + "." + (new Buffer(JSON.stringify({"preferred_username": "root", "iss": "arangodb"})).toString('base64'));
testNoneAlgDisabled: function () {
var jwt = (new Buffer(JSON.stringify({ "typ": "JWT", "alg": "none" })).toString('base64')) + "." + (new Buffer(JSON.stringify({ "preferred_username": "root", "iss": "arangodb" })).toString('base64'));
// not supported
var res = request.get({
url: baseUrl() + "/_api/version",
@ -427,9 +430,9 @@ function AuthSuite () {
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 401);
},
testIssRequired: function() {
var jwt = crypto.jwtEncode(jwtSecret, {"preferred_username": "root", "exp": Math.floor(Date.now() / 1000) + 3600 }, 'HS256');
testIssRequired: function () {
var jwt = crypto.jwtEncode(jwtSecret, { "preferred_username": "root", "exp": Math.floor(Date.now() / 1000) + 3600 }, 'HS256');
// not supported
var res = request.get({
url: baseUrl() + "/_api/version",
@ -440,9 +443,9 @@ function AuthSuite () {
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 401);
},
testIssArangodb: function() {
var jwt = crypto.jwtEncode(jwtSecret, {"preferred_username": "root", "iss": "arangodbaaa", "exp": Math.floor(Date.now() / 1000) + 3600 }, 'HS256');
testIssArangodb: function () {
var jwt = crypto.jwtEncode(jwtSecret, { "preferred_username": "root", "iss": "arangodbaaa", "exp": Math.floor(Date.now() / 1000) + 3600 }, 'HS256');
// not supported
var res = request.get({
url: baseUrl() + "/_api/version",
@ -453,10 +456,12 @@ function AuthSuite () {
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 401);
},
testExpOptional: function() {
var jwt = crypto.jwtEncode(jwtSecret, {"preferred_username": "root",
"iss": "arangodb" }, 'HS256');
testExpOptional: function () {
var jwt = crypto.jwtEncode(jwtSecret, {
"preferred_username": "root",
"iss": "arangodb"
}, 'HS256');
// not supported
var res = request.get({
url: baseUrl() + "/_api/version",
@ -467,9 +472,9 @@ function AuthSuite () {
expect(res).to.be.an.instanceof(request.Response);
expect(res).to.have.property('statusCode', 200);
},
testExp: function() {
var jwt = crypto.jwtEncode(jwtSecret, {"preferred_username": "root", "iss": "arangodbaaa", "exp": Math.floor(Date.now() / 1000) - 1000 }, 'HS256');
testExp: function () {
var jwt = crypto.jwtEncode(jwtSecret, { "preferred_username": "root", "iss": "arangodbaaa", "exp": Math.floor(Date.now() / 1000) - 1000 }, 'HS256');
// not supported
var res = request.get({
url: baseUrl() + "/_api/version",

View File

@ -32,6 +32,7 @@
const expect = require('chai').expect;
const arangodb = require("@arangodb");
const replication = require("@arangodb/replication");
const compareTicks = replication.compareTicks;
const errors = arangodb.errors;
const db = arangodb.db;
const internal = require("internal");
@ -60,28 +61,6 @@ const delay = 10;
// Flag if we need to reconnect.
let onMaster = true;
const compareTicks = function(l, r) {
if (l === null) {
l = "0";
}
if (r === null) {
r = "0";
}
if (l.length !== r.length) {
return l.length - r.length < 0 ? -1 : 1;
}
// length is equal
for (let i = 0; i < l.length; ++i) {
if (l[i] !== r[i]) {
return l[i] < r[i] ? -1 : 1;
}
}
return 0;
};
const compareIndexes = function(l, r, eq) {
// This can modify l and r and remove id and selectivityEstimate
expect(l).to.be.an("array");