Исправлена критическая уязвимость безопасности, которая потенциально позволяла владельцам тенантов получить доступ к админ-панели Django. Изменения: - Добавлены явные setdefault для is_staff=False и is_superuser=False в CustomUserManager.create_user() - Добавлены явные флаги безопасности при создании владельца тенанта - Добавлены явные флаги безопасности при создании пользователей через систему ролей - Создан TenantAdminAccessMiddleware для защиты /admin/ на уровне middleware - Создана миграция данных для исправления флагов у существующих пользователей Реализована трёхуровневая защита (Defense-in-Depth): 1. Уровень модели: явные дефолты в create_user() 2. Уровень views: явные флаги при создании 3. Уровень middleware: runtime блокировка доступа Файлы: - accounts/models.py: явные флаги в create_user() - tenants/admin.py: явные флаги при создании владельца - user_roles/views.py: явные флаги при создании через роли - myproject/admin_access_middleware.py: новый middleware - myproject/settings.py: регистрация middleware - accounts/migrations/0002_fix_owner_staff_flags.py: миграция данных ВАЖНО: После применения этого коммита необходимо выполнить: 1. python manage.py migrate accounts 2. python manage.py migrate_schemas 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
45 lines
2.3 KiB
Python
45 lines
2.3 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
Middleware для ограничения доступа к админке Django на поддоменах тенантов.
|
||
|
||
SECURITY: Этот middleware обеспечивает дополнительный слой защиты,
|
||
блокируя доступ владельцев тенантов к /admin/ даже если у них
|
||
случайно установлен is_staff=True.
|
||
|
||
Правила доступа:
|
||
- На tenant поддоменах (shop1.localhost): только is_superuser=True может входить в /admin/
|
||
- На public схеме (localhost): обычные правила Django (is_staff=True достаточно)
|
||
- Суперпользователи имеют доступ везде
|
||
"""
|
||
from django.http import HttpResponseForbidden
|
||
|
||
|
||
class TenantAdminAccessMiddleware:
|
||
"""
|
||
Дополнительный слой безопасности: блокирует доступ владельцев тенантов к /admin/
|
||
даже если у них случайно установлен is_staff=True.
|
||
"""
|
||
|
||
def __init__(self, get_response):
|
||
self.get_response = get_response
|
||
|
||
def __call__(self, request):
|
||
# Проверяем, это admin URL?
|
||
if request.path.startswith('/admin/'):
|
||
from django.db import connection
|
||
|
||
# Если мы в tenant схеме (не public)
|
||
if hasattr(connection, 'tenant') and connection.tenant:
|
||
# Проверяем: это не public схема?
|
||
if connection.tenant.schema_name != 'public':
|
||
# Если пользователь авторизован, но НЕ суперпользователь - блокируем
|
||
if request.user.is_authenticated and not request.user.is_superuser:
|
||
return HttpResponseForbidden(
|
||
"Доступ запрещен. Только системные администраторы могут "
|
||
"заходить в админ-панель на поддоменах тенантов. "
|
||
"Используйте панель управления тенанта."
|
||
)
|
||
|
||
response = self.get_response(request)
|
||
return response
|