Fine-grained authorization for IncusOS system API

Hello,

I’m deploying IncusOS as part of an effort to replace a proprietary hypervisor, plus I really like the underlying concept.

One of my requirements for functional parity with my current system is UPS management.

My idea is to run a container that manages the UPS and, when necessary, performs an action on the IncusOS host.

The IncusOS API appears to provide the endpoints I need:

  • POST /1.0/system/:poweroff

  • POST /1.0/system/:suspend

  • POST /1.0/system/:reboot

However, I don’t see a way to authorize a client to perform only these operations while denying access to everything else.

I looked at both Scriptlet and OpenFGA authorization, but I’m not sure whether either can be used to restrict access to these IncusOS system endpoints specifically.

I would also prefer not to introduce a middleware/proxy solely for this purpose.

Is there an existing authorization mechanism that would fit this use case? Ideally, I’d like to give the UPS container a credential that permits only the required power-management operations and nothing else.

Thanks!

It’s a bit messy because those APIs are accessed through the Incus API and OpenFGA/scriptlet live at the Incus API logic, but it’s just a passthrough and Incus itself has no understanding of what’s under /os/.

I don’t see a super good way to handle that at the OpenFGA level as this level of granularity would need a bunch of extra model entries and we don’t really want to have Incus have to be aware of every IncusOS API endpoint.

I think what may be reasonable is having a specific entry for CanManageOS or something similar which controls all of /os/XYZ. Then we may be able to pass in the URL path as metadata to the scriptlet so you can have the scriptlet check for the actual path whenever it processes a CanManageOS.

@bensmrs I think you’re somewhat familiar with the current auth scriptlet, do you see a problem with exposing some of the request data to it?

That sounds alright. We could even always pass the request URL to the scriptlet, just in case someone wants to do filtering based on that…

First, thank you for answering my question!

My thinking was indeed to add the endpoint as part of the scriptlet’s arguments, which would avoid the need for more complex handling in Incus. I don’t see any additional security concern with this, since the endpoint is already consumed by Incus itself and the scriptlet remains the gatekeeper.

Whao, quick answer, it would be perfect!

I can have a look next week @stgraber if you’re ok with extending the details struct

Yup, sounds good to me!