PostgreSQL ACL权限

Pigsty提供一套开箱即用的ACL模型,可以对读、写、DDL、离线访问进行区分,满足基本访问控制需求。

Pigsty的默认权限模型与默认角色紧密关联。使用Pigsty访问控制模型时,新创建的业务用户都应当属于四种默认角色之一,默认角色拥有的权限如下所示:

  • 所有用户都可以访问所有模式
  • 只读用户可以读取所有表
  • 读写用户可以对所有表进行DML操作(INSERT, UPDATE, DELETE)
  • 管理员可以执行DDL变更操作(CREATE, USAGE, TRUNCATE, REFERENCES, TRIGGER)
  • 离线用户与只读用户类似,但只允许访问pg_role == 'offline'pg_offline_query = true 的实例
  1. GRANT USAGE ON SCHEMAS TO dbrole_readonly;
  2. GRANT SELECT ON TABLES TO dbrole_readonly;
  3. GRANT SELECT ON SEQUENCES TO dbrole_readonly;
  4. GRANT EXECUTE ON FUNCTIONS TO dbrole_readonly;
  5. GRANT USAGE ON SCHEMAS TO dbrole_offline;
  6. GRANT SELECT ON TABLES TO dbrole_offline;
  7. GRANT SELECT ON SEQUENCES TO dbrole_offline;
  8. GRANT EXECUTE ON FUNCTIONS TO dbrole_offline;
  9. GRANT INSERT, UPDATE, DELETE ON TABLES TO dbrole_readwrite;
  10. GRANT USAGE, UPDATE ON SEQUENCES TO dbrole_readwrite;
  11. GRANT TRUNCATE, REFERENCES, TRIGGER ON TABLES TO dbrole_admin;
  12. GRANT CREATE ON SCHEMAS TO dbrole_admin;
  13. GRANT USAGE ON TYPES TO dbrole_admin;
OwnerSchemaTypeAccess privileges
usernameschemapostgres=UC/postgres
dbrole_readonly=U/postgres
dbrole_offline=U/postgres
dbrole_admin=C/postgres
usernamesequencepostgres=rwU/postgres
dbrole_readonly=r/postgres
dbrole_readwrite=wU/postgres
dbrole_offline=r/postgres
usernametablepostgres=arwdDxt/postgres
dbrole_readonly=r/postgres
dbrole_readwrite=awd/postgres
dbrole_offline=r/postgres
dbrole_admin=Dxt/postgres
usernamefunction=X/postgres
postgres=X/postgres
dbrole_readonly=X/postgres
dbrole_offline=X/postgres

对象权限的维护

数据库对象的默认访问权限通过PostgreSQL的ALTER DEFAULT PRIVILEGES确保。

所有由 {{ dbsu }}, {{ pg_admin_username }}, {{ dbrole_admin }} 创建的对象,都会拥有以上默认权限。 反过来说,如果是由其他角色创建的对象,则并不会配置有正确的默认访问权限。

Pigsty非常不建议使用业务用户执行DDL变更,因为PostgreSQL的ALTER DEFAULT PRIVILEGE仅针对“由特定用户创建的对象”生效, 默认情况下超级用户postgresdbuser_dba创建的对象拥有默认的权限配置,如果希望授予业务用户执行DDL的权限,那么除了为业务用户赋予 dbrole_admin 角色外,使用者还需牢记在执行DDL变更时首先要执行:

  1. SET ROLE dbrole_admin; -- dbrole_admin 创建的对象具有正确的默认权限

这样创建的对象才会具有默认的访问权限。

数据库的权限

