АйТи Фреш
Главная / Статьи / Серверы и хостинг
Серверы и хостинг

API-токен PBS 4.2 с правами на datastore, а Proxmox VE его не видит: при чём тут права самого пользователя

Автор: Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш» · · ~22 мин чтения
API-токен PBS 4.2 с правами на datastore, а Proxmox VE его не видит: при чём тут права самого пользователя
Иллюстрация к статье «API-токен PBS 4.2 с правами на datastore, а Proxmox VE его не видит: при чём тут права самого пользователя».

Если вы завели в Proxmox Backup Server отдельного пользователя под бэкапы, выдали его API-токену DatastoreBackup на нужный датастор, а Proxmox VE упрямо показывает пустой список хранилищ и ругается, что датастора не существует — статья для вас. Разберу, почему прав токена всегда недостаточно, как считаются эффективные разрешения, какими двумя командами это диагностируется за пять минут, и как выдавать доступ автоматизации так, чтобы не раздавать DatastoreAdmin направо и налево. С разбором реального случая, где неверный ACL оставил архитектурное бюро на девять суток без резервных копий проектов.

«Cannot find datastore» — это не про имя и не про сеть

Классика жанра. Админ заводит в Proxmox Backup Server отдельного пользователя под бэкапы, генерирует ему API-токен, честно выдаёт токену роль DatastoreBackup на нужный датастор — и идёт подключать хранилище в Proxmox VE. А PVE в ответ либо показывает пустой выпадающий список датасторов, либо валится с сообщением в духе «datastore не существует или недоступен». Дальше начинается ритуальный танец: перепроверяют имя датастора (оно верное), пингуют PBS (пингуется), лезут в фаервол и открывают 8007 (он и так был открыт), меняют fingerprint, пересоздают токен. Ничего не помогает.

Механика тут простая и неочевидная одновременно. Когда PVE спрашивает у PBS список датасторов, PBS не отдаёт всё подряд — он отдаёт только то, на что у обратившегося auth-id есть хоть какие-то права. Нет прав — датастора в ответе нет. А для клиента «в списке нет» и «не существует» выглядят одинаково. Отсюда и формулировка ошибки, которая уводит в сторону: она честно описывает то, что видит PVE, но не описывает причину. В разных версиях PVE точный текст отличается, но смысл один — сервер вернул пустоту.

И вот тут вылезает то, ради чего я вообще пишу эту статью. Прав, выданных токену, недостаточно. Нужны ещё права у пользователя, которому этот токен принадлежит. Это не баг и не странность конкретной сборки — это задокументированное поведение модели доступа PBS, которое ломает интуицию примерно всем, кто настраивает это в первый раз.

Отдельно замечу, почему ошибка так упорно уводит не туда. Мы привыкли, что система разграничения доступа честно говорит «доступ запрещён». В веб-панелях так и происходит: 403, красная плашка, всё понятно. Но API, отдающие списки объектов, почти всегда фильтруют выдачу молча — иначе по кодам ответа можно было бы перебором выяснять, какие датасторы вообще существуют на сервере. PBS ведёт себя ровно так же, и это правильно с точки зрения безопасности, но крайне неудобно с точки зрения диагностики. Держите это в голове: «пустой список» в любом API — это чаще всего вопрос прав, а не вопрос существования.

Если PBS отвечает, TLS-отпечаток совпал, а датастора «нет» — считайте по умолчанию, что это права. Экономит полчаса на каждой такой настройке.
Порядок действий: «Cannot find datastore» — это не про имя и не про сеть — схема
Порядок действий: «Cannot find datastore» — это не про имя и не про сеть. Открыть схему в полном размере

Как устроены права в PBS: дерево путей, роли, propagate

Модель доступа PBS — это дерево путей, похожее на файловую систему. Корень /, под ним ветки /datastore, /datastore/{store}, /datastore/{store}/{ns} для конкретных пространств имён, /remote для удалённых серверов, /tape/ для ленты, /system/network для сетевых настроек, /access/users для управления учётками. ACL вешается на путь, привязывается к auth-id (пользователю, группе или токену) и по умолчанию распространяется вниз по дереву.

