[SOLVED] Working with API, getting 401 No Ticket

WhiteStarEOF

Active Member
Mar 6, 2012
96
10
28
Hello,

tl;dr
I'm trying to create a new storage object on a single node Proxmox box using Python 3 and the Proxmox API. When I try, it gives me a 401 No Ticket error. I am grabbing the CSRFPreventionToken, and the Ticket. I have tried passing them through to the API via the data section and via the headers section. It doesn't seem to like either of those. So I'm wondering if the token and ticket need to be passed some other way.
/tl;dr

I am working with the Proxmox API on Proxmox 6.2-10, and am using Python 3 with the requests module. I've got my get commands working as expected. Then, as I understand it, when doing a post, put, or delete, I need to use the CSRFPreventionToken and the Ticket that I got when authenticating with the API.

Here's the start:

Python:
self.proxsession = requests.Session()
self.debug = self.proxsession.post(url,data={"username": "{}".format(self.user_name), "realm": "{}".format(self.realm), "password": "{}".format(self.password)},verify=False)
A little ugly, but that's the result of a bunch of troubleshooting I had done. I'll get that cleaned up. But for now, it works. If I jump into pdb3 and print self.debug.content, I get this.

Code:
b'{"data":{"CSRFPreventionToken":"5F4B6D6E:3yiC4dgr08WOz2iGYiRhfeoaqn8dYYHX9iK4ssOmjdg","username":"root@pam","cap":{"access":{"Permissions.Modify":1,"Group.Allocate":1,"User.Modify":1},"storage":{"Datastore.AllocateSpace":1,"Datastore.Audit":1,"Permissions.Modify":1,"Datastore.AllocateTemplate":1,"Datastore.Allocate":1},"sdn":{"SDN.Allocate":1,"Permissions.Modify":1,"SDN.Audit":1},"vms":{"VM.Snapshot":1,"VM.Backup":1,"VM.Console":1,"VM.Allocate":1,"VM.Config.CDROM":1,"Permissions.Modify":1,"VM.Config.Disk":1,"VM.PowerMgmt":1,"VM.Config.HWType":1,"VM.Monitor":1,"VM.Clone":1,"VM.Config.Options":1,"VM.Config.Cloudinit":1,"VM.Config.Network":1,"VM.Snapshot.Rollback":1,"VM.Config.Memory":1,"VM.Migrate":1,"VM.Config.CPU":1,"VM.Audit":1},"dc":{"SDN.Allocate":1,"Sys.Audit":1,"SDN.Audit":1},"nodes":{"Sys.PowerMgmt":1,"Sys.Syslog":1,"Permissions.Modify":1,"Sys.Audit":1,"Sys.Modify":1,"Sys.Console":1}},"ticket":"PVE:root@pam:5F4B6D6E::H9Bz6nPuOVeBRG03Cw/pfqXBvnpe9Xgkr7q8Y1TqfDwnwKBr0CcvkHa0CP3pE/hUZ9AekgMCHdzQB11w1W0En0gWZjFkX4veZ1fA6rpOVpg2ZW29YalqL1ZLktX57yr32v/Gb06lonF38q0/nUke0M1DPQOUX0QU68VJdHtM27M28QNaj2mr4fgGBN0yAqsY/SKXWNYbB9a8OTawevlxgkye7uz3Soy+NMxarUSkX16qX3PpSk8daK6zt9lgpvZxc6bggJ9tlWuqyKiDCN88vxnmlmsB5HZLDGo6KnpEfxhYyG3szU47dFgX/1P4yWAfysklpBzwSXWqWa+sGxBLTw=="}}'

And to format that a little better,
Code:
b'{
  "data": {
    "CSRFPreventionToken": "5F4B6D6E:3yiC4dgr08WOz2iGYiRhfeoaqn8dYYHX9iK4ssOmjdg",
    "username": "root@pam",
    "cap": {
      "access": {
        "Permissions.Modify": 1,
        "Group.Allocate": 1,
        "User.Modify": 1
      },
      "storage": {
        "Datastore.AllocateSpace": 1,
        "Datastore.Audit": 1,
        "Permissions.Modify": 1,
        "Datastore.AllocateTemplate": 1,
        "Datastore.Allocate": 1
      },
      "sdn": {
        "SDN.Allocate": 1,
        "Permissions.Modify": 1,
        "SDN.Audit": 1
      },
      "vms": {
        "VM.Snapshot": 1,
        "VM.Backup": 1,
        "VM.Console": 1,
        "VM.Allocate": 1,
        "VM.Config.CDROM": 1,
        "Permissions.Modify": 1,
        "VM.Config.Disk": 1,
        "VM.PowerMgmt": 1,
        "VM.Config.HWType": 1,
        "VM.Monitor": 1,
        "VM.Clone": 1,
        "VM.Config.Options": 1,
        "VM.Config.Cloudinit": 1,
        "VM.Config.Network": 1,
        "VM.Snapshot.Rollback": 1,
        "VM.Config.Memory": 1,
        "VM.Migrate": 1,
        "VM.Config.CPU": 1,
        "VM.Audit": 1
      },
      "dc": {
        "SDN.Allocate": 1,
        "Sys.Audit": 1,
        "SDN.Audit": 1
      },
      "nodes": {
        "Sys.PowerMgmt": 1,
        "Sys.Syslog": 1,
        "Permissions.Modify": 1,
        "Sys.Audit": 1,
        "Sys.Modify": 1,
        "Sys.Console": 1
      }
    },
    "ticket": "PVE:root@pam:5F4B6D6E::H9Bz6nPuOVeBRG03Cw/pfqXBvnpe9Xgkr7q8Y1TqfDwnwKBr0CcvkHa0CP3pE/hUZ9AekgMCHdzQB11w1W0En0gWZjFkX4veZ1fA6rpOVpg2ZW29YalqL1ZLktX57yr32v/Gb06lonF38q0/nUke0M1DPQOUX0QU68VJdHtM27M28QNaj2mr4fgGBN0yAqsY/SKXWNYbB9a8OTawevlxgkye7uz3Soy+NMxarUSkX16qX3PpSk8daK6zt9lgpvZxc6bggJ9tlWuqyKiDCN88vxnmlmsB5HZLDGo6KnpEfxhYyG3szU47dFgX/1P4yWAfysklpBzwSXWqWa+sGxBLTw=="
  }
}'

