Restore API ability to query all choices via a client without write permissions #4281

Closed
opened 2025-12-29 18:34:23 +01:00 by adam · 12 comments
Owner

Originally created by @ajknv on GitHub (Nov 16, 2020).

Environment

  • Python version: 3.6.8
  • NetBox version: 2.9.9

Proposed Functionality

The API should expose endpoints that are fully functionally equivalent to the old "_choices" endpoints, in that they will return all of the available choices even when queried by a read-only client. The deprecation of the "_choices" endpoints was motivated by the purported claim that the OPTIONS queries could substitute for the existing behavior (https://github.com/netbox-community/netbox/issues/3416), however this is not true given that OPTIONS requests do not return valid information to clients without write permissions.

The simplest approach to addressing this situation therefore is of course to simply resurrect the _choices endpoints. issues/5351 If there are reasons why that is not preferred, a suggested alternative is to provide endpoints for the choice types that support GET requests and return responses equivalent to what _choices requests previously returned, as an example:

GET https:///api/dcim/cables/status"

Use Case

Clients implement abstraction wrappers that query for choices and encapsulate them in symbolic references. Those enum-reference objects can then internally handle mapping to actual choice values in later API queries (including as filters in read-only GET queries) or to do things like filter client-side on result sets. This avoids the need to spread constants around in client-side code, and/or maintain manual encodings inside code of all known choices -- which might change on upgrades to Netbox -- or to compromise security posture by giving clients write permissions that aren't otherwise needed.

Database Changes

None.

External Dependencies

None.

Originally created by @ajknv on GitHub (Nov 16, 2020). ### Environment * Python version: 3.6.8 * NetBox version: 2.9.9 ### Proposed Functionality The API should expose endpoints that are fully functionally equivalent to the old "_choices" endpoints, in that they will return all of the available choices even when queried by a read-only client. The deprecation of the "_choices" endpoints was motivated by the purported claim that the OPTIONS queries could substitute for the existing behavior (https://github.com/netbox-community/netbox/issues/3416), however this is not true given that OPTIONS requests do not return valid information to clients without write permissions. The simplest approach to addressing this situation therefore is of course to simply resurrect the _choices endpoints. [issues/5351](https://blog.codinghorror.com/thats-not-a-bug-its-a-feature-request/) If there are reasons why that is not preferred, a suggested alternative is to provide endpoints for the choice types that support GET requests and return responses equivalent to what _choices requests previously returned, as an example: GET https:///api/dcim/cables/status" ### Use Case Clients implement abstraction wrappers that query for choices and encapsulate them in symbolic references. Those enum-reference objects can then internally handle mapping to actual choice values in later API queries (including as filters in read-only GET queries) or to do things like filter client-side on result sets. This avoids the need to spread constants around in client-side code, and/or maintain manual encodings inside code of all known choices -- which might change on upgrades to Netbox -- or to compromise security posture by giving clients write permissions that aren't otherwise needed. ### Database Changes None. ### External Dependencies None.
adam added the type: featurepending closurestatus: under review labels 2025-12-29 18:34:23 +01:00
adam closed this issue 2025-12-29 18:34:23 +01:00
Author
Owner

@sdktr commented on GitHub (Nov 16, 2020):

Would allowing OPTION queries for read only clients suffice? (I'm blindly assuming that a user needs write access for this ATM, as you're stating)

@sdktr commented on GitHub (Nov 16, 2020): Would allowing OPTION queries for read only clients suffice? (I'm blindly assuming that a user needs write access for this ATM, as you're stating)
Author
Owner

@ajknv commented on GitHub (Nov 16, 2020):

Technically the OPTION queries are "allowed" to a read-only client, it's just that they don't return any information about the choices in the response payload -- namely the choices information is only made available under an ["actions"]["POST"] subkey, and that action, and thus key, is omitted for a read-only client. BTW -- I know this from direct comparison of requests using tokens for a read-only user vs a write-enabled user.

So if the choices information could be allowed (in the sense of made available) via response content delivered under a different subkey -- the obvious candidate would be ["actions"]["GET"] -- then yes that would solve the problem. The output of the queries using a read-only token (which contain no "actions" subkeys) suggest that such a key doesn't even theoretically exist, though.

@ajknv commented on GitHub (Nov 16, 2020): Technically the OPTION queries are "allowed" to a read-only client, it's just that they don't return any information about the choices in the response payload -- namely the choices information is only made available under an ["actions"]["POST"] subkey, and that action, and thus key, is omitted for a read-only client. BTW -- I know this from direct comparison of requests using tokens for a read-only user vs a write-enabled user. So if the choices information could be allowed (in the sense of made available) via response content delivered under a different subkey -- the obvious candidate would be ["actions"]["GET"] -- then yes that would solve the problem. The output of the queries using a read-only token (which contain no "actions" subkeys) suggest that such a key doesn't even theoretically exist, though.
Author
Owner

@jeremystretch commented on GitHub (Nov 16, 2020):

An OPTIONS request returns the specific actions permissible for the authenticated client. For example, it would return PATCH but not POST if the current user has permission to modify but not create records. This is valuable information for the API client, so the existing behavior must remain intact.

@jeremystretch commented on GitHub (Nov 16, 2020): An `OPTIONS` request returns the specific actions permissible for the authenticated client. For example, it would return `PATCH` but not `POST` if the current user has permission to modify but not create records. This is valuable information for the API client, so the existing behavior must remain intact.
Author
Owner

@candlerb commented on GitHub (Nov 27, 2020):

On a system that permits read-only access to unauthenticated users, it does seem odd that:

  1. curl localhost/api/dcim/interfaces/ returns all the interfaces

  2. curl -XOPTIONS localhost/api/dcim/interfaces/ doesn't return the choices data:

    {"name":"Interface","description":"","renders":["application/json","text/html"],"parses":["application/json","application/x-www-form-urlencoded","multipart/form-data"]}
    

    To see the available interface choices, I have to provide a valid API token.

It's odd because case (1) is the "valuable" data, which I'm happy not to restrict. The choices (2) are nothing more than generic information that I could get from any Netbox installation, or the source code, and yet they are restricted.

@candlerb commented on GitHub (Nov 27, 2020): On a system that permits read-only access to unauthenticated users, it does seem odd that: 1. `curl localhost/api/dcim/interfaces/` returns all the interfaces 2. `curl -XOPTIONS localhost/api/dcim/interfaces/` _doesn't_ return the choices data: ``` {"name":"Interface","description":"","renders":["application/json","text/html"],"parses":["application/json","application/x-www-form-urlencoded","multipart/form-data"]} ``` To see the available interface choices, I have to provide a valid API token. It's odd because case (1) is the "valuable" data, which I'm happy not to restrict. The choices (2) are nothing more than generic information that I could get from *any* Netbox installation, or the source code, and yet they are restricted.
Author
Owner

@jeremystretch commented on GitHub (Nov 30, 2020):

To see the available interface choices, I have to provide a valid API token.

Right, because an unauthenticated user has no ability to write to this (or any) field, and thus has no choices: By design, an unauthenticated user cannot be permitted to make changes. Again, the API is informing the user of his options.

The choices (2) are nothing more than generic information that I could get from any Netbox installation, or the source code, and yet they are restricted.

You can, but attempting to write them to a field will obviously fail.

Here's an example that might help clarify the constraint: Suppose a user has permission to create interfaces, but only with Ethernet types (by leveraging the object-based permissions introduce in v2.9). It would be helpful if an OPTIONS request initiated by that user returned only the permitted types. By contrast, a user without this restriction would see all possible types. (This doesn't currently work, unfortunately, but it might be worth tackling.)

