用户/角色

用户/角色指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的逻辑对象。

在这里的上下文中,“用户” 指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的 逻辑对象

在PostgreSQL中,用户默认直接隶属于数据库集簇,而非某个具体的数据库。

因此在创建业务数据库和业务用户时,应当遵循 “先用户,后数据库” 的原则。


定义用户

Pigsty通过两个配置参数定义数据库集群中的角色与用户,二者形式相同,均为用户对象的数组:

  • pg_default_roles:定义全局统一使用的角色和用户
  • pg_users:在数据库集群层面定义业务用户和角色

前者用于定义了整套环境中共用的角色与用户,后者定义单个集群中特有的业务角色与用户。

你可以定义多个用户/角色,它们会按照先全局(pg_default_roles),后集群(pg_users)的顺序创建,

此外,用户创建的顺序等同于数组内用户定义的顺序,所以后面的用户可以隶属于前面定义的角色。

下面是 Pigsty 演示环境中默认集群 pg-meta 中的业务用户定义:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_users:
      - {name: dbuser_meta     ,password: DBUser.Meta     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: pigsty admin user }
      - {name: dbuser_view     ,password: DBUser.Viewer   ,pgbouncer: true ,roles: [dbrole_readonly] ,comment: read-only viewer for meta database }
      - {name: dbuser_grafana  ,password: DBUser.Grafana  ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for grafana database    }
      - {name: dbuser_bytebase ,password: DBUser.Bytebase ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for bytebase database   }
      - {name: dbuser_kong     ,password: DBUser.Kong     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for kong api gateway    }
      - {name: dbuser_gitea    ,password: DBUser.Gitea    ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for gitea service       }
      - {name: dbuser_wiki     ,password: DBUser.Wiki     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for wiki.js service     }
      - {name: dbuser_noco     ,password: DBUser.Noco     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for nocodb service      }

每个用户/角色定义都是一个 object,可能包括以下字段,以 dbuser_meta 用户为例:

- name: dbuser_meta               # 必需,`name` 是用户定义的唯一必选字段
  password: DBUser.Meta           # 可选,密码,可以是 scram-sha-256 哈希字符串或明文
  login: true                     # 可选,默认情况下可以登录
  superuser: false                # 可选,默认为 false,是超级用户吗?
  createdb: false                 # 可选,默认为 false,可以创建数据库吗?
  createrole: false               # 可选,默认为 false,可以创建角色吗?
  inherit: true                   # 可选,默认情况下,此角色可以使用继承的权限吗?
  replication: false              # 可选,默认为 false,此角色可以进行复制吗?
  bypassrls: false                # 可选,默认为 false,此角色可以绕过行级安全吗?
  pgbouncer: true                 # 可选,默认为 false,将此用户添加到 pgbouncer 用户列表吗?(使用连接池的生产用户应该显式定义为 true)
  connlimit: -1                   # 可选,用户连接限制,默认 -1 禁用限制
  expire_in: 3650                 # 可选,此角色过期时间:从创建时 + n天计算(优先级比 expire_at 更高)
  expire_at: '2030-12-31'         # 可选,此角色过期的时间点,使用 YYYY-MM-DD 格式的字符串指定一个特定日期(优先级没 expire_in 高)
  comment: pigsty admin user      # 可选,此用户/角色的说明与备注字符串
  roles: [dbrole_admin]           # 可选,默认角色为:dbrole_{admin,readonly,readwrite,offline}
  parameters: {}                  # 可选,使用 `ALTER ROLE SET` 针对这个角色,配置角色级的数据库参数
  pool_mode: transaction          # 可选,默认为 transaction 的 pgbouncer 池模式,用户级别
  pool_connlimit: -1              # 可选,用户级别的最大数据库连接数,默认 -1 禁用限制
  search_path: public             # 可选,根据 postgresql 文档的键值配置参数(例如:使用 pigsty 作为默认 search_path)
  • 唯一 必需 的字段是 name,它应当是 PostgreSQL 集群中的一个有效且唯一的用户名。
  • 角色不需要 password,但对于可登录的业务用户,通常是需要指定一个密码的。
  • password 可以是明文或 scram-sha-256 / md5 哈希字符串,请最好不要使用明文密码。
  • 用户/角色按数组顺序逐一创建,因此,请确保角色/分组的定义在成员之前。
  • loginsuperusercreatedbcreateroleinheritreplicationbypassrls 是布尔标志。
  • pgbouncer 默认 禁用:要将业务用户添加到 pgbouncer 链接池用户列表中,您应当显式将其设置为 true

