Версия ====== pve-manager-7.0.11-alt5 Дистрибутивы ============ * p10-server-10-x86-64 Предусловия =========== Развернут PVE из трёх нод (pve01, pve02, pve03) со следующими хранилищами: # cat /etc/pve/storage.cfg dir: mycephfs path /mnt/mycephfs content snippets,iso,vztmpl,backup,images,rootdir prune-backups keep-last=1 shared 1 drbd: drbd1001 resourcegroup defaultpool content rootdir,images controller pve01 rbd: rbd content images,rootdir krbd 0 pool rbd dir: local path /var/lib/vz content snippets,iso,vztmpl,images,backup,rootdir prune-backups keep-all=1 dir: mystorage path /mnt/mycephfs/template/mystorage content vztmpl,rootdir,backup,images,iso,snippets prune-backups keep-all=1 shared 1 dir: teststorage path /mnt/mycephfs/template/teststorage content iso,snippets,vztmpl,rootdir,backup,images prune-backups keep-all=1 shared 1 Примонтирован CEPH: # cat /etc/fstab | grep ceph 192.168.0.1,192.168.0.2,192.168.0.3:/ /mnt/mycephfs ceph name=admin,secretfile=/etc/ceph/admin.secret,noatime,_netdev,x-systemd.automount 0 0 Существует системный пользователь test: uid=500(test) gid=500(test) группы=10(wheel),14(uucp),19(proc),22(cdrom),71(floppy),80(cdwriter),81(audio),83(radio),100(users),481(vboxusers),467(scanner),466(xgrp),440(camera),488(video),483(fuse),455(vboxadd),454(vboxsf),500(test) Шаги воспроизведения ==================== 1. Создать тестовую группу: Датацентр → Разрешения → Группы → Создать → задать имя как testgroup. 2. Создать пользователя test@pam: Датацентр → Разрешения → Пользователи → Добавить → заполнить следующие параметры 1. Имя пользователя: test 2. Область: Linux PAM standard authentication 3. Группа: testgroup → нажать кнопку Добавить. 3. Добавить роль TestAudit: Датацентр → Разрешения → Роли → Создать → заполнить следующие параметры 1. Имя: TestAudit 2. Привелегии: Sys.Audit, Datastore.Audit 4. Добавить роль TestAllocateTemplate: Датацентр → Разрешения → Роли → Создать → заполнить следующие параметры 1. Имя: TestAllocateTemplate 2. Привелегии: Datastore.AllocateSpace, Datastore.AllocateTemplate, Datastore.Audit 5. Добавить разрешение: Датацентр → Разрешения → Добавить → Разрешения группы → заполнить следующие параметры 1. Путь: / 2. Группа: testgroup 3. TestAudit 4. Стоит галочка Распространять. 6. Добавить разрешение: Датацентр → Разрешения → Добавить → Разрешения группы → заполнить следующие параметры 1. Путь: /storage 2. Группа: testgroup 3. TestAudit 4. Стоит галочка Распространять. 7. Добавить разрешение: Датацентр → Разрешения → Добавить → Разрешения группы → заполнить следующие параметры 1. Путь: /storage/mystorage 2. Группа: testgroup 3. TestAllocateTemplate 4. Стоит галочка Распространять. 8. Убедиться, что в итоге у пользователя test такие права: # pveum user permissions test@pam ┌────────────────────┬────────────────────────────────┐ │ ACL path │ Permissions │ ╞════════════════════╪════════════════════════════════╡ │ / │ Datastore.Audit (*) │ │ │ Sys.Audit (*) │ ├────────────────────┼────────────────────────────────┤ │ /access │ Datastore.Audit (*) │ │ │ Sys.Audit (*) │ ├────────────────────┼────────────────────────────────┤ │ /access/groups │ Datastore.Audit (*) │ │ │ Sys.Audit (*) │ ├────────────────────┼────────────────────────────────┤ │ /nodes │ Datastore.Audit (*) │ │ │ Sys.Audit (*) │ ├────────────────────┼────────────────────────────────┤ │ /pools │ Datastore.Audit (*) │ │ │ Sys.Audit (*) │ ├────────────────────┼────────────────────────────────┤ │ /storage │ Datastore.Audit (*) │ │ │ Sys.Audit (*) │ ├────────────────────┼────────────────────────────────┤ │ /storage/mystorage │ Datastore.AllocateSpace (*) │ │ │ Datastore.AllocateTemplate (*) │ │ │ Datastore.Audit (*) │ ├────────────────────┼────────────────────────────────┤ │ /vms │ Datastore.Audit (*) │ │ │ Sys.Audit (*) │ └────────────────────┴────────────────────────────────┘ 9. Зайти в веб-интерфейс, залогинится под пользователем test. 10. Перейти по Датацентр → pve01 → teststorage → ISO Images. 11. Проверить доступность кнопки Загрузить. Ожидаемый результат: Кнопка Загрузить находится в неактивном состоянии (её невозможно нажать). Фактический результат: Кнопка Загрузить находится в активном состоянии (её возможно нажать). То есть право Datastore.AllocateTemplate присвоено /storage/mystorage, но при этом доступно /storage/teststorage. При попытке загрузить образ на teststorage, показывается сообщение об ошибке: Error '0' occurred while receiving the document
Результат проверки актуальности Состояние: Sisyphus: pve-manager 9.2.5, Browser.js всё ещё enableUpload по глобальному GuiCap.storage, API проверяет /storage/{id}. Баг на бумаге жив. Рекомендация: ретест кнопки «Загрузить» без права на конкретное хранилище на Sisyphus
Проверено на ALT Virtualization 11.0 (PVE Edition), обновлённом до текущей ветки: pve-manager-9.2.5-alt5, pve-access-control-9.1.1-alt2 (те же версии, что сейчас в Sisyphus). Воспроизводится. Схема прав из описания (роль с Datastore.AllocateTemplate только на одно хранилище) даёт вот такой ответ /access/ticket: cap.storage = {"Datastore.AllocateTemplate": 1, "Datastore.Audit": 1, "Datastore.AllocateSpace": 1} при том что по путям права разные: /storage/mystorage: Datastore.AllocateTemplate есть /storage/teststorage: Datastore.AllocateTemplate нет /storage/local: Datastore.AllocateTemplate нет cap.storage — объединение по всем хранилищам, а www/manager6/storage/Browser.js:62 берёт право именно оттуда: let enableUpload = !!caps.storage['Datastore.AllocateTemplate']; и раздаёт его всем вкладкам текущего хранилища (строки 105, 117, 166). GuiCap ставится один раз при входе из loginData.cap (Workspace.js:31), про конкретный storeid он ничего не знает. В интерфейсе под таким пользователем на хранилище teststorage кнопка «Загрузить» активна, хотя «Скачать по URL» и «Удалить» рядом корректно погашены. При нажатии диалог открывается полностью рабочим, файл выбирается, прогресс доходит до 100.00% — и замирает, никакого сообщения пользователю. Отказ виден только в логе сервера: "POST /api2/json/nodes/<node>/storage/teststorage/upload HTTP/1.1" 403 - Тот же файл в mystorage, где право есть, загружается штатно (200, UPID ... imgcopy). Итого два дефекта: Browser.js должен проверять право на /storage/<storeid>, а не глобальный caps.storage; и диалог загрузки должен показывать 403, а не зависать на 100%. Скриншоты сохранены, могу приложить.