Postgres 角色最佳实践实施

Postgres 角色最佳实践实施

各位朋友,

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

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

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

  • 具有非默认密码的超级用户 postgres
  • 管理员角色不具备日常维护、数据库创建、备份、恢复等超级用户权限。应该能够对所有客户数据库执行任何操作。
  • 用户角色只具有在各自数据库中进行 CRUD 的能力。如果简化实现,则可以容忍对其自身数据库拥有更多权限。

我对实现该设计不太有信心。数据库与表的所有权以及谁应该从谁那里继承有点模糊。下面是我的数据库和我的用户。这些信息足以评估实施情况吗?

     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

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

local   all             all                                     md5
host    all             all             127.0.0.1/32            md5
host    all             all             ::1/128                 md5

答案1

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

你想做的事情叫做多租户在数据库级别。这可以通过两种方式实现:

  1. 在单个数据库集群中,正如OP所描述的,我个人的选择是这样的:

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

    • 这个带来了非常好的数据分离。您可以为每个客户提供单独的存储卷,分配 CPU 和内存限制(使用 docker?)。
    • 真正灵活地满足每个客户的需求。它们可以相似,也可以具有不同的功能。
    • 非常容易在两个方向 (向上和向外) 扩展。
    • 我还使用单独的虚拟 IP,每个集群都监听连接,从而无需重新配置数据源即可进行扩展。
    • PITR 备份是针对每个客户的,因此与每个模式的多租户相比,恢复单个客户会更容易。
    • 在复杂的设置中,每个客户可能需要多个数据库、模式、用户和角色等,因此在这些情况下这是一种更好的解决方案。

您还可以使用上述方法的组合,并使用 pgBouncer 作为路由器。

相关内容