ACL系统

Pigsty 具有一套内置的,开箱即用的访问控制 / ACL 系统,您只需将以下四个默认角色分配给业务用户即可轻松使用:

  • dbrole_readwrite:全局读写访问的角色(主属业务使用的生产账号应当具有数据库读写权限)
  • dbrole_readonly:全局只读访问的角色(如果别的业务想要只读访问,可以使用此角色)
  • dbrole_admin:拥有DDL权限的角色 (业务管理员,需要在应用中建表的场景)
  • dbrole_offline:受限的只读访问角色(只能访问 offline 实例,通常是个人用户)

如果您希望重新设计您自己的 ACL 系统,可以考虑定制以下参数和模板:


创建用户

pg_default_rolespg_users定义的用户和角色,将在集群初始化阶段中自动逐一创建。

如果您希望在现有的集群上 创建用户,可以使用 bin/pgsql-user 命令行或直接使用 pgsql-user.yml 剧本。

将新用户/角色定义添加到 all.children.<cls>.pg_users,并使用以下方法创建该数据库:

bin/pgsql-user <cls> <username>                        # 使用命令行
./pgsql-user.yml -l <cls> -e username=<username>       # 使用剧本

不同于数据库,创建用户的剧本总是幂等的。当目标用户已经存在时,Pigsty 会修改目标用户的属性使其符合配置。


修改用户

修改 PostgreSQL 用户的属性的方式与 创建用户 相同。

首先,调整您的用户定义,修改需要调整的属性,然后执行以下命令应用:

bin/pgsql-user <cls> <username>                        # 使用命令行
./pgsql-user.yml -l <cls> -e username=<username>       # 使用剧本

请注意,修改用户不会删除用户,而是通过 ALTER USER 命令修改用户属性;也不会回收用户的权限与分组,并使用 GRANT 命令授予新的角色。


删除用户

出于安全考虑,Pigsty 不会自动删除用户,即使您在配置中删除了用户定义,Pigsty 也不会删除现有的用户。

您需要使用 SQL 命令 DROP USER 手动删除用户

DROP USER "<username>";

如果您要删除的角色是一个组(有其他用户属于该组),您需要先将其他用户从该组中移除,然后再删除该组。

REVOKE "<rolename>" FROM "<other_user>";

如果你要删除的用户 拥有 数据库对象,你需要先将这些对象的所有者更改为其他用户,然后再删除该用户。

REASSIGN OWNED BY "<username>" TO "<another_user>";

Pgbouncer用户

Pigsty 在默认情况下会安装并启用 Pgbouncer 链接池,并管理链接池中的用户。

Pigsty 默认会将 pg_users 中显式带有 pgbouncer: true 标志的用户添加到 pgbouncer 用户列表中。

配置文件

Pgbouncer 连接池中的用户在 /etc/pgbouncer/userlist.txt 中列出:

"postgres" ""
"dbuser_wiki" "SCRAM-SHA-256$4096:+77dyhrPeFDT/TptHs7/7Q==$KeatuohpKIYzHPCt/tqBu85vI11o9mar/by0hHYM2W8=:X9gig4JtjoS8Y/o1vQsIX/gY1Fns8ynTXkbWOjUfbRQ="
"dbuser_view" "SCRAM-SHA-256$4096:DFoZHU/DXsHL8MJ8regdEw==$gx9sUGgpVpdSM4o6A2R9PKAUkAsRPLhLoBDLBUYtKS0=:MujSgKe6rxcIUMv4GnyXJmV0YNbf39uFRZv724+X1FE="
"dbuser_monitor" "SCRAM-SHA-256$4096:fwU97ZMO/KR0ScHO5+UuBg==$CrNsmGrx1DkIGrtrD1Wjexb/aygzqQdirTO1oBZROPY=:L8+dJ+fqlMQh7y4PmVR/gbAOvYWOr+KINjeMZ8LlFww="
"dbuser_meta" "SCRAM-SHA-256$4096:leB2RQPcw1OIiRnPnOMUEg==$eyC+NIMKeoTxshJu314+BmbMFpCcspzI3UFZ1RYfNyU=:fJgXcykVPvOfro2MWNkl5q38oz21nSl1dTtM65uYR1Q="
"dbuser_kong" "SCRAM-SHA-256$4096:bK8sLXIieMwFDz67/0dqXQ==$P/tCRgyKx9MC9LH3ErnKsnlOqgNd/nn2RyvThyiK6e4=:CDM8QZNHBdPf97ztusgnE7olaKDNHBN0WeAbP/nzu5A="
"dbuser_grafana" "SCRAM-SHA-256$4096:HjLdGaGmeIAGdWyn2gDt/Q==$jgoyOB8ugoce+Wqjr0EwFf8NaIEMtiTuQTg1iEJs9BM=:ed4HUFqLyB4YpRr+y25FBT7KnlFDnan6JPVT9imxzA4="
"dbuser_gitea" "SCRAM-SHA-256$4096:l1DBGCc4dtircZ8O8Fbzkw==$tpmGwgLuWPDog8IEKdsaDGtiPAxD16z09slvu+rHE74=:pYuFOSDuWSofpD9OZhG7oWvyAR0PQjJBffgHZLpLHds="
"dbuser_dba" "SCRAM-SHA-256$4096:zH8niABU7xmtblVUo2QFew==$Zj7/pq+ICZx7fDcXikiN7GLqkKFA+X5NsvAX6CMshF0=:pqevR2WpizjRecPIQjMZOm+Ap+x0kgPL2Iv5zHZs0+g="
"dbuser_bytebase" "SCRAM-SHA-256$4096:OMoTM9Zf8QcCCMD0svK5gg==$kMchqbf4iLK1U67pVOfGrERa/fY818AwqfBPhsTShNQ=:6HqWteN+AadrUnrgC0byr5A72noqnPugItQjOLFw0Wk="

而用户级别的连接池参数则是使用另一个单独的文件: /etc/pgbouncer/useropts.txt 进行维护,比如:

dbuser_dba                  = pool_mode=session max_user_connections=16
dbuser_monitor              = pool_mode=session max_user_connections=8

连接池用户配置文件 userlist.txtuseropts.txt 会在您创建用户时自动刷新,并通过在线重载配置的方式生效,正常不会影响现有的连接。

当您创建数据库时,Pgbouncer 的数据库列表定义文件将会被刷新,并通过在线重载配置的方式生效,不会影响现有的连接。

管理用户

Pgbouncer 使用和 PostgreSQL 同样的 dbsu 运行,默认为 postgres 操作系统用户,您可以使用 pgb 别名,使用 dbsu 访问 pgbouncer 管理功能。

sudo su - postgres
pgb   # 使用管理用户登录 pgbouncer 命令行控制界面

Pigsty 还提供了一个实用函数 pgb-route ,可以将 pgbouncer 数据库流量快速切换至集群中的其他节点,用于零停机迁移:

删除用户

出于安全考虑,Pigsty 默认不提供删除数据库/链接池用户的命令,

从 pgbouncer 链接池中删除用户,只需在配置文件中删除相应的行,并重新 reload pgbouncer 即可。

链接池用户列表采用全量刷新覆盖的方式进行管理, 如果您确保所有数据库用户都是由 Pigsty 剧本/命令行创建, 那么可以使用以下命令全量刷新覆盖 pgbouncer 链接池中的用户列表:

./pgsql.yml -t pgbouncer_user,pgbouncer_reload -e pg_reload=true

动态用户认证

请注意,pgbouncer_auth_query 参数允许你使用动态查询来完成连接池用户认证,当您懒得管理连接池中的用户时,这是一种折中的方案。


最后修改 2025-03-21: replace vonng to pgsty (35fb95c)