Okay, so we see the CSRFPrevention token and the ticket. Great. Now let's jump ahead to the usage. Here's the work in pdb3.

Code:
(Pdb) mytoken = json.loads(self.debug.content)["data"]["CSRFPreventionToken"]

(Pdb) print(mytoken)
5F4B6E21:XdRZNmVvnvX3hcmTpphFL8w9J3MXPuErkec1pChNtu0

(Pdb) myticket = json.loads(self.debug.content)["data"]["ticket"]

(Pdb) print(myticket)
PVE:root@pam:5F4B6E21::cDvOJXxf6cWj1yyt4yV1wWeEDmVOqOyx1jMw2E0nRXuPFT/NQj4vcc7lhDSrRD5LoPB867hsUhGmov53ZEsktWoR0kU6mPWKSGPGXUAnJ/Fy/zYTnj982+YvlJC5mf9bNWLuJVUl87RW2E1IywF69BurRbTaOcDpLrrf2jLDU631Snm6dSTOqEIaXTkJM46xdg9wR8QRGFwumKrPZ1Ur5CAcYxun6ezLqi/ZZwXgSHozzdppFE2fpkQUQAImqdv4+t+kysVCiGABs2PK90estmc5ZkFCB8FlVGp+KGFlFLMsy4+QRLA+ct9KMQ2pXYaULMEVy1R0dZ8amsbQI6xkbw==

(Pdb) print(url)
https://192.168.15.130:8006/api2/json/storage

(Pdb) print(data)
{'storage': 'Customer02', 'type': 'zfspool', 'sparse': 1, 'content': 'images'}

(Pdb) self.proxsession.post(url,data=data,headers={"CSRFPreventionToken": mytoken, "ticket": myticket},verify=False)
DEBUG:urllib3.connectionpool:Resetting dropped connection: 192.168.15.130
send: b'POST /api2/json/storage HTTP/1.1\r\nHost: 192.168.15.130:8006\r\nUser-Agent: python-requests/2.22.0\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nCSRFPreventionToken: 5F4B6E21:XdRZNmVvnvX3hcmTpphFL8w9J3MXPuErkec1pChNtu0\r\nticket: PVE:root@pam:5F4B6E21::cDvOJXxf6cWj1yyt4yV1wWeEDmVOqOyx1jMw2E0nRXuPFT/NQj4vcc7lhDSrRD5LoPB867hsUhGmov53ZEsktWoR0kU6mPWKSGPGXUAnJ/Fy/zYTnj982+YvlJC5mf9bNWLuJVUl87RW2E1IywF69BurRbTaOcDpLrrf2jLDU631Snm6dSTOqEIaXTkJM46xdg9wR8QRGFwumKrPZ1Ur5CAcYxun6ezLqi/ZZwXgSHozzdppFE2fpkQUQAImqdv4+t+kysVCiGABs2PK90estmc5ZkFCB8FlVGp+KGFlFLMsy4+QRLA+ct9KMQ2pXYaULMEVy1R0dZ8amsbQI6xkbw==\r\nContent-Length: 55\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n'
send: b'storage=Customer02&type=zfspool&sparse=1&content=images'
reply: 'HTTP/1.1 401 No ticket\r\n'
header: Cache-Control: max-age=0
header: Connection: close
header: Date: Sun, 30 Aug 2020 09:18:00 GMT
header: Pragma: no-cache
header: Server: pve-api-daemon/3.0
header: Expires: Sun, 30 Aug 2020 09:18:00 GMT
DEBUG:urllib3.connectionpool:https://192.168.15.130:8006 "POST /api2/json/storage HTTP/1.1" 401 None
<Response [401]>

What I'm not sure about is if I'm putting the token and ticket in the right spot. I've tried putting it in the headers section, because that works for get commands where just the token is needed. I've also tried adding the token and ticket to the data section. I have also tried adding the username to the headers and data sections, but to no avail. Everything I do results in 401 No Ticket.

Not sure if I'm using the API wrong, or just can't Python.
 
It does indeed! Thank you!

For future searches, here's what I was doing wrong.

I was presuming that I should pass my ticket to a "ticket" field via the header or a cookie. But the field I'm looking for is PVEAuthCookie.

Python:
self.proxsession.post(url,data=data,verify=False,cookies={"PVEAuthCookie": "{}".format(myticket)},headers={"CSRFPreventionToken": "{}".format(mytoken)})

I'm wondering if PVEAuthCookie would also work in the headers field. But this works for now. i will investigate further.

Thank you much for your help!
 
API Token seems to be easier:


headers = {
'Authorization': 'PVEAPIToken=root@pam!token=6148dff7-b102-4f03-9257-283da32df917'
}
 

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!