root@pam Token API restricted?

almdudler777

New Member
Feb 7, 2021
1
0
1
35
Hello Proxmox Team,


recently i'm trying to setup my lab through ansible.
I found the ansibe collection community.general that has a proxmox_kvm module which seems to work pretty well for this.

I switched the the API from providing my root password to using a PVE API Token for root@pam.
I had hoped that later on i could just enable the Privilege Separation and limit the token to vm creation.

But it seems that certain problems arise when doing this.

Problem:
When switching to API Tokens for the root user the proxmox_kvm module dies with a 500 Error "Only root can set args".
This is a clearly a fault in the proxmox_kvm module as noted here: https://github.com/ansible-collections/community.general/issues/1641
and i already provided a temp fix for that. (Happens because the module always appends the args param... even if explicitly set to None)

After that i ported the hookscript parameter into the kvm module (only exists currenty in the container module) just to find that this produce a new 500 Error "Only root can set hookscript"...


Questions to you:
  1. Could you kindly confirm that using API Tokens for the root account instead of a password indeed uses a different code path in the API - i.e. that this is an expected behaviour on your end? If so i would gladly provide a patch to the ansible module so it exits with a more descriptive error message, currently it only checks for the account name.... not if a token was used for authentication
  2. I also found the following params which also seem to have this error appear:
    1. "spice_enhancements": "foldersharing=1", "vmgenid": "1", "rng0": "/dev/urandom", "keephugepages": 1, "hostpci0": "host=00:02.0", "args": "-serial unix:/var/run/qemu-server/211.serial,server,nowait", "hookscript": "local:snippets/myhook.sh", "hugepages": "any", "arch": "x86_64", "lock": "backup", "ivshmem": "size=2",
    2. did i miss any?
  3. Im currently not using containers but, could you confirm that this would apply to the container API Endpoint aswell? I will probably provide a pull request for that module aswell then.
  4. I can see some parameters are deprecated that are still used in the ansible module, is there some sort of versioning behind the Proxmox API? I.e. can i find out in which pve version a param was added or removed?

Thank you very much for your response and the splendid work on PVE :)


PS: This is my ticket response... should be all the necessary permissions? ie. currently for developing purpose i have disabled the Privilege Separation for the root@pam Token.