Распространение регулируется флагом propagate. В CLI это опция --propagate, значение по умолчанию — true. Права, выданные на более глубоком уровне, перекрывают унаследованные с верхнего. Это важно, когда вы хотите пустить клиента ровно в одно пространство имён внутри общего датастора: на сам датастор даёте минимальную роль без распространения, а рабочую роль вешаете уже на namespace.

Ролей в PBS немного, и путаться в них не надо. По датасторам это: DatastoreAdmin (полный контроль над существующими датасторами), DatastorePowerUser (создавать бэкапы, восстанавливать и удалять через prune свои), DatastoreBackup (создавать бэкапы и восстанавливать свои), DatastoreReader (смотреть содержимое, восстанавливать и запускать verify), DatastoreAudit (видеть настройки и метрики, но не данные). За ними стоят привилегии Datastore.Audit, Datastore.Modify, Datastore.Read, Datastore.Verify, Datastore.Backup, Datastore.Prune. Раскладка по коду PBS такая: DatastoreBackup — это одна-единственная привилегия Datastore.Backup, которая сама по себе разрешает чтение и проверку только для групп, где вы владелец; DatastorePowerUser — Datastore.Backup плюс Datastore.Prune; DatastoreReader — Audit, Read и Verify; DatastoreAdmin — все шесть. Плюс отдельные семейства для удалённых серверов (RemoteAudit, RemoteAdmin, RemoteSyncOperator) и для ленты (TapeAudit, TapeOperator, TapeReader, TapeAdmin).

Ещё один момент, на котором спотыкаются: ACL можно вешать не только на пользователя и токен, но и на группу — в CLI за это отвечает опция --group вместо --auth-id. Групповая выдача удобна, когда людей много, но для машинной автоматизации я её не использую: труднее потом ответить на вопрос «а почему у этого токена такие права», приходится разматывать членство. Для бэкапов держите ACL плоскими и явными, их всё равно будет пять строк на клиента.

Базовые команды, которыми я пользуюсь чаще всего:

Флаг --propagate по умолчанию true. Если вы «на всякий случай» выдали DatastoreAdmin на /datastore, вы выдали его на все датасторы и все namespace разом, включая те, которые появятся завтра.
API-токен PBS 4.2 с правами на datastore, а Proxmox VE его не видит: при чём тут права самого пользователя — схема
Схема к статье. Открыть схему в полном размере

Главное: права токена пересекаются с правами пользователя

Вот дословная формулировка из официальной документации PBS, раздел User Management: «API token permissions are calculated based on ACLs containing their ID, independently of those of their corresponding user. The resulting permission set on a given path is then intersected with that of the corresponding user». Перевожу на человеческий: права токена считаются отдельно, по его собственным ACL, а потом пересекаются с правами пользователя. Пересечение с пустым множеством — пустое множество. Токен не может получить больше, чем есть у владельца. Токен — это ограничитель, а не самостоятельная учётка.

Именно поэтому схема «пользователю ничего не дам, безопаснее, а токену дам DatastoreBackup» не работает. Она выглядит логично, она проходит code review в голове, и она гарантированно не поедет. Там же в документации прямым текстом: «Newly generated API tokens don't have any permissions» и «Newly created users do not have any permissions». То есть по умолчанию пусто и там, и там — ACL нужно ставить в двух местах.

Идентификатор токена имеет вид user@realm!tokenname — например, john@pbs!client1. Это полноценный auth-id, его можно указывать в --auth-id при выдаче ACL, и его же вы вписываете в поле username при подключении хранилища в PVE. Секрет показывается ровно один раз при создании: в выводе proxmox-backup-manager user generate-token john@pbs client1 вы увидите блок вида {"tokenid": "john@pbs!client1", "value": "d63e505a-..."}, и второй раз это значение получить нельзя — только пересоздать токен.

