diff --git a/tsl/src/chunk_api.c b/tsl/src/chunk_api.c index 2982cc209bc..70dad973527 100644 --- a/tsl/src/chunk_api.c +++ b/tsl/src/chunk_api.c @@ -315,10 +315,17 @@ chunk_create(PG_FUNCTION_ARGS) HeapTuple tuple; bool created; const char *parse_err; + AclResult acl_result; Assert(NULL != ht); - ts_hypertable_permissions_check(hypertable_relid, GetUserId()); + acl_result = pg_class_aclcheck(hypertable_relid, GetUserId(), ACL_INSERT); + if (acl_result != ACLCHECK_OK) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied for table \"%s\"", get_rel_name(hypertable_relid)), + errdetail("Insert privileges required on \"%s\" to create chunks.", + get_rel_name(hypertable_relid)))); if (NULL == slices) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid slices"))); diff --git a/tsl/test/expected/chunk_api-11.out b/tsl/test/expected/chunk_api-11.out index 933d5ddced5..e42cc968651 100644 --- a/tsl/test/expected/chunk_api-11.out +++ b/tsl/test/expected/chunk_api-11.out @@ -80,17 +80,23 @@ CONTEXT: JSON data, line 1: {"time: [1515024000000000] "device... -- Valid chunk, but no permissions SET ROLE :ROLE_DEFAULT_PERM_USER_2; SELECT * FROM _timescaledb_internal.create_chunk('chunkapi',' {"time": [1515024000000000, 1519024000000000], "device": [-9223372036854775808, 1073741823]}', 'ChunkSchema', 'My_chunk_Table_name'); -ERROR: must be owner of hypertable "chunkapi" -SET ROLE :ROLE_DEFAULT_PERM_USER; +ERROR: permission denied for table "chunkapi" +DETAIL: Insert privileges required on "chunkapi" to create chunks. \set ON_ERROR_STOP 1 -\set VERBOSITY terse --- Create a chunk that does not collide and with custom schema and name +-- Test that granting insert on tables allow create_chunk to be +-- called. This will also create a chunk that does not collide and has +-- a custom schema and name. +SET ROLE :ROLE_SUPERUSER; +GRANT INSERT ON chunkapi TO :ROLE_DEFAULT_PERM_USER_2; +SET ROLE :ROLE_DEFAULT_PERM_USER_2; SELECT * FROM _timescaledb_internal.create_chunk('chunkapi',' {"time": [1515024000000000, 1519024000000000], "device": [-9223372036854775808, 1073741823]}', 'ChunkSchema', 'My_chunk_Table_name'); chunk_id | hypertable_id | schema_name | table_name | relkind | slices | created ----------+---------------+-------------+---------------------+---------+----------------------------------------------------------------------------------------------+--------- 2 | 1 | ChunkSchema | My_chunk_Table_name | r | {"time": [1515024000000000, 1519024000000000], "device": [-9223372036854775808, 1073741823]} | t (1 row) +SET ROLE :ROLE_DEFAULT_PERM_USER; +\set VERBOSITY terse SELECT (_timescaledb_internal.show_chunk(show_chunks)).* FROM show_chunks('chunkapi') ORDER BY chunk_id; diff --git a/tsl/test/expected/chunk_api-12.out b/tsl/test/expected/chunk_api-12.out index c9bcd1bc7b7..819045504e9 100644 --- a/tsl/test/expected/chunk_api-12.out +++ b/tsl/test/expected/chunk_api-12.out @@ -80,17 +80,23 @@ CONTEXT: JSON data, line 1: {"time: [1515024000000000] "device... -- Valid chunk, but no permissions SET ROLE :ROLE_DEFAULT_PERM_USER_2; SELECT * FROM _timescaledb_internal.create_chunk('chunkapi',' {"time": [1515024000000000, 1519024000000000], "device": [-9223372036854775808, 1073741823]}', 'ChunkSchema', 'My_chunk_Table_name'); -ERROR: must be owner of hypertable "chunkapi" -SET ROLE :ROLE_DEFAULT_PERM_USER; +ERROR: permission denied for table "chunkapi" +DETAIL: Insert privileges required on "chunkapi" to create chunks. \set ON_ERROR_STOP 1 -\set VERBOSITY terse --- Create a chunk that does not collide and with custom schema and name +-- Test that granting insert on tables allow create_chunk to be +-- called. This will also create a chunk that does not collide and has +-- a custom schema and name. +SET ROLE :ROLE_SUPERUSER; +GRANT INSERT ON chunkapi TO :ROLE_DEFAULT_PERM_USER_2; +SET ROLE :ROLE_DEFAULT_PERM_USER_2; SELECT * FROM _timescaledb_internal.create_chunk('chunkapi',' {"time": [1515024000000000, 1519024000000000], "device": [-9223372036854775808, 1073741823]}', 'ChunkSchema', 'My_chunk_Table_name'); chunk_id | hypertable_id | schema_name | table_name | relkind | slices | created ----------+---------------+-------------+---------------------+---------+----------------------------------------------------------------------------------------------+--------- 2 | 1 | ChunkSchema | My_chunk_Table_name | r | {"time": [1515024000000000, 1519024000000000], "device": [-9223372036854775808, 1073741823]} | t (1 row) +SET ROLE :ROLE_DEFAULT_PERM_USER; +\set VERBOSITY terse SELECT (_timescaledb_internal.show_chunk(show_chunks)).* FROM show_chunks('chunkapi') ORDER BY chunk_id; diff --git a/tsl/test/expected/dist_grant.out b/tsl/test/expected/dist_grant.out index b338c2288e0..502343e744e 100644 --- a/tsl/test/expected/dist_grant.out +++ b/tsl/test/expected/dist_grant.out @@ -668,3 +668,35 @@ REVOKE SELECT ON _timescaledb_internal._hyper_3_35_chunk FROM PUBLIC; | | | =w/cluster_super_user | | (1 row) +DROP TABLE conditions; +-- Test that we can create a writer role, assign users to that role, +-- and allow the users to insert data and create new chunks. +\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; +CREATE TABLE conditions( + time timestamptz, + device int CHECK (device > 0), + temp float, + PRIMARY KEY (time,device) +); +SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device', 3); +WARNING: the number of partitions in dimension "device" is too low to make use of all attached data nodes + hypertable_id | schema_name | table_name | created +---------------+-------------+------------+--------- + 4 | public | conditions | t +(1 row) + +-- Test that we can create a writer role, assign users to that role, +-- and allow the users to insert data and create new chunks. +SET ROLE :ROLE_DEFAULT_PERM_USER_2; +\set ON_ERROR_STOP 0 +INSERT INTO conditions +SELECT time, 1 + (random()*30)::int, random()*80 +FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; +ERROR: permission denied for table conditions +\set ON_ERROR_STOP 1 +RESET ROLE; +GRANT INSERT ON conditions TO :ROLE_DEFAULT_PERM_USER_2; +SET ROLE :ROLE_DEFAULT_PERM_USER_2; +INSERT INTO conditions +SELECT time, 1 + (random()*30)::int, random()*80 +FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; diff --git a/tsl/test/sql/chunk_api.sql.in b/tsl/test/sql/chunk_api.sql.in index b8d233d92a1..05c92775cfa 100644 --- a/tsl/test/sql/chunk_api.sql.in +++ b/tsl/test/sql/chunk_api.sql.in @@ -43,14 +43,20 @@ SELECT * FROM _timescaledb_internal.create_chunk('chunkapi',' {"time: [151502400 -- Valid chunk, but no permissions SET ROLE :ROLE_DEFAULT_PERM_USER_2; SELECT * FROM _timescaledb_internal.create_chunk('chunkapi',' {"time": [1515024000000000, 1519024000000000], "device": [-9223372036854775808, 1073741823]}', 'ChunkSchema', 'My_chunk_Table_name'); -SET ROLE :ROLE_DEFAULT_PERM_USER; - \set ON_ERROR_STOP 1 -\set VERBOSITY terse --- Create a chunk that does not collide and with custom schema and name +-- Test that granting insert on tables allow create_chunk to be +-- called. This will also create a chunk that does not collide and has +-- a custom schema and name. +SET ROLE :ROLE_SUPERUSER; +GRANT INSERT ON chunkapi TO :ROLE_DEFAULT_PERM_USER_2; +SET ROLE :ROLE_DEFAULT_PERM_USER_2; SELECT * FROM _timescaledb_internal.create_chunk('chunkapi',' {"time": [1515024000000000, 1519024000000000], "device": [-9223372036854775808, 1073741823]}', 'ChunkSchema', 'My_chunk_Table_name'); +SET ROLE :ROLE_DEFAULT_PERM_USER; + +\set VERBOSITY terse + SELECT (_timescaledb_internal.show_chunk(show_chunks)).* FROM show_chunks('chunkapi') ORDER BY chunk_id; diff --git a/tsl/test/sql/dist_grant.sql b/tsl/test/sql/dist_grant.sql index dff15f3d8e1..66bd50e2af7 100644 --- a/tsl/test/sql/dist_grant.sql +++ b/tsl/test/sql/dist_grant.sql @@ -183,3 +183,36 @@ GRANT UPDATE ON _timescaledb_internal._hyper_3_35_chunk TO PUBLIC; \z _timescaledb_internal._hyper_3_35_chunk REVOKE SELECT ON _timescaledb_internal._hyper_3_35_chunk FROM PUBLIC; \z _timescaledb_internal._hyper_3_35_chunk + +DROP TABLE conditions; + +-- Test that we can create a writer role, assign users to that role, +-- and allow the users to insert data and create new chunks. +\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; + +CREATE TABLE conditions( + time timestamptz, + device int CHECK (device > 0), + temp float, + PRIMARY KEY (time,device) +); + +SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device', 3); + +-- Test that we can create a writer role, assign users to that role, +-- and allow the users to insert data and create new chunks. + +SET ROLE :ROLE_DEFAULT_PERM_USER_2; +\set ON_ERROR_STOP 0 +INSERT INTO conditions +SELECT time, 1 + (random()*30)::int, random()*80 +FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; +\set ON_ERROR_STOP 1 + +RESET ROLE; +GRANT INSERT ON conditions TO :ROLE_DEFAULT_PERM_USER_2; + +SET ROLE :ROLE_DEFAULT_PERM_USER_2; +INSERT INTO conditions +SELECT time, 1 + (random()*30)::int, random()*80 +FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time;