Complete getting rid of passlib

Farewell passlib. It served us good job but sadly became unmaintaned
with lot of issues coming with the py313.

Change-Id: I6027752bb3adb1ebf9c815433fe967037965b91a
This commit is contained in:
Artem Goncharov 2024-09-23 18:02:34 +02:00
parent 412b477eb4
commit 7edc299148
4 changed files with 9 additions and 99 deletions

View File

@ -11,7 +11,6 @@
# under the License.
from oslo_config import cfg
import passlib.utils
from keystone.conf import utils
@ -116,7 +115,7 @@ identity caching are enabled.
max_password_length = cfg.IntOpt(
'max_password_length',
default=4096,
max=passlib.utils.MAX_PASSWORD_SIZE,
max=4096,
help=utils.fmt(
"""
Maximum allowed length for user passwords. Decrease this value to improve

View File

@ -15,7 +15,6 @@ import secrets
import string
from oslo_config import fixture as config_fixture
import passlib.hash
from keystone.common import password_hashing
import keystone.conf
@ -47,30 +46,6 @@ class TestPasswordHashing(unit.BaseTestCase):
hashed = password_hashing.hash_password(password)
self.assertTrue(password_hashing.check_password(password, hashed))
def test_scrypt_passlib_compat(self):
"""Test how a password hashed using passlib can be still used without
passlib
"""
self.config_fixture.config(strict_password_check=True)
self.config_fixture.config(
group="identity", password_hash_algorithm="scrypt"
)
self.config_fixture.config(group="identity", max_password_length="96")
# Few iterations to test different inputs
for _ in range(self.ITERATIONS):
# Would be nice to check all pass lengths from 1 till max, but it
# takes too much time, thus using rand to pick up the password
# length
password: str = "".join( # type: ignore
secrets.choice(string.printable)
for i in range(random.randint(1, 96))
)
hashed_passlib = passlib.hash.scrypt.hash(password)
self.assertTrue(
password_hashing.check_password(password, hashed_passlib)
)
def test_bcrypt(self):
self.config_fixture.config(strict_password_check=True)
self.config_fixture.config(
@ -86,23 +61,6 @@ class TestPasswordHashing(unit.BaseTestCase):
hashed = password_hashing.hash_password(password)
self.assertTrue(password_hashing.check_password(password, hashed))
def test_bcrypt_passlib_compat(self):
self.config_fixture.config(strict_password_check=True)
self.config_fixture.config(
group="identity", password_hash_algorithm="bcrypt"
)
self.config_fixture.config(group="identity", max_password_length="72")
# Few iterations to test different inputs
for _ in range(self.ITERATIONS):
password: str = "".join( # type: ignore
secrets.choice(string.printable)
for i in range(random.randint(1, 72))
)
hashed_passlib = passlib.hash.bcrypt.hash(password)
self.assertTrue(
password_hashing.check_password(password, hashed_passlib)
)
def test_bcrypt_sha256(self):
self.config_fixture.config(strict_password_check=True)
self.config_fixture.config(
@ -118,43 +76,6 @@ class TestPasswordHashing(unit.BaseTestCase):
hashed = password_hashing.hash_password(password)
self.assertTrue(password_hashing.check_password(password, hashed))
def test_bcrypt_sha256_passlib_compat(self):
self.config_fixture.config(strict_password_check=True)
self.config_fixture.config(
group="identity", password_hash_algorithm="bcrypt_sha256"
)
self.config_fixture.config(group="identity", max_password_length="96")
# Few iterations to test different inputs
for _ in range(self.ITERATIONS):
password: str = "".join( # type: ignore
secrets.choice(string.printable)
for i in range(random.randint(1, 96))
)
hashed_passlib = passlib.hash.bcrypt_sha256.hash(password)
self.assertTrue(
password_hashing.check_password(password, hashed_passlib)
)
def test_sha512_crypt_passlib_compat(self):
self.config_fixture.config(strict_password_check=True)
# sha512_crypt is deprecated and is not supported to be set.
# We want to ensure that user is still able to login, thus
# set algo to whatever and go verify pwd
self.config_fixture.config(
group="identity", password_hash_algorithm="bcrypt"
)
self.config_fixture.config(group="identity", max_password_length="72")
# few iterations to test multiple random values
for _ in range(self.ITERATIONS):
password: str = "".join( # type: ignore
secrets.choice(string.printable)
for i in range(random.randint(1, 72))
)
hashed_passlib = passlib.hash.sha512_crypt.hash(password)
self.assertTrue(
password_hashing.check_password(password, hashed_passlib)
)
def test_pbkdf2_sha512(self):
self.config_fixture.config(strict_password_check=True)
self.config_fixture.config(
@ -169,20 +90,3 @@ class TestPasswordHashing(unit.BaseTestCase):
)
hashed = password_hashing.hash_password(password)
self.assertTrue(password_hashing.check_password(password, hashed))
def test_pbkdf2_sha512_passlib_compat(self):
self.config_fixture.config(strict_password_check=True)
self.config_fixture.config(
group="identity", password_hash_algorithm="pbkdf2_sha512"
)
self.config_fixture.config(group="identity", max_password_length="72")
# Do few iterations to process different inputs
for _ in range(self.ITERATIONS):
password: str = "".join( # type: ignore
secrets.choice(string.printable)
for i in range(random.randint(1, 72))
)
hashed_passlib = passlib.hash.pbkdf2_sha512.hash(password)
self.assertTrue(
password_hashing.check_password(password, hashed_passlib)
)

View File

@ -0,0 +1,8 @@
---
upgrade:
- |
Dependency on abandoned library `passlib` has been dropped in favor of
using `bcrypt` and `cryptography` directly. It was ensured that passwords
hashed with `passlib` are still supported, but absence of cornercases can
not be guaranteed. If users are not able to login using old password such
password must be rotated.

View File

@ -13,7 +13,6 @@ Flask-RESTful>=0.3.5 # BSD
cryptography>=2.7 # BSD/Apache-2.0
SQLAlchemy>=1.4.0 # MIT
stevedore>=1.20.0 # Apache-2.0
passlib>=1.7.0 # BSD
python-keystoneclient>=3.8.0 # Apache-2.0
keystonemiddleware>=7.0.0 # Apache-2.0
bcrypt>=3.1.3 # Apache-2.0