Re[28]: Каких программ вам не хватает?
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.04.25 17:10
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>и как и откуда в эту схему кладутся данные?

Маппером, который сгенерирован по типу данных. Кладутся из DTO, который поднят из базы.

КЛ>я, кажется, начинаю понимать — по dto на роль, ORM, отдельные endpoints и вуаля?

Конечно.
КЛ>но тут есть 2 проблемы — работает только на простых security моделях,
Модели безопасности и должны быть простыми. Сложные модели снижают надёжность. Парадокс в том, что когда стоимость ошибки в секурити низкая, на неё можно просто забить. А когда высокая, то сложные модели слишком рискованны.
КЛ>и никак не решает проблем, когда внутри этого dto есть многокардинальные поля (массивы etc, которые тоже надо фильтровать по роли).
Их не надо фильтровать по роли. Это плохая идея — слишком легко напороть.
КЛ>ну есть еще конечно другой вариант — когда очень много денег и очень много ответственности и надо прям все по-красоте. но это не индустриальный стандарт
Да, я и говорю про серьёзные приложения, где ответственности много. А если её мало, то примерно любая секурити подойдёт.

КЛ>я вообще про микросервисы ничего не писал, я утверждаю, что ты делаешь ту же самую работу по проверке пермиссий для резалтсета, только криво, а мы прямо)

Ну, с моей точки зрения криво делаете вы.
Получившимся API совершенно невозможно пользоваться, кроме как напрямую выкладывать его в ГУЙ. Любой сервис, который пытается стать клиентом этого API, вынужден жить в постоянной готовности получить не данные, а фигу.
И как-то осмысленно объяснять пользователю, что "у тебя, брат, нет пермиссии на атрибут 'НДС', сходи к админу, попроси, чтоб выдал". Ну, либо (что скорее всего) внезапно падать с internal error 500, потому что внутрях там NullReferenceException. Разобраться, что там стало первопричиной, потребует привлечения дорогостоящего саппорта. Так что в пет проджектах, где пользователей меньше, чем ролей и пермиссий вместе взятых — велком, можно и так. А для чего-то серьёзного, где нужна предсказуемость работы — увольте.

КЛ>вот и начинается, часть пермиссий через средства субд, часть сбоку, чтд

Где это я предложил часть пермиссий через средства СУБД? Я вам привёл стандартный способ разделения доступа "построчно" без использования row-level security.

КЛ>так у вас нет row-level permission же

Я вроде дал пошаговое описание того, как решается проблема отсутствия row-level permissions в RDBMS. Причём не как рекомендацию использовать эту схему, а как пример реализации "послойной" безопасности.
Точно такие же рецепты применяются и в сервисах.
То есть токен пользователя у нас роляет только во фронт-сервисе. Когда пользователь U запрашивает API сервиса A, а сервис A в рамках этого запроса стучится в сервис B, то никакие токены U в этот B не передаются. У U вообще нет никакого доступа до сервиса B. В этот сервис обращается A, под собственным токеном.
Поэтому идея "а давайте у нас инвойс будет содержать данные контрагента если у вызывающего пользователя есть пермиссия на этого контрагента" сразу идёт навзничь.
У вызываюшего пользователя нет никаких пермиссий на контрагента — господь упаси. А вот право видеть реквизиты получателя платежа по выставленному счёту у него есть в силу федерального закона.


КЛ>" SQL исполнялся в контексте безопасности конечного пользователя " — вот это вообще что такое?

Это когда мы заводим для пользователя №44487 виндовый аккаунт, даём этому аккаунту права на SQL базу с табличками forums, topics, replies, и marks, при логине на сайт создаём виндовую сессию, и все запросы в SQL Server выполняем через новое соединение под правами этого виндового аккаунта.

КЛ>что тут ты понимаешь под контекстом? а когда ты делаешь эти свои лишние телодвижения из 3х пунктов, ты разве не мапишь "контексте безопасности конечного пользователя, пришедшего из интернета" на конкретную роль в базе?

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

КЛ>sql исполняется от админа всегда и точка. резалсеты зависят от пермиссий юзера из интернета.

