Безопасность на уровне строк в сценарии клиентской базы данных

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

  • Запрещение пользователям видеть в результатах запроса строки, на просмотр которых у них нет разрешения
  • Разрешение пользователям ВСТАВЛЯТЬ и ОБНОВЛЯТЬ свои собственные строки в таблице, что дает им разрешение на их просмотр.
  • (мягкое требование), позволяющее пользователям предоставлять другим доступ для чтения или записи их строк
  • Недорогое решение с открытым исходным кодом, работающее в Linux. Насколько я понимаю, ни одна бесплатная база данных не реализует безопасность на уровне строк как таковую. Oracle поддерживает это, но это слишком $$$$. Postgres мог бы реализовывать это в 9.4, но изначально он был нацелен на 9.3, но соскользнул, и есть обсуждение машинного обучения. что он может снова поскользнуться. Я предварительно подумываю об использовании postgres только потому, что они кажутся наиболее продвинутыми в этой функции.

Некоторые (не очень хорошие) идеи у меня были:

  • Используйте представления барьера безопасности postgresql и запретите пользователю доступ к базовой таблице. К сожалению, нет хорошего способа вставить строку в представление барьера безопасности, поэтому некоторые привилегированные прокси / веб-сервисы должны будут обрабатывать вставить инструкции. Кажется, это сложно сделать правильно.
  • Используйте обычные представления и запретите пользователю доступ к базовой таблице. Это позволяет insert, но мне нужно было бы довольно жестко заблокировать разрешения (например, без функций создания) и Похоже, есть много ошибок (например, деление на ноль), которые приводят к утечке информации.
  • Определите некоторое подмножество SQL и создайте прокси-сервер, который будет вашей единственной точкой связи с базой данных. Прокси-сервер анализирует ваш SQL-запрос и перезаписывает его, чтобы обеспечить соблюдение требований безопасности. В целом это кажется трудным, но, возможно, я смогу обойтись очень маленьким подмножеством SQL, пока postgres не реализует безопасность на уровне строк по-настоящему.
  • Просто имейте разные таблицы для разных пользователей (или даже разных БД). Однако я не уверен, насколько хорошо это масштабируется для многих пользователей. Кроме того, это не соответствует мягким требованиям.
  • Найдите коммерческую, но недорогую БД, которая действительно поддерживает эту
  • Используйте Veil, но похоже, что это не так. поддерживается, и у него есть большинство ограничений других решений

Я много гуглил по этой теме, но мне еще предстоит увидеть вскрытие того, как кто-то решил эту проблему в реальном сценарии. Есть некоторая документация для MS SQL, но, похоже, не рекомендуется в MySQL, а записи для postgres практически отсутствуют.

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


person Drew    schedule 07.04.2014    source источник
comment
Да, безопасность строк для PostgreSQL снизилась до версии 9.4. Текущий патч довольно хорош, но мне все еще нужно исправить хотя бы одну ошибку, связанную с представлениями барьеров безопасности в существующей кодовой базе, исправить регрессионные тесты и выполнить некоторую общую очистку, чтобы сделать его фиксируемым. Уже поздно для 9.4.   -  person Craig Ringer    schedule 07.04.2014
comment
Однако было бы полезно, если бы вы добавили хорошее слово для включения автоматически обновляемых представлений барьеров безопасности в 9.4. Нажатие пользователя на эту функцию может быть разницей между включением и пропуском крайнего срока.   -  person Craig Ringer    schedule 07.04.2014


Ответы (3)


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

person kristok    schedule 11.04.2014

Я сделал это в Oracle и SQL Server на уровне базы данных, а также через веб-сервер с предустановленными элементами управления авторизацией (запрос не в свободной форме), а также через синтаксический анализатор SQL, который позволяет выполнять запросы в произвольной форме. Мое мнение:

1. Approach 1: Use database-level mechanisms, where user A is the database user
   that creates / owns / fully controls all tables, views, and other
   objects, and user B, C, D... are the end user accounts that utilize
   the objects that A grants access to.
  a. Pros
    i. Might be easier to maintain; you may need fewer test cases to confirm that it 
       works properly
    ii. Allows you to distribute an application that uses direct ODBC connections 
        (such as a Microsoft Access file) to multiple users, who can each have separate
        row-level security
    iii. Allows real-time updates to access control (either to individual permissions, 
         or to entire sets of permissions), via back-end database changes
    iv. You don't have to worry about application security, because you are relying on
        the database for all security (including the security of your admin account)
  b. Cons:
    i. Requires a separate database user account for each end user. This is generally
       not desirable for, for example, tens of thousands of users
    ii. By using ODBC, users are directly connecting to the database server, which could
        be a security weakness under some circumstances (which depends on more factors than
        are in scope for this question)
    iii. Performance takes a significant hit. Another barrier to scalability
    iv. For these and other reasons, this approach is generally not considered best
        practice for production use
  c. Implementation:
    i. For Oracle, as you noted, there is built-in support
    ii. For SQL Server, this can be implemented using views and instead-of triggers,
        where the view or stored proc does SELECTs and triggers perform writes
        in a controlled manner. This can get the job done,
        but it is cumbersome, and requires a fair amount of code, much of which needs to
        be changed whenever your authorization approach changes (such as changing what
        fields in what ACL tables will authorize what actions based on what values in the
        tables you want to secure). Furthermore, each set of code needs to be added to each
        table you want to secure. Oracle, on the other hand, does something akin to
        parsing the SQL statement and interjecting a where clause whenever the table you
        are securing is involved. This is a far more flexible approach, but would be very
        difficult to implement in SQL server unless you can write a SQL parser in T-SQL
    iii. For postgreql and mysql, I believe you can implement the same approach as described
         above for SQL Server, if this is the way you want to go. I suppose, in postgresql
         you could write a SQL parser in C which performs the transformation to add the
         necessary where clauses, make it available as a database function, pass your free-
         form SQL to this function in your trigger or stored proc, and use the resulting
         modified SQL as the query that gets run (or just have the C function run the query
         and pass that back to the view). But that might be a lot of work for some added
         flexibility for queries that you could not anticipate.

2. Approach 2: Use an application in the middle. So either your application uses User A to log
   in and do its stuff (not recommended, but technically, works fine), or you can set up a
   more restricted User B just for your application, which can do everything that any end user
   can do (e.g. view / change data), but nothing more (e.g. drop table). You rely on the
   application to control access.
  a. Pros: this is how most web and similar client-server applications work, and you'll find
     lots of resources available for doing this
  b. Cons:
   i. you can't use this approach if you want to provide end users with an ODBC connection
      (or an application that uses ODBC)
   ii. As you point out, usually this is implemented in a manner that does not allow for
       free-form SQL. There are two ways to address this latter concern:
    A. Create your own SQL parser (this is your "proxy" solution), which your application
       will use to parse any free-form SQL request (this will end up being similar to
       Oracle's implementation, except that your SQL monkeying occurs in your application,
       whereas Oracles occurs in the database). For all elements of the request that your
       parser identifies as a table, you will perform a lookup in your ACL table to determine
       what the "WHERE" predicate is (if any) related to that table, that will be added to
       the SQL request before it is sent to the server. If you are familiar with creating
       your own programming language parsers, this approach shouldn't be too hard, but if not,
       you might not want to try-- you may find that trying to solve even simple use cases
       ends up being just as complicated as solving any use case, so you either build a proper
       parser that is completely flexible, or you get mired in bug fixing forever. In
       addition, this approach will hit your performance hard just as Approach 1 does.
    B. Create a user-interface that provides the type of query functionality you want without
       truly being free-form. You would have to ensure the interface can support every
       conceivable query you want to accept. While this is not ideal based on what you asked,
       you may find it to be a more cost-effective approach given the amount of work to get
       your SQL parser correct, if you haven't done it before, 

В целом, я рекомендую использовать подход 1, если у вас очень небольшой проект, и это сэкономит вам время на использование ODBC (например, я сделал это для пилотного / тестового проекта, в котором мы создали приложение в Microsoft Access в 2 недели), а в противном случае, если гибкость действительно не является приоритетом номер 1, а производительность не важна, перейти к подходу 2 с использованием структурированного интерфейса, который позволяет приложению контролировать доступ, а также предоставляет вам больший контроль над производительностью.

person mwag    schedule 03.09.2014

Я работаю над таким прокси здесь https://github.com/jbaliuka/sql-analytic Это изначально был разработан для отчетов / аналитических целей, но я планирую реализовать приложение-шлюз, чтобы я мог перемещаться по БД и выполнять SQL с DML через JavaScript из браузера. Это может быть полезно в качестве плагина Olingo для публикации базы данных как службы OData.

person jbaliuka    schedule 12.04.2016