Add better errors for no permission in callbacks

Have better permission errors when setting
the integer now func and the partitioning func.

Also move tests from tsl to apache2 for the now func.
This commit is contained in:
Matvey Arye 2019-10-09 15:07:26 -04:00 committed by Matvey Arye
parent d2f68cbd64
commit 01f2bbaf5a
6 changed files with 106 additions and 64 deletions

View File

@ -1930,6 +1930,7 @@ ts_hypertable_set_integer_now_func(PG_FUNCTION_ARGS)
Cache *hcache;
Dimension *open_dim;
Oid open_dim_type;
AclResult aclresult;
ts_hypertable_permissions_check(table_relid, GetUserId());
@ -1962,6 +1963,12 @@ ts_hypertable_set_integer_now_func(PG_FUNCTION_ARGS)
ts_interval_now_func_validate(now_func_oid, open_dim_type);
aclresult = pg_proc_aclcheck(now_func_oid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for function %s", get_func_name(now_func_oid))));
dimension_update(table_relid,
&open_dim->fd.column_name,
DIMENSION_TYPE_OPEN,

View File

@ -25,6 +25,7 @@
#include <parser/parse_coerce.h>
#include <nodes/makefuncs.h>
#include <nodes/pg_list.h>
#include <miscadmin.h>
#include "partitioning.h"
#include "compat.h"
@ -68,12 +69,19 @@ ts_partitioning_func_is_valid(regproc funcoid, DimensionType dimtype, Oid argtyp
{
HeapTuple tuple;
bool isvalid;
AclResult aclresult;
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for function %u", funcoid);
aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for function %s", get_func_name(funcoid))));
isvalid = IS_VALID_PARTITIONING_FUNC((Form_pg_proc) GETSTRUCT(tuple), dimtype, argtype);
ReleaseSysCache(tuple);

View File

@ -582,3 +582,53 @@ NOTICE: adding not-null constraint to column "time"
SELECT create_hypertable('test_schema.test_sql_cmd', 'time', chunk_time_interval => 604800000000, create_default_indexes=>FALSE);
(1 row)
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
CREATE TABLE test_table_int(time bigint, junk int);
SELECT hypertable_id AS "TEST_TABLE_INT_HYPERTABLE_ID" FROM create_hypertable('test_table_int', 'time', chunk_time_interval => 1) \gset
NOTICE: adding not-null constraint to column "time"
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA IF NOT EXISTS my_schema;
create or replace function my_schema.dummy_now2() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
grant execute on ALL FUNCTIONS IN SCHEMA my_schema to public;
create or replace function dummy_now3() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
grant execute on ALL FUNCTIONS IN SCHEMA my_schema to public;
REVOKE execute ON function dummy_now3() FROM PUBLIC;
CREATE SCHEMA IF NOT EXISTS my_user_schema;
GRANT ALL ON SCHEMA my_user_schema to PUBLIC;
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
create or replace function dummy_now() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
create or replace function my_user_schema.dummy_now4() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
select set_integer_now_func('test_table_int', 'dummy_now');
set_integer_now_func
----------------------
(1 row)
select * from _timescaledb_catalog.dimension WHERE hypertable_id = :TEST_TABLE_INT_HYPERTABLE_ID;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func
----+---------------+-------------+-------------+---------+------------+--------------------------+-------------------+-----------------+-------------------------+------------------
24 | 15 | time | bigint | t | | | | 1 | public | dummy_now
(1 row)
\set ON_ERROR_STOP 0
select set_integer_now_func('test_table_int', 'dummy_now');
ERROR: integer_now_func is already set for hypertable "test_table_int"
select set_integer_now_func('test_table_int', 'my_schema.dummy_now2', replace_if_exists => TRUE);
ERROR: permission denied for schema my_schema at character 47
select set_integer_now_func('test_table_int', 'dummy_now3', replace_if_exists => TRUE);
ERROR: permission denied for function dummy_now3
\set ON_ERROR_STOP
select set_integer_now_func('test_table_int', 'my_user_schema.dummy_now4', replace_if_exists => TRUE);
set_integer_now_func
----------------------
(1 row)
\c :TEST_DBNAME :ROLE_SUPERUSER
ALTER SCHEMA my_user_schema RENAME TO my_new_schema;
select * from _timescaledb_catalog.dimension WHERE hypertable_id = :TEST_TABLE_INT_HYPERTABLE_ID;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func
----+---------------+-------------+-------------+---------+------------+--------------------------+-------------------+-----------------+-------------------------+------------------
24 | 15 | time | bigint | t | | | | 1 | my_new_schema | dummy_now4
(1 row)

View File

@ -336,3 +336,36 @@ DROP TABLE test_schema.test_sql_cmd CASCADE;
CREATE TABLE test_schema.test_sql_cmd(time TIMESTAMPTZ, temp FLOAT8, device_id TEXT, device_type TEXT, location TEXT, id INT, id2 INT);
SELECT test.execute_sql(:'create_cmd');
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
CREATE TABLE test_table_int(time bigint, junk int);
SELECT hypertable_id AS "TEST_TABLE_INT_HYPERTABLE_ID" FROM create_hypertable('test_table_int', 'time', chunk_time_interval => 1) \gset
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA IF NOT EXISTS my_schema;
create or replace function my_schema.dummy_now2() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
grant execute on ALL FUNCTIONS IN SCHEMA my_schema to public;
create or replace function dummy_now3() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
grant execute on ALL FUNCTIONS IN SCHEMA my_schema to public;
REVOKE execute ON function dummy_now3() FROM PUBLIC;
CREATE SCHEMA IF NOT EXISTS my_user_schema;
GRANT ALL ON SCHEMA my_user_schema to PUBLIC;
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
create or replace function dummy_now() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
create or replace function my_user_schema.dummy_now4() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
select set_integer_now_func('test_table_int', 'dummy_now');
select * from _timescaledb_catalog.dimension WHERE hypertable_id = :TEST_TABLE_INT_HYPERTABLE_ID;
\set ON_ERROR_STOP 0
select set_integer_now_func('test_table_int', 'dummy_now');
select set_integer_now_func('test_table_int', 'my_schema.dummy_now2', replace_if_exists => TRUE);
select set_integer_now_func('test_table_int', 'dummy_now3', replace_if_exists => TRUE);
\set ON_ERROR_STOP
select set_integer_now_func('test_table_int', 'my_user_schema.dummy_now4', replace_if_exists => TRUE);
\c :TEST_DBNAME :ROLE_SUPERUSER
ALTER SCHEMA my_user_schema RENAME TO my_new_schema;
select * from _timescaledb_catalog.dimension WHERE hypertable_id = :TEST_TABLE_INT_HYPERTABLE_ID;

View File

@ -231,14 +231,6 @@ select remove_drop_chunks_policy('test_table');
-- Test set_integer_now_func and add_drop_chunks_policy with
-- hypertables that have integer time dimension
\set ON_ERROR_STOP 0
select set_integer_now_func('test_table', 42);
ERROR: integer_now_func can only be set for hypertables that have integer time dimensions
select set_integer_now_func('test_table', 'set_integer_now_func');
ERROR: integer_now_func can only be set for hypertables that have integer time dimensions
select set_integer_now_func('test_table_int', 'set_integer_now_func');
ERROR: integer_now_func must take no arguments and it must be STABLE
\set ON_ERROR_STOP 1
select * from _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func
----+---------------+-------------+--------------------------+---------+------------+--------------------------+-------------------+-----------------+-------------------------+------------------
@ -247,44 +239,15 @@ select * from _timescaledb_catalog.dimension;
(2 rows)
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA IF NOT EXISTS my_schema;
create or replace function my_schema.dummy_now2() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
grant execute on ALL FUNCTIONS IN SCHEMA my_schema to public;
-- \c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
create or replace function dummy_now() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
select set_integer_now_func('test_table_int', 'dummy_now');
CREATE SCHEMA IF NOT EXISTS my_new_schema;
create or replace function my_new_schema.dummy_now2() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
grant execute on ALL FUNCTIONS IN SCHEMA my_new_schema to public;
select set_integer_now_func('test_table_int', 'my_new_schema.dummy_now2');
set_integer_now_func
----------------------
(1 row)
\set ON_ERROR_STOP 0
select set_integer_now_func('test_table_int', 'dummy_now');
ERROR: integer_now_func is already set for hypertable "test_table_int"
\set ON_ERROR_STOP 1
select * from _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func
----+---------------+-------------+--------------------------+---------+------------+--------------------------+-------------------+-----------------+-------------------------+------------------
1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | |
2 | 2 | time | bigint | t | | | | 1 | public | dummy_now
(2 rows)
select set_integer_now_func('test_table_int', 'my_schema.dummy_now2', replace_if_exists => TRUE);
set_integer_now_func
----------------------
(1 row)
select * from _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func
----+---------------+-------------+--------------------------+---------+------------+--------------------------+-------------------+-----------------+-------------------------+------------------
1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | |
2 | 2 | time | bigint | t | | | | 1 | my_schema | dummy_now2
(2 rows)
-- \c :TEST_DBNAME :ROLE_SUPERUSER q:: should all of the following be execed in super user mode?
-- partitioning.sql test does something similar bu tnot sure why superuser is necessary.
ALTER SCHEMA my_schema RENAME TO my_new_schema;
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
select * from _timescaledb_catalog.dimension;
id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func

View File

@ -100,33 +100,14 @@ select remove_drop_chunks_policy('test_table');
-- Test set_integer_now_func and add_drop_chunks_policy with
-- hypertables that have integer time dimension
\set ON_ERROR_STOP 0
select set_integer_now_func('test_table', 42);
select set_integer_now_func('test_table', 'set_integer_now_func');
select set_integer_now_func('test_table_int', 'set_integer_now_func');
\set ON_ERROR_STOP 1
select * from _timescaledb_catalog.dimension;
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA IF NOT EXISTS my_schema;
create or replace function my_schema.dummy_now2() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
grant execute on ALL FUNCTIONS IN SCHEMA my_schema to public;
-- \c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
CREATE SCHEMA IF NOT EXISTS my_new_schema;
create or replace function my_new_schema.dummy_now2() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
grant execute on ALL FUNCTIONS IN SCHEMA my_new_schema to public;
select set_integer_now_func('test_table_int', 'my_new_schema.dummy_now2');
create or replace function dummy_now() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 1::BIGINT';
select set_integer_now_func('test_table_int', 'dummy_now');
\set ON_ERROR_STOP 0
select set_integer_now_func('test_table_int', 'dummy_now');
\set ON_ERROR_STOP 1
select * from _timescaledb_catalog.dimension;
select set_integer_now_func('test_table_int', 'my_schema.dummy_now2', replace_if_exists => TRUE);
select * from _timescaledb_catalog.dimension;
-- \c :TEST_DBNAME :ROLE_SUPERUSER q:: should all of the following be execed in super user mode?
-- partitioning.sql test does something similar bu tnot sure why superuser is necessary.
ALTER SCHEMA my_schema RENAME TO my_new_schema;
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
select * from _timescaledb_catalog.dimension;