Kirmi13/pg-hba-lock

GitHub: Kirmi13/pg-hba-lock

通过动态重写 pg_hba.conf 实现单个 PostgreSQL 数据库的临时连接锁定,带自动备份与语法错误回滚,适用于维护窗口期间的安全隔离。

Stars: 0 | Forks: 0

# pg-hba-lock 通过动态重写 `pg_hba.conf`,临时锁定单个 PostgreSQL 数据库,而无需影响集群的其余部分。包含自动备份和回滚功能,以防新配置无法正常解析。 典型用例: - 需要独占访问数据库的 schema 迁移 - 维护操作(`VACUUM FULL`、重建索引、大版本升级等) - 应急响应(隔离受损的应用程序账号) - 时间点恢复 / 还原操作 - 在将读取流量切换到 replica 之前冻结数据库 ## 功能说明 - 阻止所有与目标数据库的新连接,专用的 `migrator` 角色除外。 - 集群上的所有其他数据库保持与之前一样的可达状态。 - 在进行任何更改之前,备份当前的 `pg_hba.conf`。 - 通过 `pg_hba_file_rules` 验证新配置,如果包含语法错误会自动回滚——集群绝不会因为错误的配置而被锁死。 - 只需调用一次 `unlock_db()` 即可还原原始配置。 ## 使用前须知 - **需要 superuser 权限。** 这使得 SQL 会话能够直接在磁盘上重写服务器的身份验证配置。在运行之前,请务必了解这对您的环境意味着什么。 - **仅限自托管的 PostgreSQL。** 它直接写入支撑 `hba_file` 的文件中。托管服务(RDS、Cloud SQL 等)不公开该文件,因此无法在其中使用。 - **密码可能会被记录。** `create_migrator()` 将密码作为普通的 SQL 参数接收。根据您的 `log_statement` 设置,它可能会出现在服务器日志、`pg_stat_activity` 或您的 shell 历史记录中。请使用仅在维护窗口生效的一次性密码。 - **对象所有权。** 如果 `migrator` 角色在维护窗口期间创建或拥有对象,则在这些对象被重新分配或删除之前,`drop_migrator()` 将会失败。 - 同一时间只能有一个锁处于活动状态(通过备份表上的 partial unique index 强制执行)。在锁定其他数据库之前,请调用 `unlock_db()`。 ## 安装说明 ``` psql -d your_database -f db_lock.sql ``` 这将创建一个 `maintenance` schema,其中包含备份表以及下文所有的存储过程。要使用不同的 schema 名称,请在运行之前在 `db_lock.sql` 中查找并替换 `maintenance`——在纯 SQL/DDL 中,schema 名称无法参数化。 ## 用法 ``` -- 1. Create a role that stays reachable while everyone else is locked out CALL maintenance.create_migrator('temporary-password'); -- 2. Lock the target database CALL maintenance.lock_db('my_database'); -- ... connect as migrator and do your maintenance work ... -- 3. Restore normal access CALL maintenance.unlock_db(); -- 4. Clean up the temporary role CALL maintenance.drop_migrator(); ``` ### 自定义角色名称或身份验证方法 ``` CALL maintenance.create_migrator('temporary-password', 'svc_migrator'); CALL maintenance.lock_db('my_database', 'svc_migrator', 'scram-sha-256'); CALL maintenance.drop_migrator('svc_migrator'); ``` ## 工作原理 1. `lock_db(target_db)` 读取当前的 `pg_hba.conf`,将其保存到 `maintenance.pg_hba_backup` 中,然后在开头添加新规则: - migrator 角色获得对所有数据库的访问权限(必须放在第一位——`pg_hba.conf` 规则是自上而下评估的,匹配到第一个即生效), - 所有其他角色在 `target_db` 上被拒绝访问, - 所有其他角色保持对其他所有数据库的正常密码访问权限。 2. `target_db` 上的现有会话将被终止,migrator 角色除外。 3. `pg_reload_conf()` 应用更改,并检查 `pg_hba_file_rules` 是否存在解析错误。如果发现任何错误,会立即还原之前的配置,并将备份标记为已使用。 4. `unlock_db()` 还原最近的备份,重新加载配置,并在将备份标记为已还原之前再次进行验证。 ## 参考 | 存储过程 | 参数 | 描述 | |---|---|---| | `create_migrator` | `p_password`, `p_role_name = 'migrator'` | 创建一个 superuser 登录角色(如果已存在则不执行操作) | | `drop_migrator` | `p_role_name = 'migrator'` | 终止会话并删除该角色 | | `lock_db` | `p_target_db`, `p_migrator_role = 'migrator'`, `p_auth_method = 'scram-sha-256'` | 锁定数据库,同时保持 migrator 的访问权限处于开放状态 | | `unlock_db` | — | 还原最近未还原的备份 |
标签:PostgreSQL, Streamlit, 多线程, 数据库运维, 测试用例, 系统维护, 访问控制