moving this discussion to a new thread... On Thu, Jan 19, 2023 at 10:20:33AM -0500, Robert Haas wrote: > On Wed, Jan 18, 2023 at 6:17 PM Nathan Bossart <nathandboss...@gmail.com> > wrote: >> However, as the attribute >> system becomes more sophisticated, I think we ought to improve the error >> messages in user.c. IMHO messages like "permission denied" could be >> greatly improved with some added context. >> >> This probably shouldn't block your patch, but I think it's worth doing in >> v16 since there are other changes in this area. I'm happy to help. > > That would be great. I agree that it's good to try to improve the > error messages. It hasn't been entirely clear to me how to do that. > For instance, I don't think we want to say something like: > > ERROR: must have CREATEROLE privilege and ADMIN OPTION on the target > role, or in lieu of both of those to be superuser, to set the > CONNECTION LIMIT for another role > ERROR: must have CREATEROLE privilege and ADMIN OPTION on the target > role, plus also CREATEDB, or in lieu of all that to be superuser, to > remove the CREATEDB property from another role > > Such messages are long and we'd end up with a lot of variants. It's > possible that the messages could be multi-tier. For instance, if we > determine that you're trying to manage users and you don't have > permission to manage ANY user, we could say: > > ERROR: permission to manage roles denied > DETAIL: You must have the CREATEROLE privilege or be a superuser to > manage roles. > > If you could potentially manage some user, but not the one you're > trying to manage, we could say: > > ERROR: permission to manage role "%s" denied > DETAIL: You need ADMIN OPTION on the target role to manage it. > > If you have permission to manage the target role but not in the > requested manner, we could then say something like: > > ERROR: permission to manage CREATEDB for role "%s" denied > DETAIL: You need CREATEDB to manage it. > > This is just one idea, and maybe not the best one. I'm just trying to > say that I think this is basically an organizational problem. We need > a plan for how we're going to report errors that is not too > complicated to implement with reasonable effort, and that will produce > messages that users will understand. I'd be delighted if you wanted to > provide either ideas or patches...
Here is an early draft of some modest improvements to the user.c error messages. I basically just tried to standardize the style of and add context to the existing error messages. I used errhint() for this extra context, but errdetail() would work, too. This isn't perfect. You might still have to go through a couple rounds of errors before your role has all the privileges it needs for a command, but this seems to improve matters a little. I think there is still a lot of room for improvement, but I wanted to at least get the discussion started before I went too far. -- Nathan Bossart Amazon Web Services: https://aws.amazon.com
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 3a92e930c0..1982831e2a 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -316,23 +316,28 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) if (!has_createrole_privilege(currentUserId)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied to create role"))); + errmsg("permission denied to create role"), + errhint("You must have CREATEROLE privilege to create roles."))); if (issuper) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to create superusers"))); + errmsg("permission denied to create role"), + errhint("You must have SUPERUSER privilege to create roles with SUPERUSER."))); if (createdb && !have_createdb_privilege()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must have createdb permission to create createdb users"))); + errmsg("permission denied to create role"), + errhint("You must have CREATEDB privilege to create roles with CREATEDB."))); if (isreplication && !has_rolreplication(currentUserId)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must have replication permission to create replication users"))); + errmsg("permission denied to create role"), + errhint("You must have REPLICATION privilege to create roles with REPLICATION."))); if (bypassrls && !has_bypassrls_privilege(currentUserId)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must have bypassrls to create bypassrls users"))); + errmsg("permission denied to create role"), + errhint("You must have BYPASSRLS privilege to create roles with BYPASSRLS."))); } /* @@ -747,7 +752,8 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt) if (!superuser() && (authform->rolsuper || dissuper)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to alter superuser roles or change superuser attribute"))); + errmsg("permission denied to alter role"), + errhint("You must have SUPERUSER privilege to alter roles with SUPERUSER."))); /* * Most changes to a role require that you both have CREATEROLE privileges @@ -758,16 +764,13 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt) { /* things an unprivileged user certainly can't do */ if (dinherit || dcreaterole || dcreatedb || dcanlogin || dconnlimit || - dvalidUntil || disreplication || dbypassRLS) + dvalidUntil || disreplication || dbypassRLS || + (dpassword && roleid != currentUserId)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied"))); - - /* an unprivileged user can change their own password */ - if (dpassword && roleid != currentUserId) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must have CREATEROLE privilege to change another user's password"))); + errmsg("permission denied to alter role"), + errhint("You must have CREATEROLE privilege and ADMIN OPTION on role \"%s\".", + rolename))); } else if (!superuser()) { @@ -779,23 +782,27 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt) if (dcreatedb && !have_createdb_privilege()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must have createdb privilege to change createdb attribute"))); + errmsg("permission denied to alter role"), + errhint("You must have CREATEDB privilege to alter roles with CREATEDB."))); if (disreplication && !has_rolreplication(currentUserId)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must have replication privilege to change replication attribute"))); + errmsg("permission denied to alter role"), + errhint("You must have REPLICATION privilege to alter roles with REPLICATION."))); if (dbypassRLS && !has_bypassrls_privilege(currentUserId)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must have bypassrls privilege to change bypassrls attribute"))); + errmsg("permission denied to alter role"), + errhint("You must have BYPASSRLS privilege to alter roles with BYPASSRLS."))); } /* To add members to a role, you need ADMIN OPTION. */ if (drolemembers && !is_admin_of_role(currentUserId, roleid)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must have admin option on role \"%s\" to add members", - rolename))); + errmsg("permission denied to alter role"), + errhint("You must have ADMIN OPTION on role \"%s\" to add members.", + rolename))); /* Convert validuntil to internal form */ if (dvalidUntil) @@ -838,7 +845,8 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt) if (!should_be_super && roleid == BOOTSTRAP_SUPERUSERID) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied: bootstrap user must be superuser"))); + errmsg("permission denied to alter role"), + errhint("The bootstrap user must be superuser."))); new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(should_be_super); new_record_repl[Anum_pg_authid_rolsuper - 1] = true; @@ -999,7 +1007,8 @@ AlterRoleSet(AlterRoleSetStmt *stmt) if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to alter superusers"))); + errmsg("permission denied to alter role"), + errhint("You must have SUPERUSER privilege to alter roles with SUPERUSER."))); } else { @@ -1008,7 +1017,9 @@ AlterRoleSet(AlterRoleSetStmt *stmt) && roleid != GetUserId()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied"))); + errmsg("permission denied to alter role"), + errhint("You must have CREATEROLE privilege and ADMIN OPTION on role \"%s\".", + NameStr(roleform->rolname)))); } ReleaseSysCache(roletuple); @@ -1038,7 +1049,8 @@ AlterRoleSet(AlterRoleSetStmt *stmt) if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to alter settings globally"))); + errmsg("permission denied to alter setting"), + errhint("You must have SUPERUSER privilege to alter settings globally."))); } AlterSetting(databaseid, roleid, stmt->setstmt); @@ -1061,7 +1073,8 @@ DropRole(DropRoleStmt *stmt) if (!have_createrole_privilege()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied to drop role"))); + errmsg("permission denied to drop role"), + errhint("You must have CREATEROLE privilege and ADMIN OPTION on the target roles."))); /* * Scan the pg_authid relation to find the Oid of the role(s) to be @@ -1131,12 +1144,14 @@ DropRole(DropRoleStmt *stmt) if (roleform->rolsuper && !superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to drop superusers"))); + errmsg("permission denied to drop role"), + errhint("You must have SUPERUSER privilege to drop roles with SUPERUSER."))); if (!is_admin_of_role(GetUserId(), roleid)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must have admin option on role \"%s\"", - role))); + errmsg("permission denied to drop role"), + errhint("You must have CREATEROLE privilege and ADMIN OPTION on role \"%s\".", + NameStr(roleform->rolname)))); /* DROP hook for the role being removed */ InvokeObjectDropHook(AuthIdRelationId, roleid, 0); @@ -1378,12 +1393,13 @@ RenameRole(const char *oldname, const char *newname) * Only superusers can mess with superusers. Otherwise, a user with * CREATEROLE can rename a role for which they have ADMIN OPTION. */ - if (((Form_pg_authid) GETSTRUCT(oldtuple))->rolsuper) + if (authform->rolsuper) { if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to rename superusers"))); + errmsg("permission denied to rename role"), + errhint("You must have SUPERUSER privilege to rename roles with SUPERUSER."))); } else { @@ -1391,7 +1407,9 @@ RenameRole(const char *oldname, const char *newname) !is_admin_of_role(GetUserId(), roleid)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied to rename role"))); + errmsg("permission denied to rename role"), + errhint("You must have CREATEROLE privilege and ADMIN OPTION on role \"%s\".", + NameStr(authform->rolname)))); } /* OK, construct the modified tuple */ @@ -1554,7 +1572,9 @@ DropOwnedObjects(DropOwnedStmt *stmt) if (!has_privs_of_role(GetUserId(), roleid)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied to drop objects"))); + errmsg("permission denied to drop objects"), + errhint("You must have privileges of role \"%s\".", + GetUserNameFromId(roleid, false)))); } /* Ok, do it */ @@ -1581,7 +1601,9 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt) if (!has_privs_of_role(GetUserId(), roleid)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied to reassign objects"))); + errmsg("permission denied to reassign objects"), + errhint("You must have privileges of role \"%s\".", + GetUserNameFromId(roleid, false)))); } /* Must have privileges on the receiving side too */ @@ -1590,7 +1612,9 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt) if (!has_privs_of_role(GetUserId(), newrole)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied to reassign objects"))); + errmsg("permission denied to reassign objects"), + errhint("You must have privileges of role \"%s\".", + GetUserNameFromId(newrole, false)))); /* Ok, do it */ shdepReassignOwned(role_ids, newrole); @@ -1738,7 +1762,7 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, if (memberid == BOOTSTRAP_SUPERUSERID) ereport(ERROR, (errcode(ERRCODE_INVALID_GRANT_OPERATION), - errmsg("admin option cannot be granted back to your own grantor"))); + errmsg("ADMIN OPTION cannot be granted back to your own grantor"))); plan_member_revoke(memlist, actions, memberid); } @@ -1763,7 +1787,7 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, if (i >= memlist->n_members) ereport(ERROR, (errcode(ERRCODE_INVALID_GRANT_OPERATION), - errmsg("admin option cannot be granted back to your own grantor"))); + errmsg("ADMIN OPTION cannot be granted back to your own grantor"))); ReleaseSysCacheList(memlist); } @@ -2081,9 +2105,20 @@ check_role_membership_authorization(Oid currentUserId, Oid roleid, if (superuser_arg(roleid)) { if (!superuser_arg(currentUserId)) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to alter superusers"))); + { + if (is_grant) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied to grant role \"%s\"", + GetUserNameFromId(roleid, false)), + errhint("You must have SUPERUSER privilege to grant roles with SUPERUSER."))); + else + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied to revoke role \"%s\"", + GetUserNameFromId(roleid, false)), + errhint("You must have SUPERUSER privilege to revoke roles with SUPERUSER."))); + } } else { @@ -2091,10 +2126,22 @@ check_role_membership_authorization(Oid currentUserId, Oid roleid, * Otherwise, must have admin option on the role to be changed. */ if (!is_admin_of_role(currentUserId, roleid)) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must have admin option on role \"%s\"", - GetUserNameFromId(roleid, false)))); + { + if (is_grant) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied to grant role \"%s\"", + GetUserNameFromId(roleid, false)), + errhint("You must have ADMIN OPTION on role \"%s\".", + GetUserNameFromId(roleid, false)))); + else + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied to revoke role \"%s\"", + GetUserNameFromId(roleid, false)), + errhint("You must have ADMIN OPTION on role \"%s\".", + GetUserNameFromId(roleid, false)))); + } } } @@ -2173,14 +2220,18 @@ check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId, bool is_grant) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied to grant privileges as role \"%s\"", - GetUserNameFromId(grantorId, false)))); + GetUserNameFromId(grantorId, false)), + errhint("You must have privileges of role \"%s\".", + GetUserNameFromId(grantorId, false)))); if (grantorId != BOOTSTRAP_SUPERUSERID && select_best_admin(grantorId, roleid) != grantorId) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("grantor must have ADMIN OPTION on \"%s\"", - GetUserNameFromId(roleid, false)))); + errmsg("permission denied to grant privileges as role \"%s\"", + GetUserNameFromId(grantorId, false)), + errhint("The grantor must have ADMIN OPTION on role \"%s\".", + GetUserNameFromId(roleid, false)))); } else { @@ -2188,7 +2239,9 @@ check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId, bool is_grant) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied to revoke privileges granted by role \"%s\"", - GetUserNameFromId(grantorId, false)))); + GetUserNameFromId(grantorId, false)), + errhint("You must have privileges of role \"%s\".", + GetUserNameFromId(grantorId, false)))); } /* diff --git a/src/test/regress/expected/create_role.out b/src/test/regress/expected/create_role.out index c8beb36bab..7549873ee5 100644 --- a/src/test/regress/expected/create_role.out +++ b/src/test/regress/expected/create_role.out @@ -7,26 +7,35 @@ CREATE ROLE regress_role_normal; -- fail, CREATEROLE user can't give away role attributes without having them SET SESSION AUTHORIZATION regress_role_limited_admin; CREATE ROLE regress_nosuch_superuser SUPERUSER; -ERROR: must be superuser to create superusers +ERROR: permission denied to create role +HINT: You must have SUPERUSER privilege to create roles with SUPERUSER. CREATE ROLE regress_nosuch_replication_bypassrls REPLICATION BYPASSRLS; -ERROR: must have replication permission to create replication users +ERROR: permission denied to create role +HINT: You must have REPLICATION privilege to create roles with REPLICATION. CREATE ROLE regress_nosuch_replication REPLICATION; -ERROR: must have replication permission to create replication users +ERROR: permission denied to create role +HINT: You must have REPLICATION privilege to create roles with REPLICATION. CREATE ROLE regress_nosuch_bypassrls BYPASSRLS; -ERROR: must have bypassrls to create bypassrls users +ERROR: permission denied to create role +HINT: You must have BYPASSRLS privilege to create roles with BYPASSRLS. CREATE ROLE regress_nosuch_createdb CREATEDB; -ERROR: must have createdb permission to create createdb users +ERROR: permission denied to create role +HINT: You must have CREATEDB privilege to create roles with CREATEDB. -- ok, can create a role without any special attributes CREATE ROLE regress_role_limited; -- fail, can't give it in any of the restricted attributes ALTER ROLE regress_role_limited SUPERUSER; -ERROR: must be superuser to alter superuser roles or change superuser attribute +ERROR: permission denied to alter role +HINT: You must have SUPERUSER privilege to alter roles with SUPERUSER. ALTER ROLE regress_role_limited REPLICATION; -ERROR: must have replication privilege to change replication attribute +ERROR: permission denied to alter role +HINT: You must have REPLICATION privilege to alter roles with REPLICATION. ALTER ROLE regress_role_limited CREATEDB; -ERROR: must have createdb privilege to change createdb attribute +ERROR: permission denied to alter role +HINT: You must have CREATEDB privilege to alter roles with CREATEDB. ALTER ROLE regress_role_limited BYPASSRLS; -ERROR: must have bypassrls privilege to change bypassrls attribute +ERROR: permission denied to alter role +HINT: You must have BYPASSRLS privilege to alter roles with BYPASSRLS. DROP ROLE regress_role_limited; -- ok, can give away these role attributes if you have them SET SESSION AUTHORIZATION regress_role_admin; @@ -43,9 +52,11 @@ ALTER ROLE regress_createdb NOCREATEDB; ALTER ROLE regress_createdb CREATEDB; -- fail, can't toggle SUPERUSER ALTER ROLE regress_createdb SUPERUSER; -ERROR: must be superuser to alter superuser roles or change superuser attribute +ERROR: permission denied to alter role +HINT: You must have SUPERUSER privilege to alter roles with SUPERUSER. ALTER ROLE regress_createdb NOSUPERUSER; -ERROR: must be superuser to alter superuser roles or change superuser attribute +ERROR: permission denied to alter role +HINT: You must have SUPERUSER privilege to alter roles with SUPERUSER. -- ok, having CREATEROLE is enough to create users with these privileges CREATE ROLE regress_createrole CREATEROLE NOINHERIT; GRANT CREATE ON DATABASE regression TO regress_createrole WITH GRANT OPTION; @@ -59,7 +70,8 @@ CREATE ROLE regress_noiseword SYSID 12345; NOTICE: SYSID can no longer be specified -- fail, cannot grant membership in superuser role CREATE ROLE regress_nosuch_super IN ROLE regress_role_super; -ERROR: must be superuser to alter superusers +ERROR: permission denied to grant role "regress_role_super" +HINT: You must have SUPERUSER privilege to grant roles with SUPERUSER. -- fail, database owner cannot have members CREATE ROLE regress_nosuch_dbowner IN ROLE pg_database_owner; ERROR: role "pg_database_owner" cannot have explicit members @@ -97,8 +109,10 @@ COMMENT ON ROLE regress_role_normal IS 'some comment'; ERROR: must have admin option on role "regress_role_normal" ALTER ROLE regress_role_normal RENAME TO regress_role_abnormal; ERROR: permission denied to rename role +HINT: You must have CREATEROLE privilege and ADMIN OPTION on role "regress_role_normal". ALTER ROLE regress_role_normal NOINHERIT NOLOGIN CONNECTION LIMIT 7; -ERROR: permission denied +ERROR: permission denied to alter role +HINT: You must have CREATEROLE privilege and ADMIN OPTION on role "regress_role_normal". -- ok, regress_tenant can create objects within the database SET SESSION AUTHORIZATION regress_tenant; CREATE TABLE tenant_table (i integer); @@ -123,6 +137,7 @@ ERROR: must be able to SET ROLE "regress_tenant" -- fail, we don't inherit permissions from regress_tenant REASSIGN OWNED BY regress_tenant TO regress_createrole; ERROR: permission denied to reassign objects +HINT: You must have privileges of role "regress_tenant". -- ok, create a role with a value for createrole_self_grant SET createrole_self_grant = 'set, inherit'; CREATE ROLE regress_tenant2; @@ -150,25 +165,35 @@ ERROR: must be able to SET ROLE "regress_tenant2" DROP TABLE tenant2_table; -- fail, CREATEROLE is not enough to create roles in privileged roles CREATE ROLE regress_read_all_data IN ROLE pg_read_all_data; -ERROR: must have admin option on role "pg_read_all_data" +ERROR: permission denied to grant role "pg_read_all_data" +HINT: You must have ADMIN OPTION on role "pg_read_all_data". CREATE ROLE regress_write_all_data IN ROLE pg_write_all_data; -ERROR: must have admin option on role "pg_write_all_data" +ERROR: permission denied to grant role "pg_write_all_data" +HINT: You must have ADMIN OPTION on role "pg_write_all_data". CREATE ROLE regress_monitor IN ROLE pg_monitor; -ERROR: must have admin option on role "pg_monitor" +ERROR: permission denied to grant role "pg_monitor" +HINT: You must have ADMIN OPTION on role "pg_monitor". CREATE ROLE regress_read_all_settings IN ROLE pg_read_all_settings; -ERROR: must have admin option on role "pg_read_all_settings" +ERROR: permission denied to grant role "pg_read_all_settings" +HINT: You must have ADMIN OPTION on role "pg_read_all_settings". CREATE ROLE regress_read_all_stats IN ROLE pg_read_all_stats; -ERROR: must have admin option on role "pg_read_all_stats" +ERROR: permission denied to grant role "pg_read_all_stats" +HINT: You must have ADMIN OPTION on role "pg_read_all_stats". CREATE ROLE regress_stat_scan_tables IN ROLE pg_stat_scan_tables; -ERROR: must have admin option on role "pg_stat_scan_tables" +ERROR: permission denied to grant role "pg_stat_scan_tables" +HINT: You must have ADMIN OPTION on role "pg_stat_scan_tables". CREATE ROLE regress_read_server_files IN ROLE pg_read_server_files; -ERROR: must have admin option on role "pg_read_server_files" +ERROR: permission denied to grant role "pg_read_server_files" +HINT: You must have ADMIN OPTION on role "pg_read_server_files". CREATE ROLE regress_write_server_files IN ROLE pg_write_server_files; -ERROR: must have admin option on role "pg_write_server_files" +ERROR: permission denied to grant role "pg_write_server_files" +HINT: You must have ADMIN OPTION on role "pg_write_server_files". CREATE ROLE regress_execute_server_program IN ROLE pg_execute_server_program; -ERROR: must have admin option on role "pg_execute_server_program" +ERROR: permission denied to grant role "pg_execute_server_program" +HINT: You must have ADMIN OPTION on role "pg_execute_server_program". CREATE ROLE regress_signal_backend IN ROLE pg_signal_backend; -ERROR: must have admin option on role "pg_signal_backend" +ERROR: permission denied to grant role "pg_signal_backend" +HINT: You must have ADMIN OPTION on role "pg_signal_backend". -- fail, role still owns database objects DROP ROLE regress_tenant; ERROR: role "regress_tenant" cannot be dropped because some objects depend on it @@ -211,11 +236,13 @@ DROP ROLE regress_inroles; DROP ROLE regress_adminroles; -- fail, cannot drop ourself, nor superusers or roles we lack ADMIN for DROP ROLE regress_role_super; -ERROR: must be superuser to drop superusers +ERROR: permission denied to drop role +HINT: You must have SUPERUSER privilege to drop roles with SUPERUSER. DROP ROLE regress_role_admin; ERROR: current user cannot be dropped DROP ROLE regress_rolecreator; -ERROR: must have admin option on role "regress_rolecreator" +ERROR: permission denied to drop role +HINT: You must have CREATEROLE privilege and ADMIN OPTION on role "regress_rolecreator". -- ok RESET SESSION AUTHORIZATION; REVOKE CREATE ON DATABASE regression FROM regress_role_admin CASCADE; diff --git a/src/test/regress/expected/dependency.out b/src/test/regress/expected/dependency.out index 520035f6a0..0556068e32 100644 --- a/src/test/regress/expected/dependency.out +++ b/src/test/regress/expected/dependency.out @@ -48,12 +48,16 @@ SET SESSION AUTHORIZATION regress_dep_user0; -- permission denied DROP OWNED BY regress_dep_user1; ERROR: permission denied to drop objects +HINT: You must have privileges of role "regress_dep_user1". DROP OWNED BY regress_dep_user0, regress_dep_user2; ERROR: permission denied to drop objects +HINT: You must have privileges of role "regress_dep_user2". REASSIGN OWNED BY regress_dep_user0 TO regress_dep_user1; ERROR: permission denied to reassign objects +HINT: You must have privileges of role "regress_dep_user1". REASSIGN OWNED BY regress_dep_user1 TO regress_dep_user0; ERROR: permission denied to reassign objects +HINT: You must have privileges of role "regress_dep_user1". -- this one is allowed DROP OWNED BY regress_dep_user0; CREATE TABLE deptest1 (f1 int unique); diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out index 95d1e5515f..e0f5a486b9 100644 --- a/src/test/regress/expected/privileges.out +++ b/src/test/regress/expected/privileges.out @@ -37,7 +37,7 @@ CREATE ROLE regress_priv_role; GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION; GRANT regress_priv_user1 TO regress_priv_user3 WITH ADMIN OPTION GRANTED BY regress_priv_user2; GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION GRANTED BY regress_priv_user3; -ERROR: admin option cannot be granted back to your own grantor +ERROR: ADMIN OPTION cannot be granted back to your own grantor -- need CASCADE to revoke grant or admin option if dependent grants exist REVOKE ADMIN OPTION FOR regress_priv_user1 FROM regress_priv_user2; -- fail ERROR: dependent privileges exist @@ -156,7 +156,8 @@ ALTER GROUP regress_priv_group2 ADD USER regress_priv_user2; -- duplicate NOTICE: role "regress_priv_user2" has already been granted membership in role "regress_priv_group2" by role "regress_priv_user1" ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2; ALTER USER regress_priv_user2 PASSWORD 'verysecret'; -- not permitted -ERROR: must have CREATEROLE privilege to change another user's password +ERROR: permission denied to alter role +HINT: You must have CREATEROLE privilege and ADMIN OPTION on role "regress_priv_user2". RESET SESSION AUTHORIZATION; ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2; REVOKE ADMIN OPTION FOR regress_priv_group2 FROM regress_priv_user1; @@ -168,7 +169,8 @@ CREATE FUNCTION leak(integer,integer) RETURNS boolean ALTER FUNCTION leak(integer,integer) OWNER TO regress_priv_user1; -- test owner privileges GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY regress_priv_role; -- error, doesn't have ADMIN OPTION -ERROR: grantor must have ADMIN OPTION on "regress_priv_role" +ERROR: permission denied to grant privileges as role "regress_priv_role" +HINT: The grantor must have ADMIN OPTION on role "regress_priv_role". GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY CURRENT_ROLE; REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY foo; -- error ERROR: role "foo" does not exist @@ -1795,7 +1797,8 @@ REFRESH MATERIALIZED VIEW sro_mv; ERROR: cannot fire deferred trigger within security-restricted operation CONTEXT: SQL function "mv_action" statement 1 BEGIN; SET CONSTRAINTS ALL IMMEDIATE; REFRESH MATERIALIZED VIEW sro_mv; COMMIT; -ERROR: must have admin option on role "regress_priv_group2" +ERROR: permission denied to grant role "regress_priv_group2" +HINT: You must have ADMIN OPTION on role "regress_priv_group2". CONTEXT: SQL function "unwanted_grant" statement 1 SQL statement "SELECT unwanted_grant()" PL/pgSQL function sro_trojan() line 1 at PERFORM @@ -1825,10 +1828,12 @@ CREATE FUNCTION dogrant_ok() RETURNS void LANGUAGE sql SECURITY DEFINER AS GRANT regress_priv_group2 TO regress_priv_user5; -- ok: had ADMIN OPTION SET ROLE regress_priv_group2; GRANT regress_priv_group2 TO regress_priv_user5; -- fails: SET ROLE suspended privilege -ERROR: must have admin option on role "regress_priv_group2" +ERROR: permission denied to grant role "regress_priv_group2" +HINT: You must have ADMIN OPTION on role "regress_priv_group2". SET SESSION AUTHORIZATION regress_priv_user1; GRANT regress_priv_group2 TO regress_priv_user5; -- fails: no ADMIN OPTION -ERROR: must have admin option on role "regress_priv_group2" +ERROR: permission denied to grant role "regress_priv_group2" +HINT: You must have ADMIN OPTION on role "regress_priv_group2". SELECT dogrant_ok(); -- ok: SECURITY DEFINER conveys ADMIN NOTICE: role "regress_priv_user5" has already been granted membership in role "regress_priv_group2" by role "regress_priv_user4" dogrant_ok @@ -1838,10 +1843,12 @@ NOTICE: role "regress_priv_user5" has already been granted membership in role " SET ROLE regress_priv_group2; GRANT regress_priv_group2 TO regress_priv_user5; -- fails: SET ROLE did not help -ERROR: must have admin option on role "regress_priv_group2" +ERROR: permission denied to grant role "regress_priv_group2" +HINT: You must have ADMIN OPTION on role "regress_priv_group2". SET SESSION AUTHORIZATION regress_priv_group2; GRANT regress_priv_group2 TO regress_priv_user5; -- fails: no self-admin -ERROR: must have admin option on role "regress_priv_group2" +ERROR: permission denied to grant role "regress_priv_group2" +HINT: You must have ADMIN OPTION on role "regress_priv_group2". SET SESSION AUTHORIZATION regress_priv_user4; DROP FUNCTION dogrant_ok(); REVOKE regress_priv_group2 FROM regress_priv_user5;