IP-Address creation allows specifying 'dcim.cable' as 'assigned_object_type' #4135

Closed
opened 2025-12-29 18:33:22 +01:00 by adam · 4 comments
Owner

Originally created by @jokvar on GitHub (Sep 24, 2020).

Originally assigned to: @jeremystretch on GitHub.

Environment

  • Python version: 3.7.5
  • NetBox version: 2.9.4
  • Pynetbox version: 5.0.8 (optional)

Steps to Reproduce

  1. Create a cable connection between any two interfaces on any two devices (in my example the cable id is 107).
  2. Using pynetbox, create an IP address, specifying any address, assigned_object_type as dcim.cable and assigned_object_id as the created cable id.
import pynetbox
nb = pynetbox.api("http://localhost", token="hidden") #token removed
ip = { 'address': '10.10.10.1/32', 'assigned_object_type': 'dcim.device_type', 'assigned_object_id': 107}
nb.ipam.ip_addresses.create(ip)
  1. Alternatively, send a Post request to the ip-addresses endpoint, specifying any address, assigned_object_type as dcim.cable and assigned_object_id as the created cable id.:
curl -X POST "http://localhost/api/ipam/ip-addresses/" -H  "accept: application/json" -H  "Content-Type: application/json" -H  "X-CSRFToken: token_removed" -d "{  \"address\": \"10.10.10.1/32\",  \"assigned_object_type\": \"dcim.cable\",  \"assigned_object_id\": 107}"
  1. Alternatively, create an IPAddress object from a script/report or using the NetBox shell, specifying assigned_object_type as the "dcim | cable" ContentType and assigned_object_id as the created cable id.:
from django.contrib.contenttypes.models import ContentType
from ipam.models import IPAddress
type = ContentType.objects.get(app_label="dcim", model="cable")
IPAddress.objects.create(address='10.10.10.1/32', assigned_object_type=type, assigned_object_id=107)
  1. Navigate to ipam/ip-addresses/ and find the created IP address.

Expected Behavior

If using pynetbox or sending a Post:

  • request fails and NetBox api returns:
    400 Bad Request: {'assigned_object_type': ['Invalid content type: dcim.cable']}

If using nbshell or a script/report:

  • creation fails with an appropriate exception regarding invalid content type.

Observed Behavior

Creation succeeds. The IP address shows a tick in the "Assigned" label.
If this was done using pynetbox, navigating to the IP address view also shows the cable label as its "Assignment". This field is empty otherwise.

Important Notes

The NetBox shell/script/report method allows specifying any invalid content type (provided it can be obtained from ContentTypes) - will save it and never display it to a user.
The API call allows specifying some invalid object types, I have successfully assigned 'virtualiztion.cluster' but not 'extras.tags'.
The only invalid object type Pynetbox allows assigning is 'dcim.cable' for some reason - the cluster type attempt fails properly.

