客户端 - 数据库方案中的行级安全性

时间:2014-04-07 05:14:45

标签: database security postgresql architecture row-level-security

我正在寻找一种良好的模式来实现适合在客户端 - >数据库环境中使用的行级安全控制(通过例如代理,中间人Web服务或存储过程)。我控制客户端和数据库。一些要求:

  • 禁止用户查看他们无权查看的查询结果中的行
  • 允许用户将自己的行插入并更新到表中,这使他们有权查看它们
  • (软要求)允许用户授予其他人读取或写入行的权限
  • 在Linux上运行的开源或低成本解决方案。据我了解,没有免费的数据库实现行级安全性。 Oracle支持这一点,但它的方式也是如此。 Postgres might be implementing this in 9.4,但最初的目标是9.3并且滑落,并且对ML的讨论可能会再次滑落。我暂时考虑使用postgres,因为它们似乎是这个功能最远的。

我曾经有过一些(非常好的)想法:

  • 使用postgresql的安全屏障视图,并拒绝用户访问基础表。不幸的是有no good way to insert a row into a security barrier view,所以一些特权代理/ web服务必须处理插入语句。这似乎很难做对。
  • 使用常规视图,并拒绝用户访问基础表。这允许insert,但我需要非常严格地锁定权限(例如,不创建函数)和there seem to be a lot of gotchas (like divide by zero) that leak information
  • 定义SQL的某个子集,并创建一个代理,它是您与数据库唯一的通信点。代理解析您的SQL查询并重写它以强制执行安全性要求。这似乎很难做到,但也许我可以使用一个非常小的SQL子集,直到postgres为实际实现行级安全性。
  • 为不同的用户(甚至不同的DB)设置不同的表。但是,我不确定它对很多用户的影响程度如何。此外,这似乎不符合软要求。
  • 查找一些实际支持此
  • 的商业但价格合理的数据库
  • 使用Veil但似乎无法维护,并且它具有其他解决方案的大部分限制

我已经在这个主题上做了大量的谷歌搜索,但我还没有看到有人如何在真实场景中解决这个问题。有some documentation for MS SQL但似乎是discouraged in MySQL并且对于postgres基本上不存在写入。

这似乎是一个非常常见的问题,但我想很多人都在编写Web应用程序并且满足于将用户手铐放到某些经过预先审查的查询中,但我真的需要尽可能多地为用户提供查询与我的客户的数据。

3 个答案:

答案 0 :(得分:2)

整个行级安全主题颇具争议。我个人对此的看法是,你正试图在数据库ACL层实现这一点。我知道Oracle支持这一点,但从一开始就是一个非常糟糕的主意,并且引起了更多的挫折而不是好。我知道你很想重复使用现有的访问控制功能只是为了节省代码行,但我自己也不敢走这条路只是因为你可能会因为ACL的预期与现实而陷入死胡同已实施与您希望如何运作。

答案 1 :(得分:1)

我已经在数据库级别的Oracle和SQL Server中以及通过具有预设授权控件(非自由格式查询)的Web服务器以及通过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的时间(例如,我为我们构建应用程序的试验/测试项目做了这个微软Access在2周内),否则,除非灵活性确实是第一优先级且性能并不重要,否则使用方法2使用允许应用程序控制访问的结构化界面,并为您提供更好的控制权性能

答案 2 :(得分:0)

我在这里处理这样的代理https://github.com/jbaliuka/sql-analytic 它最初是为报告/分析目的而开发的,但我计划实现网关应用程序,以便我可以通过浏览器中的JavaScript导航数据库并使用DML执行SQL。它可能有用作Olingo插件,也可以将数据库作为OData服务发布。