Проверять эффективные права нужно обязательно для обоих auth-id. Обратите внимание на кавычки вокруг идентификатора токена — восклицательный знак в bash при интерактивной сессии раскрывается в history expansion и превращает команду в мусор. Проверка выглядит так:

proxmox-backup-manager user permissions john@pbs --path /datastore/store1
proxmox-backup-manager user permissions 'john@pbs!client1' --path /datastore/store1

Если первая команда возвращает пусто — вторая не имеет значения, пересечение всё обнулит.

Зачем вообще нужны токены, если они не могут расширить права? Документация формулирует две задачи прямо: быстрый отзыв в случае компрометации клиента и ограничение прав каждого конкретного клиента внутри прав его пользователя. Обе — про снижение ущерба, а не про удобство раздачи доступа. Скомпрометировали гипервизор — удалили один токен, остальные узлы продолжают бэкапиться, пароль пользователя менять не надо. Отдали подрядчику доступ на время работ — выдали ему токен с урезанным ACL и сроком жизни. Это ровно та модель, в которой токен всегда «меньше или равен» своему владельцу, и, если принять её сразу, вся дальнейшая настройка становится очевидной.

Не путайте «у пользователя есть права где-то» и «у пользователя есть права на этом пути». DatastoreBackup, выданный пользователю на /datastore/other-store, никак не поможет токену на /datastore/store1: пересечение считается по конкретному пути, и проверять надо именно его через --path.

Разбор из практики: архитектурное бюро «Проектная мысль», два узла PVE и девять суток без копий

Архитектурное бюро «Проектная мысль», 38 рабочих мест: проектировщики в Revit и AutoCAD, файловый сервер с рабочими моделями, лицензионный сервер, 1С и почтовый шлюз. Всё это крутится на двух узлах Proxmox VE, а резервные копии уходят на отдельную физическую машину с Proxmox Backup Server 4.2. Датастор pm-prod на ZFS RAIDZ2 из шести дисков по 4 ТБ (проектные архивы у бюро тяжёлые), 21 виртуальная машина, окно бэкапа с 01:00. До нас всё бэкапилось от root@pam с паролем в открытом виде в конфиге PVE — классика наследства.

Мы приводили это в порядок: завели пользователя pve-backup@pbs, сгенерировали два токена — по одному на узел (!node1, !node2), чтобы при компрометации одного узла отзывать только его. Каждому токену выдали DatastoreBackup на /datastore/pm-prod. Пользователю не выдали ничего — сознательно, «чтобы сам пользователь никуда не ходил». Переключили storage в PVE на токены, увидели, что задание запустилось, и ушли.

Дальше девять суток инфраструктура жила без единой копии. Задание бэкапа падало каждую ночь, но письма о результате уходили на ящик, который никто не читал, а внешнего мониторинга на возраст последнего снимка не было — это отдельный грех, к нему вернусь. Всплыло, когда главный архитектор случайно перезаписал модель жилого комплекса и попросил откатить файловый сервер на позавчера. В логе задания — сообщение о том, что датастор не существует или недоступен, в веб-интерфейсе PVE при попытке выбрать датастор — пустой список.

Диагностика заняла три минуты, когда мы наконец посмотрели на права правильно. proxmox-backup-manager user permissions 'pve-backup@pbs!node1' --path /datastore/pm-prod показывал ожидаемую Datastore.Backup (DatastoreBackup больше ничего и не содержит). А proxmox-backup-manager user permissions pve-backup@pbs --path /datastore/pm-prod возвращал пусто. Пересечение непустого множества с пустым — пусто. Токен формально имел права, фактически не имел ничего, и PBS честно не показывал ему датастор.

