Merge pull request #14606 from overleaf/jpa-bcrypt-metrics

[web] add metrics for bcrypt operations

GitOrigin-RevId: 42bf9bedb84295ceea7f660f1daac3adb7b853d9
This commit is contained in:
Jakob Ackermann
2023-09-05 08:04:56 +00:00
committed by Copybot
parent 77364240a0
commit 45c9d805dd
2 changed files with 24 additions and 11 deletions
@@ -70,6 +70,10 @@ const AuthenticationManager = {
if (!user || !user.hashedPassword) {
return callback(null, null, null)
}
Metrics.inc('bcrypt', 1, {
method: 'compare',
path: bcrypt.getRounds(user.hashedPassword),
})
bcrypt.compare(password, user.hashedPassword, function (error, match) {
if (error) {
return callback(error)
@@ -255,13 +259,16 @@ const AuthenticationManager = {
checkRounds(user, hashedPassword, password, callback) {
// Temporarily disable this function, TODO: re-enable this
if (Settings.security.disableBcryptRoundsUpgrades) {
Metrics.inc('bcrypt_check_rounds', 1, { status: 'disabled' })
return callback()
}
// check current number of rounds and rehash if necessary
const currentRounds = bcrypt.getRounds(hashedPassword)
if (currentRounds < BCRYPT_ROUNDS) {
Metrics.inc('bcrypt_check_rounds', 1, { status: 'upgrade' })
AuthenticationManager._setUserPasswordInMongo(user, password, callback)
} else {
Metrics.inc('bcrypt_check_rounds', 1, { status: 'success' })
callback()
}
},
@@ -276,6 +283,10 @@ const AuthenticationManager = {
if (error) {
return callback(error)
}
Metrics.inc('bcrypt', 1, {
method: 'hash',
path: BCRYPT_ROUNDS,
})
bcrypt.hash(password, salt, callback)
})
},
@@ -24,7 +24,9 @@ describe('AuthenticationManager', function () {
db: (this.db = { users: {} }),
ObjectId,
},
bcrypt: (this.bcrypt = {}),
bcrypt: (this.bcrypt = {
getRounds: sinon.stub().returns(4),
}),
'@overleaf/settings': this.settings,
'../User/UserGetter': (this.UserGetter = {}),
'./AuthenticationErrors': AuthenticationErrors,
@@ -137,10 +139,6 @@ describe('AuthenticationManager', function () {
it('should not return the user', function () {
this.callback.calledWith(null, null).should.equal(true)
})
it('should not send metrics', function () {
expect(this.metrics.inc.called).to.equal(false)
})
})
describe('when another request runs in parallel', function () {
@@ -307,10 +305,6 @@ describe('AuthenticationManager', function () {
)
})
it('should not send metrics', function () {
expect(this.metrics.inc.called).to.equal(false)
})
it('should not return the user', function () {
this.callback.calledWith(null, null).should.equal(true)
this.UserAuditLogHandler.addEntry.callCount.should.equal(0)
@@ -374,7 +368,11 @@ describe('AuthenticationManager', function () {
})
it('should check the number of rounds', function () {
this.bcrypt.getRounds.called.should.equal(true)
expect(this.metrics.inc).to.have.been.calledWith(
'bcrypt_check_rounds',
1,
{ status: 'upgrade' }
)
})
it('should set the users password (with a higher number of rounds)', function () {
@@ -408,7 +406,11 @@ describe('AuthenticationManager', function () {
})
it('should not check the number of rounds', function () {
this.bcrypt.getRounds.called.should.equal(false)
expect(this.metrics.inc).to.have.been.calledWith(
'bcrypt_check_rounds',
1,
{ status: 'disabled' }
)
})
it('should not set the users password (with a higher number of rounds)', function () {