Источник событий и изменение пароля влияют на безопасность - PullRequest
0 голосов
/ 19 мая 2018

Я недавно начал работать над Event Sourcing , когда возник вопрос об обновлении пароля.

Я понимаю следующее:

  1. События хранятся в хранилище событий , которое действует как единый источник правды для текущего приложения и состояния объекта.Мы могли бы воспроизвести серию событий для данного объекта с момента создания указанного объекта и найти текущее состояние объекта.

  2. События должны храниться бесконечно долго, так как разрыв в цепи приводит к потенциально противоречивому состоянию.Мы можем сделать снимок цепочки событий (т. Е. Текущего состояния объекта), если слишком много событий нужно обрабатывать каждый раз для какого-либо представления.

Для меня это имеет очевидные последствия для безопасностикогда дело доходит до чего-то вроде user updated password.В этом случае мы увидим что-то вроде:

- UserCreatedEvent(user)
- ... // other events that might change the state of the User object
- UserChangedPasswordEvent(updatedPassword)

Проблема, с которой я сталкиваюсь при таком подходе, состоит в том, что для того, чтобы приложение сохраняло согласованное состояние, мы должны хранить все предыдущие пароли пользователя , потому что мы не можем сказать, является ли данный пароль текущим или только одним из предыдущих паролей пользователя (учитывая только UserChangedPasswordEvent).

Ради аргумента предположим, что приложение хранитпароли с использованием более слабого алгоритма, отличного от BCrypt, и пароли, которые можно взломать через заданный период времени (т. е. таблица перебора / радуга).

В случае поиска событий злоумышленник, которому удается получить доступв магазине UserChangedPasswordEvent теперь будет список всех паролей, которые пользователь когда-либо использовал в приложении.В этом сценарии не исключено, что у них будет доступ к хранилищу UserCreatedEvent, следовательно, также (обычно) уникальной электронной почте пользователя.

Поскольку, к сожалению, большинство обычных пользователей повторно используют пароли на разных платформах, злоумышленник теперь потенциально может получить доступ к любому количеству паролей, которые пользователь мог когда-либо использовать на разных платформах.Это становится еще хуже, если существует такой механизм, как «обязательное возобновление пароля после X времени».

Несмотря на это, является ли это наиболее распространенным подходом при поиске событий и обновлении пароля, или существует стандартизированный способобрабатывать эту часть приложения?Я допускаю, что предпосылка сценария (слабое хеширование паролей) является слабой, но она лучше всего отражает мою точку зрения.

Я могу придумать два способа справиться с этим:

  • Зашифрованохранилища событий и / или файловая система;влияет на производительность
  • UserChangedPasswordEvent только информирование о самом изменении, пароль хранится в другом месте через другой канал;однако идет вразрез с идеей источников событий)

Обдумываю ли я здесь проблему? Есть ли проблема здесь, если используются правильные алгоритмы хеширования?

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

По сути, хранение истории паролей на самом деле не отличается от хранения одного пароля - возникают те же проблемы.

Насколько мне известно, не существует "стандартизированного способа" обработки вещей, номножество разных подходов, которые разные люди пытаются

  1. Сохранить действительный пароль вне потока событий.

  2. Сохраните пароль в событии, но зашифруйте значение, чтобы оно было доступно только авторизованным процессам.

Сейчас это довольно актуальная тема, потому что GDPR ;что значит хранить секреты в постоянном хранилище данных, когда субъекты данных имеют право на удаление .

Реализация, которую я видел, обсуждаемая чаще всего, этоиспользовать уникальный ключ шифрования для каждого субъекта данных, поэтому, если вам нужно «стереть» данные, вы отбрасываете ключ.(Примечание: не ясно, что такой подход удовлетворит суды.)

В более широком смысле, нужно помнить, что «события» служат нескольким целям, и нам не нужно использовать один и тот жесобытия или те же представления, для обоих.У вас есть «частное» постоянное хранилище, которое позволяет этой модели домена восстанавливать свое собственное состояние, а затем у вас есть «публичные» представления, которые публикуются для использования другими службами по своему усмотрению..

Так, например, как служба управления паролями, я мог бы передать миру событие, что Боб изменил свой пароль, но не включает новый пароль в публичное представление.

Просмотрите Уди Дахана о границах обслуживания или его доклад о поиске границ обслуживания в сфере здравоохранения .

0 голосов
/ 19 мая 2018

Действительно, хранение пароля внутри событий - очень опасная вещь, но у вас нет реальной причины хранить пароль внутри полезной нагрузки события.На самом деле вы даже не можете использовать источник событий для UserCredentialsSubdomain или для всего AuthenticationDomain.

Если вы все еще решите использовать источник событий для AuthenticationDomain (что не обязательно плохо), вывам не нужно хранить пароль внутри UserChangedPasswordEvent, потому что вам не нужна вся история паролей (хэшированная или открытый текст) внутри вашей модели записи.Последний пароль (или хэш) используется только службой аутентификации для проверки личности пользователя.Никакая другая модель чтения не нуждается в этом;Сценарии использования, в которых вам понадобится недавняя история паролей (то есть, чтобы не допустить смены старого пароля), могут быть реализованы с использованием журнала паролей или чего-то подобного, для этого вам не нужен источник событий.UserChangedPasswordEvent может быть полезно, например, для отображения пользователю последней даты, когда пароль был изменен, но без указания самого пароля.

ОБНОВЛЕНИЕ после комментариев:

Вы не обязаны использовать ES для всего приложения, это не все ES или не-ES.В общем, для аутентификации люди используют плоскую модель.Но если вы решите использовать ES, вы все равно можете использовать его для перестройки состояния UserAggregate, даже если у вас нет пароля пользователя, потому что вам на самом деле не нужен этот пароль внутри этого состояния.

В этом случаеЯ имею в виду, что проверка пароля выполняется до того, как UserAggregate (владелец потока событий) обрабатывает LoginCommand, вызывая PasswordCheckingService, который использует постоянное постоянство.Это делается на прикладном уровне: сначала проверяется пароль, а затем проверяется логин UserAggregate (т. Е. Если пользователь все еще активен, он может войти).

Фактически исключение пароля из потока событий позволяет понять, что проверка личности пользователя должна быть отдельной подсистемой, а также проверка по телефону или биометрическим сканированием.Это немного изменит вашу архитектуру, сделав ее более понятной, на мой взгляд.Вся проверка личности может быть скрыта за простым интерфейсом с несколькими реализациями.

Разве сценарий, который вы описали явно, не вызовет какой-то другой вид вызова

Нет, этоне будет или, по крайней мере, не в восстановлении государства Агрегата.Этот удаленный вызов будет сделан на прикладном уровне.

Вызов внешних служб при восстановлении состояния против источника событий - потока событий должно быть достаточно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...