Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions nbxsync/tests/utils/test_get_assigned_zabbixobjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,36 @@ def test_direct_assignments(self):
self.assertEqual(len(result['macros']), 1)
self.assertEqual(len(result['tags']), 1)
self.assertEqual(len(result['hostgroups']), 1)


class VirtualMachineDeviceLeakTestCase(TestCase):
"""A VM linked to its hosting device (NetBox 4.3+) must not inherit the
host's hardware-tier assignments (manufacturer etc. via 'device'-prefixed
chain paths). A guest is not the hypervisor's hardware.
"""

def setUp(self):
from virtualization.models import VirtualMachine

self.server = ZabbixServer.objects.create(name='Leak Server', url='http://zabbix.local', token='abc123', validate_certs=True)
self.template = ZabbixTemplate.objects.create(name='Vendor OOB by SNMP', zabbixserver=self.server, templateid=10255)
self.dell = Manufacturer.objects.create(name='Dell', slug='dell-oss')
self.host = create_test_device(name='esx-host-01')
host_type = self.host.device_type
host_type.manufacturer = self.dell
host_type.save()
self.vm = VirtualMachine.objects.create(name='guest-vm-01', device=self.host)

self.assignment = ZabbixTemplateAssignment.objects.create(
zabbixtemplate=self.template,
assigned_object_type=ContentType.objects.get_for_model(Manufacturer),
assigned_object_id=self.dell.pk,
)

def test_device_inherits_manufacturer_template(self):
result = get_assigned_zabbixobjects(self.host)
self.assertIn(self.template.pk, [obj.zabbixtemplate_id for obj in result['templates']])

def test_vm_does_not_inherit_manufacturer_template_via_associated_device(self):
result = get_assigned_zabbixobjects(self.vm)
self.assertNotIn(self.template.pk, [obj.zabbixtemplate_id for obj in result['templates']])
16 changes: 13 additions & 3 deletions nbxsync/utils/inheritance.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from collections import OrderedDict

from django.db.models import Model, QuerySet
from django.db.models.manager import BaseManager
from django.contrib.contenttypes.models import ContentType
from django.db.models import QuerySet
from django.db.models.manager import BaseManager
from virtualization.models import VirtualMachine

from nbxsync.constants import PATH_LABELS
from nbxsync.models import ZabbixHostgroupAssignment, ZabbixHostInterface, ZabbixHostInventory, ZabbixMacroAssignment, ZabbixTagAssignment, ZabbixTemplateAssignment, ZabbixConfigurationGroupAssignment
from nbxsync.models import ZabbixConfigurationGroupAssignment, ZabbixHostgroupAssignment, ZabbixHostInterface, ZabbixHostInventory, ZabbixMacroAssignment, ZabbixTagAssignment, ZabbixTemplateAssignment
from nbxsync.settings import get_plugin_settings
from nbxsync.tables import ZabbixHostgroupAssignmentObjectViewTable, ZabbixMacroAssignmentObjectViewTable, ZabbixTagAssignmentObjectViewTable, ZabbixTemplateAssignmentObjectViewTable

Expand Down Expand Up @@ -116,6 +117,15 @@ def resolve_path(obj, path):

pluginsettings = get_plugin_settings()
for path in pluginsettings.inheritance_chain:
# 'device'-prefixed paths describe the *associated physical device*
# (the VDC's parent, or — since NetBox 4.3 — a VM's hosting device).
# For a VirtualMachine that association is the hypervisor/sidecar, so
# walking these paths would leak host properties (manufacturer, role,
# hardware templates) onto the guest. VDCs keep the paths: a VDC is
# part of its parent device by definition.
if path and path[0] == 'device' and isinstance(assigned_object, VirtualMachine):
continue

related_obj = resolve_path(assigned_object, path)
# label = '.'.join(path)

Expand Down