mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-09 08:10:09 +08:00
Restrict the privileges of CREATEROLE users.
Previously, CREATEROLE users were permitted to make nearly arbitrary changes to roles that they didn't create, with certain exceptions, particularly superuser roles. Instead, allow CREATEROLE users to make such changes to roles for which they possess ADMIN OPTION, and to grant membership only in roles for which they possess ADMIN OPTION. When a CREATEROLE user who is not a superuser creates a role, grant ADMIN OPTION on the newly-created role to the creator, so that they can administer roles they create or for which they have been given privileges. With these changes, CREATEROLE users still have very significant powers that unprivileged users do not receive: they can alter, rename, drop, comment on, change the password for, and change security labels on roles. However, they can now do these things only for roles for which they possess appropriate privileges, rather than all non-superuser roles; moreover, they cannot grant a role such as pg_execute_server_program unless they themselves possess it. Patch by me, reviewed by Mark Dilger. Discussion: https://postgr.es/m/CA+TgmobN59ct+Emmz6ig1Nua2Q-_o=r6DSD98KfU53kctq_kQw@mail.gmail.com
This commit is contained in:
parent
f026c16a2c
commit
cf5eb37c5e
@ -3216,13 +3216,11 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
|
||||
name. Therefore, if each user has a separate schema, they access
|
||||
their own schemas by default.) This pattern is a secure schema
|
||||
usage pattern unless an untrusted user is the database owner or
|
||||
holds the <literal>CREATEROLE</literal> privilege, in which case no
|
||||
secure schema usage pattern exists.
|
||||
has been granted <literal>ADMIN OPTION</literal> on a relevant role,
|
||||
in which case no secure schema usage pattern exists.
|
||||
</para>
|
||||
<!-- A database owner can attack the database's users via "CREATE SCHEMA
|
||||
trojan; ALTER DATABASE $mydb SET search_path = trojan, public;". A
|
||||
CREATEROLE user can issue "GRANT $dbowner TO $me" and then use the
|
||||
database owner attack. -->
|
||||
trojan; ALTER DATABASE $mydb SET search_path = trojan, public;". -->
|
||||
|
||||
<para>
|
||||
In <productname>PostgreSQL</productname> 15 and later, the default
|
||||
@ -3250,7 +3248,7 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
|
||||
unreliable</link>. If you create functions or extensions in the public
|
||||
schema, use the first pattern instead. Otherwise, like the first
|
||||
pattern, this is secure unless an untrusted user is the database owner
|
||||
or holds the <literal>CREATEROLE</literal> privilege.
|
||||
or has been granted <literal>ADMIN OPTION</literal> on a relevant role.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
@ -73,7 +73,8 @@ ALTER ROLE { <replaceable class="parameter">role_specification</replaceable> | A
|
||||
Roles having <literal>CREATEROLE</literal> privilege can change any of these
|
||||
settings except <literal>SUPERUSER</literal>, <literal>REPLICATION</literal>,
|
||||
and <literal>BYPASSRLS</literal>; but only for non-superuser and
|
||||
non-replication roles.
|
||||
non-replication roles for which they have been
|
||||
granted <literal>ADMIN OPTION</literal>.
|
||||
Ordinary roles can only change their own password.
|
||||
</para>
|
||||
|
||||
@ -81,7 +82,7 @@ ALTER ROLE { <replaceable class="parameter">role_specification</replaceable> | A
|
||||
The second variant changes the name of the role.
|
||||
Database superusers can rename any role.
|
||||
Roles having <literal>CREATEROLE</literal> privilege can rename non-superuser
|
||||
roles.
|
||||
roles for which they have been granted <literal>ADMIN OPTION</literal>.
|
||||
The current session user cannot be renamed.
|
||||
(Connect as a different user if you need to do that.)
|
||||
Because <literal>MD5</literal>-encrypted passwords use the role name as
|
||||
@ -116,7 +117,8 @@ ALTER ROLE { <replaceable class="parameter">role_specification</replaceable> | A
|
||||
<para>
|
||||
Superusers can change anyone's session defaults. Roles having
|
||||
<literal>CREATEROLE</literal> privilege can change defaults for non-superuser
|
||||
roles. Ordinary roles can only set defaults for themselves.
|
||||
roles for which they have been granted <literal>ADMIN OPTION</literal>.
|
||||
Ordinary roles can only set defaults for themselves.
|
||||
Certain configuration variables cannot be set this way, or can only be
|
||||
set if a superuser issues the command. Only superusers can change a setting
|
||||
for all roles in all databases.
|
||||
|
@ -99,7 +99,8 @@ COMMENT ON
|
||||
For most kinds of object, only the object's owner can set the comment.
|
||||
Roles don't have owners, so the rule for <literal>COMMENT ON ROLE</literal> is
|
||||
that you must be superuser to comment on a superuser role, or have the
|
||||
<literal>CREATEROLE</literal> privilege to comment on non-superuser roles.
|
||||
<literal>CREATEROLE</literal> privilege and have been granted
|
||||
<literal>ADMIN OPTION</literal> on the target role.
|
||||
Likewise, access methods don't have owners either; you must be superuser
|
||||
to comment on an access method.
|
||||
Of course, a superuser can comment on anything.
|
||||
|
@ -119,8 +119,8 @@ in sync when changing the above synopsis!
|
||||
<listitem>
|
||||
<para>
|
||||
These clauses determine whether a role will be permitted to
|
||||
create, alter, drop, comment on, change the security label for,
|
||||
and grant or revoke membership in other roles.
|
||||
create, alter, drop, comment on, and change the security label for
|
||||
other roles.
|
||||
See <xref linkend='role-creation' /> for more details about what
|
||||
capabilities are conferred by this privilege.
|
||||
If not specified, <literal>NOCREATEROLE</literal> is the default.
|
||||
|
@ -252,8 +252,7 @@ PostgreSQL documentation
|
||||
<listitem>
|
||||
<para>
|
||||
The new user will be allowed to create, alter, drop, comment on,
|
||||
change the security label for, and grant or revoke membership in
|
||||
other roles; that is,
|
||||
change the security label for other roles; that is,
|
||||
this user will have <literal>CREATEROLE</literal> privilege.
|
||||
See <xref linkend='role-creation' /> for more details about what
|
||||
capabilities are conferred by this privilege.
|
||||
|
@ -32,7 +32,7 @@ DROP ROLE [ IF EXISTS ] <replaceable class="parameter">name</replaceable> [, ...
|
||||
<command>DROP ROLE</command> removes the specified role(s).
|
||||
To drop a superuser role, you must be a superuser yourself;
|
||||
to drop non-superuser roles, you must have <literal>CREATEROLE</literal>
|
||||
privilege.
|
||||
privilege and have been granted <literal>ADMIN OPTION</literal> on the role.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -35,9 +35,10 @@ PostgreSQL documentation
|
||||
<para>
|
||||
<application>dropuser</application> removes an existing
|
||||
<productname>PostgreSQL</productname> user.
|
||||
Only superusers and users with the <literal>CREATEROLE</literal> privilege can
|
||||
remove <productname>PostgreSQL</productname> users. (To remove a
|
||||
superuser, you must yourself be a superuser.)
|
||||
Superusers can use this command to remove any role; otherwise, only
|
||||
non-superuser roles can be removed, and only by a user who possesses
|
||||
the <literal>CREATEROLE</literal> privilege and has been granted
|
||||
<literal>ADMIN OPTION</literal> on the target role.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -271,9 +271,7 @@ GRANT <replaceable class="parameter">role_name</replaceable> [, ...] TO <replace
|
||||
in the role as well. Without the admin option, ordinary users cannot
|
||||
do that. A role is not considered to hold <literal>WITH ADMIN
|
||||
OPTION</literal> on itself. Database superusers can grant or revoke
|
||||
membership in any role to anyone. Roles having
|
||||
<literal>CREATEROLE</literal> privilege can grant or revoke membership
|
||||
in any role that is not a superuser. This option defaults to
|
||||
membership in any role to anyone. This option defaults to
|
||||
<literal>FALSE</literal>.
|
||||
</para>
|
||||
|
||||
|
@ -199,7 +199,12 @@ CREATE USER <replaceable>name</replaceable>;
|
||||
checks). To create such a role, use <literal>CREATE ROLE
|
||||
<replaceable>name</replaceable> CREATEROLE</literal>.
|
||||
A role with <literal>CREATEROLE</literal> privilege can alter and drop
|
||||
other roles, too, as well as grant or revoke membership in them.
|
||||
roles which have been granted to the <literal>CREATEROLE</literal>
|
||||
user with the <literal>ADMIN</literal> option. Such a grant occurs
|
||||
automatically when a <literal>CREATEROLE</literal> user that is not
|
||||
a superuser creates a new role, so that by default, a
|
||||
<literal>CREATEROLE</literal> user can alter and drop the roles
|
||||
which they have created.
|
||||
Altering a role includes most changes that can be made using
|
||||
<literal>ALTER ROLE</literal>, including, for example, changing
|
||||
passwords. It also includes modifications to a role that can
|
||||
@ -224,15 +229,6 @@ CREATE USER <replaceable>name</replaceable>;
|
||||
confer the ability to grant or revoke the <literal>BYPASSRLS</literal>
|
||||
privilege.
|
||||
</para>
|
||||
<para>
|
||||
Because the <literal>CREATEROLE</literal> privilege allows a user
|
||||
to grant or revoke membership even in roles to which it does not (yet)
|
||||
have any access, a <literal>CREATEROLE</literal> user can obtain access
|
||||
to the capabilities of every predefined role in the system, including
|
||||
highly privileged roles such as
|
||||
<literal>pg_execute_server_program</literal> and
|
||||
<literal>pg_write_server_files</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -329,6 +325,34 @@ ALTER ROLE myname SET enable_indexscan TO off;
|
||||
<literal>LOGIN</literal> privilege are fairly useless, since they will never
|
||||
be invoked.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When a non-superuser creates a role using the <literal>CREATEROLE</literal>
|
||||
privilege, the created role is automatically granted back to the creating
|
||||
user, just as if the bootstrap superuser had executed the command
|
||||
<literal>GRANT created_user TO creating_user WITH ADMIN TRUE, SET FALSE,
|
||||
INHERIT FALSE</literal>. Since a <literal>CREATEROLE</literal> user can
|
||||
only exercise special privileges with regard to an existing role if they
|
||||
have <literal>ADMIN OPTION</literal> on it, this grant is just sufficient
|
||||
to allow a <literal>CREATEROLE</literal> user to administer the roles they
|
||||
created. However, because it is created with <literal>INHERIT FALSE, SET
|
||||
FALSE</literal>, the <literal>CREATEROLE</literal> user doesn't inherit the
|
||||
privileges of the created role, nor can it access the privileges of that
|
||||
role using <literal>SET ROLE</literal>. However, since any user who has
|
||||
<literal>ADMIN OPTION</literal> on a role can grant membership in that
|
||||
role to any other user, the <literal>CREATEROLE</literal> user can gain
|
||||
access to the created role by simplying granting that role back to
|
||||
themselves with the <literal>INHERIT</literal> and/or <literal>SET</literal>
|
||||
options. Thus, the fact that privileges are not inherited by default nor
|
||||
is <literal>SET ROLE</literal> granted by default is a safeguard against
|
||||
accidents, not a security feature. Also note that, because this automatic
|
||||
grant is granted by the bootstrap user, it cannot be removed or changed by
|
||||
the <literal>CREATEROLE</literal> user; however, any superuser could
|
||||
revoke it, modify it, and/or issue additional such grants to other
|
||||
<literal>CREATEROLE</literal> users. Whichever <literal>CREATEROLE</literal>
|
||||
users have <literal>ADMIN OPTION</literal> on a role at any given time
|
||||
can administer it.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="role-membership">
|
||||
|
@ -2538,7 +2538,9 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
|
||||
|
||||
/*
|
||||
* We treat roles as being "owned" by those with CREATEROLE priv,
|
||||
* except that superusers are only owned by superusers.
|
||||
* provided that they also have admin option on the role.
|
||||
*
|
||||
* However, superusers are only owned by superusers.
|
||||
*/
|
||||
if (superuser_arg(address.objectId))
|
||||
{
|
||||
@ -2553,6 +2555,12 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must have CREATEROLE privilege")));
|
||||
if (!is_admin_of_role(roleid, address.objectId))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must have admin option on role \"%s\"",
|
||||
GetUserNameFromId(address.objectId,
|
||||
true))));
|
||||
}
|
||||
break;
|
||||
case OBJECT_TSPARSER:
|
||||
|
@ -519,6 +519,42 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the current user isn't a superuser, make them an admin of the new
|
||||
* role so that they can administer the new object they just created.
|
||||
* Superusers will be able to do that anyway.
|
||||
*
|
||||
* The grantor of record for this implicit grant is the bootstrap
|
||||
* superuser, which means that the CREATEROLE user cannot revoke the
|
||||
* grant. They can however grant the created role back to themselves
|
||||
* with different options, since they enjoy ADMIN OPTION on it.
|
||||
*/
|
||||
if (!superuser())
|
||||
{
|
||||
RoleSpec *current_role = makeNode(RoleSpec);
|
||||
GrantRoleOptions poptself;
|
||||
|
||||
current_role->roletype = ROLESPEC_CURRENT_ROLE;
|
||||
current_role->location = -1;
|
||||
|
||||
poptself.specified = GRANT_ROLE_SPECIFIED_ADMIN
|
||||
| GRANT_ROLE_SPECIFIED_INHERIT
|
||||
| GRANT_ROLE_SPECIFIED_SET;
|
||||
poptself.admin = true;
|
||||
poptself.inherit = false;
|
||||
poptself.set = false;
|
||||
|
||||
AddRoleMems(BOOTSTRAP_SUPERUSERID, stmt->role, roleid,
|
||||
list_make1(current_role), list_make1_oid(GetUserId()),
|
||||
BOOTSTRAP_SUPERUSERID, &poptself);
|
||||
|
||||
/*
|
||||
* We must make the implicit grant visible to the code below, else
|
||||
* the additional grants will fail.
|
||||
*/
|
||||
CommandCounterIncrement();
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the specified members to this new role. adminmembers get the admin
|
||||
* option, rolemembers don't.
|
||||
@ -694,9 +730,7 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
|
||||
/*
|
||||
* To mess with a superuser or replication role in any way you gotta be
|
||||
* superuser. We also insist on superuser to change the BYPASSRLS
|
||||
* property. Otherwise, if you don't have createrole, you're only allowed
|
||||
* to (1) change your own password or (2) add members to a role for which
|
||||
* you have ADMIN OPTION.
|
||||
* property.
|
||||
*/
|
||||
if (authform->rolsuper || dissuper)
|
||||
{
|
||||
@ -719,29 +753,35 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to change bypassrls attribute")));
|
||||
}
|
||||
else if (!have_createrole_privilege())
|
||||
|
||||
/*
|
||||
* Most changes to a role require that you both have CREATEROLE privileges
|
||||
* and also ADMIN OPTION on the role.
|
||||
*/
|
||||
if (!have_createrole_privilege() ||
|
||||
!is_admin_of_role(GetUserId(), roleid))
|
||||
{
|
||||
/* things you certainly can't do without CREATEROLE */
|
||||
/* things an unprivileged user certainly can't do */
|
||||
if (dinherit || dcreaterole || dcreatedb || dcanlogin || dconnlimit ||
|
||||
dvalidUntil)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
/* without CREATEROLE, can only change your own password */
|
||||
/* 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")));
|
||||
|
||||
/* without CREATEROLE, can only add members to roles you admin */
|
||||
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)));
|
||||
}
|
||||
|
||||
/* 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)));
|
||||
|
||||
/* Convert validuntil to internal form */
|
||||
if (dvalidUntil)
|
||||
{
|
||||
@ -935,8 +975,9 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
|
||||
shdepLockAndCheckObject(AuthIdRelationId, roleid);
|
||||
|
||||
/*
|
||||
* To mess with a superuser you gotta be superuser; else you need
|
||||
* createrole, or just want to change your own settings
|
||||
* To mess with a superuser you gotta be superuser; otherwise you
|
||||
* need CREATEROLE plus admin option on the target role; unless you're
|
||||
* just trying to change your own settings
|
||||
*/
|
||||
if (roleform->rolsuper)
|
||||
{
|
||||
@ -947,7 +988,9 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!have_createrole_privilege() && roleid != GetUserId())
|
||||
if ((!have_createrole_privilege() ||
|
||||
!is_admin_of_role(GetUserId(), roleid))
|
||||
&& roleid != GetUserId())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
@ -1067,13 +1110,18 @@ DropRole(DropRoleStmt *stmt)
|
||||
|
||||
/*
|
||||
* For safety's sake, we allow createrole holders to drop ordinary
|
||||
* roles but not superuser roles. This is mainly to avoid the
|
||||
* scenario where you accidentally drop the last superuser.
|
||||
* roles but not superuser roles, and only if they also have ADMIN
|
||||
* OPTION.
|
||||
*/
|
||||
if (roleform->rolsuper && !superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to drop superusers")));
|
||||
if (!is_admin_of_role(GetUserId(), roleid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must have admin option on role \"%s\"",
|
||||
role)));
|
||||
|
||||
/* DROP hook for the role being removed */
|
||||
InvokeObjectDropHook(AuthIdRelationId, roleid, 0);
|
||||
@ -1312,7 +1360,8 @@ RenameRole(const char *oldname, const char *newname)
|
||||
errmsg("role \"%s\" already exists", newname)));
|
||||
|
||||
/*
|
||||
* createrole is enough privilege unless you want to mess with a superuser
|
||||
* 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)
|
||||
{
|
||||
@ -1323,7 +1372,8 @@ RenameRole(const char *oldname, const char *newname)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!have_createrole_privilege())
|
||||
if (!have_createrole_privilege() ||
|
||||
!is_admin_of_role(GetUserId(), roleid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied to rename role")));
|
||||
@ -2023,11 +2073,9 @@ check_role_membership_authorization(Oid currentUserId, Oid roleid,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Otherwise, must have createrole or admin option on the role to be
|
||||
* changed.
|
||||
* Otherwise, must have admin option on the role to be changed.
|
||||
*/
|
||||
if (!has_createrole_privilege(currentUserId) &&
|
||||
!is_admin_of_role(currentUserId, roleid))
|
||||
if (!is_admin_of_role(currentUserId, roleid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must have admin option on role \"%s\"",
|
||||
@ -2049,7 +2097,7 @@ check_role_membership_authorization(Oid currentUserId, Oid roleid,
|
||||
* be passed as InvalidOid, and this function will infer the user to be
|
||||
* recorded as the grantor. In many cases, this will be the current user, but
|
||||
* things get more complicated when the current user doesn't possess ADMIN
|
||||
* OPTION on the role but rather relies on having CREATEROLE privileges, or
|
||||
* OPTION on the role but rather relies on having SUPERUSER privileges, or
|
||||
* on inheriting the privileges of a role which does have ADMIN OPTION. See
|
||||
* below for details.
|
||||
*
|
||||
@ -2075,7 +2123,7 @@ check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId, bool is_grant)
|
||||
* not depend on any other existing grants, so always default to this
|
||||
* interpretation when possible.
|
||||
*/
|
||||
if (has_createrole_privilege(currentUserId))
|
||||
if (superuser_arg(currentUserId))
|
||||
return BOOTSTRAP_SUPERUSERID;
|
||||
|
||||
/*
|
||||
|
@ -6,9 +6,11 @@ CREATE EXTENSION dummy_seclabel;
|
||||
SET client_min_messages TO 'warning';
|
||||
DROP ROLE IF EXISTS regress_dummy_seclabel_user1;
|
||||
DROP ROLE IF EXISTS regress_dummy_seclabel_user2;
|
||||
DROP ROLE IF EXISTS regress_dummy_seclabel_user3;
|
||||
RESET client_min_messages;
|
||||
CREATE USER regress_dummy_seclabel_user1 WITH CREATEROLE;
|
||||
CREATE USER regress_dummy_seclabel_user2;
|
||||
CREATE USER regress_dummy_seclabel_user3;
|
||||
CREATE TABLE dummy_seclabel_tbl1 (a int, b text);
|
||||
CREATE TABLE dummy_seclabel_tbl2 (x int, y text);
|
||||
CREATE VIEW dummy_seclabel_view1 AS SELECT * FROM dummy_seclabel_tbl2;
|
||||
@ -16,6 +18,8 @@ CREATE FUNCTION dummy_seclabel_four() RETURNS integer AS $$SELECT 4$$ language s
|
||||
CREATE DOMAIN dummy_seclabel_domain AS text;
|
||||
ALTER TABLE dummy_seclabel_tbl1 OWNER TO regress_dummy_seclabel_user1;
|
||||
ALTER TABLE dummy_seclabel_tbl2 OWNER TO regress_dummy_seclabel_user2;
|
||||
GRANT regress_dummy_seclabel_user2, regress_dummy_seclabel_user3
|
||||
TO regress_dummy_seclabel_user1 WITH ADMIN TRUE, INHERIT FALSE, SET FALSE;
|
||||
--
|
||||
-- Test of SECURITY LABEL statement with a plugin
|
||||
--
|
||||
@ -43,16 +47,16 @@ SECURITY LABEL ON TABLE dummy_seclabel_tbl2 IS 'classified'; -- OK
|
||||
-- Test for shared database object
|
||||
--
|
||||
SET SESSION AUTHORIZATION regress_dummy_seclabel_user1;
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user1 IS 'classified'; -- OK
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user1 IS '...invalid label...'; -- fail
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user3 IS 'classified'; -- OK
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user3 IS '...invalid label...'; -- fail
|
||||
ERROR: '...invalid label...' is not a valid security label
|
||||
SECURITY LABEL FOR 'dummy' ON ROLE regress_dummy_seclabel_user2 IS 'unclassified'; -- OK
|
||||
SECURITY LABEL FOR 'unknown_seclabel' ON ROLE regress_dummy_seclabel_user1 IS 'unclassified'; -- fail
|
||||
ERROR: security label provider "unknown_seclabel" is not loaded
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user1 IS 'secret'; -- fail (not superuser)
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user3 IS 'secret'; -- fail (not superuser)
|
||||
ERROR: only superuser can set 'secret' label
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user3 IS 'unclassified'; -- fail (not found)
|
||||
ERROR: role "regress_dummy_seclabel_user3" does not exist
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user4 IS 'unclassified'; -- fail (not found)
|
||||
ERROR: role "regress_dummy_seclabel_user4" does not exist
|
||||
SET SESSION AUTHORIZATION regress_dummy_seclabel_user2;
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user2 IS 'unclassified'; -- fail (not privileged)
|
||||
ERROR: must have CREATEROLE privilege
|
||||
@ -81,8 +85,8 @@ SELECT objtype, objname, provider, label FROM pg_seclabels
|
||||
domain | dummy_seclabel_domain | dummy | classified
|
||||
function | dummy_seclabel_four() | dummy | classified
|
||||
publication | dummy_pub | dummy | classified
|
||||
role | regress_dummy_seclabel_user1 | dummy | classified
|
||||
role | regress_dummy_seclabel_user2 | dummy | unclassified
|
||||
role | regress_dummy_seclabel_user3 | dummy | classified
|
||||
schema | dummy_seclabel_test | dummy | unclassified
|
||||
subscription | dummy_sub | dummy | classified
|
||||
table | dummy_seclabel_tbl1 | dummy | top secret
|
||||
@ -115,3 +119,4 @@ DROP SUBSCRIPTION dummy_sub;
|
||||
DROP PUBLICATION dummy_pub;
|
||||
DROP ROLE regress_dummy_seclabel_user1;
|
||||
DROP ROLE regress_dummy_seclabel_user2;
|
||||
DROP ROLE regress_dummy_seclabel_user3;
|
||||
|
@ -8,11 +8,13 @@ SET client_min_messages TO 'warning';
|
||||
|
||||
DROP ROLE IF EXISTS regress_dummy_seclabel_user1;
|
||||
DROP ROLE IF EXISTS regress_dummy_seclabel_user2;
|
||||
DROP ROLE IF EXISTS regress_dummy_seclabel_user3;
|
||||
|
||||
RESET client_min_messages;
|
||||
|
||||
CREATE USER regress_dummy_seclabel_user1 WITH CREATEROLE;
|
||||
CREATE USER regress_dummy_seclabel_user2;
|
||||
CREATE USER regress_dummy_seclabel_user3;
|
||||
|
||||
CREATE TABLE dummy_seclabel_tbl1 (a int, b text);
|
||||
CREATE TABLE dummy_seclabel_tbl2 (x int, y text);
|
||||
@ -22,6 +24,8 @@ CREATE DOMAIN dummy_seclabel_domain AS text;
|
||||
|
||||
ALTER TABLE dummy_seclabel_tbl1 OWNER TO regress_dummy_seclabel_user1;
|
||||
ALTER TABLE dummy_seclabel_tbl2 OWNER TO regress_dummy_seclabel_user2;
|
||||
GRANT regress_dummy_seclabel_user2, regress_dummy_seclabel_user3
|
||||
TO regress_dummy_seclabel_user1 WITH ADMIN TRUE, INHERIT FALSE, SET FALSE;
|
||||
|
||||
--
|
||||
-- Test of SECURITY LABEL statement with a plugin
|
||||
@ -47,12 +51,12 @@ SECURITY LABEL ON TABLE dummy_seclabel_tbl2 IS 'classified'; -- OK
|
||||
--
|
||||
SET SESSION AUTHORIZATION regress_dummy_seclabel_user1;
|
||||
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user1 IS 'classified'; -- OK
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user1 IS '...invalid label...'; -- fail
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user3 IS 'classified'; -- OK
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user3 IS '...invalid label...'; -- fail
|
||||
SECURITY LABEL FOR 'dummy' ON ROLE regress_dummy_seclabel_user2 IS 'unclassified'; -- OK
|
||||
SECURITY LABEL FOR 'unknown_seclabel' ON ROLE regress_dummy_seclabel_user1 IS 'unclassified'; -- fail
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user1 IS 'secret'; -- fail (not superuser)
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user3 IS 'unclassified'; -- fail (not found)
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user3 IS 'secret'; -- fail (not superuser)
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user4 IS 'unclassified'; -- fail (not found)
|
||||
|
||||
SET SESSION AUTHORIZATION regress_dummy_seclabel_user2;
|
||||
SECURITY LABEL ON ROLE regress_dummy_seclabel_user2 IS 'unclassified'; -- fail (not privileged)
|
||||
@ -113,3 +117,4 @@ DROP PUBLICATION dummy_pub;
|
||||
|
||||
DROP ROLE regress_dummy_seclabel_user1;
|
||||
DROP ROLE regress_dummy_seclabel_user2;
|
||||
DROP ROLE regress_dummy_seclabel_user3;
|
||||
|
@ -1,6 +1,7 @@
|
||||
-- ok, superuser can create users with any set of privileges
|
||||
CREATE ROLE regress_role_super SUPERUSER;
|
||||
CREATE ROLE regress_role_admin CREATEDB CREATEROLE REPLICATION BYPASSRLS;
|
||||
CREATE ROLE regress_role_normal;
|
||||
-- fail, only superusers can create users with these privileges
|
||||
SET SESSION AUTHORIZATION regress_role_admin;
|
||||
CREATE ROLE regress_nosuch_superuser SUPERUSER;
|
||||
@ -13,7 +14,7 @@ CREATE ROLE regress_nosuch_bypassrls BYPASSRLS;
|
||||
ERROR: must be superuser to create bypassrls users
|
||||
-- ok, having CREATEROLE is enough to create users with these privileges
|
||||
CREATE ROLE regress_createdb CREATEDB;
|
||||
CREATE ROLE regress_createrole CREATEROLE;
|
||||
CREATE ROLE regress_createrole CREATEROLE NOINHERIT;
|
||||
CREATE ROLE regress_login LOGIN;
|
||||
CREATE ROLE regress_inherit INHERIT;
|
||||
CREATE ROLE regress_connection_limit CONNECTION LIMIT 5;
|
||||
@ -51,7 +52,19 @@ CREATE ROLE regress_plainrole;
|
||||
-- ok, roles with CREATEROLE can create new roles with it
|
||||
CREATE ROLE regress_rolecreator CREATEROLE;
|
||||
-- ok, roles with CREATEROLE can create new roles with privilege they lack
|
||||
CREATE ROLE regress_tenant CREATEDB CREATEROLE LOGIN INHERIT CONNECTION LIMIT 5;
|
||||
CREATE ROLE regress_hasprivs CREATEDB CREATEROLE LOGIN INHERIT
|
||||
CONNECTION LIMIT 5;
|
||||
-- ok, we should be able to modify a role we created
|
||||
COMMENT ON ROLE regress_hasprivs IS 'some comment';
|
||||
ALTER ROLE regress_hasprivs RENAME TO regress_tenant;
|
||||
ALTER ROLE regress_tenant NOINHERIT NOLOGIN CONNECTION LIMIT 7;
|
||||
-- fail, we should be unable to modify a role we did not create
|
||||
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
|
||||
ALTER ROLE regress_role_normal NOINHERIT NOLOGIN CONNECTION LIMIT 7;
|
||||
ERROR: permission denied
|
||||
-- ok, regress_tenant can create objects within the database
|
||||
SET SESSION AUTHORIZATION regress_tenant;
|
||||
CREATE TABLE tenant_table (i integer);
|
||||
@ -70,20 +83,35 @@ ALTER VIEW tenant_view OWNER TO regress_role_admin;
|
||||
ERROR: must be owner of view tenant_view
|
||||
DROP VIEW tenant_view;
|
||||
ERROR: must be owner of view tenant_view
|
||||
-- fail, cannot take ownership of these objects from 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
|
||||
-- ok, having CREATEROLE is enough to create roles in privileged roles
|
||||
-- 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"
|
||||
CREATE ROLE regress_write_all_data IN ROLE pg_write_all_data;
|
||||
ERROR: 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"
|
||||
CREATE ROLE regress_read_all_settings IN ROLE pg_read_all_settings;
|
||||
ERROR: 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"
|
||||
CREATE ROLE regress_stat_scan_tables IN ROLE pg_stat_scan_tables;
|
||||
ERROR: 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"
|
||||
CREATE ROLE regress_write_server_files IN ROLE pg_write_server_files;
|
||||
ERROR: 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"
|
||||
CREATE ROLE regress_signal_backend IN ROLE pg_signal_backend;
|
||||
ERROR: 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
|
||||
DETAIL: owner of table tenant_table
|
||||
owner of view tenant_view
|
||||
-- fail, creation of these roles failed above so they do not now exist
|
||||
SET SESSION AUTHORIZATION regress_role_admin;
|
||||
DROP ROLE regress_nosuch_superuser;
|
||||
@ -114,22 +142,6 @@ DROP ROLE regress_password_null;
|
||||
DROP ROLE regress_noiseword;
|
||||
DROP ROLE regress_inroles;
|
||||
DROP ROLE regress_adminroles;
|
||||
DROP ROLE regress_rolecreator;
|
||||
DROP ROLE regress_read_all_data;
|
||||
DROP ROLE regress_write_all_data;
|
||||
DROP ROLE regress_monitor;
|
||||
DROP ROLE regress_read_all_settings;
|
||||
DROP ROLE regress_read_all_stats;
|
||||
DROP ROLE regress_stat_scan_tables;
|
||||
DROP ROLE regress_read_server_files;
|
||||
DROP ROLE regress_write_server_files;
|
||||
DROP ROLE regress_execute_server_program;
|
||||
DROP ROLE regress_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
|
||||
DETAIL: owner of table tenant_table
|
||||
owner of view tenant_view
|
||||
-- fail, cannot drop ourself nor superusers
|
||||
DROP ROLE regress_role_super;
|
||||
ERROR: must be superuser to drop superusers
|
||||
@ -143,3 +155,4 @@ DROP VIEW tenant_view;
|
||||
DROP ROLE regress_tenant;
|
||||
DROP ROLE regress_role_admin;
|
||||
DROP ROLE regress_role_super;
|
||||
DROP ROLE regress_role_normal;
|
||||
|
@ -1,6 +1,7 @@
|
||||
-- ok, superuser can create users with any set of privileges
|
||||
CREATE ROLE regress_role_super SUPERUSER;
|
||||
CREATE ROLE regress_role_admin CREATEDB CREATEROLE REPLICATION BYPASSRLS;
|
||||
CREATE ROLE regress_role_normal;
|
||||
|
||||
-- fail, only superusers can create users with these privileges
|
||||
SET SESSION AUTHORIZATION regress_role_admin;
|
||||
@ -11,7 +12,7 @@ CREATE ROLE regress_nosuch_bypassrls BYPASSRLS;
|
||||
|
||||
-- ok, having CREATEROLE is enough to create users with these privileges
|
||||
CREATE ROLE regress_createdb CREATEDB;
|
||||
CREATE ROLE regress_createrole CREATEROLE;
|
||||
CREATE ROLE regress_createrole CREATEROLE NOINHERIT;
|
||||
CREATE ROLE regress_login LOGIN;
|
||||
CREATE ROLE regress_inherit INHERIT;
|
||||
CREATE ROLE regress_connection_limit CONNECTION LIMIT 5;
|
||||
@ -54,7 +55,18 @@ CREATE ROLE regress_plainrole;
|
||||
CREATE ROLE regress_rolecreator CREATEROLE;
|
||||
|
||||
-- ok, roles with CREATEROLE can create new roles with privilege they lack
|
||||
CREATE ROLE regress_tenant CREATEDB CREATEROLE LOGIN INHERIT CONNECTION LIMIT 5;
|
||||
CREATE ROLE regress_hasprivs CREATEDB CREATEROLE LOGIN INHERIT
|
||||
CONNECTION LIMIT 5;
|
||||
|
||||
-- ok, we should be able to modify a role we created
|
||||
COMMENT ON ROLE regress_hasprivs IS 'some comment';
|
||||
ALTER ROLE regress_hasprivs RENAME TO regress_tenant;
|
||||
ALTER ROLE regress_tenant NOINHERIT NOLOGIN CONNECTION LIMIT 7;
|
||||
|
||||
-- fail, we should be unable to modify a role we did not create
|
||||
COMMENT ON ROLE regress_role_normal IS 'some comment';
|
||||
ALTER ROLE regress_role_normal RENAME TO regress_role_abnormal;
|
||||
ALTER ROLE regress_role_normal NOINHERIT NOLOGIN CONNECTION LIMIT 7;
|
||||
|
||||
-- ok, regress_tenant can create objects within the database
|
||||
SET SESSION AUTHORIZATION regress_tenant;
|
||||
@ -71,10 +83,10 @@ DROP TABLE tenant_table;
|
||||
ALTER VIEW tenant_view OWNER TO regress_role_admin;
|
||||
DROP VIEW tenant_view;
|
||||
|
||||
-- fail, cannot take ownership of these objects from regress_tenant
|
||||
-- fail, we don't inherit permissions from regress_tenant
|
||||
REASSIGN OWNED BY regress_tenant TO regress_createrole;
|
||||
|
||||
-- ok, having CREATEROLE is enough to create roles in privileged roles
|
||||
-- fail, CREATEROLE is not enough to create roles in privileged roles
|
||||
CREATE ROLE regress_read_all_data IN ROLE pg_read_all_data;
|
||||
CREATE ROLE regress_write_all_data IN ROLE pg_write_all_data;
|
||||
CREATE ROLE regress_monitor IN ROLE pg_monitor;
|
||||
@ -86,6 +98,9 @@ CREATE ROLE regress_write_server_files IN ROLE pg_write_server_files;
|
||||
CREATE ROLE regress_execute_server_program IN ROLE pg_execute_server_program;
|
||||
CREATE ROLE regress_signal_backend IN ROLE pg_signal_backend;
|
||||
|
||||
-- fail, role still owns database objects
|
||||
DROP ROLE regress_tenant;
|
||||
|
||||
-- fail, creation of these roles failed above so they do not now exist
|
||||
SET SESSION AUTHORIZATION regress_role_admin;
|
||||
DROP ROLE regress_nosuch_superuser;
|
||||
@ -109,20 +124,6 @@ DROP ROLE regress_password_null;
|
||||
DROP ROLE regress_noiseword;
|
||||
DROP ROLE regress_inroles;
|
||||
DROP ROLE regress_adminroles;
|
||||
DROP ROLE regress_rolecreator;
|
||||
DROP ROLE regress_read_all_data;
|
||||
DROP ROLE regress_write_all_data;
|
||||
DROP ROLE regress_monitor;
|
||||
DROP ROLE regress_read_all_settings;
|
||||
DROP ROLE regress_read_all_stats;
|
||||
DROP ROLE regress_stat_scan_tables;
|
||||
DROP ROLE regress_read_server_files;
|
||||
DROP ROLE regress_write_server_files;
|
||||
DROP ROLE regress_execute_server_program;
|
||||
DROP ROLE regress_signal_backend;
|
||||
|
||||
-- fail, role still owns database objects
|
||||
DROP ROLE regress_tenant;
|
||||
|
||||
-- fail, cannot drop ourself nor superusers
|
||||
DROP ROLE regress_role_super;
|
||||
@ -136,3 +137,4 @@ DROP VIEW tenant_view;
|
||||
DROP ROLE regress_tenant;
|
||||
DROP ROLE regress_role_admin;
|
||||
DROP ROLE regress_role_super;
|
||||
DROP ROLE regress_role_normal;
|
||||
|
Loading…
Reference in New Issue
Block a user