Подготовка безопасности приложений Django Rest Framework для производства (Auth и Admin Panel)
Intro
Я создал веб-приложение с несколькими службами:
- фронтенд (react)
- backend (API и административная панель) (Django Rest Framework + простой jwt auth)
- Redis, DB, Nginx и т.д.
- Kubernetes кластер
Приложение не маленькое, как 60k+ строк кода. Это стартап. Я упомянул это, чтобы вы знали, что, вероятно, я не буду иметь столько внимания от хакеров или трафика вообще. Поэтому у меня есть пространство для постепенного улучшения.
Аутентификация осуществляется с помощью простой jwt библиотеки DRF. Истекающий доступ + токен Refresh.
Заявление о проблеме
Я провел аудит безопасности и обнаружил недостатки с точки зрения архитектуры безопасности. Я не знаю, насколько эти недостатки критичны, как я должен их исправить, или какие недостатки можно исправить позже. Поэтому я ищу решения и советы. Я бы предпочел оптимальную пропорцию между скоростью и качеством, а не только качеством (если я упустил этот момент, дайте мне знать), следовательно, если что-то "приятно иметь", а не "важно", я бы отложил это в бэклог следующих релизов.
Фактический список вопросов
Давайте ссылаться на его номер, если хотите.
#1 Методы аутентификации
Моя текущая установка:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
.....
}
Как вы видите, у меня есть 3 метода. JWT в порядке, но BasicAuthentication и SessionAuthentication, похоже, не в порядке. Я хочу добиться того, чтобы настоящий JWT аутентификатор был единственным способом аутентификации для API представлений (и я действительно верил, что у меня это получилось, пока не узнал обратное).
Как я понял (могу ошибаться), мне не нужны SessionAuthentication и BasicAuthentication в производственной установке, но нужны для dev, потому что это позволяет мне войти в DRF API UI с помощью формы входа, что очень удобно для тестирования. Я прав?
#2 Сессии
Когда я добрался до Chrome Dev Tools и проверил куки, я был обескуражен. На данный момент я отказался от SessionAuthentication и BasicAuthentication как для теста.
Как я понял, у меня есть куки с идентификатором сессии из-за SessionMiddleware. И это нормально, потому что он используется только для аутентификации в админ панели и игнорируется представлениями DRF API так что единственным способом аутентификации является JWT но так ли это? Возможно, это может иметь больше последствий и эксплойтов. Следовательно, должен ли я полностью отказаться от SessionMiddleware, особенно для достижения цели иметь JWT auth как единственный тип аутентификации?
* Я понимаю, что это приведет к отказу от возможности использовать функцию панели администратора, и я рассмотрю этот вопрос позже.
#3 Я храню токены Access и Refresh в локальном хранилище
Да, похоже, я не прав. Я признаю это. Это был недостаток опыта в начале. Фронтенд приложение и тесты (я использую Cypress) сильно зависят от токенов, которые должны быть в локальном хранилище, но это осуществимо для миграции. С другой стороны, я просто боюсь новых ошибок, которые могут появиться после этого. Кроме того, я подозреваю, что миграция может быть немного болезненной. Вопрос в том, насколько это критично, и, следовательно, должен ли я мигрировать хранилище токенов на куки сейчас или могу сделать это позже?
#4.1 Отделение панели администратора от API
Django Admin panel - это потрясающе, мы все знаем, но она тесно связана с приложением. Но проблема №2 привела меня к идее разделить API и Admin. Так как я использую Kubernetes, идея состоит в том, чтобы запустить два сервиса. Один - API, я представляю его как ту же кодовую базу, но настройки разные (отключенные SessionMiddlware и админ-панель). И другой сервис, где функция админ-панели полностью включена. Имеет ли это смысл?
* Мне кажется, что это немного попахивает чрезмерной инженерией. Поэтому, пожалуйста, остановитесь, если я ошибаюсь в этом.
** Похоже, что это сильно зависит от #2, потому что если нет проблем и эксплойтов с SessionMiddleware, следовательно, нет веских причин делать это.
#4.2 Настройка производства панели администратора
Мне просто интересно, каковы лучшие практики безопасности для настройки доступа к панели администратора в prod. У меня абсолютно пустая настройка. Никакой капчи. Никаких VPN. Полностью ванильная. И вопрос в том, какова наиболее реальная, но эффективная настройка доступа? Я чувствую, что это должно быть как-то защищено. По крайней мере, /admin не должен быть публичной конечной точкой (VPN?), но я понятия не имею, как этого добиться. Я на Google Cloud Platform, так что, возможно, я могу использовать одно из ее решений?
Аутро
Какие еще проверки безопасности вы проводите перед выходом на производство в качестве инженера? То есть, конечно, лучший способ - нанять команду безопасности, но я не могу этого сделать
Что я сделал:
- убедились, что нет никаких возможностей для утечки данных (тесты и надежная архитектура бэкенда и фронтенда приложения)
- провели обширное приемочное и e2e тестирование на аутентификацию
- проверили сериализатор и убедились, что в нем нет эксплойтов (по крайней мере, видимых) (конечно, много юнит- и e2e-тестов)
Спасибо, Артем
#1 Да, удалите оба других метода авторизации и оставьте только jwt auth, это только для фреймворка REST, поэтому не должно быть проблемой для /admin.
#2 Первые пункты уже решают эту проблему. Но помните, что вы также можете изменять пути к cookies из django. Таким образом, вы можете установить, что /admin в вашем django приложении использует другие cookies. Это позволит вам полностью отделить /admin от других урлов вашего приложения. Вы найдете это интересным:
SESSION_COOKIE_PATH = '/admin'
CSRF_COOKIE_PATH = '/admin'
LANGUAGE_COOKIE_PATH = '/admin'
SESSION_COOKIE_NAME = 'backend-sessionid'
CSRF_COOKIE_NAME = 'backend-csrftoken'
#3 Насколько я знаю... это единственный способ сохранить токены во внешнем приложении. Таким образом, безопасность там обеспечивается за счет наличия "срока действия" токенов, в случае если кто-то получит токены от клиента, он будет иметь доступ только в течение короткого периода времени. Это во многом зависит от логики работы предприятия и от того, как вы хотите управлять истечением срока действия
#4.1 Я не рекомендую запускать ваше приложение в двух экземплярах, вы должны уметь правильно настроить приложение и избегать подобных решений.
#4.2 Как вы упомянули, /admin должен иметь ограниченный доступ. Я сделал это с помощью белых списков IP (это можно сделать на nginx), но вам придется знать IP заранее. Вы также можете сделать это с помощью http auth в nginx, чтобы у вас был пользователь и пароль (которые вы можете разделить без необходимости знать IP), запрашиваемые еще до подключения к приложению django.
Рекомендации:
- Запустите сканирование вашего приложения, например: https://observatory.mozilla.org/ Это позволит вам узнать много других вещей безопасности, которые вам понадобятся в вашем приложении. С этим вы должны быть готовы чувствовать себя в безопасности. И еще, бывает, что вы не можете избежать провала некоторых тестов, просто постарайтесь сделать лучше, чтобы уменьшить проблемы. .