数据库有三种权限:CONNECT, CREATE, TEMP,以及特殊的属主OWNERSHIP。数据库的定义由参数pg_database控制。一个完整的数据库定义如下所示:

  1. pg_databases: # define business databases on this cluster, array of database definition
  2. # define the default `meta` database
  3. - name: meta # required, `name` is the only mandatory field of a database definition
  4. baseline: cmdb.sql # optional, database sql baseline path, (relative path among ansible search path, e.g files/)
  5. owner: postgres # optional, database owner, postgres by default
  6. template: template1 # optional, which template to use, template1 by default
  7. encoding: UTF8 # optional, database encoding, UTF8 by default. (MUST same as template database)
  8. locale: C # optional, database locale, C by default. (MUST same as template database)
  9. lc_collate: C # optional, database collate, C by default. (MUST same as template database)
  10. lc_ctype: C # optional, database ctype, C by default. (MUST same as template database)
  11. tablespace: pg_default # optional, default tablespace, 'pg_default' by default.
  12. allowconn: true # optional, allow connection, true by default. false will disable connect at all
  13. revokeconn: false # optional, revoke public connection privilege. false by default. (leave connect with grant option to owner)
  14. pgbouncer: true # optional, add this database to pgbouncer database list? true by default
  15. comment: pigsty meta database # optional, comment string for this database
  16. connlimit: -1 # optional, database connection limit, default -1 disable limit
  17. schemas: [pigsty] # optional, additional schemas to be created, array of schema names
  18. extensions: # optional, additional extensions to be installed: array of schema definition `{name,schema}`
  19. - {name: adminpack, schema: pg_catalog} # install adminpack to pg_catalog and install postgis to public
  20. - {name: postgis, schema: public} # if schema is omitted, extension will be installed according to search_path.

默认情况下,如果数据库没有配置属主,那么数据库超级用户dbsu将会作为数据库的默认OWNER,否则将为指定用户。

默认情况下,所有用户都具有对新创建数据库的CONNECT 权限,如果希望回收该权限,设置 revokeconn == true,则该权限会被回收。只有默认用户(dbsu|admin|monitor|replicator)与数据库的属主才会被显式赋予CONNECT权限。同时,admin|owner将会具有CONNECT权限的GRANT OPTION,可以将CONNECT权限转授他人。

如果希望实现不同数据库之间的访问隔离,可以为每一个数据库创建一个相应的业务用户作为owner,并全部设置revokeconn选项,这种配置对于多租户实例尤为实用。

一个进行权限隔离的数据库样例

  1. #--------------------------------------------------------------#
  2. # pg-infra (example database for cluster loading)
  3. #--------------------------------------------------------------#
  4. pg-infra:
  5. hosts:
  6. 10.10.10.40: { pg_seq: 1, pg_role: primary }
  7. 10.10.10.41: { pg_seq: 2, pg_role: replica , pg_offline_query: true }
  8. vars:
  9. pg_cluster: pg-infrastructure
  10. pg_version: 14
  11. vip_address: 10.10.10.4
  12. pgbouncer_poolmode: session
  13. pg_hba_rules_extra:
  14. - title: allow confluence jira gitlab eazybi direct access
  15. role: common
  16. rules:
  17. - host confluence dbuser_confluence 10.0.0.0/8 md5
  18. - host jira dbuser_jira 10.0.0.0/8 md5
  19. - host gitlab dbuser_gitlab 10.0.0.0/8 md5
  20. pg_users:
  21. # infra prod user
  22. - { name: dbuser_hybridcloud, password: ssag-2xd, pgbouncer: true, roles: [ dbrole_readwrite ] }
  23. - { name: dbuser_confluence, password: mc2iohos , pgbouncer: true, roles: [ dbrole_admin ] }
  24. - { name: dbuser_gitlab, password: sdf23g22sfdd , pgbouncer: true, roles: [ dbrole_readwrite ] }
  25. - { name: dbuser_jira, password: sdpijfsfdsfdfs , pgbouncer: true, roles: [ dbrole_admin ] }
  26. pg_databases:
  27. # infra database
  28. - { name: hybridcloud , revokeconn: true, owner: dbuser_hybridcloud , parameters: { search_path: yay,public } , connlimit: 100 }
  29. - { name: confluence , revokeconn: true, owner: dbuser_confluence , connlimit: 100 }
  30. - { name: gitlab , revokeconn: true, owner: dbuser_gitlab, connlimit: 100 }
  31. - { name: jira , revokeconn: true, owner: dbuser_jira , connlimit: 100 }

创建对象的权限

默认情况下,出于安全考虑,Pigsty会撤销PUBLIC用户在数据库下CREATE新模式的权限, 同时也会撤销PUBLIC用户在public模式下创建新关系的权限。 数据库超级用户与管理员不受此限制,他们总是可以在任何地方执行DDL变更。

在数据库中创建对象的权限与用户是否为数据库属主无关,这只取决于创建该用户时是否为该用户赋予管理员权限

  1. pg_users:
  2. - {name: test1, password: xxx , groups: [dbrole_readwrite]} # 不能创建Schema与对象
  3. - {name: test2, password: xxx , groups: [dbrole_admin]} # 可以创建Schema与对象

最后修改 2022-07-05: fix https://github.com/Vonng/pigsty/issues/147 (e588a1e)