Воот, уже лучше.

КЛ>>>это все не надо. у каждой строки есть поле, по которому мы понимаем какая пермиссия нужна, чтобы его читать.

S>>"Его" — это кого? Поле?

КЛ>строку, опечатка конечно


КЛ>>>селект учитывает пермиссии юзера, получение по токену, чтобы выбрать только нужные строки, поля. работает с любым сочетанием и количеством ролей и пермиссий.

S>>Можете привести пример такого select? Я вроде понимаю, о чём вы пишете, но уверенности нет.

КЛ>select * from rows r

КЛ>join rows_perms p on r.id = p.r_id
КЛ> where p.perm = 'row_read' and p.user_id = :userid
Прекрасно. Вы себе представляете производительность такого решения? Когда у нас табличка на пару миллионов строк, и есть тысяча пользователей с частично пересекающимися правами на эти строки?
КЛ>или
КЛ>select * from rows r where r.group_id in :user_groups
А как же "любое сочетание ролей и пермиссий"? Вы прибиваете доступ к r только к одной роли; невозможно выдать доступ к конкретной строке нескольким разным группам.
Собственно, вы изобретаете нормальную изоляцию на основе бизнес-правил, только задом наперёд.
Потому что в прямом направлении мы не стесняемся назвать этот абстрактный group_id своим именем.
Например,
select * from topics t where t.owner_id = :user_id

Или
select * from invoices i where i.sender_organization = :current_org_id


Это — совершенно нормальная история, которая работает и применяется.
КЛ>userid/user_groups резолвятся по токену из запроса
Ну, вы же только что собирались сделать универсальную схему, которая работает с любым количеством пермиссий и ролей. А получается вполне себе узкоспециализированная штука.

КЛ>да как угодно, при том, что работает тот самый швейцарский сыр, про который тут упоминали —

КЛ>возможность вообще что-то читать из таблицы rows проверяется до отправки sql в базу. все запросы от админа. в базе никакой встроенной security не используется, потому что, опять же, нет нормально row-level security встроенного. С полями — либо динамически генеришь строку sql, либо jooq (предпочтительнее)
КЛ>select fields from field_perm where field_perm.perm = 'row_read_for_report'
КЛ>и дальше ипользуешь результат для генерации верхних селектов с конкретными полями.
КЛ>либо уже просто в коде фильтруешь
Непонятно. Как я смогу получить разный набор полей для разных строк одной и той же таблицы? Речь-то шла именно об этом — что состав результата определяется не объектом, а правами пользователя на него.

КЛ>ABAC, это когда ты принимаешь решение не только от роли, но и контекста — времени запроса и пт. То есть довольно часто.

Я в курсе.

КЛ>да, но ничего с точки зрения трейдоффа разработка/результат не придумали. открываешь google aim и видишь и роли, и отдельные пермиссии.

Надо внимательно смотреть на то, как именно используются эти роли и пермиссии. Потому что я так-то не против ролей и пермиссий; я против смешивания мух и котлет.
И если я запрашиваю, допустим, GET /resources/{resourceId}?$include(usageHistory), а у меня нет пермиссий смотреть usageHistory по этому ресурсу, я получаю не пустую историю и не JSON с "вырезанным" атрибутом, а честный 403. А если у меня пермиссия есть, то я могу полагаться на то, что в результате будет атрибут usageHistory с описанной в схеме структурой.
В итоге сторонний сервис, который потребляет мой API, может выдавать осмысленные ошибки, которые можно быстро исправить. А не просто падать оттого, что его авторы тестировались с аккаунтом, у которого были все нужные пермиссии, и понятия не имели, что у кого-то пермиссия на usageHistory на какой-то отдельный объект может быть отобрана.

Обратите внимание — это то самое "разведение ресурсов по разным URL", над которым вы так потешались.


КЛ>много ролей, много разных пермиссий

Количество ни на что не влияет.

КЛ>ага, то есть любой смоук тест у нас в лобой системе обнаруживает любую проблему?

Нет, только детерминистические вещи.

КЛ>и никто ее не делает, потому что это невозможно поддерживать

Надо просто уметь это готовить.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.