Skip to content

Commit f6cb7c3

Browse files
epuertatpecastro
authored andcommitted
mgr: fix pyO3 import issues
The latest versions of pyO3 (a Python binding for Rust) explicitly added a check to detect multiple imports. In subinterpreter environments, this leads to an ImportError: "PyO3 modules may only be initialized once per interpreter process" (it has been recenlty replaced with a more specific: "PyO3 modules may only be initialized once per interpreter process". This is only a workaround while the root cause is fixed (see PyO3/pyo3#4162). Fixes: https://tracker.ceph.com/issues/64213 Signed-off-by: Ernesto Puerta <epuertat@redhat.com>
1 parent 7bae2f5 commit f6cb7c3

File tree

2 files changed

+20
-29
lines changed

2 files changed

+20
-29
lines changed

src/pybind/mgr/dashboard/services/access_control.py

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,21 @@
22
# pylint: disable=too-many-arguments,too-many-return-statements
33
# pylint: disable=too-many-branches, too-many-locals, too-many-statements
44

5+
import base64
56
import errno
7+
import hashlib
8+
import hmac
69
import json
710
import logging
11+
import os
812
import re
913
import threading
1014
import time
1115
from datetime import datetime, timedelta
1216
from string import ascii_lowercase, ascii_uppercase, digits, punctuation
1317
from typing import List, Optional, Sequence
1418

15-
import bcrypt
1619
from mgr_module import CLICheckNonemptyFileInput, CLIReadCommand, CLIWriteCommand
17-
from mgr_util import password_hash
1820

1921
from .. import mgr
2022
from ..exceptions import PasswordPolicyException, PermissionNotValid, \
@@ -26,7 +28,7 @@
2628

2729
logger = logging.getLogger('access_control')
2830
DEFAULT_FILE_DESC = 'password/secret'
29-
31+
SCRYPT_SALT_LEN = 29
3032

3133
_P = Permission # short alias
3234

@@ -353,8 +355,17 @@ def enabled(self, value):
353355
self._enabled = value
354356
self.refresh_last_update()
355357

358+
@staticmethod
359+
def calculate_password_hash(password: str, input_salt: Optional[str] = None) -> str:
360+
if input_salt is None:
361+
salt = os.urandom(SCRYPT_SALT_LEN)
362+
else:
363+
salt = base64.b64decode(salt)[:SCRYPT_SALT_LEN]
364+
hash = hashlib.scrypt(password.encode('utf8'), salt=salt, n=2**14, r=8, p=1)
365+
return base64.b64encode(salt + hash).decode('utf8')
366+
356367
def set_password(self, password):
357-
self.set_password_hash(password_hash(password))
368+
self.set_password_hash(self.calculate_password_hash(password))
358369

359370
def set_password_hash(self, hashed_password):
360371
self.invalid_auth_attempt = 0
@@ -371,8 +382,8 @@ def compare_password(self, password):
371382
:return: `True` if the passwords are equal, otherwise `False`.
372383
:rtype: bool
373384
"""
374-
pass_hash = password_hash(password, salt_password=self.password)
375-
return pass_hash == self.password
385+
pass_hash = self.calculate_password_hash(password, salt_password=self.password)
386+
return hmac.compare_digest(pass_hash, self.password)
376387

377388
def is_pwd_expired(self):
378389
if self.pwd_expiration_date:
@@ -501,7 +512,7 @@ def create_user(self, username, password, name, email, enabled=True,
501512
if pwd_expiration_date and \
502513
(pwd_expiration_date < int(time.mktime(datetime.utcnow().timetuple()))):
503514
raise PwdExpirationDateNotValid()
504-
user = User(username, password_hash(password), name, email, enabled=enabled,
515+
user = User(username, User.calculate_password_hash(password), name, email, enabled=enabled,
505516
pwd_expiration_date=pwd_expiration_date,
506517
pwd_update_required=pwd_update_required)
507518
self.users[username] = user
@@ -906,27 +917,6 @@ def ac_user_set_password(_, username: str, inbuf: str,
906917
return -errno.ENOENT, '', str(ex)
907918

908919

909-
@CLIWriteCommand('dashboard ac-user-set-password-hash')
910-
@CLICheckNonemptyFileInput(desc=DEFAULT_FILE_DESC)
911-
def ac_user_set_password_hash(_, username: str, inbuf: str):
912-
'''
913-
Set user password bcrypt hash from -i <file>
914-
'''
915-
hashed_password = inbuf
916-
try:
917-
# make sure the hashed_password is actually a bcrypt hash
918-
bcrypt.checkpw(b'', hashed_password.encode('utf-8'))
919-
user = mgr.ACCESS_CTRL_DB.get_user(username)
920-
user.set_password_hash(hashed_password)
921-
922-
mgr.ACCESS_CTRL_DB.save()
923-
return 0, json.dumps(user.to_dict()), ''
924-
except ValueError:
925-
return -errno.EINVAL, '', 'Invalid password hash'
926-
except UserDoesNotExist as ex:
927-
return -errno.ENOENT, '', str(ex)
928-
929-
930920
@CLIWriteCommand('dashboard ac-user-set-info')
931921
def ac_user_set_info(_, username: str, name: str, email: str):
932922
'''

src/pybind/mgr/mgr_util.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
if 'UNITTEST' in os.environ:
1111
import tests # noqa
1212

13-
import bcrypt
1413
import cephfs
1514
import contextlib
1615
import datetime
@@ -976,6 +975,8 @@ def wrapper(*args: Any, **kwargs: Any) -> T:
976975

977976

978977
def password_hash(password: Optional[str], salt_password: Optional[str] = None) -> Optional[str]:
978+
import bcrypt
979+
979980
if not password:
980981
return None
981982
if not salt_password:

0 commit comments

Comments
 (0)