Files
octopus/myproject/accounts/migrations/0002_fix_owner_staff_flags.py
Andrey Smakotin 0d3f07ad25 SECURITY: Ограничен доступ владельцев тенантов к админке Django
Исправлена критическая уязвимость безопасности, которая потенциально позволяла
владельцам тенантов получить доступ к админ-панели 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>
2025-12-02 10:57:39 +03:00

95 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
Миграция данных для исправления флагов is_staff/is_superuser у существующих пользователей.
SECURITY FIX: Убираем флаги is_staff и is_superuser у владельцев тенантов и обычных пользователей,
которые могли быть созданы до внедрения явных проверок безопасности.
Эта миграция должна быть запущена:
1. На public схеме: python manage.py migrate accounts
2. На всех tenant схемах: python manage.py migrate_schemas
"""
from django.db import migrations
def fix_owner_staff_flags(apps, schema_editor):
"""
Исправляет флаги is_staff/is_superuser у существующих владельцев тенантов и обычных пользователей.
"""
User = apps.get_model('accounts', 'CustomUser')
# Пытаемся получить модели системы ролей (могут не существовать на момент миграции)
try:
UserRole = apps.get_model('user_roles', 'UserRole')
Role = apps.get_model('user_roles', 'Role')
# Находим роль owner
try:
owner_role = Role.objects.get(code='owner')
# Получаем всех пользователей с ролью owner
owner_user_ids = UserRole.objects.filter(
role=owner_role,
is_active=True
).values_list('user_id', flat=True)
# Убираем is_staff и is_superuser у всех владельцев
updated_staff = User.objects.filter(
id__in=owner_user_ids,
is_staff=True
).update(is_staff=False)
updated_super = User.objects.filter(
id__in=owner_user_ids,
is_superuser=True
).update(is_superuser=False)
if updated_staff > 0 or updated_super > 0:
print(f"[SECURITY FIX] Исправлено владельцев: is_staff={updated_staff}, is_superuser={updated_super}")
except Role.DoesNotExist:
print("[SECURITY FIX] Роль 'owner' не найдена, пропускаем исправление владельцев")
except LookupError:
# Модели user_roles еще не существуют - это нормально для новых инсталляций
print("[SECURITY FIX] Модели user_roles не найдены (это нормально для новых инсталляций)")
# Убираем is_staff у всех НЕ-суперпользователей (дополнительная безопасность)
# Только суперпользователи должны иметь is_staff=True
updated = User.objects.filter(
is_staff=True,
is_superuser=False
).update(is_staff=False)
if updated > 0:
print(f"[SECURITY FIX] Убран is_staff у {updated} НЕ-суперпользователей")
# Итоговая статистика
total_staff = User.objects.filter(is_staff=True).count()
total_super = User.objects.filter(is_superuser=True).count()
print(f"[SECURITY FIX] Текущее состояние: is_staff={total_staff}, is_superuser={total_super}")
def reverse_fix(apps, schema_editor):
"""
Откат не требуется - мы только исправляем безопасность, не меняем структуру данных.
"""
pass
class Migration(migrations.Migration):
"""
Миграция данных для исправления флагов безопасности.
ВАЖНО: Эту миграцию нужно запустить на всех тенантах командой:
python manage.py migrate_schemas
"""
dependencies = [
('accounts', '0001_initial'),
]
operations = [
migrations.RunPython(fix_owner_staff_flags, reverse_fix),
]