Починка — две команды на клиента: выдать DatastoreBackup пользователю pve-backup@pbs на тот же путь и перепроверить эффективные права. После этого первое же ручное задание отработало, но не до конца: на группах, созданных ещё от root@pam, задание споткнулось на проверке владельца. DatastoreBackup даёт права только на свои группы, а старые принадлежали прежней учётке. Сменили владельца групп на токен соответствующего узла в веб-интерфейсе PBS (Datastore → Content → Change Owner) — и ночной прогон прошёл полностью, 21 из 21. Заодно навесили на Zabbix проверку возраста последнего снимка через API PBS, порог 36 часов, и перевели уведомления на живой ящик.

Отдельная мораль этой истории: после смены учётки бэкапа обязательно дождитесь успешного прогона и глазами убедитесь, что в датасторе появился новый снимок. «Задание запустилось» — не то же самое, что «бэкап есть».

Как я это чиню и как выдаю права с самого начала

Рецепт, который я применяю по умолчанию. Пользователь получает ровно те же права, что и токен, на том же пути — не больше. Смысл токена при этом не теряется: он остаётся отзываемым в один клик, его секрет живёт на конкретном узле, и его можно ограничить уже, чем пользователя. А вот шире — нельзя, физически.

Для простого случая, когда датастор целиком отдан под бэкапы одного кластера PVE, хватает пяти шагов из списка ниже: создать пользователя, выпустить токен на узел, выдать одну и ту же роль DatastoreBackup обоим auth-id на путь /datastore/<store> и сверить эффективные права. Порядок шагов 3 и 4 не важен, важно не забыть ни один.

Если датастор общий, а разные клиенты пишут в свои пространства имён — схема чуть тоньше. На сам датастор даём DatastoreAudit без распространения (чтобы клиент увидел хранилище в списке и мог узнать свободное место), а рабочую роль вешаем уже на namespace. Именно так рекомендуют делать и в профильных руководствах по namespace-изоляции в PBS.

После этого в PVE подключаем хранилище с токеном в поле username. Пароль (секрет токена) при этом лежит отдельно в /etc/pve/priv/storage/<STORAGE-ID>.pw с доступом только для root. Проще всего добавить хранилище из консоли узла — ключ --password без значения запросит секрет интерактивно, и он не останется в истории shell:

pvesm add pbs pbs-pm --server 10.20.0.10 --datastore pm-prod \
  --username 'pve-backup@pbs!node1' --fingerprint aa:bb:cc:dd:... --password

Два практических замечания по PVE-стороне. Первое: realm в имени пользователя обязателен, документация PVE это подчёркивает отдельно — не pve-backup, а pve-backup@pbs, и с токеном полностью pve-backup@pbs!node1. Второе: если сертификат PBS самоподписанный (а он самоподписанный у всех, кто не заморачивался с ACME), поле fingerprint обязательно, иначе клиент откажется соединяться, и вы получите совсем другую ошибку — про недоверенный сертификат, а не про отсутствующий датастор. Отпечаток берётся на PBS в разделе Dashboard → Show Fingerprint или командой proxmox-backup-manager cert info на самом сервере.

Про порядок операций. Я всегда сначала выдаю ACL и проверяю их командой permissions, и только потом иду подключать хранилище в PVE. Обратный порядок порождает лишний слой сомнений: непонятно, вы неправильно ввели секрет, ошиблись в отпечатке или всё-таки промахнулись с правами. Пять секунд на проверку прав снимают этот вопрос заранее.

Изоляция по namespace: ```bash # видеть датастор, но не лезть в чужие namespace proxmox-backup-manager acl update /datastore/shared DatastoreAudit \ --auth-id 'pve-backup@pbs!node1' --propagate false # рабочие права только в своём пространстве имён proxmox-backup-manager acl update /datastore/shared/pm DatastoreBackup \ --auth-id 'pve-backup@pbs!node1' ``` Те же две команды повторить для самого pve-backup@pbs — иначе пересечение снова даст ноль.
Порядок действий: Как я это чиню и как выдаю права с самого начала — схема
Порядок действий: Как я это чиню и как выдаю права с самого начала. Открыть схему в полном размере