@jeremystretch commented on GitHub (Nov 30, 2020): > To see the available interface choices, I have to provide a valid API token. Right, because an unauthenticated user has no ability to write to this (or any) field, and thus has no choices: By design, an unauthenticated user cannot be permitted to make changes. Again, the API is informing the user of his options. > The choices (2) are nothing more than generic information that I could get from any Netbox installation, or the source code, and yet they are restricted. You can, but attempting to write them to a field will obviously fail. Here's an example that might help clarify the constraint: Suppose a user has permission to create interfaces, but only with Ethernet types (by leveraging the object-based permissions introduce in v2.9). It would be helpful if an `OPTIONS` request initiated by that user returned _only_ the permitted types. By contrast, a user without this restriction would see _all_ possible types. (This doesn't currently work, unfortunately, but it might be worth tackling.)
Author
Owner

@candlerb commented on GitHub (Nov 30, 2020):

My use case is: "As a developer, or as someone preparing a CSV file to be uploaded, I want to refer to documentation with a list of permitted interface types".

I can see all the API documentation under /api/docs/, but I can't see the allowed constants for the API unless I first authenticate to it.

@candlerb commented on GitHub (Nov 30, 2020): My use case is: "As a developer, or as someone preparing a CSV file to be uploaded, I want to refer to documentation with a list of permitted interface types". I can see all the API documentation under `/api/docs/`, but I can't see the allowed constants for the API unless I first authenticate to it.
Author
Owner

