chore: replace passlib with bcrypt

passlib uses deprecated crypt module which is deprecated and scheduled
for removal in 3.13. Unfortunately, this module seems to be
unmaintained, so this commit replaces passlib with bcrypt, unfortunately
breaking current passwords
This commit is contained in:
Evgenii Alekseev 2024-10-05 15:59:51 +03:00
parent 910d178c71
commit cd0ac7a7bd
12 changed files with 66 additions and 37 deletions

View File

@ -10,7 +10,7 @@ echo -e '[arcanisrepo]\nServer = https://repo.arcanis.me/$arch\nSigLevel = Never
# refresh the image
pacman -Syyu --noconfirm
# main dependencies
pacman -S --noconfirm devtools git pyalpm python-inflection python-passlib python-pyelftools python-requests python-systemd sudo
pacman -S --noconfirm devtools git pyalpm python-bcrypt python-inflection python-pyelftools python-requests python-systemd sudo
# make dependencies
pacman -S --noconfirm --asdeps base-devel python-build python-flit python-installer python-tox python-wheel
# optional dependencies

View File

@ -35,8 +35,8 @@ RUN pacman -S --noconfirm --asdeps \
devtools \
git \
pyalpm \
python-bcrypt \
python-inflection \
python-passlib \
python-pyelftools \
python-requests \
&& \

View File

@ -147,7 +147,7 @@ There are multiple subdirectories, some of them are commons for any repository,
* ``pacman/{repository}/{architecture}`` is the repository and architecture specific caches for pacman's databases.
* ``repository/{repository}/{architecture}`` is a repository packages directory.
Normally you should avoid direct interaction with the application tree. For tree migration process refer to the :doc:`migration notes <migration>`.
Normally you should avoid direct interaction with the application tree. For tree migration process refer to the :doc:`migration notes <migrations/index>`.
Database
--------

View File

@ -34,7 +34,7 @@ Contents
configuration
command-line
faq/index
migration
migrations/index
architecture
advanced-usage
triggers

View File

@ -1,25 +1,5 @@
Manual migrations
=================
Normally the most of migrations are handled automatically after application start, however, some upgrades require manual interventions; this document describes them.
Upgrades to breakpoints
-----------------------
To 2.9.0
^^^^^^^^
This release includes major upgrade for the newest devtools and archlinux repository structure. In order to upgrade package need to:
#. Upgrade to the latest major release of python (3.11) (required by other changes).
#. Upgrade devtools to the latest release.
#. Backup local settings, ``/etc/ahriman.ini.d/00-setup-overrides.ini`` by default.
#. Run setup command (i.e. ``ahriman service-setup``) again with the same arguments as used before. This step can be done manually by moving ``devtools`` configuration (something like ``/usr/share/devtools/pacman-ahriman*.conf``) to new location ``/usr/share/devtools/pacman.conf.d/`` under name ``ahriman.conf``. After that make sure to remove any ``community`` mentions from configurations (e.g. ``/usr/share/devtools/pacman.conf.d/ahriman.conf``, ``/etc/ahriman.ini``) if there were any. The only thing which will change is ``devtools`` configuration.
#. Remove build chroot as it is incompatible, e.g. ``sudo ahriman service-clean --chroot``.
#. Run ``sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy`` in order to update local databases.
To 2.12.0
^^^^^^^^^
---------
This release includes paths migration. Unlike usual case, no automatic migration is performed because it might break user configuration. The following noticeable changes have been made:

View File

@ -0,0 +1,16 @@
To 2.16.0
---------
This release replaces ``passlib`` dependency with ``bcrypt``.
The reason behind this change is that python developers have deprecated and scheduled for removal ``crypt`` module, which is used by ``passlib``. (By the way, they recommend to use ``passlib`` as a replacement.) Unfortunately, it appears that ``passlib`` is unmaintained (see `the issue <https://foss.heptapod.net/python-libs/passlib/-/issues/187>`__), so the only solution is to migrate to anoher library.
Because passwords are stored as hashes, it is near to impossible to shadow change passwords in database, the manual intervention is required if:
#. Authentication is used.
#. Notification provider is ``configuration`` or a user with explicitly set password exists.
Manual steps might look as:
#. Get list of users with their roles ``ahriman user-list``.
#. For each user run update command, i.e. ``ahriman user-add <username> -R <role>``. Type password when it will be requested.

11
docs/migrations/2.9.0.rst Normal file
View File

