Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cache for Bcrypt password #11904

Merged
merged 1 commit into from
Nov 9, 2023
Merged

Add cache for Bcrypt password #11904

merged 1 commit into from
Nov 9, 2023

Conversation

INNOCENT-BOY
Copy link
Contributor

@INNOCENT-BOY INNOCENT-BOY commented Oct 30, 2023

Cisco Wap Storage Team add cache to optimize query logic. Bcrypt decrypt is a time-consuming operator. So we could add cache to reduce query time. And We set expire time of each password is 24h.

Fix: Issue 11902

Hi @xiangfu0 , please help to review this pr.

@codecov-commenter
Copy link

codecov-commenter commented Oct 30, 2023

Codecov Report

Merging #11904 (8f24a3c) into master (73d82ec) will increase coverage by 0.01%.
The diff coverage is 0.00%.

@@             Coverage Diff              @@
##             master   #11904      +/-   ##
============================================
+ Coverage     61.42%   61.44%   +0.01%     
  Complexity     1129     1129              
============================================
  Files          2385     2385              
  Lines        129188   129193       +5     
  Branches      20000    20002       +2     
============================================
+ Hits          79355    79378      +23     
+ Misses        44082    44059      -23     
- Partials       5751     5756       +5     
Flag Coverage Δ
custom-integration1 <0.01% <0.00%> (ø)
integration <0.01% <0.00%> (ø)
integration1 <0.01% <0.00%> (ø)
integration2 0.00% <0.00%> (ø)
java-11 61.37% <0.00%> (+<0.01%) ⬆️
java-21 61.32% <0.00%> (+0.02%) ⬆️
skip-bytebuffers-false 61.43% <0.00%> (+0.02%) ⬆️
skip-bytebuffers-true 61.25% <0.00%> (-0.01%) ⬇️
temurin 61.44% <0.00%> (+0.01%) ⬆️
unittests 61.43% <0.00%> (+0.01%) ⬆️
unittests1 46.67% <0.00%> (+<0.01%) ⬆️
unittests2 27.61% <0.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
...broker/broker/ZkBasicAuthAccessControlFactory.java 0.00% <0.00%> (ø)
.../pinot/server/access/ZkBasicAuthAccessFactory.java 0.00% <0.00%> (ø)
...er/api/access/ZkBasicAuthAccessControlFactory.java 0.00% <0.00%> (ø)
...ava/org/apache/pinot/common/utils/BcryptUtils.java 0.00% <0.00%> (ø)
...common/config/provider/AccessControlUserCache.java 0.00% <0.00%> (ø)

... and 15 files with indirect coverage changes

📣 Codecov offers a browser extension for seamless coverage viewing on GitHub. Try it in Chrome or Firefox today!

@xiangfu0
Copy link
Contributor

What if user changed the auth, how long will it reflect?

I feel a better solution is to use zookeeper listener to update the cache, so it's up to date and you just need to init it once during startup time.

@INNOCENT-BOY
Copy link
Contributor Author

INNOCENT-BOY commented Oct 31, 2023

What if user changed the auth, how long will it reflect?

I feel a better solution is to use zookeeper listener to update the cache, so it's up to date and you just need to init it once during startup time.

Hi @xiangfu0 . If users change their password, it will take effect immediately. Because encrypted password is used as key of cache entry. When user change password, it will get null from cache entries, so it will execute Brypt.checkpw to check and put it to cache right now. The reason why we set expire time is that cache will save all old password before delete.
As for zookeeper listener, i don't think it will work. Because we don't know the plain text password. For security reasons, ZooKeeper only stores the encrypted passwords. We also cannot decrypt passwords encrypted using the bcrypt algorithm. Therefore, it is not possible to establish a direct mapping between passwords and encrypted passwords relying solely on ZooKeeper

@@ -135,7 +135,8 @@ private Optional<ZkBasicAuthPrincipal> getPrincipalAuth(RequesterIdentity reques

Optional<ZkBasicAuthPrincipal> principalOpt =
password2principal.entrySet().stream()
.filter(entry -> BcryptUtils.checkpw(entry.getKey(), entry.getValue().getPassword()))
.filter(entry -> BcryptUtils.checkpwWithCache(entry.getKey(), entry.getValue().getPassword(),
_userCache.getUserPasswordAuthCache()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(code format) Can you apply Pinot Style and reformat all the changes in this PR

Copy link
Contributor Author

@INNOCENT-BOY INNOCENT-BOY Nov 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Jackie-Jiang , I have reformat all changes about files in this PR, Please review again.

boolean isMatch = true;
String cachedPassword = userPasswordAuthCache.getIfPresent(encryptedPassword);
if (cachedPassword == null || !cachedPassword.equals(password)) {
isMatch = checkpw(password, encryptedPassword);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means wrong credential will force the checkpw every time right?
Since we already have a zk subscribe, is it necessary to check the password?

Copy link
Contributor Author

@INNOCENT-BOY INNOCENT-BOY Nov 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @xiangfu0 , You are right, each wrong credential will force the checkpw every time. In my opnion, If we have n users, the time complexity for executing checkpw is almost O(n) in one day. And I think this should be tolerable for pinot users.
I think it is necessary to check to password. I will give an example. Such we have a user: admin, password: admin. The path /PinotCluster/PROPERTYSTORE/CONFIGS/USER/admin_CONTROLLER in zookeeper will store below details which save password as encrypted password: "$2a$10$DoCs2UyjBeBk9H7pvZw8kehCa9ot7ofdcF8uKx30PNHdyTyvG4Tiq" other than plain text password "admin".

{
  "id" : "admin",
  "simpleFields" : {
    "password" : "$2a$10$DoCs2UyjBeBk9H7pvZw8kehCa9ot7ofdcF8uKx30PNHdyTyvG4Tiq",
    "component" : "CONTROLLER",
    "role" : "ADMIN",
    "username" : "admin"
  },
  "mapFields" : { },
  "listFields" : { }
}

@xiangfu0 xiangfu0 merged commit 10afb1a into apache:master Nov 9, 2023
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve the performance of ZkBasicAuthAccessFactory
4 participants