@candlerb commented on GitHub (Nov 30, 2020):

Update: when logged into the GUI, I do indeed see the Enum choices.

image

But this only shows the API values not the descriptions, and unfortunately, CSV upload only works with the descriptions.

@candlerb commented on GitHub (Nov 30, 2020): Update: when logged into the GUI, I do indeed see the Enum choices. ![image](https://user-images.githubusercontent.com/44789/100624821-c0665e80-331b-11eb-9f18-77fde1279795.png) But this only shows the API values not the descriptions, and unfortunately, CSV upload only works with the descriptions.
Author
Owner

@jeremystretch commented on GitHub (Nov 30, 2020):

My use case is: "As a developer, or as someone preparing a CSV file to be uploaded, I want to refer to documentation with a list of permitted interface types".

That's perfectly valid for justifying some new functionality; e.g. a separate endpoint or other mechanism. I was just explaining why I believe the existing behavior for OPTIONS requests should remain intact.

@jeremystretch commented on GitHub (Nov 30, 2020): > My use case is: "As a developer, or as someone preparing a CSV file to be uploaded, I want to refer to documentation with a list of permitted interface types". That's perfectly valid for justifying some _new_ functionality; e.g. a separate endpoint or other mechanism. I was just explaining why I believe the existing behavior for `OPTIONS` requests should remain intact.
Author
Owner

@candlerb commented on GitHub (Nov 30, 2020):

Agreed, and as the OP said, resurrecting the _choices endpoint would be one way to do that.

@candlerb commented on GitHub (Nov 30, 2020): Agreed, and as the OP said, resurrecting the `_choices` endpoint would be one way to do that.
Author
Owner

@jeremystretch commented on GitHub (Dec 22, 2020):

Work on #5470 introduced a new custom MetaData class to support bulk update and delete operations. What we could do is tweak this to check for a specific request parameter (e.g. ?show_all=True or similar); if present, NetBox would return all supported actions regardless of the user's permissions.

@jeremystretch commented on GitHub (Dec 22, 2020): Work on #5470 introduced a new [custom MetaData class](https://github.com/netbox-community/netbox/blob/8f4197c0207dd9467dc09b8e89dfcd896b2c8a79/netbox/netbox/api/metadata.py#L11) to support bulk update and delete operations. What we could do is tweak this to check for a specific request parameter (e.g. `?show_all=True` or similar); if present, NetBox would return _all_ supported actions regardless of the user's permissions.
Author
Owner

@stale[bot] commented on GitHub (Feb 6, 2021):

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. Please see our contributing guide.

@stale[bot] commented on GitHub (Feb 6, 2021): This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/develop/CONTRIBUTING.md).
Author
Owner

@stale[bot] commented on GitHub (Feb 22, 2021):

This issue has been automatically closed due to lack of activity. In an effort to reduce noise, please do not comment any further. Note that the core maintainers may elect to reopen this issue at a later date if deemed necessary.

@stale[bot] commented on GitHub (Feb 22, 2021): This issue has been automatically closed due to lack of activity. In an effort to reduce noise, please do not comment any further. Note that the core maintainers may elect to reopen this issue at a later date if deemed necessary.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#4281