> GET /api2/json/access/permissions HTTP/1.1 > Host: nas:8006 > User-Agent: insomnia/2020.5.2 > Authorization: PVEAPIToken=root@pam!ansible=38c6bf63-************ > Accept: */*


JSON:
{
  "data": {
    "/vms": {
      "Sys.Console": 1,
      "SDN.Allocate": 1,
      "Group.Allocate": 1,
      "VM.Config.Cloudinit": 1,
      "VM.Allocate": 1,
      "Sys.Modify": 1,
      "VM.Audit": 1,
      "VM.Console": 1,
      "Sys.Audit": 1,
      "Datastore.Allocate": 1,
      "VM.Backup": 1,
      "Datastore.Audit": 1,
      "Realm.AllocateUser": 1,
      "Datastore.AllocateSpace": 1,
      "VM.Migrate": 1,
      "VM.Config.Network": 1,
      "Realm.Allocate": 1,
      "VM.Config.HWType": 1,
      "Sys.Syslog": 1,
      "VM.Config.CDROM": 1,
      "VM.Monitor": 1,
      "VM.Config.Disk": 1,
      "VM.Config.Memory": 1,
      "VM.Config.Options": 1,
      "VM.Clone": 1,
      "VM.Snapshot": 1,
      "SDN.Audit": 1,
      "Permissions.Modify": 1,
      "VM.Snapshot.Rollback": 1,
      "Pool.Allocate": 1,
      "VM.Config.CPU": 1,
      "User.Modify": 1,
      "VM.PowerMgmt": 1,
      "Sys.PowerMgmt": 1,
      "Datastore.AllocateTemplate": 1
    },
    "/nodes": {
      "VM.Config.HWType": 1,
      "Sys.Syslog": 1,
      "VM.Config.CDROM": 1,
      "VM.Config.Disk": 1,
      "VM.Config.Memory": 1,
      "VM.Monitor": 1,
      "VM.Config.Options": 1,
      "VM.Clone": 1,
      "VM.Snapshot": 1,
      "SDN.Audit": 1,
      "Pool.Allocate": 1,
      "VM.Snapshot.Rollback": 1,
      "Permissions.Modify": 1,
      "User.Modify": 1,
      "VM.Config.CPU": 1,
      "VM.PowerMgmt": 1,
      "Sys.PowerMgmt": 1,
      "Datastore.AllocateTemplate": 1,
      "Sys.Console": 1,
      "Group.Allocate": 1,
      "SDN.Allocate": 1,
      "VM.Config.Cloudinit": 1,
      "Sys.Modify": 1,
      "VM.Allocate": 1,
      "VM.Audit": 1,
      "VM.Console": 1,
      "Datastore.Allocate": 1,
      "Sys.Audit": 1,
      "VM.Backup": 1,
      "Datastore.Audit": 1,
      "Realm.AllocateUser": 1,
      "Datastore.AllocateSpace": 1,
      "VM.Migrate": 1,
      "Realm.Allocate": 1,
      "VM.Config.Network": 1
    },
    "/storage": {
      "VM.Config.Options": 1,
      "VM.Config.Disk": 1,
      "VM.Config.Memory": 1,
      "VM.Monitor": 1,
      "VM.Config.CDROM": 1,
      "Sys.Syslog": 1,
      "VM.Config.HWType": 1,
      "Datastore.AllocateTemplate": 1,
      "Sys.PowerMgmt": 1,
      "VM.PowerMgmt": 1,
      "User.Modify": 1,
      "VM.Config.CPU": 1,
      "VM.Snapshot.Rollback": 1,
      "Pool.Allocate": 1,
      "Permissions.Modify": 1,
      "VM.Snapshot": 1,
      "SDN.Audit": 1,
      "VM.Clone": 1,
      "VM.Audit": 1,
      "Sys.Modify": 1,
      "VM.Allocate": 1,
      "VM.Config.Cloudinit": 1,
      "Group.Allocate": 1,
      "SDN.Allocate": 1,
      "Sys.Console": 1,
      "VM.Config.Network": 1,
      "Realm.Allocate": 1,
      "VM.Migrate": 1,
      "Datastore.AllocateSpace": 1,
      "Realm.AllocateUser": 1,
      "Datastore.Audit": 1,
      "VM.Backup": 1,
      "Datastore.Allocate": 1,
      "Sys.Audit": 1,
      "VM.Console": 1
    },
    "/access": {
      "Pool.Allocate": 1,
      "VM.Snapshot.Rollback": 1,
      "Permissions.Modify": 1,
      "VM.Clone": 1,
      "SDN.Audit": 1,
      "VM.Snapshot": 1,
      "Sys.PowerMgmt": 1,
      "Datastore.AllocateTemplate": 1,
      "User.Modify": 1,
      "VM.Config.CPU": 1,
      "VM.PowerMgmt": 1,
      "VM.Config.CDROM": 1,
      "VM.Config.Memory": 1,
      "VM.Config.Disk": 1,
      "VM.Monitor": 1,
      "VM.Config.HWType": 1,
      "Sys.Syslog": 1,
      "VM.Config.Options": 1,
      "Datastore.Allocate": 1,
      "Sys.Audit": 1,
      "VM.Backup": 1,
      "VM.Console": 1,
      "VM.Config.Network": 1,
      "Realm.Allocate": 1,
      "Datastore.Audit": 1,
      "Realm.AllocateUser": 1,
      "Datastore.AllocateSpace": 1,
      "VM.Migrate": 1,
      "VM.Config.Cloudinit": 1,
      "Sys.Modify": 1,
      "VM.Allocate": 1,
      "Sys.Console": 1,
      "Group.Allocate": 1,
      "SDN.Allocate": 1,
      "VM.Audit": 1
    },
    "/": {
      "Pool.Allocate": 1,
      "VM.Snapshot.Rollback": 1,
      "Permissions.Modify": 1,
      "VM.Clone": 1,
      "SDN.Audit": 1,
      "VM.Snapshot": 1,
      "Sys.PowerMgmt": 1,
      "Datastore.AllocateTemplate": 1,
      "User.Modify": 1,
      "VM.Config.CPU": 1,
      "VM.PowerMgmt": 1,
      "VM.Config.CDROM": 1,
      "VM.Config.Memory": 1,
      "VM.Config.Disk": 1,
      "VM.Monitor": 1,
      "VM.Config.HWType": 1,
      "Sys.Syslog": 1,
      "VM.Config.Options": 1,
      "Datastore.Allocate": 1,
      "Sys.Audit": 1,
      "VM.Backup": 1,
      "VM.Console": 1,
      "VM.Config.Network": 1,
      "Realm.Allocate": 1,
      "Datastore.AllocateSpace": 1,
      "Realm.AllocateUser": 1,
      "Datastore.Audit": 1,
      "VM.Migrate": 1,
      "VM.Config.Cloudinit": 1,
      "Sys.Modify": 1,
      "VM.Allocate": 1,
      "Sys.Console": 1,
      "Group.Allocate": 1,
      "SDN.Allocate": 1,
      "VM.Audit": 1
    },
    "/pools": {
      "VM.Console": 1,
      "Datastore.Allocate": 1,
      "Sys.Audit": 1,
      "VM.Backup": 1,
      "Realm.AllocateUser": 1,
      "Datastore.Audit": 1,
      "Datastore.AllocateSpace": 1,
      "VM.Migrate": 1,
      "VM.Config.Network": 1,
      "Realm.Allocate": 1,
      "Sys.Console": 1,
      "Group.Allocate": 1,
      "SDN.Allocate": 1,
      "VM.Config.Cloudinit": 1,
      "Sys.Modify": 1,
      "VM.Allocate": 1,
      "VM.Audit": 1,
      "VM.Clone": 1,
      "VM.Snapshot": 1,
      "SDN.Audit": 1,
      "VM.Snapshot.Rollback": 1,
      "Pool.Allocate": 1,
      "Permissions.Modify": 1,
      "User.Modify": 1,
      "VM.Config.CPU": 1,
      "VM.PowerMgmt": 1,
      "Sys.PowerMgmt": 1,
      "Datastore.AllocateTemplate": 1,
      "VM.Config.HWType": 1,
      "Sys.Syslog": 1,
      "VM.Config.CDROM": 1,
      "VM.Config.Disk": 1,
      "VM.Config.Memory": 1,
      "VM.Monitor": 1,
      "VM.Config.Options": 1
    },
    "/access/groups": {
      "Datastore.Allocate": 1,
      "Sys.Audit": 1,
      "VM.Backup": 1,
      "VM.Console": 1,
      "VM.Config.Network": 1,
      "Realm.Allocate": 1,
      "Realm.AllocateUser": 1,
      "Datastore.Audit": 1,
      "Datastore.AllocateSpace": 1,
      "VM.Migrate": 1,
      "VM.Config.Cloudinit": 1,
      "Sys.Modify": 1,
      "VM.Allocate": 1,
      "Sys.Console": 1,
      "Group.Allocate": 1,
      "SDN.Allocate": 1,
      "VM.Audit": 1,
      "VM.Snapshot.Rollback": 1,
      "Pool.Allocate": 1,
      "Permissions.Modify": 1,
      "VM.Clone": 1,
      "SDN.Audit": 1,
      "VM.Snapshot": 1,
      "Sys.PowerMgmt": 1,
      "Datastore.AllocateTemplate": 1,
      "User.Modify": 1,
      "VM.Config.CPU": 1,
      "VM.PowerMgmt": 1,
      "VM.Config.CDROM": 1,
      "VM.Config.Memory": 1,
      "VM.Config.Disk": 1,
      "VM.Monitor": 1,
      "VM.Config.HWType": 1,
      "Sys.Syslog": 1,
      "VM.Config.Options": 1
    }
  }
}
}
 
Last edited:
Hello Proxmox Team,

recently i'm trying to setup my lab through ansible.
I found the ansibe collection community.general that has a proxmox_kvm module which seems to work pretty well for this.

I switched the the API from providing my root password to using a PVE API Token for root@pam.
I had hoped that later on i could just enable the Privilege Separation and limit the token to vm creation.

a valid approach ;) although I'd start with least privileges and only add what's really needed after consideration.

But it seems that certain problems arise when doing this.

Problem:
When switching to API Tokens for the root user the proxmox_kvm module dies with a 500 Error "Only root can set args".
This is a clearly a fault in the proxmox_kvm module as noted here: https://github.com/ansible-collections/community.general/issues/1641
and i already provided a temp fix for that. (Happens because the module always appends the args param... even if explicitly set to None)

yes, that is a bug. some parameters are intentionally limited to root@pam because they have security or stability implications.

After that i ported the hookscript parameter into the kvm module (only exists currenty in the container module) just to find that this produce a new 500 Error "Only root can set hookscript"...

hookscripts are a kind of special case.. they are a fairly recent addition, and new stuff often starts out as quite restricted until all the kinks are ironed out, it becomes clear how big the scope actually is, etc.pp.. there is no way currently to limit access to a hook script except on the storage level, and the hook scripts run in a privileged context, and they can be triggered by non-privileged actions (such as guest restarts). so the attack surface is quite high, and setting a hookscript is thus something that requires high(est) privileges. this could be eased somewhat (e.g., we could make hookscripts referencable in ACLs, which would allow the admin to specify that user A can in fact use hook script X, but not hook script Y), but so far there hasn't really been demand for it.

Questions to you:
  1. Could you kindly confirm that using API Tokens for the root account instead of a password indeed uses a different code path in the API - i.e. that this is an expected behaviour on your end? If so i would gladly provide a patch to the ansible module so it exits with a more descriptive error message, currently it only checks for the account name.... not if a token was used for authentication

the code path is the same for regular accounts and tokens. it's just that in some places we explicitly check for 'root@pam' and that does not include root@pam's tokens (since the tokens could have less privileges, and the "super privilege" of being root is not encoded in the privilege system at all so we can't know whether it applies to the token as well.

  1. I also found the following params which also seem to have this error appear:
    1. "spice_enhancements": "foldersharing=1", "vmgenid": "1", "rng0": "/dev/urandom", "keephugepages": 1, "hostpci0": "host=00:02.0", "args": "-serial unix:/var/run/qemu-server/211.serial,server,nowait", "hookscript": "local:snippets/myhook.sh", "hugepages": "any", "arch": "x86_64", "lock": "backup", "ivshmem": "size=2",
    2. did i miss any?
that looks like quite the complete list - you can grep for 'root@pam' in /usr/share/perl5/PVE if you want to make it 100% ;) for some parameters, it also depends on the value. e.g., regular users can set disks/mountpoints to volumes that they have access to, while root can pass through host disks or bind-mount host directories.

vmgenid might just be a "nobody bothered to set explicit permission checks". lock is not something the user sets, it's set by the code when doing long operations that require locking a guest.

you might also be interested in subscribing to https://bugzilla.proxmox.com/show_bug.cgi?id=2582 which tracks adding a special "root" privilege that should allow making other users and tokens root@pam equivalent - including the option of limiting it to certain sub paths of the ACL tree instead of globally.

  • Im currently not using containers but, could you confirm that this would apply to the container API Endpoint aswell? I will probably provide a pull request for that module aswell then.

some of the list above is VM specific (args, vmgenid, keephugepages,hostpci,hugepages,ivshmem). container has some additional ones that are restricted.

  • I can see some parameters are deprecated that are still used in the ansible module, is there some sort of versioning behind the Proxmox API? I.e. can i find out in which pve version a param was added or removed?
we normally only remove stuff in major releases (and sometimes we forget to actually do the removal). new additions happen all the time, but we try to remain as backwards compatible as reasonably possible within a release (e.g., some guest option might start out as simple integer or string parameter, and then we add additional optional flags and the original parameter becomes the default key for that property string. or an alias gets added that maps the old to the new name).
 
  • Like
Reactions: matiaspecchia
a valid approach ;) although I'd start with least privileges and only add what's really needed after consideration.

What's the recommended practice here? root@pam with privilege separation? dedicated "API" user?
 
it depends on your environment. usually I'd add a user per actual person using the system, and then API tokens for each of those when some system is doing automated stuff on behalf of that user. but if something like a deployment script needs API access, a non-person user + token is of course also valid. for automated access I'd always use tokens, since they are easily revokable, and don't need a round-trip for getting a ticket that then needs to be refreshed periodically (simplifying the client flow).
 
When switching to API Tokens for the root user the proxmox_kvm module dies with a 500 Error "Only root can set args".
I got this when I tried to set rootfs=10 (to set size), but then later I realized it was because of the ostemplate path! Fixing the template path solved the issue.
When the response is not in the body, it's quite hard to know which parameter is affected...
 
The proxmoxer python api doesn't support 2FA, so when we enable 2fa for the root user, we're no longer able to set certain args. Is there a recommended workaround?
 
When switching to API Tokens for the root user the proxmox_kvm module dies with a 500 Error "Only root can set args".
This is a clearly a fault in the proxmox_kvm module as noted here: https://github.com/ansible-collections/community.general/issues/1641
Is there any fix for that already? If you have 2FA enabled for the root@pam account with an API token then this still does not work. Disabling 2FA for this is just a really bad and dirty fix.
I'd always use tokens, since they are easily revokable, and don't need a round-trip for getting a ticket that then needs to be refreshed periodically (simplifying the client flow).
But is there a solution for API requests facing the "Only root can set args" limitation?
 
or teach your API client to support 2FA, or avoid the need for root-only settings, yes.
 
to setup such a mapping, you need Mapping.Modify. to use it (configure a guest to use the resource via pass through), you then only need Mapping.Use. neither action requires root ;)
Thank you for the clarification, I am still running a legacy 7.4 cluster that will be upgraded in a few weeks. I hope this will be resolved then.
 
yeah I ran against this issue when trying to remote-migrate a vm with a hookscript.

It would be nice if hookscripts could be set by API tokens...
 

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!