Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow anyone to use size utilities on distributed hypertables #3701

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions tsl/src/data_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -1577,12 +1577,16 @@ data_node_name_list_check_acl(List *data_node_names, AclMode mode)

foreach (lc, data_node_names)
{
/* Validate the servers, but privilege check is optional */
ForeignServer *server = GetForeignServerByName(lfirst(lc), false);

/* Must have permissions on the server object */
aclresult = pg_foreign_server_aclcheck(server->serverid, curuserid, mode);
if (mode != ACL_NO_CHECK)
{
/* Must have permissions on the server object */
aclresult = pg_foreign_server_aclcheck(server->serverid, curuserid, mode);

if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_FOREIGN_SERVER, server->servername);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_FOREIGN_SERVER, server->servername);
}
}
}
6 changes: 3 additions & 3 deletions tsl/src/remote/dist_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ ts_dist_cmd_params_invoke_on_data_nodes(const char *sql, StmtParams *params, Lis
switch (nodeTag(data_nodes))
{
case T_OidList:
data_nodes = data_node_oids_to_node_name_list(data_nodes, ACL_USAGE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it make sense to add mode argument to the ts_dist_cmd_params_invoke_on_data_nodes() here? Not sure if it is needed in other places

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think invoking queries on remote tables should not require any privileges on the foreign server. According to the docs:

USAGE: For foreign servers, allows creation of foreign tables using the server. Grantees may also create, alter, or drop their own user mappings associated with that server.

So, privileges on foreign servers do not govern querying, which should be restricted by permissions on a table or function, as appropriate.

data_nodes = data_node_oids_to_node_name_list(data_nodes, ACL_NO_CHECK);
break;
case T_List:
/* Already in the format we want. Just check permissions. */
data_node_name_list_check_acl(data_nodes, ACL_USAGE);
/* Already in the format we want */
data_node_name_list_check_acl(data_nodes, ACL_NO_CHECK);
break;
default:
elog(ERROR, "invalid list type %u", nodeTag(data_nodes));
Expand Down
124 changes: 124 additions & 0 deletions tsl/test/expected/dist_util.out
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,130 @@ SELECT * FROM hypertable_index_size('nondisttable_pkey');
40960
(1 row)

-- Make sure functions work for non-superuser
CREATE TABLE size_test_table (value int);
INSERT INTO size_test_table SELECT * FROM generate_series(0, 10000);
SET ROLE :ROLE_1;
-- No query permissions
\set ON_ERROR_STOP 0
SELECT count(*) FROM disttable;
ERROR: permission denied for table disttable
SELECT count(*) FROM size_test_table;
ERROR: permission denied for table size_test_table
\set ON_ERROR_STOP 1
-- Size functions work anyway, similar to pg_table_size, et al.
-- pg_table_size() can vary with platform so not outputting
SELECT 1 FROM pg_table_size('size_test_table');
?column?
----------
1
(1 row)

SELECT 1 FROM pg_table_size('disttable');
?column?
----------
1
(1 row)

SELECT 1 FROM pg_table_size('nondisttable');
?column?
----------
1
(1 row)

SELECT * FROM hypertable_size('disttable');
hypertable_size
-----------------
131072
(1 row)

SELECT * FROM hypertable_size('nondisttable');
hypertable_size
-----------------
114688
(1 row)

SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name;
table_bytes | index_bytes | toast_bytes | total_bytes | node_name
-------------+-------------+-------------+-------------+-------------
16384 | 49152 | 8192 | 73728 | data_node_1
8192 | 32768 | 8192 | 49152 | data_node_2
0 | 8192 | 0 | 8192 |
(3 rows)

SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name;
table_bytes | index_bytes | toast_bytes | total_bytes | node_name
-------------+-------------+-------------+-------------+-----------
24576 | 73728 | 16384 | 114688 |
(1 row)

SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name;
chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name
-----------------------+-----------------------+-------------+-------------+-------------+-------------+-------------
_timescaledb_internal | _dist_hyper_2_2_chunk | 8192 | 24576 | 8192 | 40960 | data_node_1
_timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 24576 | 8192 | 40960 | data_node_2
_timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1
(3 rows)

SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name;
chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name
-----------------------+------------------+-------------+-------------+-------------+-------------+-----------
_timescaledb_internal | _hyper_1_1_chunk | 8192 | 24576 | 8192 | 40960 |
_timescaledb_internal | _hyper_1_3_chunk | 8192 | 24576 | 8192 | 40960 |
_timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 |
(3 rows)

SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name;
total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name
--------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------
2 | 1 | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_1
1 | 1 | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_2
(2 rows)

SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name;
total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name
--------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-----------
3 | 2 | 16384 | 32768 | 0 | 49152 | 16384 | 32768 | 16384 | 65536 |
(1 row)

SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name;
chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name
-----------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------
_timescaledb_internal | _dist_hyper_2_2_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_1
_timescaledb_internal | _dist_hyper_2_5_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_2
_timescaledb_internal | _dist_hyper_2_6_chunk | Uncompressed | | | | | | | | | data_node_1
(3 rows)

SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name;
chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name
-----------------------+------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-----------
_timescaledb_internal | _hyper_1_1_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 |
_timescaledb_internal | _hyper_1_3_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 |
_timescaledb_internal | _hyper_1_4_chunk | Uncompressed | | | | | | | | |
(3 rows)

SELECT * FROM hypertable_index_size('disttable_pkey');
hypertable_index_size
-----------------------
57344
(1 row)

SELECT * FROM hypertable_index_size('nondisttable_pkey');
hypertable_index_size
-----------------------
40960
(1 row)

RESET ROLE;
GRANT SELECT ON disttable TO :ROLE_1;
SET ROLE :ROLE_1;
-- Querying should now work
SELECT count(*) FROM disttable;
count
-------
5
(1 row)

-- Make sure timescaledb.ssl_dir and passfile gucs can be read by a non-superuser
\c :TEST_DBNAME :ROLE_1
\unset ECHO
Expand Down
36 changes: 36 additions & 0 deletions tsl/test/sql/dist_util.sql
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,42 @@ SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chu
SELECT * FROM hypertable_index_size('disttable_pkey');
SELECT * FROM hypertable_index_size('nondisttable_pkey');

-- Make sure functions work for non-superuser
CREATE TABLE size_test_table (value int);
INSERT INTO size_test_table SELECT * FROM generate_series(0, 10000);

SET ROLE :ROLE_1;

-- No query permissions
\set ON_ERROR_STOP 0
SELECT count(*) FROM disttable;
SELECT count(*) FROM size_test_table;
\set ON_ERROR_STOP 1

-- Size functions work anyway, similar to pg_table_size, et al.
-- pg_table_size() can vary with platform so not outputting
SELECT 1 FROM pg_table_size('size_test_table');
SELECT 1 FROM pg_table_size('disttable');
SELECT 1 FROM pg_table_size('nondisttable');
SELECT * FROM hypertable_size('disttable');
SELECT * FROM hypertable_size('nondisttable');
SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name;
SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name;
SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name;
SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name;
SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name;
SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name;
SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name;
SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name;
SELECT * FROM hypertable_index_size('disttable_pkey');
SELECT * FROM hypertable_index_size('nondisttable_pkey');

RESET ROLE;
GRANT SELECT ON disttable TO :ROLE_1;
SET ROLE :ROLE_1;
-- Querying should now work
SELECT count(*) FROM disttable;

-- Make sure timescaledb.ssl_dir and passfile gucs can be read by a non-superuser
\c :TEST_DBNAME :ROLE_1
\unset ECHO
Expand Down