Сегодня хочу разобрать, как для моей системы виртуализации в лице связки Debian 11 + Proxmox 7.4-3 создать API Token. Мне это нужно, т.к. я хочу практически познакомиться, как взаимодействовать с Proxmox через Ansible в рамках управления, развертывания и т.д. И вот в чтении различных источников я вышел на этап, где говорится что нужен будет API Token. А как его создать, что это такое и как его практически использовать, как посмотреть перед тем как уже через Ansible все разбирать, одним словом куча вопросов.
Ну а вроде как можно подключаться к Proxmox не используя логин и пароль, а через API вызовы.
API Token =
- привязан к пользователю
- не требует пароля
- имеет строго заданные права
- идеально для
Ansible / Terraform/ скриптов
В наличии: Debian 11 + Proxmox 7.4-3
Шаг №1: Запускаю браузер и обращаюсь к своему Proxmox:
https://172.35.35.102:8006 - user&pass (Linux PAM standard authentication)
Шаг №2: Создаю группу:
https://172.35.35.102:8006 - user&pass - (Folder View) Datacenter - Permissions - Groups - Create
Name: GRP_PROVISIONComment: GRP_PROVISION
и нажимаю Create
Шаг №3: Создаю пользователя:
https://172.35.35.102:8006 - user&pass - (Folder View) Datacenter - Permissions - Users - Add
User name: us_provisionRealm: Proxmox VE authenticationFirst Name: us_provisionLast Name: us_provisionE-Mail: support@ekzorchik.comPassword: Aa1234567aAConfirm password: Aa1234567aAGroup: GRP_PROVISIONExpire: neverEnabled: отмечаю галочкойComment: ничего не указываюKey IDs: ничего не указываюAdvanced: отмечено галочкой
и нажимаю Add
Шаг №4: Создаю роль разрешений:
https://172.35.35.102:8006 - user&pass - (Folder View) Datacenter - Permissions - Roles
это если заморочиться, но я пока не буду.
https://172.35.35.102:8006 - user&pass - (Folder View) Datacenter - Permissions - Add — выбираю Group Permission
Path: выбираю "/", т.е. все праваGroup: GRP_PROVISIONRole: выбираю дефолтную роль "Administrator"Propagate: отмечаю галочкой
и нажимаю "Add"
Шаг №5: Создаю API Token:
https://172.35.35.102:8006 - user&pass - (Folder View) Datacenter - Permissions - API Tokens - Add
User: выбираю us_provision@pveToken ID: к примеру наберу ansiblePrivilege Separation: отмечаю галочкойExpire: neverComment: ничего не указываю
и нажимаю Add
На заметку:
В Proxmox VE токен API (API Token ID) имеет формат {username}!{tokenname}. Максимальная длина полного токена определяется ограничениями Proxmox на имя пользователя и имя токена: имя пользователя до 32 символов, восклицательный знак, и имя токена также до 32 символов.
Формат: userid!tokenname
Пример: root@pam!mytoken
после получаю окно где сгенерирован на основе указанно Token ID секретный ключ:

На заметку: Secret: Сгенерированный секрет появится автоматически.
На заметку: Скопируйте и сохраните Secret, так как он отображается только один раз.
На заметку: Потом его восстановить нельзя — только пересоздать токен.
Нажимаю "Copy Secret Value" и вот его (1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb) уже и буду в запросах использовать
после нажимаю на крестик окна "Token Secret"
Шаг №6: Как теперь API Token использовать?
Формат авторизации строго такой (т.е. должно быть два символа "=", а не один):
Authorization: PVEAPIToken=USER@REALM!TOKENID=SECRET
На заметку: Справа по обращениям (GET/POST), как через CLI, так и через http (https://pve.proxmox.com/pve-docs/api-viewer/index.html#/access)
ekzorchik@srv-us2204a:~$ curl -k -H "Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb" https://172.35.35.102:8006/api2/json/version
-bash: !ansible=1ed9ec69: event not found
ekzorchik@srv-us2204a:~$
ошибка "-bash: !ansible=1ed9ec69: event not found" — это не ошибка запроса, это В bash символ ! — это history expansion.
ekzorchik@srv-us2204a:~$ curl -k -H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' https://172.35.35.102:8006/api2/json/version
{"data":{"version":"7.4-3","repoid":"9002ab8a","release":"7.4"}}
ekzorchik@srv-us2204a:~$
Ура ну наконец-таки я разобрал, а что вроде делаешь правильно, видишь пример, а в ответ ошибка, а ошибка не того что сделал правильно, а встроенного интерпретатора. Спрашивается зачем тогда приводить примеры. Вот всегда на этот и тратиться много времени пытаясь понять, как работает примеры, оторванные от практического применения.
На заметку: а можно экранировать символ "!" и строка начинающаяся с Authorization будет в двойных кавычках, получается @pve\!ansible.
если нужно вывод не в одну строку, а как JSON вывод построчно
ekzorchik@srv-us2204a:~$ sudo apt-get install -y jq
ekzorchik@srv-us2204a:~$ curl -k -H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' https://172.35.35.102:8006/api2/json/version | jq .
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 64 100 64 0 0 5766 0 --:--:-- --:--:-- --:--:-- 6400
{
"data": {
"repoid": "9002ab8a",
"version": "7.4-3",
"release": "7.4"
}
}
ekzorchik@srv-us2204a:~$
Шаг №7: Т.к. у меня нет Cluster а одна нода, то узнаем имя ноды:
ekzorchik@srv-us2204a:~$ curl -k -H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' https://172.35.35.102:8006/api2/json/nodes | jq .
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 218 100 218 0 0 17969 0 --:--:-- --:--:-- --:--:-- 18166
{
"data": [
{
"level": "",
"ssl_fingerprint": "D2:21:B4:E7:A3:37:49:AD:CA:50:5B:02:BD:01:2C:9A:D1:9F:74:D8:A4:1F:E5:DB:14:C0:44:64:EF:88:6C:3D",
"id": "node/srv-proxmox2",
"node": "srv-proxmox2",
"status": "online",
"type": "node"
}
]
}
На заметку: Вот это имя (node) и есть правильное.
Шаг №8: Получить список всех VM на хосте:
ekzorchik@srv-us2204a:~$ curl -k \
-H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' \
https://172.35.35.102:8006/api2/json/nodes/srv-proxmox2/qemu \
| jq .
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 11 100 11 0 0 291 0 --:--:-- --:--:-- --:--:-- 297
{
"data": []
}
ekzorchik@srv-us2204a:~$
начал читать по чему так, при вышел на упоминание, что API Token не получает права через группу, даже если:
Пользователь входит в группу
у группы роль Administrator
На заметку: Для API Token права нужно назначать явно и это логика Proxmox и вот с ней и происходит недопонимание. Т.е. сейчас схема, которую я сделал выше:
Group: GRP_PROVISION
└─ Role: Administrator (PVEAdmin)
└─ User: us_provision@pve
└─ API Token: ansible
и API Token не наследует роль группы.
Решением может служить, назначение роль на токен:
https://172.35.35.102:8006 - user&pass - (Folder View) Datacenter - Permissions - Add - API Token Permission
Path: /API Token: выбираю us_provision@pve!ansibleRole: выбираю AdministratorPropagate: отмечаю галочкой
и нажимаю Add
После чего запрос получения списка всех VM на ноде возвращает их:
ekzorchik@srv-us2204a:~$ curl -k -H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' https://172.35.35.102:8006/api2/json/nodes/srv-proxmox2/qemu | jq '.data[] | {vmid,name,status}'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4369 100 4369 0 0 157k 0 --:--:-- --:--:-- --:--:-- 164k
{
"vmid": 102,
"name": "srv-backup",
"status": "stopped"
}
{
"vmid": 115,
"name": "srv-mail-ekzorchik-com",
"status": "running"
}
{
"vmid": 116,
"name": "srv-mail-ekzorchik-ru",
"status": "running"
}
Шаг №9: Узнаем именование сети в своем Proxmox:
pvesh get /nodes/srv-proxmox2/network
curl -k \
-H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' \
https://172.35.35.102:8006/api2/json/nodes/srv-proxmox2/network | jq .
Шаг №10: Узнаем именование storage в своем Proxmox:
pvesh get /storage
curl -k \
-H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' \
https://172.35.35.102:8006/api2/json/storage | jq .
Шаг №11: Проверяем, что VMID если занят:
ekzorchik@srv-us2204a:~$ curl -k -H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' https://172.35.35.102:8006/api2/json/nodes/srv-proxmox2/qemu | jq '.data[].vmid' | head -n 10
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4369 100 4369 0 0 205k 0 --:--:-- --:--:-- --:--:-- 213k
204
205
206
101
103
116
115
100
107
102
ekzorchik@srv-us2204a:~$
Шаг №12: А можно ли создать контейнер VM:
На заметку: scsi0 должен быть типа storage:volume,size
curl -k -X POST \
-H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' \
-d "vmid=600" \
-d "name=vm-ekz" \
-d "memory=2048" \
-d "cores=2" \
-d "net0=virtio,bridge=vmbr0" \
-d "scsi0=m2st:10" \
-d "ostype=l26" \
https://172.35.35.102:8006/api2/json/nodes/srv-proxmox2/qemu
{"data":null,"errors":{"net0":"invalid format - duplicate key in comma-separated list property: model\n"}}ekzorchik@srv-us2204a:~$
Это писец какой-то не могу понять, чтобы запросом создать просто контейнер VM, читаю доку и не понимаю, как это задействовать. Блин.
curl -k -X POST \
-H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' \
-d "vmid=600" \
-d "name=vm-ekz" \
-d "memory=2048" \
-d "cores=2" \
-d "ostype=l26" \
https://172.35.35.102:8006/api2/json/nodes/srv-proxmox2/qemu
в ответ получил:
{"data":"UPID:srv-proxmox2:0029D3D8:0D50B306:69788A96:qmcreate:600:us_provision@pve!ansible:"}root@srv-proxmox2:~#
смотрю создался контейнер без диска и сети, ну хотя бы запрос верен, значит нужно разобраться с синтаксисом для диска и сетевого интерфейса.
root@srv-proxmox2:~# cat /etc/pve/nodes/srv-proxmox2/qemu-server/107.conf — изучаю уже существующие параметры созданных виртуальных машин.
На заметку: у меня диск m2st — это LVM Thin, параметр format=raw нельзя. Proxmox считает, что ты передаешь параметр file=, а format в таком случае конфликтует — поэтому идет ошибка "invalid format - duplicate key in comma-separated list property: file". Т.е. Proxmox думает, что ты создаешь диск как файл, а не как LVM. Для LVM Thin дисков format не нужен, потому что LVM всегда RAW.
curl -k -X POST \
-H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' \
-d "vmid=600" \
-d "name=vm-ekz" \
-d "memory=2048" \
-d "cores=2" \
-d "scsihw=virtio-scsi-single"\
-d "scsi0=m2st:10" \
-d "ostype=l26" \
https://172.35.35.102:8006/api2/json/nodes/srv-proxmox2/qemu
и контейнер создался:

Чтобы была еще сеть нужно оказалось указать MAC адрес (произвольный), синтаксис без MAC адреса, строка "net0=virtio0,bridge=vmbr0,firewall=1" — не работает, выдает ошибку, а вот ниже работает.
curl -k -X POST \
-H 'Authorization: PVEAPIToken=us_provision@pve!ansible=1ed9ec69-9f7e-4b6c-9455-e1d90a2036eb' \
-d "vmid=600" \
-d "name=vm-ekz" \
-d "memory=2048" \
-d "cores=2" \
-d "scsihw=virtio-scsi-single" \
-d "scsi0=m2st:10" \
-d "net0=virtio=BA:D4:45:09:87:6C,bridge=vmbr0,firewall=1" \
-d "ostype=l26" \
https://172.35.35.102:8006/api2/json/nodes/srv-proxmox2/qemu
{"data":"UPID:srv-proxmox2:0029F3BB:0D54A995:697894BB:qmcreate:600:us_provision@pve!ansible:"}root@srv-proxmox2:~#
Вот что, значит оформляя себе заметку и расписывая ее в шагах получаем что и как работает, выясняя что не так и почему-то что правильно указано не работает.
Пусть пока заметку завершу, главное, что я приобщился к теме как через API Token взаимодействовать, а вот уже все остальное, как создание VM, изменение, настройка — это дело наживное.
На этом все, встретимся чуть позже, с уважением автор блога Олло Александр aka ekzorchik.