From 9180e771aaca6e1e6c14c5b0b1ce4446b4e47109 Mon Sep 17 00:00:00 2001 From: Ashish Pandey Date: Mon, 5 Aug 2024 17:10:02 +0530 Subject: [PATCH] Noobaa Account: Remove password hashing Signed-off-by: Ashish Pandey --- package.json | 1 - src/server/common_services/auth_server.js | 14 ++++- src/server/system_services/account_server.js | 63 ++++++++----------- .../system_services/schemas/account_schema.js | 2 +- src/tools/bcrypt_cli.js | 15 ----- .../5.18.0/remove_account_password.js | 30 +++++++++ 6 files changed, 70 insertions(+), 55 deletions(-) delete mode 100644 src/tools/bcrypt_cli.js create mode 100644 src/upgrade/upgrade_scripts/5.18.0/remove_account_password.js diff --git a/package.json b/package.json index e32115521c..c0802e8bde 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,6 @@ "@smithy/node-http-handler": "3.1.2", "ajv": "8.17.1", "aws-sdk": "2.1659.0", - "bcrypt": "5.1.1", "big-integer": "1.6.52", "bindings": "1.5.0", "bufferutil": "4.0.8", diff --git a/src/server/common_services/auth_server.js b/src/server/common_services/auth_server.js index 76cfa58012..2623502e62 100644 --- a/src/server/common_services/auth_server.js +++ b/src/server/common_services/auth_server.js @@ -2,7 +2,6 @@ 'use strict'; const _ = require('lodash'); -const bcrypt = require('bcrypt'); const ip_module = require('ip'); const P = require('../../util/promise'); @@ -20,7 +19,18 @@ const jwt_utils = require('../../util/jwt_utils'); const config = require('../../../config'); const s3_bucket_policy_utils = require('../../endpoint/s3/s3_bucket_policy_utils'); +function verify_password(password, target_account) { + if (!password || !target_account.password) { + return true; + } + + if (password.unwrap() === target_account.password.unwrap()) { + return true; + } else { + return false; + } +} /** * * CREATE_AUTH @@ -66,7 +76,7 @@ function create_auth(req) { if (!password) return; return P.resolve() - .then(() => bcrypt.compare(password.unwrap(), target_account.password.unwrap())) + .then(() => verify_password(password, target_account)) .then(match => { if (!match) { dbg.log0('password mismatch', email, system_name); diff --git a/src/server/system_services/account_server.js b/src/server/system_services/account_server.js index 98a5d6be4d..3c17ba0c38 100644 --- a/src/server/system_services/account_server.js +++ b/src/server/system_services/account_server.js @@ -6,7 +6,6 @@ const _ = require('lodash'); const net = require('net'); const chance = require('chance')(); const GoogleStorage = require('../../util/google_storage_wrap'); -const bcrypt = require('bcrypt'); const server_rpc = require('../server_rpc'); const config = require('../../../config'); @@ -42,6 +41,7 @@ const check_new_azure_connection_timeout = 20 * 1000; * */ async function create_account(req) { + const account = { _id: ( req.rpc_params.new_system_parameters ? @@ -77,10 +77,12 @@ async function create_account(req) { system_store.parse_system_store_id(req.rpc_params.new_system_parameters.new_system_id) : req.system._id; - if (req.rpc_params.has_login) { - account.password = req.rpc_params.password; - const password_hash = await bcrypt_password(account.password.unwrap()); - account.password = password_hash; + if (req.rpc_params.has_login && req.rpc_params.password) { + if (account.email.unwrap() === 'admin@noobaa.io') { + account.password = req.rpc_params.password; + } else { + throw new RpcError('Invalid account configuration - Password should not be set'); + } } if (req.rpc_params.s3_access) { @@ -574,7 +576,7 @@ async function reset_password(req) { const params = req.rpc_params; - const password = await bcrypt_password(params.password.unwrap()); + const password = params.password.unwrap(); const changes = { password: new SensitiveString(password), @@ -1334,35 +1336,25 @@ function ensure_support_account() { } console.log('CREATING SUPPORT ACCOUNT...'); - return bcrypt_password(system_store.get_server_secret()) - .then(password => { - const support_account = { - _id: system_store.new_system_store_id(), - name: new SensitiveString('Support'), - email: new SensitiveString('support@noobaa.com'), - password: new SensitiveString(password), - has_login: true, - is_support: true, - }; - - return system_store.make_changes({ - insert: { - accounts: [support_account] - } - }); - }) - .then(() => console.log('SUPPORT ACCOUNT CREATED')); + const support_account = { + _id: system_store.new_system_store_id(), + name: new SensitiveString('Support'), + email: new SensitiveString('support@noobaa.com'), + has_login: true, + is_support: true, + }; + + return system_store.make_changes({ + insert: { + accounts: [support_account] + } + }); }) .catch(function(err) { console.error('FAILED CREATE SUPPORT ACCOUNT', err); }); } -function bcrypt_password(password) { - return P.resolve() - .then(() => password && bcrypt.hash(password, 10)); -} - function is_support_or_admin_or_me(system, account, target_account) { return account.is_support || (target_account && String(target_account._id) === String(account._id)) || @@ -1426,10 +1418,6 @@ function validate_create_account_params(req) { } if (req.rpc_params.has_login) { - if (!req.rpc_params.password) { - throw new RpcError('BAD_REQUEST', 'Password is missing'); - } - // Verify that account with login access have full s3 access permissions. const { default_resource } = req.rpc_params.new_system_parameters || req.rpc_params; const allow_bucket_creation = req.rpc_params.new_system_parameters ? @@ -1444,17 +1432,20 @@ function validate_create_account_params(req) { throw new RpcError('BAD_REQUEST', 'Accounts with login access must have full s3 access permissions'); } - } else if (req.rpc_params.password) { - throw new RpcError('BAD_REQUEST', 'Password should not be sent'); + } + if (req.rpc_params.password) { + dbg.warn('Password should not be sent; password/has_login', req.rpc_params.password, req.rpc_params.has_login); } } async function verify_authorized_account(req) { //operator connects by token and doesn't have the password property. + if (req.role === 'operator') { return true; } - return bcrypt.compare(req.rpc_params.verification_password.unwrap(), req.account.password.unwrap()); + + return (req.rpc_params.verification_password.unwrap() === req.account.password.unwrap()); } function _list_connection_usage(account, credentials) { diff --git a/src/server/system_services/schemas/account_schema.js b/src/server/system_services/schemas/account_schema.js index 3f3a7c94d3..fb12b4d4f6 100644 --- a/src/server/system_services/schemas/account_schema.js +++ b/src/server/system_services/schemas/account_schema.js @@ -25,7 +25,7 @@ module.exports = { // password login has_login: { type: 'boolean' }, - password: { wrapper: SensitiveString }, // bcrypted password + password: { wrapper: SensitiveString }, // password next_password_change: { date: true }, // default policy for new buckets diff --git a/src/tools/bcrypt_cli.js b/src/tools/bcrypt_cli.js deleted file mode 100644 index fa01f8b1d7..0000000000 --- a/src/tools/bcrypt_cli.js +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (C) 2016 NooBaa */ -'use strict'; - -const bcrypt = require('bcrypt'); - -// This is to support shell scripts -// It is used in order to bcrypt support account password in mongo_upgrade -const password = process.argv[2] || ''; -const hash = process.argv[3] || ''; - -if (hash) { - console.log(bcrypt.compareSync(password, hash)); -} else { - console.log(bcrypt.hashSync(password, 10)); -} diff --git a/src/upgrade/upgrade_scripts/5.18.0/remove_account_password.js b/src/upgrade/upgrade_scripts/5.18.0/remove_account_password.js new file mode 100644 index 0000000000..ca00faeb75 --- /dev/null +++ b/src/upgrade/upgrade_scripts/5.18.0/remove_account_password.js @@ -0,0 +1,30 @@ +/* Copyright (C) 2024 NooBaa */ +"use strict"; + +async function run({ dbg, system_store }) { + try { + dbg.log0('starting upgrade accounts...'); + const accounts = system_store.data.accounts + .map(a => a.password && ({ + _id: a._id, + $unset: { password: true } + })) + .filter(Boolean); + if (accounts.length > 0) { + dbg.log0(`deleting "passwords" from accounts: ${accounts.map(b => b._id).join(', ')}`); + await system_store.make_changes({ update: { accounts } }); + } else { + dbg.log0('upgrade accounts: no upgrade needed...'); + } + } catch (err) { + dbg.error('got error while upgrading accounts:', err); + throw err; + } +} + + +module.exports = { + run, + description: 'Update accounts to remove "password" field' +}; +