Почему не надо лечить это ролью DatastoreAdmin

Самый частый «фикс» из интернета: дать пользователю и токену DatastoreAdmin на /datastore — и всё заработает. Заработает, да. И вместе с этим ваш узел PVE получит право удалять чужие снимки, менять настройки любого датастора, включая те, которых сейчас ещё нет, и в общем случае — читать чужие бэкапы. Если PBS один на несколько клиентов или несколько отделов, это уже не мелочь, а полноценная проблема разграничения доступа. Смысл сегментации на токены при этом обнуляется: компрометация одного гипервизора даёт доступ ко всему архиву.

DatastoreBackup — правильный минимум для узла PVE. Он позволяет создавать бэкапы и читать/восстанавливать свои собственные. Ключевое слово — «свои». В PBS у каждой группы бэкапов есть владелец (owner), по умолчанию им становится тот auth-id, который группу создал. И вот здесь ждёт вторая засада при миграции со старой учётки: старые группы принадлежат root@pam, а пишет теперь pve-backup@pbs!node1, и задание падает на проверке владельца — сообщение про backup owner check. Лечится сменой владельца группы: в веб-интерфейсе PBS это Datastore → Content → Change Owner, из консоли — proxmox-backup-client change-owner <group> <new-owner> (например, proxmox-backup-client change-owner vm/101 'pve-backup@pbs!node1' --repository root@pam@10.20.0.10:pm-prod). У proxmox-backup-manager такой подкоманды нет, так что искать её там бесполезно.

Если узлу нужно ещё и чистить старые снимки самостоятельно (prune из PVE через параметр prune-backups хранилища, а не задание на стороне PBS), берите DatastorePowerUser — это Datastore.Backup плюс Datastore.Prune, причём удалять можно только свои группы. Без Prune попытка почистить снимки со стороны PVE закончится ответом PBS «permission check failed». Я обычно так не делаю: prune и garbage collection живут расписанием на самом PBS, а гипервизор пусть только пишет. Меньше прав у стороны, которую с большей вероятностью скомпрометируют.

С verify похожая история. Привилегия Datastore.Verify входит в DatastoreReader и DatastoreAdmin, а DatastoreBackup разрешает проверку только собственных групп. Задания verify по расписанию я настраиваю на самом PBS под администратором, а если проверку должен запускать мониторинг или отдельный скрипт аудита, выдаю его токену DatastoreReader на нужный путь — и не забываю про ту же роль у пользователя, иначе снова пустое пересечение и «permission check failed» в логе.

И честно про спорное. Некоторые коллеги считают, что раз токен всё равно не может больше пользователя, то отдельный пользователь под каждый кластер избыточен — можно один backup@pbs и десяток токенов. Я с этим не согласен, когда серверов несколько и они принадлежат разным юрлицам: общий пользователь становится общим потолком прав, и однажды кто-то расширит его «на пять минут» и забудет. Один клиент — один пользователь, внутри него токены по узлам. Стоит это ровно четыре лишние команды при заведении.

DatastoreAdmin на /datastore — это не «настроил бэкапы», это «выдал гипервизору ключи от всего архива». В аудите такое всплывает регулярно, и объясняться потом приходится долго.

Диагностика за пять минут: порядок действий

Когда прилетает «бэкапы не идут, PBS не видит датастор», я иду строго по этому списку и почти никогда не дохожу до конца — причина находится на втором-третьем шаге. Порядок важен: он идёт от самой частой причины к самой редкой.

Отдельно про проверку с самого узла PVE, минуя веб-интерфейс. Она полезна тем, что отделяет проблему прав от проблемы конфигурации хранилища в PVE: если клиент из консоли видит снимки, а PVE — нет, значит дело в storage.cfg, отпечатке или файле с паролем, а не в ACL.

