Postgres 角色最佳实践实施

JP *_*dry 24 postgresql psql

各位,

我可以利用你的帮助使我的 Postgres 用户访问控制设计更好,更符合最佳实践。我正在帮助推出一个小型生产 Postgres 服务器,但我不是数据库管理员,所以我知道足够危险。

一台服务器安装了一次 Postgres v9.2。此安装托管多个数据库,每个数据库都完全服务于不同的“客户”。换句话说,customer1 不会,也不应该使用 database2,依此类推。在正常操作期间,每个数据库都由一个匹配的 CakePHP 实例访问,所有实例都与 Postgres 位于同一服务器上。虽然此部署可能会有优化,但我最感兴趣的是 Psql 角色。

根据我所读到的,似乎三种类型的角色是有意义的:

  • 具有非默认密码的超级用户 postgres
  • 没有日常维护、数据库创建、备份、恢复的超级用户权限的管理员角色。应该能够对所有客户数据库做任何事情。
  • 只能在其各自的数据库中进行 CRUD 的用户角色。如果清理实现,则可以容忍对他们自己的数据库的更多权限。

实现该设计是我不太自信的地方。DB与表的所有权以及谁应该从谁那里继承有点混乱。下面是我的数据库和我的用户。这些信息足以评估实施吗?

     Role name |                   Attributes                   |     Member of     
    -----------+------------------------------------------------+-------------------
     admin     | Create role, Create DB                         | {user1, user2}
     postgres  | Superuser, Create role, Create DB              | {}
     user1     |                                                | {}
     user2     |                                                | {}

    postgres=# \l
                                 List of databases
       Name    |  Owner   | Encoding | Collate | Ctype |   Access privileges   
    -----------+----------+----------+---------+-------+-----------------------
     admin     | postgres | UTF8     | en_US   | en_US | =Tc/postgres         +
               |          |          |         |       | postgres=CTc/postgres+
               |          |          |         |       | admin=CTc/postgres
     postgres  | postgres | UTF8     | en_US   | en_US | 
     template0 | postgres | UTF8     | en_US   | en_US | =c/postgres          +
               |          |          |         |       | postgres=CTc/postgres
     template1 | postgres | UTF8     | en_US   | en_US | =c/postgres          +
               |          |          |         |       | postgres=CTc/postgres
     user1     | admin    | UTF8     | en_US   | en_US | =Tc/admin            +
               |          |          |         |       | admin=CTc/admin      +
               |          |          |         |       | user1=CTc/admin
     user2     | admin    | UTF8     | en_US   | en_US | =Tc/admin            +
               |          |          |         |       | admin=CTc/admin      +
               |          |          |         |       | user2=CTc/admin
Run Code Online (Sandbox Code Playgroud)

为了防止外部连接和密码明文,pg_hba.conf 如下:

local   all             all                                     md5
host    all             all             127.0.0.1/32            md5
host    all             all             ::1/128                 md5
Run Code Online (Sandbox Code Playgroud)

Flo*_*aie 5

我知道这是一个古老的问题,但即使现在我也会尝试回答它,因为我必须做一些与此相关的研究。

您尝试做的是在数据库级别称为多租户。这可以通过两种方式实现:

  1. 在单个数据库集群中,有点像 OP 描述的那样,但是,我个人的选择是这样的:

    • postgres 用户使用对等身份验证并且不允许密码连接。在我看来,MD5 身份验证是一种不好的做法。如果您在数据库一致性或此类问题上遇到任何麻烦,如果您让 postgres 使用对等身份验证,您仍然可以登录。
    • 每个客户都应该获得自己的架构而不是数据库。这有多种原因:
      • 拥有整个数据库将授予很多特权。
      • 只拥有特定的表会给开发人员带来问题,并且总是需要要求管理员添加权限和内容。
      • 因此,在正常设置中,他们每个人都可以访问在其架构中创建内容,包括表、视图、触发器等。
      • 除了用户名之外,所有这些都使用相同的连接字符串。在 postgres 中,默认情况下,如果您有一个带有用户名的模式,它会自动在您的 search_path 中。
    • 作为安全措施,我会选择没有能够访问每个架构的管理员用户。您应该通过使用自己的用户转储每个模式或使用 PostgreSQL 的 PITR 技术来进行备份。您仍然需要使用 postgres 用户来创建新模式,我会为此使用 sudo 规则和脚本。
    • 许多安全性良好实践建议删除默认模式 - 我们就这样吧。
    • 如果每个客户的数据库很小并且您有大量客户,则此解决方案非常适合。
    • 如果您的应用程序处理多租户,它可以为所有客户使用单个连接池。当然,这消除了上述许多安全增强功能,但可能会带来性能优势,特别是当您拥有大量客户时(如果您有 500-1000 个独立的数据源,并且您使用连接池,那将是非常困难的)。
  2. 每个客户都有自己的数据库集群。这是我的首选解决方案,特别是因为我通常使用每个客户都有大型数据库的应用程序。

    • 这带来了很好的数据分离。您可以为每个客户使用单独的存储卷,分配 CPU 和内存限制(使用 docker?)。
    • 对于每个客户在他们的实例中需要什么,真的有很好的灵活性。它们可能相似或具有不同的特征。
    • 很容易在两个方向(向上和向外)缩放。
    • 我还使用单独的虚拟 IP,其中每个集群都侦听连接,从而无需重新配置数据源即可横向扩展。
    • PITR 备份是针对每个客户的,因此与每个模式多租户相比,恢复单个客户会更容易。
    • 在复杂的设置中,每个客户可能需要多个数据库、模式、用户和角色等,因此在这些情况下这是一种更好的解决方案。

您也可以结合使用上述方法,并使用 pgBouncer 作为路由器。