Access Control

battery-included access control model in Pigsty

Pigsty has a battery-included access control model based on Role System and Privileges.


Role System

Pigsty has a default role system consist of four default roles and four default users

Role nameAttributesMember ofDescription
dbrole_readonlyNOLOGINrole for global read-only access
dbrole_readwriteNOLOGINdbrole_readonlyrole for global read-write access
dbrole_adminNOLOGINpg_monitor,dbrole_readwriterole for object creation
dbrole_offlineNOLOGINrole for restricted read-only access
postgresSUPERUSERsystem superuser
replicatorREPLICATIONpg_monitor,dbrole_readonlysystem replicator
dbuser_dbaSUPERUSERdbrole_adminpgsql admin user
dbuser_monitorpg_monitor,dbrole_readonlypgsql monitor user
  1. pg_default_roles: # default roles and users in postgres cluster
  2. - { name: dbrole_readonly ,login: false ,comment: role for global read-only access }
  3. - { name: dbrole_offline ,login: false ,comment: role for restricted read-only access }
  4. - { name: dbrole_readwrite ,login: false ,roles: [dbrole_readonly] ,comment: role for global read-write access }
  5. - { name: dbrole_admin ,login: false ,roles: [pg_monitor, dbrole_readwrite] ,comment: role for object creation }
  6. - { name: postgres ,superuser: true ,comment: system superuser }
  7. - { name: replicator ,replication: true ,roles: [pg_monitor, dbrole_readonly] ,comment: system replicator }
  8. - { name: dbuser_dba ,superuser: true ,roles: [dbrole_admin] ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 , comment: pgsql admin user }
  9. - { name: dbuser_monitor ,roles: [pg_monitor, dbrole_readonly] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }

Default Roles

There are four default roles in pigsty:

  • Read Only (dbrole_readonly): Role for global read-only access
  • Read Write (dbrole_readwrite): Role for global read-write access, inherits dbrole_readonly.
  • Admin (dbrole_admin): Role for DDL commands, inherits dbrole_readwrite.
  • Offline (dbrole_offline): Role for restricted read-only access (offline instance)

Default roles are defined in pg_default_roles, change default roles is not recommended.

  1. - { name: dbrole_readonly , login: false , comment: role for global read-only access } # production read-only role
  2. - { name: dbrole_offline , login: false , comment: role for restricted read-only access (offline instance) } # restricted-read-only role
  3. - { name: dbrole_readwrite , login: false , roles: [dbrole_readonly], comment: role for global read-write access } # production read-write role
  4. - { name: dbrole_admin , login: false , roles: [pg_monitor, dbrole_readwrite] , comment: role for object creation } # production DDL change role

Default Users

There are four default users in pigsty, too.

  • Superuser (postgres), the owner and creator of the cluster, same as the OS dbsu.
  • Replication user (replicator), the system user used for primary-replica.
  • Monitor user (dbuser_monitor), a user used to monitor database and connection pool metrics.
  • Admin user (dbuser_dba), the admin user who performs daily operations and database changes.

Default users’ username/password are defined with dedicate parameters (except for dbsu password):

!> Remember to change these password in production deployment !

  1. pg_dbsu: postgres # os user for the database
  2. pg_replication_username: replicator # system replication user
  3. pg_replication_password: DBUser.Replicator # system replication password
  4. pg_monitor_username: dbuser_monitor # system monitor user
  5. pg_monitor_password: DBUser.Monitor # system monitor password
  6. pg_admin_username: dbuser_dba # system admin user
  7. pg_admin_password: DBUser.DBA # system admin password

To define extra options, specify them in pg_default_roles:

  1. - { name: postgres ,superuser: true ,comment: system superuser }
  2. - { name: replicator ,replication: true ,roles: [pg_monitor, dbrole_readonly] ,comment: system replicator }
  3. - { name: dbuser_dba ,superuser: true ,roles: [dbrole_admin] ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 , comment: pgsql admin user }
  4. - { name: dbuser_monitor ,roles: [pg_monitor, dbrole_readonly] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }

Privileges

Pigsty has a battery-included privilege model that works with default roles.

  • All users have access to all schemas.
  • Read-Only user can read from all tables. (SELECT, EXECUTE)
  • Read-Write user can write to all tables run DML. (INSERT, UPDATE, DELETE).
  • Admin user can create object and run DDL (CREATE, USAGE, TRUNCATE, REFERENCES, TRIGGER).
  • Offline user is Read-Only user with limited access on offline instance (pg_role = 'offline' or pg_offline_query = true)
  • Object created by admin users will have correct privilege.
  • Default privileges are installed on all databases, including template database.
  • Database connect privilege is covered by database definition
  • CREATE privileges of database & public schema are revoked from PUBLIC by default