Originally created by @jokvar on GitHub (Sep 24, 2020). Originally assigned to: @jeremystretch on GitHub. <!-- NOTE: IF YOUR ISSUE DOES NOT FOLLOW THIS TEMPLATE, IT WILL BE CLOSED. This form is only for reproducible bugs. If you need assistance with NetBox installation, or if you have a general question, DO NOT open an issue. Instead, post to our mailing list: https://groups.google.com/forum/#!forum/netbox-discuss Please describe the environment in which you are running NetBox. Be sure that you are running an unmodified instance of the latest stable release before submitting a bug report, and that any plugins have been disabled. --> ### Environment * Python version: 3.7.5 * NetBox version: 2.9.4 * Pynetbox version: 5.0.8 (optional) <!-- Describe in detail the exact steps that someone else can take to reproduce this bug using the current stable release of NetBox. Begin with the creation of any necessary database objects and call out every operation being performed explicitly. If reporting a bug in the REST API, be sure to reconstruct the raw HTTP request(s) being made: Don't rely on a client library such as pynetbox. --> ### Steps to Reproduce 1. Create a cable connection between any two interfaces on any two devices (in my example the cable id is 107). 2. Using pynetbox, create an IP address, specifying any address, **assigned_object_type** as _dcim.cable_ and **assigned_object_id** as the created cable id. ```python import pynetbox nb = pynetbox.api("http://localhost", token="hidden") #token removed ip = { 'address': '10.10.10.1/32', 'assigned_object_type': 'dcim.device_type', 'assigned_object_id': 107} nb.ipam.ip_addresses.create(ip) ``` 2. Alternatively, send a Post request to the _ip-addresses_ endpoint, specifying any address, **assigned_object_type** as _dcim.cable_ and **assigned_object_id** as the created cable id.: ``` curl -X POST "http://localhost/api/ipam/ip-addresses/" -H "accept: application/json" -H "Content-Type: application/json" -H "X-CSRFToken: token_removed" -d "{ \"address\": \"10.10.10.1/32\", \"assigned_object_type\": \"dcim.cable\", \"assigned_object_id\": 107}" ``` 2. Alternatively, create an _IPAddress_ object from a script/report or using the NetBox shell, specifying **assigned_object_type** as the _"dcim | cable"_ ContentType and **assigned_object_id** as the created cable id.: ```python from django.contrib.contenttypes.models import ContentType from ipam.models import IPAddress type = ContentType.objects.get(app_label="dcim", model="cable") IPAddress.objects.create(address='10.10.10.1/32', assigned_object_type=type, assigned_object_id=107) ``` 3. Navigate to _ipam/ip-addresses/_ and find the created IP address. <!-- What did you expect to happen? --> ### Expected Behavior If using pynetbox or sending a Post: * request fails and NetBox api returns: `400 Bad Request: {'assigned_object_type': ['Invalid content type: dcim.cable']}` If using nbshell or a script/report: * creation fails with an appropriate exception regarding invalid content type. <!-- What happened instead? --> ### Observed Behavior Creation succeeds. The IP address shows a tick in the "Assigned" label. If this was done using pynetbox, navigating to the IP address view also shows the cable label as its "Assignment". This field is empty otherwise. ### Important Notes The NetBox shell/script/report method allows specifying any invalid content type (provided it can be obtained from ContentTypes) - will save it and never display it to a user. The API call allows specifying some invalid object types, I have successfully assigned 'virtualiztion.cluster' but not 'extras.tags'. The only invalid object type Pynetbox allows assigning is 'dcim.cable' for some reason - the cluster type attempt fails properly.
adam added the type: bugstatus: accepted labels 2025-12-29 18:33:22 +01:00
adam closed this issue 2025-12-29 18:33:23 +01:00
Author
Owner

@lampwins commented on GitHub (Sep 26, 2020):

Not only is this case possible, but you can also set assigned_object_type to null and still provide an assigned_object_id.

@lampwins commented on GitHub (Sep 26, 2020): Not only is this case possible, but you can also set `assigned_object_type` to null and still provide an `assigned_object_id`.
Author
Owner

@jeremystretch commented on GitHub (Oct 8, 2020):

The root issue seems to be that limit_choices_to doesn't actually enforce any form of validation, which we've overlooked. AFAICT we'll need to implement custom validation for every ForeignKey to the ContentType model. (This seems wrong, but I haven't come across any documentation that indicates otherwise.)

The following fields are likely affected:

  • dcim.Cable: termination_a_type, termination_b_type
  • extras.ImageAttachment: content_type
  • ipam.IPAddress: assigned_object_type (as noted above)
@jeremystretch commented on GitHub (Oct 8, 2020): The root issue seems to be that `limit_choices_to` doesn't actually enforce any form of validation, which we've overlooked. AFAICT we'll need to implement custom validation for every ForeignKey to the ContentType model. (This seems wrong, but I haven't come across any documentation that indicates otherwise.) The following fields are likely affected: * dcim.Cable: `termination_a_type`, `termination_b_type` * extras.ImageAttachment: `content_type` * ipam.IPAddress: `assigned_object_type` (as noted above)
Author
Owner

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

This is likely solved by extending ValidatedModelSerializer.validate() to call full_clean() on the faux instance. (DRF does not, in fact, invoke model validation on its own, as discussed here.)

@jeremystretch commented on GitHub (Nov 18, 2020): This is likely solved by extending `ValidatedModelSerializer.validate()` to call `full_clean()` on the faux instance. (DRF does not, in fact, invoke model validation on its own, as discussed [here](https://github.com/encode/django-rest-framework/issues/3144).)
Author
Owner

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

This has been addressed in develop-2.10 and will be fixed in the v2.10 release.

@jeremystretch commented on GitHub (Nov 25, 2020): This has been addressed in `develop-2.10` and will be fixed in the v2.10 release.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#4135