@ -0,0 +1,11 @@
To 2.9.0
--------
This release includes major upgrade for the newest devtools and archlinux repository structure. In order to upgrade package need to:
#. Upgrade to the latest major release of python (3.11) (required by other changes).
#. Upgrade devtools to the latest release.
#. Backup local settings, ``/etc/ahriman.ini.d/00-setup-overrides.ini`` by default.
#. Run setup command (i.e. ``ahriman service-setup``) again with the same arguments as used before. This step can be done manually by moving ``devtools`` configuration (something like ``/usr/share/devtools/pacman-ahriman*.conf``) to new location ``/usr/share/devtools/pacman.conf.d/`` under name ``ahriman.conf``. After that make sure to remove any ``community`` mentions from configurations (e.g. ``/usr/share/devtools/pacman.conf.d/ahriman.conf``, ``/etc/ahriman.ini``) if there were any. The only thing which will change is ``devtools`` configuration.
#. Remove build chroot as it is incompatible, e.g. ``sudo ahriman service-clean --chroot``.
#. Run ``sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy`` in order to update local databases.

14
docs/migrations/index.rst Normal file
View File

@ -0,0 +1,14 @@
Manual migrations
=================
Normally the most of migrations are handled automatically after application start, however, some upgrades require manual interventions; this document describes them.
Upgrades to breakpoints
-----------------------
.. toctree::
:maxdepth: 2
2.9.0
2.12.0
2.16.0

View File

@ -7,7 +7,7 @@ pkgdesc="ArcH linux ReposItory MANager"
arch=('any')
url="https://github.com/arcan1s/ahriman"
license=('GPL3')
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-inflection' 'python-passlib' 'python-pyelftools' 'python-requests')
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-bcrypt' 'python-inflection' 'python-pyelftools' 'python-requests')
makedepends=('python-build' 'python-flit' 'python-installer' 'python-wheel')
optdepends=('python-aioauth-client: web server with OAuth2 authorization'
'python-aiohttp: web server'

View File

@ -21,7 +21,7 @@ It was found that there was an upgrade from old devtools package to the new one,
* remove build chroot, e.g.: ahriman service-clean --chroot;
* update local databases: ahriman update --no-aur --no-local --no-manual -yy.
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html.
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migrations/2.9.0.html.
EOF
}
@ -37,6 +37,16 @@ Whereas old local tree is still supported it is highly recommended to migrate to
* enable web and timer services again by using x86_64-aur suffix,
where x86_64 is the repository architecture and aur is the repository name.
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html.
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migrations/2.12.0.html.
EOF
}
_2_16_0_1_changes() {
cat << EOF
In order to prepare to python 3.13 the project now uses bcrypt instead of passlib for generating and validating
passwords, because the passlib seems to be unmaintained and will be broken since then. If you are using password
authentication, you'd need to generate passwords again.
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migrations/2.16.0.html.
EOF
}

View File

@ -17,8 +17,8 @@ authors = [
]
dependencies = [
"bcrypt",
"inflection",
"passlib",
"pyelftools",
"requests",
]

View File

@ -17,8 +17,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import bcrypt
from dataclasses import dataclass, replace
from passlib.hash import sha512_crypt
from secrets import token_urlsafe as generate_password
from typing import Self
@ -67,8 +68,6 @@ class User:
packager_id: str | None = None
key: str | None = None
_HASHER = sha512_crypt
def __post_init__(self) -> None:
"""
remove empty fields
@ -101,10 +100,9 @@ class User:
bool: ``True`` in case if password matches, ``False`` otherwise
"""
try:
verified: bool = self._HASHER.verify(password + salt, self.password)
return bcrypt.checkpw((password + salt).encode("utf8"), self.password.encode("utf8"))
except ValueError:
verified = False # the absence of evidence is not the evidence of absence (c) Gin Rummy
return verified
return False # the absence of evidence is not the evidence of absence (c) Gin Rummy
def hash_password(self, salt: str) -> Self:
"""
@ -120,8 +118,8 @@ class User:
# in case of empty password we leave it empty. This feature is used by any external (like OAuth) provider
# when we do not store any password here
return self
password_hash: str = self._HASHER.hash(self.password + salt)
return replace(self, password=password_hash)
password_hash = bcrypt.hashpw((self.password + salt).encode("utf8"), bcrypt.gensalt())
return replace(self, password=password_hash.decode("utf8"))
def verify_access(self, required: UserAccess) -> bool:
"""