diff --git a/api/server.js b/api/server.js index 6364630fda2..bf560bcda99 100644 --- a/api/server.js +++ b/api/server.js @@ -24,7 +24,9 @@ process logger.info('Checks passed successfully'); const uploadDefaultDocs = require('./src/upload-default-docs'); + const databases = require('./src/services/setup/databases'); logger.info('Extracting initial documents…'); + await databases.init(); await uploadDefaultDocs.run(); logger.info('Extracting initial documents completed successfully'); diff --git a/api/src/auth.js b/api/src/auth.js index 508ffc81906..06436caff55 100644 --- a/api/src/auth.js +++ b/api/src/auth.js @@ -8,17 +8,17 @@ const { roles, users } = require('@medic/user-management')(config, db, dataConte const contentLengthRegex = /^content-length$/i; -const get = (path, headers) => { +const get = async (path, headers) => { const getHeaders = { ...headers }; Object .keys(getHeaders) .filter(header => contentLengthRegex.test(header)) .forEach(header => delete getHeaders[header]); - const url = new URL(path, environment.serverUrlNoAuth); + const url = new URL(path, environment.serverUrl); return request.get({ url: url.toString(), - headers: getHeaders, + headers: { ...getHeaders, ...request.NO_DEFAULT_AUTH_HEADERS }, json: true }); }; @@ -100,13 +100,14 @@ module.exports = { * * @param {Object} Credentials object as created by basicAuthCredentials */ - validateBasicAuth: ({ username, password }) => { - const authUrl = new URL(environment.serverUrlNoAuth); + validateBasicAuth: async ({ username, password }) => { + const authUrl = new URL(environment.serverUrl); authUrl.username = username; authUrl.password = password; return request.head({ uri: authUrl.toString(), - resolveWithFullResponse: true + resolveWithFullResponse: true, + headers: request.NO_DEFAULT_AUTH_HEADERS, }) .then(res => { if (res.statusCode !== 200) { diff --git a/api/src/controllers/login.js b/api/src/controllers/login.js index f522bcce7bf..82d8c278ae4 100644 --- a/api/src/controllers/login.js +++ b/api/src/controllers/login.js @@ -166,16 +166,17 @@ const getSessionCookie = res => { ); }; -const createSession = req => { +const createSession = async (req) => { const user = req.body.user; const password = req.body.password; return request.post({ - url: new URL('/_session', environment.serverUrlNoAuth).toString(), + url: new URL('/_session', environment.serverUrl).toString(), json: true, resolveWithFullResponse: true, simple: false, // doesn't throw an error on non-200 responses body: { name: user, password: password }, auth: { user: user, pass: password }, + headers: request.NO_DEFAULT_AUTH_HEADERS }); }; diff --git a/api/src/db-batch.js b/api/src/db-batch.js index 9108946b891..afbdb6fe693 100644 --- a/api/src/db-batch.js +++ b/api/src/db-batch.js @@ -21,7 +21,6 @@ const runBatch = (ddoc, view, viewParams, iteratee) => { return request.get({ url: fullUrl, json: true, - auth: { user: environment.username, pass: environment.password }, }) .then(result => { logger.info(` Processing doc ${result.offset}`); diff --git a/api/src/db.js b/api/src/db.js index e9bdab6b643..abbcb3fcffe 100644 --- a/api/src/db.js +++ b/api/src/db.js @@ -8,6 +8,7 @@ PouchDB.plugin(require('pouchdb-find')); PouchDB.plugin(require('pouchdb-mapreduce')); const asyncLocalStorage = require('./services/async-storage'); const { REQUEST_ID_HEADER } = require('./server-utils'); +const { getMemberAuthHeaders, getAdminAuthHeaders } = require('@medic/couch-request'); const { UNIT_TEST_ENV } = process.env; @@ -73,7 +74,12 @@ if (UNIT_TEST_ENV) { module.exports[fn] = () => notStubbed(fn); }); } else { - const fetch = (url, opts) => { + const makeFetch = (promisedAuthHeaders) => async (url, opts) => { + // Add Couch Proxy Auth headers + Object + .entries(await promisedAuthHeaders) + .forEach(([name, value]) => opts.headers.set(name, value)); + // Adding audit flag (haproxy) Service that made the request initially. opts.headers.set('X-Medic-Service', 'api'); const requestId = asyncLocalStorage.getRequestId(); @@ -82,22 +88,29 @@ if (UNIT_TEST_ENV) { } return PouchDB.fetch(url, opts); }; + const fetch = makeFetch(getMemberAuthHeaders()); + const adminFetch = makeFetch(getAdminAuthHeaders()); const DB = new PouchDB(environment.couchUrl, { fetch }); const getDbUrl = name => `${environment.serverUrl}/${name}`; DB.setMaxListeners(0); module.exports.medic = DB; + module.exports.medicAsAdmin = new PouchDB(environment.couchUrl, { fetch: adminFetch }); module.exports.medicUsersMeta = new PouchDB(`${environment.couchUrl}-users-meta`, { fetch }); + module.exports.medicUsersMetaAsAdmin = new PouchDB(`${environment.couchUrl}-users-meta`, { fetch: adminFetch }); module.exports.medicLogs = new PouchDB(`${environment.couchUrl}-logs`, { fetch }); + module.exports.medicLogsAsAdmin = new PouchDB(`${environment.couchUrl}-logs`, { fetch: adminFetch }); module.exports.sentinel = new PouchDB(`${environment.couchUrl}-sentinel`, { fetch }); - module.exports.vault = new PouchDB(`${environment.couchUrl}-vault`, { fetch }); + module.exports.sentinelAsAdmin = new PouchDB(`${environment.couchUrl}-sentinel`, { fetch: adminFetch }); + module.exports.vault = new PouchDB(`${environment.couchUrl}-vault`, { fetch: adminFetch }); module.exports.createVault = () => module.exports.vault.info(); - module.exports.users = new PouchDB(getDbUrl('_users'), { fetch }); + module.exports.users = new PouchDB(getDbUrl('_users'), { fetch: adminFetch }); module.exports.builds = new PouchDB(environment.buildsUrl); // Get the DB with the given name - module.exports.get = name => new PouchDB(getDbUrl(name), { fetch }); + // TODO Does it make sense to just use this for admin dbs? Probably have to worry about closing. + module.exports.get = name => new PouchDB(getDbUrl(name), { fetch: adminFetch }); module.exports.close = db => { if (!db || db._destroyed || db._closed) { return; @@ -193,34 +206,33 @@ if (UNIT_TEST_ENV) { roles: [], }); - const addRoleToSecurity = async (dbname, role, addAsAdmin) => { - if (!dbname || !role) { - throw new Error(`Cannot add security: invalid db name ${dbname} or role ${role}`); + const addToSecurity = async (dbname, value, securityField) => { + if (!dbname || !value) { + throw new Error(`Cannot add security: invalid db name ${dbname} or ${securityField} ${value}`); } const securityUrl = new URL(environment.serverUrl); securityUrl.pathname = `${dbname}/_security`; const securityObject = await request.get({ url: securityUrl.toString(), json: true }); - const property = addAsAdmin ? 'admins' : 'members'; - if (!securityObject[property]) { - securityObject[property] = getDefaultSecurityStructure(); + if (!securityObject.members) { + securityObject.members = getDefaultSecurityStructure(); } - if (!securityObject[property].roles || !Array.isArray(securityObject[property].roles)) { - securityObject[property].roles = []; + if (!securityObject.members[securityField] || !Array.isArray(securityObject.members[securityField])) { + securityObject.members[securityField] = []; } - if (securityObject[property].roles.includes(role)) { + if (securityObject.members[securityField].includes(value)) { return; } - logger.info(`Adding "${role}" role to ${dbname} ${property}`); - securityObject[property].roles.push(role); + logger.info(`Adding "${value}" role to ${dbname} members`); + securityObject.members[securityField].push(value); await request.put({ url: securityUrl.toString(), json: true, body: securityObject }); }; - module.exports.addRoleAsAdmin = (dbname, role) => addRoleToSecurity(dbname, role, true); - module.exports.addRoleAsMember = (dbname, role) => addRoleToSecurity(dbname, role, false); + module.exports.addUserAsMember = (dbname, name) => addToSecurity(dbname, name, 'names'); + module.exports.addRoleAsMember = (dbname, role) => addToSecurity(dbname, role, 'roles'); } diff --git a/api/src/generate-service-worker.js b/api/src/generate-service-worker.js index a827e389755..a4003285f75 100644 --- a/api/src/generate-service-worker.js +++ b/api/src/generate-service-worker.js @@ -131,7 +131,7 @@ const writeServiceWorkerMetaDoc = async (hash) => { const doc = await getSwMetaDoc(); doc.generated_at = new Date().getTime(); doc.hash = hash; - await db.medic.put(doc); + await db.medicAsAdmin.put(doc); } catch (err) { // don't log conflicts if (err.status !== 409) { diff --git a/api/src/migrations/restrict-access-to-audit-db.js b/api/src/migrations/restrict-access-to-audit-db.js index df4a62e526e..eb2b27c5c6f 100644 --- a/api/src/migrations/restrict-access-to-audit-db.js +++ b/api/src/migrations/restrict-access-to-audit-db.js @@ -14,10 +14,6 @@ const addMemberToDb = () => { port: environment.port, pathname: `${environment.db}-audit/_security`, }), - auth: { - user: environment.username, - pass: environment.password - }, json: true, body: securityObject }); diff --git a/api/src/migrations/restrict-access-to-sentinel-db.js b/api/src/migrations/restrict-access-to-sentinel-db.js index c20cf96249e..6cab79d798e 100644 --- a/api/src/migrations/restrict-access-to-sentinel-db.js +++ b/api/src/migrations/restrict-access-to-sentinel-db.js @@ -15,10 +15,6 @@ const addSecurityToDb = () => { port: environment.port, pathname: `${environment.db}-sentinel/_security`, }), - auth: { - user: environment.username, - pass: environment.password - }, json: true, body: securityObject }); diff --git a/api/src/migrations/restrict-access-to-vault-db.js b/api/src/migrations/restrict-access-to-vault-db.js index c4f85109e03..8bcc1e6f37f 100644 --- a/api/src/migrations/restrict-access-to-vault-db.js +++ b/api/src/migrations/restrict-access-to-vault-db.js @@ -15,10 +15,6 @@ const addSecurityToDb = () => { port: environment.port, pathname: `${environment.db}-vault/_security`, }), - auth: { - user: environment.username, - pass: environment.password - }, json: true, body: securityObject }); diff --git a/api/src/services/generate-xform.js b/api/src/services/generate-xform.js index 46ec74d93b5..706dda14979 100644 --- a/api/src/services/generate-xform.js +++ b/api/src/services/generate-xform.js @@ -264,7 +264,7 @@ module.exports = { const doc = docs.length && docs[0]; if (doc) { logger.info(`Updating form with ID "${docId}"`); - return db.medic.put(doc); + return db.medicAsAdmin.put(doc); } logger.info(`Form with ID "${docId}" does not need to be updated.`); }); @@ -287,7 +287,7 @@ module.exports = { if (!toSave.length) { return; } - return db.saveDocs(db.medic, toSave).then(results => { + return db.saveDocs(db.medicAsAdmin, toSave).then(results => { const failures = results.filter(result => !result.ok); if (failures.length) { logger.error('Bulk save failed with: %o', failures); diff --git a/api/src/services/setup/databases.js b/api/src/services/setup/databases.js index bbeea0299b8..b8507845a54 100644 --- a/api/src/services/setup/databases.js +++ b/api/src/services/setup/databases.js @@ -9,7 +9,7 @@ const db = require('../../db'); const MEDIC_DATABASE = { name: environment.db, - db: db.medic, + db: db.medicAsAdmin, jsonFileName: 'medic.json', }; @@ -20,17 +20,17 @@ const DATABASES = [ MEDIC_DATABASE, { name: `${environment.db}-sentinel`, - db: db.sentinel, + db: db.sentinelAsAdmin, jsonFileName: 'sentinel.json', }, { name: `${environment.db}-logs`, - db: db.medicLogs, + db: db.medicLogsAsAdmin, jsonFileName: 'logs.json', }, { name: `${environment.db}-users-meta`, - db: db.medicUsersMeta, + db: db.medicUsersMetaAsAdmin, jsonFileName: 'users-meta.json', }, { @@ -40,7 +40,12 @@ const DATABASES = [ }, ]; +const addSystemUserToDbs = () => Promise.all(DATABASES + .filter(({ name }) => name !== '_users') + .map(({ name }) => db.addUserAsMember(name, environment.username))); + module.exports = { MEDIC_DATABASE, DATABASES, + init: async () => addSystemUserToDbs() }; diff --git a/api/src/services/user-db.js b/api/src/services/user-db.js index a8703748a9e..963e87a4d57 100644 --- a/api/src/services/user-db.js +++ b/api/src/services/user-db.js @@ -79,10 +79,6 @@ module.exports = { port: environment.port, pathname: `${dbName}/_security`, }), - auth: { - user: environment.username, - pass: environment.password - }, json: true, body: { admins: { names: [ username ], roles: [] }, diff --git a/couchdb/10-docker-default.ini b/couchdb/10-docker-default.ini index 8c924a92d54..c6a8533a32c 100644 --- a/couchdb/10-docker-default.ini +++ b/couchdb/10-docker-default.ini @@ -19,6 +19,10 @@ bind_address = 0.0.0.0 server_options = [{recbuf, 262144}] socket_options = [{sndbuf, 262144}, {nodelay, true}] require_valid_user = true +authentication_handlers = {chttpd_auth, cookie_authentication_handler}, {chttpd_auth, proxy_authentication_handler}, {chttpd_auth, default_authentication_handler} + +[chttpd_auth] +proxy_use_secret = true [httpd] secure_rewrites = false diff --git a/sentinel/src/db.js b/sentinel/src/db.js index 95f0643997b..f28deda4bd0 100644 --- a/sentinel/src/db.js +++ b/sentinel/src/db.js @@ -61,20 +61,29 @@ if (UNIT_TEST_ENV) { const couchUrl = environment.couchUrl; - const fetchFn = (url, opts) => { + const makeFetch = (promisedAuthHeaders) => async (url, opts) => { + // Add Couch Proxy Auth headers + Object + .entries(await promisedAuthHeaders) + .forEach(([name, value]) => opts.headers.set(name, value)); // Adding audit flags (haproxy) Service and user that made the request initially. opts.headers.set('X-Medic-Service', 'sentinel'); opts.headers.set('X-Medic-User', 'sentinel'); return PouchDB.fetch(url, opts); }; + const fetch = makeFetch(request.getMemberAuthHeaders()); + const adminFetch = makeFetch(request.getAdminAuthHeaders()); - module.exports.medic = new PouchDB(couchUrl, { fetch: fetchFn }); - module.exports.sentinel = new PouchDB(`${couchUrl}-sentinel`, { - fetch: fetchFn, - }); - module.exports.allDbs = () => request.get({ url: `${environment.serverUrl}/_all_dbs`, json: true }); - module.exports.get = db => new PouchDB(`${environment.serverUrl}/${db}`); + module.exports.medic = new PouchDB(couchUrl, { fetch }); + module.exports.sentinel = new PouchDB(`${couchUrl}-sentinel`, { fetch }); + + module.exports.allDbs = async () => { + const headers = await request.getAdminAuthHeaders(); + return request.get({ url: `${environment.serverUrl}/_all_dbs`, json: true, headers }); + }; + // TODO Should this maybe be getAsAdmin? + module.exports.get = db => new PouchDB(`${environment.serverUrl}/${db}`, { fetch: adminFetch }); module.exports.close = db => { if (!db || db._destroyed || db._closed) { return; @@ -86,7 +95,7 @@ if (UNIT_TEST_ENV) { logger.error('Error when closing db: %o', err); } }; - module.exports.users = new PouchDB(`${environment.serverUrl}/_users`, { fetch: fetchFn }); + module.exports.users = new PouchDB(`${environment.serverUrl}/_users`, { fetch: adminFetch }); module.exports.users = new PouchDB(`${environment.serverUrl}/_users`); module.exports.queryMedic = (viewPath, queryParams, body) => { const [ddoc, view] = viewPath.split('/'); diff --git a/shared-libs/couch-request/src/couch-request.js b/shared-libs/couch-request/src/couch-request.js index c33b8eac7f2..d6c4fb636e6 100644 --- a/shared-libs/couch-request/src/couch-request.js +++ b/shared-libs/couch-request/src/couch-request.js @@ -1,6 +1,8 @@ const request = require('request-promise-native'); const isPlainObject = require('lodash/isPlainObject'); const environment = require('@medic/environment'); +const { getAuthHeaders, getCouchSecret, createHeaders } = require('./proxy-auth'); + const servername = environment.host; let asyncLocalStorage; let requestIdHeader; @@ -18,8 +20,10 @@ const methods = { HEAD: 'HEAD' }; +const promisedAdminAuthHeaders = getAuthHeaders(environment.username, '_admin'); +const promisedMemberAuthHeaders = getAuthHeaders(environment.username); -const mergeOptions = (target, source, exclusions = []) => { +const mergeOptions = async (target, source, exclusions = []) => { for (const [key, value] of Object.entries(source)) { if (Array.isArray(exclusions) && exclusions.includes(key)) { continue; @@ -27,9 +31,9 @@ const mergeOptions = (target, source, exclusions = []) => { target[key] = value; // locally, mutation is preferable to spreading as it doesn't // make new objects in memory. Assuming this is a hot path. } + target.headers = { ...(await promisedMemberAuthHeaders), ...target.headers }; const requestId = asyncLocalStorage?.getRequestId(); if (requestId) { - target.headers = target.headers || {}; target.headers[requestIdHeader] = requestId; } @@ -65,7 +69,7 @@ const validate = (firstIsString, method, first, second = {}) => { }; -const req = (method, first, second = {}) => { +const req = async (method, first, second = {}) => { const firstIsString = isString(first); @@ -79,8 +83,7 @@ const req = (method, first, second = {}) => { const exclusions = firstIsString ? ['url', 'uri', 'method'] : ['method']; const target = addServername ? { servername } : { }; - - const mergedOptions = mergeOptions(target, chosenOptions, exclusions); + const mergedOptions = await mergeOptions(target, chosenOptions, exclusions); return firstIsString ? getRequestType(method)(first, mergedOptions) : getRequestType(method)(mergedOptions); }; @@ -117,6 +120,15 @@ module.exports = { asyncLocalStorage = store; requestIdHeader = header; }, + getCouchSecret, + getAuthHeaders, + getAdminAuthHeaders: () => promisedAdminAuthHeaders, + getMemberAuthHeaders: () => promisedMemberAuthHeaders, + /** + * Null-valued proxy auth headers. These can override the system user's member-level headers that are set by + * default on each request. + */ + NO_DEFAULT_AUTH_HEADERS: createHeaders(), get: (first, second = {}) => req(methods.GET, first, second), post: (first, second = {}) => req(methods.POST, first, second), diff --git a/shared-libs/couch-request/src/proxy-auth.js b/shared-libs/couch-request/src/proxy-auth.js new file mode 100644 index 00000000000..21f65bf13d9 --- /dev/null +++ b/shared-libs/couch-request/src/proxy-auth.js @@ -0,0 +1,41 @@ +const request = require('request-promise-native'); +const crypto = require('crypto'); + +const { COUCH_URL, COUCHDB_SECRET } = process.env; + +const promisedCouchSecret = (async () => { + const envarSecret = COUCHDB_SECRET?.trim(); + if (envarSecret) { + return envarSecret; + } + + // Need to look up the secret (assuming the COUCH_URL contains user/pass) + const serverUrl = new URL('/', COUCH_URL); + const response = await request.get(`${serverUrl}/_node/_local/_config/couch_httpd_auth/secret`); + return JSON + .parse(response) + .trim(); +})(); + +const createHeaders = (username, roles, token) => { + return { + 'X-Auth-CouchDB-UserName': username, + 'X-Auth-CouchDB-Roles': roles, + 'X-Auth-CouchDB-Token': token, + }; +}; + +const getAuthHeaders = async (username, roles) => { + const secret = await promisedCouchSecret; + const token = crypto + .createHmac('sha256', secret) + .update(username) + .digest('hex'); + return createHeaders(username, roles, token); +}; + +module.exports = { + createHeaders, + getAuthHeaders, + getCouchSecret: () => promisedCouchSecret, +}; diff --git a/shared-libs/environment/src/index.js b/shared-libs/environment/src/index.js index de456aa2438..a23c3a12ff9 100644 --- a/shared-libs/environment/src/index.js +++ b/shared-libs/environment/src/index.js @@ -9,7 +9,7 @@ const isTrue = value => isString(value) ? value.toLowerCase() === 'true' : value const logError = () => { logger.error( 'Please define a valid COUCH_URL in your environment e.g. \n' + - 'export COUCH_URL=\'http://admin:123qwe@localhost:5984/medic\'\n\n' + + 'export COUCH_URL=\'http://localhost:5984/medic\'\n\n' + 'If you are running unit tests use UNIT_TEST_ENV=1 in your environment.\n' ); process.exit(1); @@ -23,30 +23,27 @@ try { // strip trailing slash from to prevent bugs in path matching const couchUrl = COUCH_URL.replace(/\/$/, ''); const parsedUrl = new URL(couchUrl); + parsedUrl.username = ''; + parsedUrl.password = ''; const serverUrl = new URL('/', parsedUrl); - const serverUrlNoAuth = new URL('/', parsedUrl); - serverUrlNoAuth.username = ''; - serverUrlNoAuth.password = ''; module.exports = { - couchUrl: couchUrl.toString(), + couchUrl: parsedUrl.toString(), buildsUrl: BUILDS_URL || DEFAULT_BUILDS_URL, serverUrl: serverUrl.toString(), - serverUrlNoAuth: serverUrlNoAuth.toString(), protocol: parsedUrl.protocol, port: parsedUrl.port, host: parsedUrl.hostname, db: parsedUrl.pathname.replace('/', ''), ddoc: 'medic', - username: parsedUrl.username, - password: parsedUrl.password, + username: 'cht-system', proxies: { // See http-proxy (https://www.npmjs.com/package/http-proxy#options) // "changeOrigin: true/false, Default: false - changes the origin of the host header to the target URL" // This allows proxying from HTTP to HTTPS without encountering certificate issues // for environments where TLS termination happens elsewhere. changeOrigin: isTrue(PROXY_CHANGE_ORIGIN) - } + }, }; } catch (err) { if (err.message === 'Invalid URL') { diff --git a/shared-libs/server-checks/src/checks.js b/shared-libs/server-checks/src/checks.js index 4265d316d28..221b0b6645d 100644 --- a/shared-libs/server-checks/src/checks.js +++ b/shared-libs/server-checks/src/checks.js @@ -19,7 +19,7 @@ const checkServerUrl = (serverUrl) => { console.log(err); throw new Error('Environment variable "COUCH_URL" is required. ' + 'Please make sure your CouchDb is accessible through a URL that matches: ' + - '://:@:/'); + '://:/'); } const pathSegments = couchUrl.pathname.split('/').filter(segment => segment); @@ -27,7 +27,7 @@ const checkServerUrl = (serverUrl) => { if (pathSegments.length !== 1) { throw new Error('Environment variable "COUCH_URL" must have only one path segment. ' + 'Please make sure your CouchDb is accessible through a URL that matches: ' + - '://:@:/'); + '://:/'); } }; @@ -72,11 +72,23 @@ const sameMembershipResult = (result1, result2) => { arrayEqual(result1.all_nodes, result2.all_nodes); }; +const checkCouchSecret = async () => { + try { + const secret = await request.getCouchSecret(); + if (!secret) { + throw new Error(); + } + } catch (e) { + throw new Error('The COUCHDB_SECRET environment variable must be set.'); + } +}; + const checkCouchDbCluster = async (couchUrl) => { + const headers = await request.getAdminAuthHeaders(); const membershipResults = [ - await request.get({ url: `${couchUrl}_membership`, json: true }), - await request.get({ url: `${couchUrl}_membership`, json: true }), - await request.get({ url: `${couchUrl}_membership`, json: true }), + await request.get({ url: `${couchUrl}_membership`, json: true, headers }), + await request.get({ url: `${couchUrl}_membership`, json: true, headers }), + await request.get({ url: `${couchUrl}_membership`, json: true, headers }), ]; const consistentMembership = @@ -89,9 +101,10 @@ const checkCouchDbCluster = async (couchUrl) => { }; const checkCouchDbSystemDbs = async (couchUrl) => { + const headers = await request.getAdminAuthHeaders(); try { for (const db of SYSTEM_DBS) { - await request.get({ url: `${couchUrl}${db}`, json: true }); + await request.get({ url: `${couchUrl}${db}`, json: true, headers }); } } catch (err) { throw new Error('System databases do not exist'); @@ -116,6 +129,7 @@ const checkCouchDbVersion = async (couchUrl) => { module.exports = { checkNodeVersion, checkServerUrl, + checkCouchSecret, checkCouchDbVersion, checkCouchDbNoAdminPartyMode, checkCouchDbCluster, diff --git a/shared-libs/server-checks/src/index.js b/shared-libs/server-checks/src/index.js index 0ad4caae0f8..37548a935d5 100644 --- a/shared-libs/server-checks/src/index.js +++ b/shared-libs/server-checks/src/index.js @@ -24,6 +24,7 @@ const getServerUrl = couchUrl => { const checkCouchDb = async (serverUrl) => { do { try { + await checks.checkCouchSecret();// TODO Not ideal since we want to actually kill the server. But need to wait for server to come up... await checks.checkCouchDbVersion(serverUrl); await checks.checkCouchDbNoAdminPartyMode(serverUrl); await checks.checkCouchDbCluster(serverUrl);