Object Privilege

Default object privileges are defined in pg_default_privileges.

  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 ON TABLES TO dbrole_readwrite
  10. - GRANT UPDATE ON TABLES TO dbrole_readwrite
  11. - GRANT DELETE ON TABLES TO dbrole_readwrite
  12. - GRANT USAGE ON SEQUENCES TO dbrole_readwrite
  13. - GRANT UPDATE ON SEQUENCES TO dbrole_readwrite
  14. - GRANT TRUNCATE ON TABLES TO dbrole_admin
  15. - GRANT REFERENCES ON TABLES TO dbrole_admin
  16. - GRANT TRIGGER ON TABLES TO dbrole_admin
  17. - GRANT CREATE ON SCHEMAS TO dbrole_admin

Which will be rendered in pg-init-template.sql alone with ALTER DEFAULT PRIVILEGES statement for admin users. The \ddp+ may looks like:

TypeAccess privileges
function=X
dbrole_readonly=X
dbrole_offline=X
dbrole_admin=X
schemadbrole_readonly=U
dbrole_offline=U
dbrole_admin=UC
sequencedbrole_readonly=r
dbrole_offline=r
dbrole_readwrite=wU
dbrole_admin=rwU
tabledbrole_readonly=r
dbrole_offline=r
dbrole_readwrite=awd
dbrole_admin=arwdDxt

Newly created objects will have corresponding privileges when it is created by admin users


Default Privilege

ALTER DEFAULT PRIVILEGES allows you to set the privileges that will be applied to objects created in the future. It does not affect privileges assigned to already-existing objects, and objects created by non-admin users.

That is to say, to maintain the correct object privilege, you have to run DDL with admin users, which could be:

  1. {{ pg_dbsu }}, postgres by default
  2. {{ pg_admin_username }}, dbuser_dba by default
  3. Business admin user granted with dbrole_admin

It’s wise to use postgres as global object owner. If you wish to create objects with business admin user, YOU MUST USE SET ROLE dbrole_admin before running that DDL to maintain the correct privileges.


Database Privilege

Database privilege is covered by database definition.

There are 3 database level privileges: CONNECT, CREATE, TEMP, and a special ‘privilege’: OWNERSHIP.

  1. - name: meta # required, `name` is the only mandatory field of a database definition
  2. owner: postgres # optional, specify a database owner, {{ pg_dbsu }} by default
  3. allowconn: true # optional, allow connection, true by default. false will disable connect at all
  4. revokeconn: false # optional, revoke public connection privilege. false by default. (leave connect with grant option to owner)
  • If owner exists, it will be used as database owner instead of default {{ pg_dbsu }}
  • If revokeconn is false, all users have the CONNECT privilege of the database, this is the default behavior.
  • If revokeconn is set to true explicitly:
    • CONNECT privilege of the database will be revoked from PUBLIC
    • CONNECT privilege will be granted to {{ pg_replication_username }}, {{ pg_monitor_username }} and {{ pg_admin_username }}
    • CONNECT privilege will be granted to database owner with GRANT OPTION

revokeconn flag can be used for database access isolation, you can create different business users as the owners for each database and set the revokeconn option for all of them.

Example: Database Isolation

  1. pg-infra:
  2. hosts:
  3. 10.10.10.40: { pg_seq: 1, pg_role: primary }
  4. 10.10.10.41: { pg_seq: 2, pg_role: replica , pg_offline_query: true }
  5. vars:
  6. pg_cluster: pg-infra
  7. pg_users:
  8. - { name: dbuser_confluence, password: mc2iohos , pgbouncer: true, roles: [ dbrole_admin ] }
  9. - { name: dbuser_gitlab, password: sdf23g22sfdd , pgbouncer: true, roles: [ dbrole_readwrite ] }
  10. - { name: dbuser_jira, password: sdpijfsfdsfdfs , pgbouncer: true, roles: [ dbrole_admin ] }
  11. pg_databases:
  12. - { name: confluence , revokeconn: true, owner: dbuser_confluence , connlimit: 100 }
  13. - { name: gitlab , revokeconn: true, owner: dbuser_gitlab, connlimit: 100 }
  14. - { name: jira , revokeconn: true, owner: dbuser_jira , connlimit: 100 }

Create Privilege

Pigsty revokes the CREATE privilege on database from PUBLIC by default, for security consideration.

Pigsty revokes the CREATE privilege on public schema from PUBLIC by default. Which is the default behavior since PostgreSQL 15.

The database owner have the full capability to adjust these privileges as they see fit.

Last modified 2023-02-27: refresh en docs to v2.0 (e82b371)