И последнее, без чего вся эта настройка бессмысленна. Заведите внешнюю проверку возраста последнего снимка — в Zabbix, в самописном скрипте, в чём угодно. Мы у себя дёргаем API PBS и сравниваем поле last-backup из списка групп датастора с текущим временем; порог — 36 часов при суточном расписании. История «Проектной мысли» стоила девяти суток без копий ровно потому, что единственным индикатором были письма, которые никто не открывал. Права вы починили один раз, а мониторинг ловит следующие двадцать поломок, о которых вы ещё не знаете.

Конфиг хранилища в PVE: ```ini pbs: pbs-pm server 10.20.0.10 datastore pm-prod namespace pm username pve-backup@pbs!node1 fingerprint aa:bb:cc:dd:... content backup ``` Секрет токена сюда не пишется — он лежит в /etc/pve/priv/storage/pbs-pm.pw.
Порядок действий: Диагностика за пять минут: порядок действий — схема
Порядок действий: Диагностика за пять минут: порядок действий. Открыть схему в полном размере

Частые вопросы

Почему токену недостаточно собственных прав на датастор?

Потому что PBS считает права токена по его собственным ACL, а затем пересекает результат с правами пользователя, которому токен принадлежит. Если у пользователя на этом пути прав нет, пересечение пустое и токен не может ничего. Токен — это способ сузить доступ пользователя и быстро его отозвать, а не способ выдать доступ в обход пользователя.

Какая минимальная роль нужна узлу Proxmox VE для бэкапа в PBS?

DatastoreBackup на путь /datastore/<store> (или на конкретный namespace). В ней одна привилегия Datastore.Backup: создавать бэкапы, а читать и проверять — только собственные группы. Если узел должен сам удалять старые снимки через prune, нужен DatastorePowerUser — это Datastore.Backup плюс Datastore.Prune. Роль обязательно выдаётся и пользователю, и токену.

Как посмотреть эффективные права токена?

Командой proxmox-backup-manager user permissions с указанием пути, например: proxmox-backup-manager user permissions 'john@pbs!client1' --path /datastore/store1. Идентификатор токена обязательно в одинарных кавычках, иначе bash попытается раскрыть восклицательный знак как history expansion. Ту же команду выполните для самого пользователя john@pbs.

Я потерял секрет токена, где его посмотреть?

Нигде. Секрет показывается только один раз, в момент выполнения proxmox-backup-manager user generate-token (или создания токена в веб-интерфейсе), и повторно не отображается. Единственный вариант — удалить токен и сгенерировать новый, после чего обновить пароль хранилища на всех узлах, где он использовался.

После перехода со старой учётки задание падает на проверке владельца бэкапа — что делать?

У каждой группы бэкапов в PBS есть владелец, обычно тот auth-id, который её создал. Старые группы принадлежат прежней учётке (часто root@pam), а пишет уже токен, и роль DatastoreBackup даёт права только на свои группы. Нужно сменить владельца групп: в веб-интерфейсе PBS это Datastore → Content → Change Owner, либо из консоли командой proxmox-backup-client change-owner <группа> <новый владелец> с указанием --repository.

Можно ли просто выдать DatastoreAdmin и не мучиться?

Технически да, работать будет. Но вы отдаёте гипервизору право удалять чужие снимки и менять настройки датасторов, а при выдаче на путь /datastore — ещё и всех будущих датасторов, потому что права наследуются вниз. Если PBS обслуживает несколько клиентов или отделов, это прямая дыра в разграничении доступа. Берите DatastoreBackup.

Откуда берётся «permission check failed» при работе PVE с PBS?

Так PBS отвечает, когда у auth-id не хватает привилегии на конкретную операцию: например, узел с ролью DatastoreBackup пытается сделать prune или verify чужой группы. Проверьте командой proxmox-backup-manager user permissions эффективные права и пользователя, и токена на пути датастора или namespace и добавьте недостающую роль (DatastorePowerUser для prune, DatastoreReader для verify) обоим.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 💬 MAX: +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи