diff options
author | Peter Eisentraut <peter@eisentraut.org> | 2021-01-30 09:41:44 +0100 |
---|---|---|
committer | Peter Eisentraut <peter@eisentraut.org> | 2021-01-30 09:45:11 +0100 |
commit | 6aaaa76bb47db11cd6f567eafa3d1ee81ca59556 (patch) | |
tree | 06c71bb1c342258f85f97ecc7c7b02cda193895c | |
parent | 7da83415e5bc01bba0093f34f4f612b70c70b678 (diff) | |
download | postgresql-6aaaa76bb47db11cd6f567eafa3d1ee81ca59556.tar.gz postgresql-6aaaa76bb47db11cd6f567eafa3d1ee81ca59556.zip |
Allow GRANTED BY clause in normal GRANT and REVOKE statements
The SQL standard allows a GRANTED BY clause on GRANT and
REVOKE (privilege) statements that can specify CURRENT_USER or
CURRENT_ROLE. In PostgreSQL, both of these are the default behavior.
Since we already have all the parsing support for this for the
GRANT (role) statement, we might as well add basic support for this
for the privilege variant as well. This allows us to check off SQL
feature T332. In the future, perhaps more interesting things could be
done with this, too.
Reviewed-by: Simon Riggs <simon@2ndquadrant.com>
Discussion: https://www.postgresql.org/message-id/flat/f2feac44-b4c5-f38f-3699-2851d6a76dc9@2ndquadrant.com
-rw-r--r-- | doc/src/sgml/ref/grant.sgml | 25 | ||||
-rw-r--r-- | doc/src/sgml/ref/revoke.sgml | 13 | ||||
-rw-r--r-- | src/backend/catalog/aclchk.c | 16 | ||||
-rw-r--r-- | src/backend/catalog/sql_features.txt | 2 | ||||
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 1 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 1 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 13 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 1 | ||||
-rw-r--r-- | src/test/regress/expected/privileges.out | 6 | ||||
-rw-r--r-- | src/test/regress/sql/privileges.sql | 6 |
10 files changed, 71 insertions, 13 deletions
diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml index c3db393bdea..a897712de2e 100644 --- a/doc/src/sgml/ref/grant.sgml +++ b/doc/src/sgml/ref/grant.sgml @@ -26,58 +26,71 @@ GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } ON { [ TABLE ] <replaceable class="parameter">table_name</replaceable> [, ...] | ALL TABLES IN SCHEMA <replaceable class="parameter">schema_name</replaceable> [, ...] } TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( <replaceable class="parameter">column_name</replaceable> [, ...] ) [, ...] | ALL [ PRIVILEGES ] ( <replaceable class="parameter">column_name</replaceable> [, ...] ) } ON [ TABLE ] <replaceable class="parameter">table_name</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { { USAGE | SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON { SEQUENCE <replaceable class="parameter">sequence_name</replaceable> [, ...] | ALL SEQUENCES IN SCHEMA <replaceable class="parameter">schema_name</replaceable> [, ...] } TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] } ON DATABASE <replaceable>database_name</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { USAGE | ALL [ PRIVILEGES ] } ON DOMAIN <replaceable>domain_name</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { USAGE | ALL [ PRIVILEGES ] } ON FOREIGN DATA WRAPPER <replaceable>fdw_name</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { USAGE | ALL [ PRIVILEGES ] } ON FOREIGN SERVER <replaceable>server_name</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { EXECUTE | ALL [ PRIVILEGES ] } ON { { FUNCTION | PROCEDURE | ROUTINE } <replaceable>routine_name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) ] [, ...] | ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA <replaceable class="parameter">schema_name</replaceable> [, ...] } TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { USAGE | ALL [ PRIVILEGES ] } ON LANGUAGE <replaceable>lang_name</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON LARGE OBJECT <replaceable class="parameter">loid</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] } ON SCHEMA <replaceable>schema_name</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { CREATE | ALL [ PRIVILEGES ] } ON TABLESPACE <replaceable>tablespace_name</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT { USAGE | ALL [ PRIVILEGES ] } ON TYPE <replaceable>type_name</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH GRANT OPTION ] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] GRANT <replaceable class="parameter">role_name</replaceable> [, ...] TO <replaceable class="parameter">role_specification</replaceable> [, ...] [ WITH ADMIN OPTION ] @@ -134,6 +147,12 @@ GRANT <replaceable class="parameter">role_name</replaceable> [, ...] TO <replace </para> <para> + If <literal>GRANTED BY</literal> is specified, the specified grantor must + be the current user. This clause is currently present in this form only + for SQL compatibility. + </para> + + <para> There is no need to grant privileges to the owner of an object (usually the user that created it), as the owner has all privileges by default. (The owner could, @@ -410,9 +429,9 @@ GRANT admins TO joe; <para> The SQL standard allows the <literal>GRANTED BY</literal> option to - be used in all forms of <command>GRANT</command>. PostgreSQL only - supports it when granting role membership, and even then only superusers - may use it in nontrivial ways. + specify only <literal>CURRENT_USER</literal> or + <literal>CURRENT_ROLE</literal>. The other variants are PostgreSQL + extensions. </para> <para> diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml index 35ff87a4f5e..3014c864ea3 100644 --- a/doc/src/sgml/ref/revoke.sgml +++ b/doc/src/sgml/ref/revoke.sgml @@ -27,6 +27,7 @@ REVOKE [ GRANT OPTION FOR ] ON { [ TABLE ] <replaceable class="parameter">table_name</replaceable> [, ...] | ALL TABLES IN SCHEMA <replaceable>schema_name</replaceable> [, ...] } FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] @@ -34,6 +35,7 @@ REVOKE [ GRANT OPTION FOR ] [, ...] | ALL [ PRIVILEGES ] ( <replaceable class="parameter">column_name</replaceable> [, ...] ) } ON [ TABLE ] <replaceable class="parameter">table_name</replaceable> [, ...] FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] @@ -42,30 +44,35 @@ REVOKE [ GRANT OPTION FOR ] ON { SEQUENCE <replaceable class="parameter">sequence_name</replaceable> [, ...] | ALL SEQUENCES IN SCHEMA <replaceable>schema_name</replaceable> [, ...] } FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] } ON DATABASE <replaceable>database_name</replaceable> [, ...] FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON DOMAIN <replaceable>domain_name</replaceable> [, ...] FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON FOREIGN DATA WRAPPER <replaceable>fdw_name</replaceable> [, ...] FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON FOREIGN SERVER <replaceable>server_name</replaceable> [, ...] FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] @@ -73,36 +80,42 @@ REVOKE [ GRANT OPTION FOR ] ON { { FUNCTION | PROCEDURE | ROUTINE } <replaceable>function_name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) ] [, ...] | ALL { FUNCTIONS | PROCEDURES | ROUTINES } IN SCHEMA <replaceable>schema_name</replaceable> [, ...] } FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON LANGUAGE <replaceable>lang_name</replaceable> [, ...] FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON LARGE OBJECT <replaceable class="parameter">loid</replaceable> [, ...] FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] } ON SCHEMA <replaceable>schema_name</replaceable> [, ...] FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { CREATE | ALL [ PRIVILEGES ] } ON TABLESPACE <replaceable>tablespace_name</replaceable> [, ...] FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON TYPE <replaceable>type_name</replaceable> [, ...] FROM <replaceable class="parameter">role_specification</replaceable> [, ...] + [ GRANTED BY <replaceable class="parameter">role_specification</replaceable> ] [ CASCADE | RESTRICT ] REVOKE [ ADMIN OPTION FOR ] diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index f3c1ca18ae7..add3d147e76 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -363,6 +363,22 @@ ExecuteGrantStmt(GrantStmt *stmt) const char *errormsg; AclMode all_privileges; + if (stmt->grantor) + { + Oid grantor; + + grantor = get_rolespec_oid(stmt->grantor, false); + + /* + * Currently, this clause is only for SQL compatibility, not very + * interesting otherwise. + */ + if (grantor != GetUserId()) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("grantor must be current user"))); + } + /* * Turn the regular GrantStmt into the InternalGrant form. */ diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt index caa971c4356..86519ad2974 100644 --- a/src/backend/catalog/sql_features.txt +++ b/src/backend/catalog/sql_features.txt @@ -475,7 +475,7 @@ T324 Explicit security for SQL routines NO T325 Qualified SQL parameter references YES T326 Table functions NO T331 Basic roles YES -T332 Extended roles NO mostly supported +T332 Extended roles YES T341 Overloading of SQL-invoked functions and procedures YES T351 Bracketed SQL comments (/*...*/ comments) YES T431 Extended grouping capabilities YES diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index ba3ccc712c8..21e09c667a3 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3270,6 +3270,7 @@ _copyGrantStmt(const GrantStmt *from) COPY_NODE_FIELD(privileges); COPY_NODE_FIELD(grantees); COPY_SCALAR_FIELD(grant_option); + COPY_NODE_FIELD(grantor); COPY_SCALAR_FIELD(behavior); return newnode; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index a2ef853dc2a..5a5237c6c30 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1145,6 +1145,7 @@ _equalGrantStmt(const GrantStmt *a, const GrantStmt *b) COMPARE_NODE_FIELD(privileges); COMPARE_NODE_FIELD(grantees); COMPARE_SCALAR_FIELD(grant_option); + COMPARE_NODE_FIELD(grantor); COMPARE_SCALAR_FIELD(behavior); return true; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 7574d545e0e..b2f447bf9a2 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -6772,7 +6772,7 @@ opt_from_in: from_in *****************************************************************************/ GrantStmt: GRANT privileges ON privilege_target TO grantee_list - opt_grant_grant_option + opt_grant_grant_option opt_granted_by { GrantStmt *n = makeNode(GrantStmt); n->is_grant = true; @@ -6782,13 +6782,14 @@ GrantStmt: GRANT privileges ON privilege_target TO grantee_list n->objects = ($4)->objs; n->grantees = $6; n->grant_option = $7; + n->grantor = $8; $$ = (Node*)n; } ; RevokeStmt: REVOKE privileges ON privilege_target - FROM grantee_list opt_drop_behavior + FROM grantee_list opt_granted_by opt_drop_behavior { GrantStmt *n = makeNode(GrantStmt); n->is_grant = false; @@ -6798,11 +6799,12 @@ RevokeStmt: n->objtype = ($4)->objtype; n->objects = ($4)->objs; n->grantees = $6; - n->behavior = $7; + n->grantor = $7; + n->behavior = $8; $$ = (Node *)n; } | REVOKE GRANT OPTION FOR privileges ON privilege_target - FROM grantee_list opt_drop_behavior + FROM grantee_list opt_granted_by opt_drop_behavior { GrantStmt *n = makeNode(GrantStmt); n->is_grant = false; @@ -6812,7 +6814,8 @@ RevokeStmt: n->objtype = ($7)->objtype; n->objects = ($7)->objs; n->grantees = $9; - n->behavior = $10; + n->grantor = $10; + n->behavior = $11; $$ = (Node *)n; } ; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index dc2bb40926a..068c6ec4401 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1949,6 +1949,7 @@ typedef struct GrantStmt /* privileges == NIL denotes ALL PRIVILEGES */ List *grantees; /* list of RoleSpec nodes */ bool grant_option; /* grant or revoke grant option */ + RoleSpec *grantor; DropBehavior behavior; /* drop behavior (for REVOKE) */ } GrantStmt; diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out index 8f2fc89851b..ed98fa8376f 100644 --- a/src/test/regress/expected/privileges.out +++ b/src/test/regress/expected/privileges.out @@ -70,8 +70,10 @@ SELECT * FROM atest1; CREATE TABLE atest2 (col1 varchar(10), col2 boolean); GRANT SELECT ON atest2 TO regress_priv_user2; GRANT UPDATE ON atest2 TO regress_priv_user3; -GRANT INSERT ON atest2 TO regress_priv_user4; -GRANT TRUNCATE ON atest2 TO regress_priv_user5; +GRANT INSERT ON atest2 TO regress_priv_user4 GRANTED BY CURRENT_USER; +GRANT TRUNCATE ON atest2 TO regress_priv_user5 GRANTED BY CURRENT_ROLE; +GRANT TRUNCATE ON atest2 TO regress_priv_user4 GRANTED BY regress_priv_user5; -- error +ERROR: grantor must be current user SET SESSION AUTHORIZATION regress_priv_user2; SELECT session_user, current_user; session_user | current_user diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql index 1c250a11fe1..becbc196713 100644 --- a/src/test/regress/sql/privileges.sql +++ b/src/test/regress/sql/privileges.sql @@ -64,8 +64,10 @@ SELECT * FROM atest1; CREATE TABLE atest2 (col1 varchar(10), col2 boolean); GRANT SELECT ON atest2 TO regress_priv_user2; GRANT UPDATE ON atest2 TO regress_priv_user3; -GRANT INSERT ON atest2 TO regress_priv_user4; -GRANT TRUNCATE ON atest2 TO regress_priv_user5; +GRANT INSERT ON atest2 TO regress_priv_user4 GRANTED BY CURRENT_USER; +GRANT TRUNCATE ON atest2 TO regress_priv_user5 GRANTED BY CURRENT_ROLE; + +GRANT TRUNCATE ON atest2 TO regress_priv_user4 GRANTED BY regress_priv_user5; -- error SET SESSION AUTHORIZATION regress_priv_user2; |