mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 11:16:47 +00:00
fix(deps): libpass instead of crypt-r; gstfsd's python3-libguestfs on a RHEL compute; PyYAML for the tests
- The root password's SHA-512 crypt hash comes from libpass (the maintained passlib fork, pure Python) instead of crypt-r, a copy of the stdlib crypt module gone in Python 3.13: crypt-r ships no wheels and its build needs crypt.h, which Ubuntu 26.04 no longer brings with python3-dev, so the installer and the manual installation failed there. The hash is the same format ($6$, now with libpass's 656000 rounds), checked with glibc's crypt. - The README's RHEL compute packages left out python3-libguestfs, which gstfsd imports with the system python: setting the password or key of a shut-off VM failed there. - The tests read YAML themselves and had PyYAML only through drf-spectacular.
This commit is contained in:
parent
25a2f22b90
commit
f411659f40
5 changed files with 10 additions and 11 deletions
|
|
@ -240,7 +240,7 @@ Sign in at `http://<server-ip>`; you must set a new password at the first login,
|
|||
|
||||
A compute node is a KVM host the panel manages over libvirt.
|
||||
|
||||
1. Install KVM and libvirt. The bootstrap script handles Ubuntu, Debian, CentOS, Fedora, Rocky Linux and AlmaLinux 10, openEuler 24.03 LTS, openSUSE and SLES. On RHEL, which needs EPEL from its release RPM, install the `qemu-kvm` and `libvirt` packages yourself and enable `virtqemud.socket` (plus `virtproxyd-tcp.socket` for TCP):
|
||||
1. Install KVM and libvirt. The bootstrap script handles Ubuntu, Debian, CentOS, Fedora, Rocky Linux and AlmaLinux 10, openEuler 24.03 LTS, openSUSE and SLES. On RHEL, which needs EPEL from its release RPM, install the `qemu-kvm`, `libvirt` and `python3-libguestfs` (for gstfsd, step 3) packages yourself and enable `virtqemud.socket` (plus `virtproxyd-tcp.socket` for TCP):
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/retspen/webvirtcloud/master/dev/libvirt-bootstrap.sh | sudo sh
|
||||
|
|
|
|||
|
|
@ -23,4 +23,5 @@ python-socketio==5.18.1
|
|||
segno==1.6.6
|
||||
websockify==0.13.0
|
||||
whitenoise==6.12.0
|
||||
crypt-r>=3.13.0; python_version >= "3.11"
|
||||
# the root password's SHA-512 crypt hash (the stdlib crypt is gone in Python 3.13)
|
||||
libpass==1.9.4
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ libsass==0.23.0
|
|||
django-debug-toolbar==8.0.0
|
||||
django-debug-toolbar-template-profiler==2.1.0
|
||||
pip-audit==2.10.1
|
||||
# the tests read cloud-init's YAML
|
||||
PyYAML==6.0.3
|
||||
ruff==0.17.0
|
||||
# tracebacks of failures in manage.py test --parallel
|
||||
tblib==3.2.2
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
from passlib.hash import sha512_crypt
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
|
|
@ -45,9 +46,10 @@ class SetRootPassTestCase(TestCase):
|
|||
self.assertEqual(compute, self.compute)
|
||||
self.assertEqual(data["action"], "password")
|
||||
self.assertEqual(data["vname"], "renamed-on-host")
|
||||
# SHA-512 crypt with a random salt, not the old fixed one
|
||||
# SHA-512 crypt with a random salt, not the old fixed one, which the guest's crypt(3) checks
|
||||
self.assertTrue(data["passwd"].startswith("$6$"))
|
||||
self.assertFalse(data["passwd"].startswith("$6$kgPoiREy$"))
|
||||
self.assertTrue(sha512_crypt.verify("newSecretPassword123", data["passwd"]))
|
||||
|
||||
def test_set_root_pass_get_not_allowed(self):
|
||||
response = self.client.get(reverse("instances:rootpasswd", args=[self.instance.id]))
|
||||
|
|
|
|||
|
|
@ -7,17 +7,10 @@ import os
|
|||
import re
|
||||
import secrets
|
||||
import socket
|
||||
import sys
|
||||
import subprocess
|
||||
import time
|
||||
from ipaddress import ip_address
|
||||
|
||||
# the stdlib crypt is deprecated from Python 3.11 and gone in 3.13: crypt_r is the same module
|
||||
if sys.version_info >= (3, 11):
|
||||
import crypt_r as crypt
|
||||
else:
|
||||
import crypt
|
||||
|
||||
from accounts.models import UserInstance, UserSSHKey
|
||||
from admin.decorators import superuser_only
|
||||
from appsettings.models import AppSettings
|
||||
|
|
@ -42,6 +35,7 @@ from django.utils.translation import gettext as _
|
|||
from django.utils.translation import gettext_lazy, gettext_noop
|
||||
from django.views.decorators.http import require_POST
|
||||
from django.views.decorators.debug import sensitive_post_parameters
|
||||
from passlib.hash import sha512_crypt
|
||||
from libvirt import (VIR_DOMAIN_PAUSED,
|
||||
VIR_DOMAIN_RUNNING,
|
||||
VIR_DOMAIN_SHUTOFF,
|
||||
|
|
@ -1076,7 +1070,7 @@ def set_root_pass(request, pk):
|
|||
if request.method == "POST":
|
||||
passwd = request.POST.get("passwd", None)
|
||||
if passwd:
|
||||
passwd_hash = crypt.crypt(passwd, crypt.mksalt(crypt.METHOD_SHA512))
|
||||
passwd_hash = sha512_crypt.hash(passwd)
|
||||
# gstfsd opens the domain by name: send the host's current one.
|
||||
data = {"action": "password", "passwd": passwd_hash, "vname": instance.proxy.instance.name()}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue