各位朋友,
我可以借助您的帮助,使我的 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
我知道这是一个老问题但我现在会尝试回答它,因为我必须做一些与此相关的研究。
你想做的事情叫做多租户在数据库级别。这可以通过两种方式实现:
在单个数据库集群中,正如OP所描述的,我个人的选择是这样的:
- postgres 用户使用对等身份验证,不允许密码连接。在我看来,MD5 身份验证是一种不好的做法。如果您遇到任何与数据库一致性或此类问题有关的问题,只要让 postgres 使用对等身份验证,您仍然可以登录。
- 每个顾客都应该得到自己的架构而不是数据库。造成这种情况的原因有多种:
- 拥有整个数据库将会授予很多特权。
- 仅拥有特定的表会给开发人员带来问题,并且总是需要要求管理员添加权限等等。
- 因此,在正常设置中,他们每个人都可以访问其模式内创建的东西,包括表、视图、触发器等。
- 除了用户名之外,它们都使用相同的连接字符串。在 postgres 中,默认情况下,如果您有一个包含用户名的架构,它将自动位于您的 search_path 中。
- 作为一项安全措施,我会选择不让管理员用户访问每个架构。您应该通过使用自己的用户转储每个架构或使用 PostgreSQL 的 PITR 技术进行备份。您仍然需要使用 postgres 用户来创建新的架构,我会为此选择 sudo 规则和脚本。
- 许多安全良好实践建议放弃默认模式,所以 - 我们开始吧。
- 如果每个客户的数据库都很小并且您拥有大量客户,则此解决方案非常适合。
- 如果您的应用程序处理多租户,它可以为所有客户使用一个连接池。当然,这会消除上述许多安全增强功能,但可以带来性能优势,特别是当您拥有大量客户时(如果您拥有 500-1000 个独立数据源并使用连接池,那么这将非常令人难以承受)。
每个客户都有自己的数据库集群。这是我首选的解决方案,特别是因为我通常使用每个客户都有大型数据库的应用程序。
- 这个带来了非常好的数据分离。您可以为每个客户提供单独的存储卷,分配 CPU 和内存限制(使用 docker?)。
- 真正灵活地满足每个客户的需求。它们可以相似,也可以具有不同的功能。
- 非常容易在两个方向 (向上和向外) 扩展。
- 我还使用单独的虚拟 IP,每个集群都监听连接,从而无需重新配置数据源即可进行扩展。
- PITR 备份是针对每个客户的,因此与每个模式的多租户相比,恢复单个客户会更容易。
- 在复杂的设置中,每个客户可能需要多个数据库、模式、用户和角色等,因此在这些情况下这是一种更好的解决方案。
您还可以使用上述方法的组合,并使用 pgBouncer 作为路由器。