diff --git a/docs/additional-features/export-templates.md b/docs/additional-features/export-templates.md index 111f4101d..b3f585bee 100644 --- a/docs/additional-features/export-templates.md +++ b/docs/additional-features/export-templates.md @@ -21,6 +21,14 @@ Height: {{ rack.u_height }}U To access custom fields of an object within a template, use the `cf` attribute. For example, `{{ obj.cf.color }}` will return the value (if any) for a custom field named `color` on `obj`. +If you need to use the config context data in an export template, you'll should use the function `get_config_context` to get all the config context data. For example: +``` +{% for server in queryset %} +{% set data = server.get_config_context() %} +{{ data.syslog }} +{% endfor %} +``` + The `as_attachment` attribute of an export template controls its behavior when rendered. If true, the rendered content will be returned to the user as a downloadable file. If false, it will be displayed within the browser. (This may be handy e.g. for generating HTML content.) A MIME type and file extension can optionally be defined for each export template. The default MIME type is `text/plain`. diff --git a/docs/administration/permissions.md b/docs/administration/permissions.md index c66c65543..c7c8996dc 100644 --- a/docs/administration/permissions.md +++ b/docs/administration/permissions.md @@ -10,7 +10,7 @@ NetBox v2.9 introduced a new object-based permissions framework, which replace's | ----------- | ----------- | | `{"status": "active"}` | Status is active | | `{"status__in": ["planned", "reserved"]}` | Status is active **OR** reserved | -| `{"status": "active", "role": "testing"}` | Status is active **OR** role is testing | +| `{"status": "active", "role": "testing"}` | Status is active **AND** role is testing | | `{"name__startswith": "Foo"}` | Name starts with "Foo" (case-sensitive) | | `{"name__iendswith": "bar"}` | Name ends with "bar" (case-insensitive) | | `{"vid__gte": 100, "vid__lt": 200}` | VLAN ID is greater than or equal to 100 **AND** less than 200 | diff --git a/docs/configuration/required-settings.md b/docs/configuration/required-settings.md index dba8cdc8c..3158fc73a 100644 --- a/docs/configuration/required-settings.md +++ b/docs/configuration/required-settings.md @@ -66,6 +66,7 @@ Redis is configured using a configuration setting similar to `DATABASE` and thes * `PASSWORD` - Redis password (if set) * `DATABASE` - Numeric database ID * `SSL` - Use SSL connection to Redis +* `INSECURE_SKIP_TLS_VERIFY` - Set to `True` to **disable** TLS certificate verification (not recommended) An example configuration is provided below: diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md index 95f8bd8ab..7d99959cc 100644 --- a/docs/release-notes/version-2.10.md +++ b/docs/release-notes/version-2.10.md @@ -8,11 +8,17 @@ * [#5756](https://github.com/netbox-community/netbox/issues/5756) - Omit child devices from non-racked devices list under rack view * [#5840](https://github.com/netbox-community/netbox/issues/5840) - Add column to cable termination objects to display cable color * [#6054](https://github.com/netbox-community/netbox/issues/6054) - Display NAPALM-enabled device tabs only when relevant +* [#6083](https://github.com/netbox-community/netbox/issues/6083) - Support disabling TLS certificate validation for Redis ### Bug Fixes * [#5805](https://github.com/netbox-community/netbox/issues/5805) - Fix missing custom field filters for cables, rack reservations +* [#6070](https://github.com/netbox-community/netbox/issues/6070) - Add missing `count_ipaddresses` attribute to VMInterface serializer * [#6073](https://github.com/netbox-community/netbox/issues/6073) - Permit users to manage their own REST API tokens without needing explicit permission +* [#6081](https://github.com/netbox-community/netbox/issues/6081) - Fix interface connections REST API endpoint +* [#6108](https://github.com/netbox-community/netbox/issues/6108) - Do not infer tenant assignment from parent objects for prefixes, IP addresses +* [#6117](https://github.com/netbox-community/netbox/issues/6117) - Handle exception when attempting to assign an MPTT-enabled model as its own parent +* [#6131](https://github.com/netbox-community/netbox/issues/6131) - Correct handling of boolean fields when cloning objects --- diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index 8cce25e95..e9efe4136 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -842,7 +842,7 @@ class CablePathSerializer(serializers.ModelSerializer): class InterfaceConnectionSerializer(ValidatedModelSerializer): interface_a = serializers.SerializerMethodField() - interface_b = NestedInterfaceSerializer(source='connected_endpoint') + interface_b = NestedInterfaceSerializer(source='_path.destination') connected_endpoint_reachable = serializers.SerializerMethodField(read_only=True) class Meta: diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 25d52f8a9..26313474c 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -2,6 +2,7 @@ import socket from collections import OrderedDict from django.conf import settings +from django.contrib.contenttypes.models import ContentType from django.db.models import F from django.http import HttpResponseForbidden, HttpResponse from django.shortcuts import get_object_or_404 @@ -596,6 +597,8 @@ class PowerConnectionViewSet(ListModelMixin, GenericViewSet): class InterfaceConnectionViewSet(ListModelMixin, GenericViewSet): queryset = Interface.objects.prefetch_related('device', '_path').filter( # Avoid duplicate connections by only selecting the lower PK in a connected pair + _path__destination_type__app_label='dcim', + _path__destination_type__model='interface', _path__destination_id__isnull=False, pk__lt=F('_path__destination_id') ) diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index 1bfa5ddd3..eda262a59 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -507,6 +507,10 @@ class BaseInterface(models.Model): return super().save(*args, **kwargs) + @property + def count_ipaddresses(self): + return self.ip_addresses.count() + @extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') class Interface(ComponentModel, BaseInterface, CableTermination, PathEndpoint): @@ -674,10 +678,6 @@ class Interface(ComponentModel, BaseInterface, CableTermination, PathEndpoint): def is_lag(self): return self.type == InterfaceTypeChoices.TYPE_LAG - @property - def count_ipaddresses(self): - return self.ip_addresses.count() - # # Pass-through ports diff --git a/netbox/dcim/models/sites.py b/netbox/dcim/models/sites.py index ce9f7b4f8..247735627 100644 --- a/netbox/dcim/models/sites.py +++ b/netbox/dcim/models/sites.py @@ -7,6 +7,7 @@ from timezone_field import TimeZoneField from dcim.choices import * from dcim.constants import * +from django.core.exceptions import ValidationError from dcim.fields import ASNField from extras.utils import extras_features from netbox.models import NestedGroupModel, PrimaryModel diff --git a/netbox/netbox/configuration.example.py b/netbox/netbox/configuration.example.py index 0dadb55bc..c40e280dd 100644 --- a/netbox/netbox/configuration.example.py +++ b/netbox/netbox/configuration.example.py @@ -34,6 +34,9 @@ REDIS = { 'PASSWORD': '', 'DATABASE': 0, 'SSL': False, + # Set this to True to skip TLS certificate verification + # This can expose the connection to attacks, be careful + # 'INSECURE_SKIP_TLS_VERIFY': False, }, 'caching': { 'HOST': 'localhost', @@ -44,6 +47,9 @@ REDIS = { 'PASSWORD': '', 'DATABASE': 1, 'SSL': False, + # Set this to True to skip TLS certificate verification + # This can expose the connection to attacks, be careful + # 'INSECURE_SKIP_TLS_VERIFY': False, } } diff --git a/netbox/netbox/models.py b/netbox/netbox/models.py index 0e66ba90d..fce15c1f7 100644 --- a/netbox/netbox/models.py +++ b/netbox/netbox/models.py @@ -195,6 +195,15 @@ class NestedGroupModel(ChangeLoggingMixin, CustomFieldsMixin, BigIDModel, MPTTMo def __str__(self): return self.name + def clean(self): + super().clean() + + # An MPTT model cannot be its own parent + if self.pk and self.parent_id == self.pk: + raise ValidationError({ + "parent": "Cannot assign self as parent." + }) + class OrganizationalModel(ChangeLoggingMixin, CustomFieldsMixin, BigIDModel): """ diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index dd3de6fa0..5876405d2 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -221,6 +221,7 @@ TASKS_REDIS_SENTINEL_TIMEOUT = TASKS_REDIS.get('SENTINEL_TIMEOUT', 10) TASKS_REDIS_PASSWORD = TASKS_REDIS.get('PASSWORD', '') TASKS_REDIS_DATABASE = TASKS_REDIS.get('DATABASE', 0) TASKS_REDIS_SSL = TASKS_REDIS.get('SSL', False) +TASKS_REDIS_SKIP_TLS_VERIFY = TASKS_REDIS.get('INSECURE_SKIP_TLS_VERIFY', False) # Caching if 'caching' not in REDIS: @@ -239,6 +240,7 @@ CACHING_REDIS_SENTINEL_SERVICE = CACHING_REDIS.get('SENTINEL_SERVICE', 'default' CACHING_REDIS_PASSWORD = CACHING_REDIS.get('PASSWORD', '') CACHING_REDIS_DATABASE = CACHING_REDIS.get('DATABASE', 0) CACHING_REDIS_SSL = CACHING_REDIS.get('SSL', False) +CACHING_REDIS_SKIP_TLS_VERIFY = CACHING_REDIS.get('INSECURE_SKIP_TLS_VERIFY', False) # @@ -406,21 +408,14 @@ if CACHING_REDIS_USING_SENTINEL: 'password': CACHING_REDIS_PASSWORD, } else: - if CACHING_REDIS_SSL: - REDIS_CACHE_CON_STRING = 'rediss://' - else: - REDIS_CACHE_CON_STRING = 'redis://' - - if CACHING_REDIS_PASSWORD: - REDIS_CACHE_CON_STRING = '{}:{}@'.format(REDIS_CACHE_CON_STRING, CACHING_REDIS_PASSWORD) - - REDIS_CACHE_CON_STRING = '{}{}:{}/{}'.format( - REDIS_CACHE_CON_STRING, - CACHING_REDIS_HOST, - CACHING_REDIS_PORT, - CACHING_REDIS_DATABASE - ) - CACHEOPS_REDIS = REDIS_CACHE_CON_STRING + CACHEOPS_REDIS = { + 'host': CACHING_REDIS_HOST, + 'port': CACHING_REDIS_PORT, + 'db': CACHING_REDIS_DATABASE, + 'password': CACHING_REDIS_PASSWORD, + 'ssl': CACHING_REDIS_SSL, + 'ssl_cert_reqs': None if CACHING_REDIS_SKIP_TLS_VERIFY else 'required', + } if not CACHE_TIMEOUT: CACHEOPS_ENABLED = False @@ -568,6 +563,7 @@ else: 'DB': TASKS_REDIS_DATABASE, 'PASSWORD': TASKS_REDIS_PASSWORD, 'SSL': TASKS_REDIS_SSL, + 'SSL_CERT_REQS': None if TASKS_REDIS_SKIP_TLS_VERIFY else 'required', 'DEFAULT_TIMEOUT': RQ_DEFAULT_TIMEOUT, } diff --git a/netbox/templates/generic/object_list.html b/netbox/templates/generic/object_list.html index 738cbca49..b3b9944bb 100644 --- a/netbox/templates/generic/object_list.html +++ b/netbox/templates/generic/object_list.html @@ -1,6 +1,7 @@ {% extends 'base.html' %} {% load buttons %} {% load helpers %} +{% load render_table from django_tables2 %} {% load static %} {% block content %} @@ -28,54 +29,56 @@ {% block sidebar %}{% endblock %} {% endif %} +