mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-02 21:46:54 +02:00
Add new GUC createrole_self_grant.
Can be set to the empty string, or to either or both of "set" or "inherit". If set to a non-empty value, a non-superuser who creates a role (necessarily by relying up the CREATEROLE privilege) will grant that role back to themselves with the specified options. This isn't a security feature, because the grant that this feature triggers can also be performed explicitly. Instead, it's a user experience feature. A superuser would necessarily inherit the privileges of any created role and be able to access all such roles via SET ROLE; with this patch, you can configure createrole_self_grant = 'set, inherit' to provide a similar experience for a user who has CREATEROLE but not SUPERUSER. Discussion: https://postgr.es/m/CA+TgmobN59ct+Emmz6ig1Nua2Q-_o=r6DSD98KfU53kctq_kQw@mail.gmail.com
This commit is contained in:
parent
cf5eb37c5e
commit
e5b8a4c098
@ -9447,6 +9447,39 @@ SET XML OPTION { DOCUMENT | CONTENT };
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="guc-createrole-self-grant" xreflabel="createrole_self_grant">
|
||||||
|
<term><varname>createrole_self_grant</varname> (<type>string</type>)
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>createrole_self_grant</varname></primary>
|
||||||
|
<secondary>configuration parameter</secondary>
|
||||||
|
</indexterm>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If a user who has <literal>CREATEROLE</literal> but not
|
||||||
|
<literal>SUPERUSER</literal> creates a role, and if this
|
||||||
|
is set to a non-empty value, the newly-created role will be granted
|
||||||
|
to the creating user with the options specified. The value must be
|
||||||
|
<literal>set</literal>, <literal>inherit</literal>, or a
|
||||||
|
comma-separated list of these.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The purpose of this option is to allow a <literal>CREATEROLE</literal>
|
||||||
|
user who is not a superuser to automatically inherit, or automatically
|
||||||
|
gain the ability to <literal>SET ROLE</literal> to, any created users.
|
||||||
|
Since a <literal>CREATEROLE</literal> user is always implicitly granted
|
||||||
|
<literal>ADMIN OPTION</literal> on created roles, that user could
|
||||||
|
always execute a <literal>GRANT</literal> statement that would achieve
|
||||||
|
the same effect as this setting. However, it can be convenient for
|
||||||
|
usability reasons if the grant happens automatically. A superuser
|
||||||
|
automatically inherits the privileges of every role and can always
|
||||||
|
<literal>SET ROLE</literal> to any role, and this setting can be used
|
||||||
|
to produce a similar behavior for <literal>CREATEROLE</literal> users
|
||||||
|
for users which they create.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</sect2>
|
</sect2>
|
||||||
<sect2 id="runtime-config-client-format">
|
<sect2 id="runtime-config-client-format">
|
||||||
|
@ -506,6 +506,7 @@ CREATE ROLE <replaceable class="parameter">name</replaceable> [ WITH ADMIN <repl
|
|||||||
<member><xref linkend="sql-grant"/></member>
|
<member><xref linkend="sql-grant"/></member>
|
||||||
<member><xref linkend="sql-revoke"/></member>
|
<member><xref linkend="sql-revoke"/></member>
|
||||||
<member><xref linkend="app-createuser"/></member>
|
<member><xref linkend="app-createuser"/></member>
|
||||||
|
<member><xref linkend="guc-createrole-self-grant"/></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
@ -555,6 +555,7 @@ PostgreSQL documentation
|
|||||||
<simplelist type="inline">
|
<simplelist type="inline">
|
||||||
<member><xref linkend="app-dropuser"/></member>
|
<member><xref linkend="app-dropuser"/></member>
|
||||||
<member><xref linkend="sql-createrole"/></member>
|
<member><xref linkend="sql-createrole"/></member>
|
||||||
|
<member><xref linkend="guc-createrole-self-grant"/></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
#include "utils/timestamp.h"
|
#include "utils/timestamp.h"
|
||||||
|
#include "utils/varlena.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Removing a role grant - or the admin option on it - might recurse to
|
* Removing a role grant - or the admin option on it - might recurse to
|
||||||
@ -81,8 +82,11 @@ typedef struct
|
|||||||
#define GRANT_ROLE_SPECIFIED_INHERIT 0x0002
|
#define GRANT_ROLE_SPECIFIED_INHERIT 0x0002
|
||||||
#define GRANT_ROLE_SPECIFIED_SET 0x0004
|
#define GRANT_ROLE_SPECIFIED_SET 0x0004
|
||||||
|
|
||||||
/* GUC parameter */
|
/* GUC parameters */
|
||||||
int Password_encryption = PASSWORD_TYPE_SCRAM_SHA_256;
|
int Password_encryption = PASSWORD_TYPE_SCRAM_SHA_256;
|
||||||
|
char *createrole_self_grant = "";
|
||||||
|
bool createrole_self_grant_enabled = false;
|
||||||
|
GrantRoleOptions createrole_self_grant_options;
|
||||||
|
|
||||||
/* Hook to check passwords in CreateRole() and AlterRole() */
|
/* Hook to check passwords in CreateRole() and AlterRole() */
|
||||||
check_password_hook_type check_password_hook = NULL;
|
check_password_hook_type check_password_hook = NULL;
|
||||||
@ -533,9 +537,12 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
|
|||||||
{
|
{
|
||||||
RoleSpec *current_role = makeNode(RoleSpec);
|
RoleSpec *current_role = makeNode(RoleSpec);
|
||||||
GrantRoleOptions poptself;
|
GrantRoleOptions poptself;
|
||||||
|
List *memberSpecs;
|
||||||
|
List *memberIds = list_make1_oid(currentUserId);
|
||||||
|
|
||||||
current_role->roletype = ROLESPEC_CURRENT_ROLE;
|
current_role->roletype = ROLESPEC_CURRENT_ROLE;
|
||||||
current_role->location = -1;
|
current_role->location = -1;
|
||||||
|
memberSpecs = list_make1(current_role);
|
||||||
|
|
||||||
poptself.specified = GRANT_ROLE_SPECIFIED_ADMIN
|
poptself.specified = GRANT_ROLE_SPECIFIED_ADMIN
|
||||||
| GRANT_ROLE_SPECIFIED_INHERIT
|
| GRANT_ROLE_SPECIFIED_INHERIT
|
||||||
@ -545,7 +552,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
|
|||||||
poptself.set = false;
|
poptself.set = false;
|
||||||
|
|
||||||
AddRoleMems(BOOTSTRAP_SUPERUSERID, stmt->role, roleid,
|
AddRoleMems(BOOTSTRAP_SUPERUSERID, stmt->role, roleid,
|
||||||
list_make1(current_role), list_make1_oid(GetUserId()),
|
memberSpecs, memberIds,
|
||||||
BOOTSTRAP_SUPERUSERID, &poptself);
|
BOOTSTRAP_SUPERUSERID, &poptself);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -553,6 +560,20 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
|
|||||||
* the additional grants will fail.
|
* the additional grants will fail.
|
||||||
*/
|
*/
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Because of the implicit grant above, a CREATEROLE user who creates
|
||||||
|
* a role has the ability to grant that role back to themselves with
|
||||||
|
* the INHERIT or SET options, if they wish to inherit the role's
|
||||||
|
* privileges or be able to SET ROLE to it. The createrole_self_grant
|
||||||
|
* GUC can be used to make this happen automatically. This has no
|
||||||
|
* security implications since the same user is able to make the same
|
||||||
|
* grant using an explicit GRANT statement; it's just convenient.
|
||||||
|
*/
|
||||||
|
if (createrole_self_grant_enabled)
|
||||||
|
AddRoleMems(currentUserId, stmt->role, roleid,
|
||||||
|
memberSpecs, memberIds,
|
||||||
|
currentUserId, &createrole_self_grant_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2414,3 +2435,73 @@ InitGrantRoleOptions(GrantRoleOptions *popt)
|
|||||||
popt->inherit = false;
|
popt->inherit = false;
|
||||||
popt->set = true;
|
popt->set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GUC check_hook for createrole_self_grant
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
check_createrole_self_grant(char **newval, void **extra, GucSource source)
|
||||||
|
{
|
||||||
|
char *rawstring;
|
||||||
|
List *elemlist;
|
||||||
|
ListCell *l;
|
||||||
|
unsigned options = 0;
|
||||||
|
unsigned *result;
|
||||||
|
|
||||||
|
/* Need a modifiable copy of string */
|
||||||
|
rawstring = pstrdup(*newval);
|
||||||
|
|
||||||
|
if (!SplitIdentifierString(rawstring, ',', &elemlist))
|
||||||
|
{
|
||||||
|
/* syntax error in list */
|
||||||
|
GUC_check_errdetail("List syntax is invalid.");
|
||||||
|
pfree(rawstring);
|
||||||
|
list_free(elemlist);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(l, elemlist)
|
||||||
|
{
|
||||||
|
char *tok = (char *) lfirst(l);
|
||||||
|
|
||||||
|
if (pg_strcasecmp(tok, "SET") == 0)
|
||||||
|
options |= GRANT_ROLE_SPECIFIED_SET;
|
||||||
|
else if (pg_strcasecmp(tok, "INHERIT") == 0)
|
||||||
|
options |= GRANT_ROLE_SPECIFIED_INHERIT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
|
||||||
|
pfree(rawstring);
|
||||||
|
list_free(elemlist);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pfree(rawstring);
|
||||||
|
list_free(elemlist);
|
||||||
|
|
||||||
|
result = (unsigned *) guc_malloc(LOG, sizeof(unsigned));
|
||||||
|
*result = options;
|
||||||
|
*extra = result;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GUC assign_hook for createrole_self_grant
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
assign_createrole_self_grant(const char *newval, void *extra)
|
||||||
|
{
|
||||||
|
unsigned options = * (unsigned *) extra;
|
||||||
|
|
||||||
|
createrole_self_grant_enabled = (options != 0);
|
||||||
|
createrole_self_grant_options.specified = GRANT_ROLE_SPECIFIED_ADMIN
|
||||||
|
| GRANT_ROLE_SPECIFIED_INHERIT
|
||||||
|
| GRANT_ROLE_SPECIFIED_SET;
|
||||||
|
createrole_self_grant_options.admin = false;
|
||||||
|
createrole_self_grant_options.inherit =
|
||||||
|
(options & GRANT_ROLE_SPECIFIED_INHERIT) != 0;
|
||||||
|
createrole_self_grant_options.set =
|
||||||
|
(options & GRANT_ROLE_SPECIFIED_SET) != 0;
|
||||||
|
}
|
||||||
|
@ -3949,6 +3949,18 @@ struct config_string ConfigureNamesString[] =
|
|||||||
check_temp_tablespaces, assign_temp_tablespaces, NULL
|
check_temp_tablespaces, assign_temp_tablespaces, NULL
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
{"createrole_self_grant", PGC_USERSET, CLIENT_CONN_STATEMENT,
|
||||||
|
gettext_noop("Sets whether a CREATEROLE user automatically grants "
|
||||||
|
"the role to themselves, and with which options."),
|
||||||
|
NULL,
|
||||||
|
GUC_LIST_INPUT
|
||||||
|
},
|
||||||
|
&createrole_self_grant,
|
||||||
|
"",
|
||||||
|
check_createrole_self_grant, assign_createrole_self_grant, NULL
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
{"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
|
{"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
|
||||||
gettext_noop("Sets the path for dynamically loadable modules."),
|
gettext_noop("Sets the path for dynamically loadable modules."),
|
||||||
|
@ -703,6 +703,7 @@
|
|||||||
#xmlbinary = 'base64'
|
#xmlbinary = 'base64'
|
||||||
#xmloption = 'content'
|
#xmloption = 'content'
|
||||||
#gin_pending_list_limit = 4MB
|
#gin_pending_list_limit = 4MB
|
||||||
|
#createrole_self_grant = '' # set and/or inherit
|
||||||
|
|
||||||
# - Locale and Formatting -
|
# - Locale and Formatting -
|
||||||
|
|
||||||
|
@ -15,9 +15,11 @@
|
|||||||
#include "libpq/crypt.h"
|
#include "libpq/crypt.h"
|
||||||
#include "nodes/parsenodes.h"
|
#include "nodes/parsenodes.h"
|
||||||
#include "parser/parse_node.h"
|
#include "parser/parse_node.h"
|
||||||
|
#include "utils/guc.h"
|
||||||
|
|
||||||
/* GUC. Is actually of type PasswordType. */
|
/* GUCs */
|
||||||
extern PGDLLIMPORT int Password_encryption;
|
extern PGDLLIMPORT int Password_encryption; /* values from enum PasswordType */
|
||||||
|
extern PGDLLIMPORT char *createrole_self_grant;
|
||||||
|
|
||||||
/* Hook to check passwords in CreateRole() and AlterRole() */
|
/* Hook to check passwords in CreateRole() and AlterRole() */
|
||||||
typedef void (*check_password_hook_type) (const char *username, const char *shadow_pass, PasswordType password_type, Datum validuntil_time, bool validuntil_null);
|
typedef void (*check_password_hook_type) (const char *username, const char *shadow_pass, PasswordType password_type, Datum validuntil_time, bool validuntil_null);
|
||||||
@ -34,4 +36,8 @@ extern void DropOwnedObjects(DropOwnedStmt *stmt);
|
|||||||
extern void ReassignOwnedObjects(ReassignOwnedStmt *stmt);
|
extern void ReassignOwnedObjects(ReassignOwnedStmt *stmt);
|
||||||
extern List *roleSpecsToIds(List *memberNames);
|
extern List *roleSpecsToIds(List *memberNames);
|
||||||
|
|
||||||
|
extern bool check_createrole_self_grant(char **newval, void **extra,
|
||||||
|
GucSource source);
|
||||||
|
extern void assign_createrole_self_grant(const char *newval, void *extra);
|
||||||
|
|
||||||
#endif /* USER_H */
|
#endif /* USER_H */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
-- ok, superuser can create users with any set of privileges
|
-- ok, superuser can create users with any set of privileges
|
||||||
CREATE ROLE regress_role_super SUPERUSER;
|
CREATE ROLE regress_role_super SUPERUSER;
|
||||||
CREATE ROLE regress_role_admin CREATEDB CREATEROLE REPLICATION BYPASSRLS;
|
CREATE ROLE regress_role_admin CREATEDB CREATEROLE REPLICATION BYPASSRLS;
|
||||||
|
GRANT CREATE ON DATABASE regression TO regress_role_admin WITH GRANT OPTION;
|
||||||
CREATE ROLE regress_role_normal;
|
CREATE ROLE regress_role_normal;
|
||||||
-- fail, only superusers can create users with these privileges
|
-- fail, only superusers can create users with these privileges
|
||||||
SET SESSION AUTHORIZATION regress_role_admin;
|
SET SESSION AUTHORIZATION regress_role_admin;
|
||||||
@ -15,6 +16,7 @@ ERROR: must be superuser to create bypassrls users
|
|||||||
-- ok, having CREATEROLE is enough to create users with these privileges
|
-- ok, having CREATEROLE is enough to create users with these privileges
|
||||||
CREATE ROLE regress_createdb CREATEDB;
|
CREATE ROLE regress_createdb CREATEDB;
|
||||||
CREATE ROLE regress_createrole CREATEROLE NOINHERIT;
|
CREATE ROLE regress_createrole CREATEROLE NOINHERIT;
|
||||||
|
GRANT CREATE ON DATABASE regression TO regress_createrole WITH GRANT OPTION;
|
||||||
CREATE ROLE regress_login LOGIN;
|
CREATE ROLE regress_login LOGIN;
|
||||||
CREATE ROLE regress_inherit INHERIT;
|
CREATE ROLE regress_inherit INHERIT;
|
||||||
CREATE ROLE regress_connection_limit CONNECTION LIMIT 5;
|
CREATE ROLE regress_connection_limit CONNECTION LIMIT 5;
|
||||||
@ -83,9 +85,37 @@ ALTER VIEW tenant_view OWNER TO regress_role_admin;
|
|||||||
ERROR: must be owner of view tenant_view
|
ERROR: must be owner of view tenant_view
|
||||||
DROP VIEW tenant_view;
|
DROP VIEW tenant_view;
|
||||||
ERROR: must be owner of view tenant_view
|
ERROR: must be owner of view tenant_view
|
||||||
|
-- fail, can't create objects owned as regress_tenant
|
||||||
|
CREATE SCHEMA regress_tenant_schema AUTHORIZATION regress_tenant;
|
||||||
|
ERROR: must be able to SET ROLE "regress_tenant"
|
||||||
-- fail, we don't inherit permissions from regress_tenant
|
-- fail, we don't inherit permissions from regress_tenant
|
||||||
REASSIGN OWNED BY regress_tenant TO regress_createrole;
|
REASSIGN OWNED BY regress_tenant TO regress_createrole;
|
||||||
ERROR: permission denied to reassign objects
|
ERROR: permission denied to reassign objects
|
||||||
|
-- ok, create a role with a value for createrole_self_grant
|
||||||
|
SET createrole_self_grant = 'set, inherit';
|
||||||
|
CREATE ROLE regress_tenant2;
|
||||||
|
GRANT CREATE ON DATABASE regression TO regress_tenant2;
|
||||||
|
-- ok, regress_tenant2 can create objects within the database
|
||||||
|
SET SESSION AUTHORIZATION regress_tenant2;
|
||||||
|
CREATE TABLE tenant2_table (i integer);
|
||||||
|
REVOKE ALL PRIVILEGES ON tenant2_table FROM PUBLIC;
|
||||||
|
-- ok, because we have SET and INHERIT on regress_tenant2
|
||||||
|
SET SESSION AUTHORIZATION regress_createrole;
|
||||||
|
CREATE SCHEMA regress_tenant2_schema AUTHORIZATION regress_tenant2;
|
||||||
|
ALTER SCHEMA regress_tenant2_schema OWNER TO regress_createrole;
|
||||||
|
ALTER TABLE tenant2_table OWNER TO regress_createrole;
|
||||||
|
ALTER TABLE tenant2_table OWNER TO regress_tenant2;
|
||||||
|
-- with SET but not INHERIT, we can give away objects but not take them
|
||||||
|
REVOKE INHERIT OPTION FOR regress_tenant2 FROM regress_createrole;
|
||||||
|
ALTER SCHEMA regress_tenant2_schema OWNER TO regress_tenant2;
|
||||||
|
ALTER TABLE tenant2_table OWNER TO regress_createrole;
|
||||||
|
ERROR: must be owner of table tenant2_table
|
||||||
|
-- with INHERIT but not SET, we can take objects but not give them away
|
||||||
|
GRANT regress_tenant2 TO regress_createrole WITH INHERIT TRUE, SET FALSE;
|
||||||
|
ALTER TABLE tenant2_table OWNER TO regress_createrole;
|
||||||
|
ALTER TABLE tenant2_table OWNER TO regress_tenant2;
|
||||||
|
ERROR: must be able to SET ROLE "regress_tenant2"
|
||||||
|
DROP TABLE tenant2_table;
|
||||||
-- fail, CREATEROLE is not 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_read_all_data IN ROLE pg_read_all_data;
|
||||||
ERROR: must have admin option on role "pg_read_all_data"
|
ERROR: must have admin option on role "pg_read_all_data"
|
||||||
@ -131,6 +161,8 @@ ERROR: role "regress_nosuch_recursive" does not exist
|
|||||||
DROP ROLE regress_nosuch_admin_recursive;
|
DROP ROLE regress_nosuch_admin_recursive;
|
||||||
ERROR: role "regress_nosuch_admin_recursive" does not exist
|
ERROR: role "regress_nosuch_admin_recursive" does not exist
|
||||||
DROP ROLE regress_plainrole;
|
DROP ROLE regress_plainrole;
|
||||||
|
-- must revoke privileges before dropping role
|
||||||
|
REVOKE CREATE ON DATABASE regression FROM regress_createrole CASCADE;
|
||||||
-- ok, should be able to drop non-superuser roles we created
|
-- ok, should be able to drop non-superuser roles we created
|
||||||
DROP ROLE regress_createdb;
|
DROP ROLE regress_createdb;
|
||||||
DROP ROLE regress_createrole;
|
DROP ROLE regress_createrole;
|
||||||
@ -149,6 +181,7 @@ DROP ROLE regress_role_admin;
|
|||||||
ERROR: current user cannot be dropped
|
ERROR: current user cannot be dropped
|
||||||
-- ok
|
-- ok
|
||||||
RESET SESSION AUTHORIZATION;
|
RESET SESSION AUTHORIZATION;
|
||||||
|
REVOKE CREATE ON DATABASE regression FROM regress_role_admin CASCADE;
|
||||||
DROP INDEX tenant_idx;
|
DROP INDEX tenant_idx;
|
||||||
DROP TABLE tenant_table;
|
DROP TABLE tenant_table;
|
||||||
DROP VIEW tenant_view;
|
DROP VIEW tenant_view;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
-- ok, superuser can create users with any set of privileges
|
-- ok, superuser can create users with any set of privileges
|
||||||
CREATE ROLE regress_role_super SUPERUSER;
|
CREATE ROLE regress_role_super SUPERUSER;
|
||||||
CREATE ROLE regress_role_admin CREATEDB CREATEROLE REPLICATION BYPASSRLS;
|
CREATE ROLE regress_role_admin CREATEDB CREATEROLE REPLICATION BYPASSRLS;
|
||||||
|
GRANT CREATE ON DATABASE regression TO regress_role_admin WITH GRANT OPTION;
|
||||||
CREATE ROLE regress_role_normal;
|
CREATE ROLE regress_role_normal;
|
||||||
|
|
||||||
-- fail, only superusers can create users with these privileges
|
-- fail, only superusers can create users with these privileges
|
||||||
@ -13,6 +14,7 @@ CREATE ROLE regress_nosuch_bypassrls BYPASSRLS;
|
|||||||
-- ok, having CREATEROLE is enough to create users with these privileges
|
-- ok, having CREATEROLE is enough to create users with these privileges
|
||||||
CREATE ROLE regress_createdb CREATEDB;
|
CREATE ROLE regress_createdb CREATEDB;
|
||||||
CREATE ROLE regress_createrole CREATEROLE NOINHERIT;
|
CREATE ROLE regress_createrole CREATEROLE NOINHERIT;
|
||||||
|
GRANT CREATE ON DATABASE regression TO regress_createrole WITH GRANT OPTION;
|
||||||
CREATE ROLE regress_login LOGIN;
|
CREATE ROLE regress_login LOGIN;
|
||||||
CREATE ROLE regress_inherit INHERIT;
|
CREATE ROLE regress_inherit INHERIT;
|
||||||
CREATE ROLE regress_connection_limit CONNECTION LIMIT 5;
|
CREATE ROLE regress_connection_limit CONNECTION LIMIT 5;
|
||||||
@ -83,9 +85,40 @@ DROP TABLE tenant_table;
|
|||||||
ALTER VIEW tenant_view OWNER TO regress_role_admin;
|
ALTER VIEW tenant_view OWNER TO regress_role_admin;
|
||||||
DROP VIEW tenant_view;
|
DROP VIEW tenant_view;
|
||||||
|
|
||||||
|
-- fail, can't create objects owned as regress_tenant
|
||||||
|
CREATE SCHEMA regress_tenant_schema AUTHORIZATION regress_tenant;
|
||||||
|
|
||||||
-- fail, we don't inherit permissions from regress_tenant
|
-- fail, we don't inherit permissions from regress_tenant
|
||||||
REASSIGN OWNED BY regress_tenant TO regress_createrole;
|
REASSIGN OWNED BY regress_tenant TO regress_createrole;
|
||||||
|
|
||||||
|
-- ok, create a role with a value for createrole_self_grant
|
||||||
|
SET createrole_self_grant = 'set, inherit';
|
||||||
|
CREATE ROLE regress_tenant2;
|
||||||
|
GRANT CREATE ON DATABASE regression TO regress_tenant2;
|
||||||
|
|
||||||
|
-- ok, regress_tenant2 can create objects within the database
|
||||||
|
SET SESSION AUTHORIZATION regress_tenant2;
|
||||||
|
CREATE TABLE tenant2_table (i integer);
|
||||||
|
REVOKE ALL PRIVILEGES ON tenant2_table FROM PUBLIC;
|
||||||
|
|
||||||
|
-- ok, because we have SET and INHERIT on regress_tenant2
|
||||||
|
SET SESSION AUTHORIZATION regress_createrole;
|
||||||
|
CREATE SCHEMA regress_tenant2_schema AUTHORIZATION regress_tenant2;
|
||||||
|
ALTER SCHEMA regress_tenant2_schema OWNER TO regress_createrole;
|
||||||
|
ALTER TABLE tenant2_table OWNER TO regress_createrole;
|
||||||
|
ALTER TABLE tenant2_table OWNER TO regress_tenant2;
|
||||||
|
|
||||||
|
-- with SET but not INHERIT, we can give away objects but not take them
|
||||||
|
REVOKE INHERIT OPTION FOR regress_tenant2 FROM regress_createrole;
|
||||||
|
ALTER SCHEMA regress_tenant2_schema OWNER TO regress_tenant2;
|
||||||
|
ALTER TABLE tenant2_table OWNER TO regress_createrole;
|
||||||
|
|
||||||
|
-- with INHERIT but not SET, we can take objects but not give them away
|
||||||
|
GRANT regress_tenant2 TO regress_createrole WITH INHERIT TRUE, SET FALSE;
|
||||||
|
ALTER TABLE tenant2_table OWNER TO regress_createrole;
|
||||||
|
ALTER TABLE tenant2_table OWNER TO regress_tenant2;
|
||||||
|
DROP TABLE tenant2_table;
|
||||||
|
|
||||||
-- fail, CREATEROLE is not 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_read_all_data IN ROLE pg_read_all_data;
|
||||||
CREATE ROLE regress_write_all_data IN ROLE pg_write_all_data;
|
CREATE ROLE regress_write_all_data IN ROLE pg_write_all_data;
|
||||||
@ -113,6 +146,9 @@ DROP ROLE regress_nosuch_recursive;
|
|||||||
DROP ROLE regress_nosuch_admin_recursive;
|
DROP ROLE regress_nosuch_admin_recursive;
|
||||||
DROP ROLE regress_plainrole;
|
DROP ROLE regress_plainrole;
|
||||||
|
|
||||||
|
-- must revoke privileges before dropping role
|
||||||
|
REVOKE CREATE ON DATABASE regression FROM regress_createrole CASCADE;
|
||||||
|
|
||||||
-- ok, should be able to drop non-superuser roles we created
|
-- ok, should be able to drop non-superuser roles we created
|
||||||
DROP ROLE regress_createdb;
|
DROP ROLE regress_createdb;
|
||||||
DROP ROLE regress_createrole;
|
DROP ROLE regress_createrole;
|
||||||
@ -131,6 +167,7 @@ DROP ROLE regress_role_admin;
|
|||||||
|
|
||||||
-- ok
|
-- ok
|
||||||
RESET SESSION AUTHORIZATION;
|
RESET SESSION AUTHORIZATION;
|
||||||
|
REVOKE CREATE ON DATABASE regression FROM regress_role_admin CASCADE;
|
||||||
DROP INDEX tenant_idx;
|
DROP INDEX tenant_idx;
|
||||||
DROP TABLE tenant_table;
|
DROP TABLE tenant_table;
|
||||||
DROP VIEW tenant_view;
|
DROP VIEW tenant_view;
|
||||||
|
Loading…
Reference in New Issue
Block a user