SECRET_KEY is not something that's intended to be changed frequently. As you said, it's used to encrypt or sign cookies, so any existing cookies will be invalid if you change it - and AFAIK Django doesn't provide any built-in mechanism for smooth rotation, although apparently there's a third-party module which permits it:
Having said that, it shouldn't crash.
I can confirm that adding an 'X' to the end of my SECRET_KEY and then restarting Netbox causes the same problem. The backtrace shows whether the exception is raised within Django itself or within some Netbox code. I get:
Internal Server Error: /
Error at /
Incorrect padding
Request Method: GET
Django Version: 3.1
Python Executable: /opt/netbox/venv/bin/python3
Python Version: 3.6.9
Python Path: ['/opt/netbox/netbox', '/opt/netbox/venv/bin', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/opt/netbox/venv/lib/python3.6/site-packages']
Server time: Thu, 26 Nov 2020 07:58:45 +0000
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.humanize',
'cacheops',
'corsheaders',
'debug_toolbar',
'django_filters',
'django_tables2',
'django_prometheus',
'mptt',
'rest_framework',
'taggit',
'timezone_field',
'circuits',
'dcim',
'ipam',
'extras',
'secrets',
'tenancy',
'users',
'utilities',
'virtualization',
'django_rq',
'drf_yasg']
Installed Middleware:
['debug_toolbar.middleware.DebugToolbarMiddleware',
'django_prometheus.middleware.PrometheusBeforeMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'utilities.middleware.ExceptionHandlingMiddleware',
'utilities.middleware.RemoteUserMiddleware',
'utilities.middleware.LoginRequiredMiddleware',
'utilities.middleware.APIVersionMiddleware',
'extras.middleware.ObjectChangeMiddleware',
'django_prometheus.middleware.PrometheusAfterMiddleware']
Traceback (most recent call last):
File "/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py", line 215, in _get_session
return self._session_cache
During handling of the above exception ('SessionStore' object has no attribute '_session_cache'), another exception occurred:
File "/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py", line 118, in decode
return signing.loads(session_data, salt=self.key_salt, serializer=self.serializer)
File "/opt/netbox/venv/lib/python3.6/site-packages/django/core/signing.py", line 135, in loads
base64d = TimestampSigner(key, salt=salt).unsign(s, max_age=max_age).encode()
File "/opt/netbox/venv/lib/python3.6/site-packages/django/core/signing.py", line 201, in unsign
result = super().unsign(value)
File "/opt/netbox/venv/lib/python3.6/site-packages/django/core/signing.py", line 184, in unsign
raise BadSignature('Signature "%s" does not match' % sig)
During handling of the above exception (Signature "zSKiK_CFV8srWdAp7Rz0LOQjd-SWiuwtnvgzRkIceU4" does not match), another exception occurred:
File "/opt/netbox/venv/lib/python3.6/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/opt/netbox/venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/opt/netbox/venv/lib/python3.6/site-packages/django/views/generic/base.py", line 73, in view
return self.dispatch(request, *args, **kwargs)
File "/opt/netbox/venv/lib/python3.6/site-packages/django/views/generic/base.py", line 101, in dispatch
return handler(request, *args, **kwargs)
File "/opt/netbox/netbox/netbox/views.py", line 193, in get
connected_consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(
File "/opt/netbox/venv/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/opt/netbox/netbox/utilities/querysets.py", line 22, in restrict
if user.is_superuser or permission_is_exempt(permission_required):
File "/opt/netbox/venv/lib/python3.6/site-packages/django/utils/functional.py", line 240, in inner
self._setup()
File "/opt/netbox/venv/lib/python3.6/site-packages/django/utils/functional.py", line 376, in _setup
self._wrapped = self._setupfunc()
File "/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/auth/middleware.py", line 23, in <lambda>
request.user = SimpleLazyObject(lambda: get_user(request))
File "/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/auth/middleware.py", line 11, in get_user
request._cached_user = auth.get_user(request)
File "/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/auth/__init__.py", line 174, in get_user
user_id = _get_user_session_key(request)
File "/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/auth/__init__.py", line 58, in _get_user_session_key
return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])
File "/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py", line 65, in __getitem__
return self._session[key]
File "/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py", line 220, in _get_session
self._session_cache = self.load()
File "/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/sessions/backends/db.py", line 44, in load
return self.decode(s.session_data) if s else {}
File "/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py", line 122, in decode
return self._legacy_decode(session_data)
File "/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py", line 126, in _legacy_decode
encoded_data = base64.b64decode(session_data.encode('ascii'))
File "/usr/lib/python3.6/base64.py", line 87, in b64decode
return binascii.a2b_base64(s)
Exception Type: Error at /
Exception Value: Incorrect padding
Request information:
USER: [unable to retrieve the current user]
GET: No GET data
POST: No POST data
FILES: No FILES data
Clearly there's an attempt to raise a BadSignature error there, but for some reason it's getting masked.
/opt/netbox/venv/lib/python3.6/site-packages/django/contrib/sessions/backends/base.py
line 126, in function _legacy_decode I think the base64.b64decode() should be inside the "try", not outside.
With this change, I see that the user is treated as not logged in if the SECRET_KEY is wrong (and when corrected, they are logged in again). OTOH, I'm not sure it should really have gotten this far if the signature validation had failed.
If you want to raise this with the Django project feel free. I don't have the time to make a standalone non-Netbox replication of this problem.
Brian.