diff --git a/src/backend/distributed/shared_library_init.c b/src/backend/distributed/shared_library_init.c index a71467ad6..343ac2f0b 100644 --- a/src/backend/distributed/shared_library_init.c +++ b/src/backend/distributed/shared_library_init.c @@ -2076,6 +2076,20 @@ RegisterCitusConfigVariables(void) ShowShardsForAppNamePrefixesAssignHook, NULL); + DefineCustomBoolVariable( + "citus.skip_advisory_lock_permission_checks", + gettext_noop("Postgres would normally enforce some " + "ownership checks while acquiring locks. " + "When this setting is 'off', Citus skips" + "ownership checks on internal advisory " + "locks."), + NULL, + &SkipAdvisoryLockPermissionChecks, + false, + GUC_SUPERUSER_ONLY, + GUC_NO_SHOW_ALL, + NULL, NULL, NULL); + DefineCustomBoolVariable( "citus.skip_jsonb_validation_in_copy", gettext_noop("Skip validation of JSONB columns on the coordinator during COPY " diff --git a/src/backend/distributed/utils/resource_lock.c b/src/backend/distributed/utils/resource_lock.c index 35991ade1..a4187aa65 100644 --- a/src/backend/distributed/utils/resource_lock.c +++ b/src/backend/distributed/utils/resource_lock.c @@ -109,6 +109,8 @@ PG_FUNCTION_INFO_V1(lock_relation_if_exists); /* Config variable managed via guc.c */ bool EnableAcquiringUnsafeLockFromWorkers = false; +bool SkipAdvisoryLockPermissionChecks = false; + /* * lock_shard_metadata allows the shard distribution metadata to be locked @@ -248,7 +250,10 @@ lock_shard_resources(PG_FUNCTION_ARGS) continue; } - EnsureTablePermissions(relationId, aclMask); + if (!SkipAdvisoryLockPermissionChecks) + { + EnsureTablePermissions(relationId, aclMask); + } LockShardResource(shardId, lockMode); } diff --git a/src/include/distributed/resource_lock.h b/src/include/distributed/resource_lock.h index f2a331451..375f6abbf 100644 --- a/src/include/distributed/resource_lock.h +++ b/src/include/distributed/resource_lock.h @@ -149,6 +149,7 @@ enum DistLockConfigs DIST_LOCK_NOWAIT = 2 }; + /* Lock shard/relation metadata for safe modifications */ extern void LockShardDistributionMetadata(int64 shardId, LOCKMODE lockMode); extern void LockPlacementCleanup(void); @@ -194,5 +195,6 @@ extern void AcquireDistributedLockOnRelations(List *relationList, LOCKMODE lockM extern void PreprocessLockStatement(LockStmt *stmt, ProcessUtilityContext context); extern bool EnableAcquiringUnsafeLockFromWorkers; +extern bool SkipAdvisoryLockPermissionChecks; #endif /* RESOURCE_LOCK_H */ diff --git a/src/test/regress/expected/adv_lock_permission.out b/src/test/regress/expected/adv_lock_permission.out new file mode 100644 index 000000000..d034fbb67 --- /dev/null +++ b/src/test/regress/expected/adv_lock_permission.out @@ -0,0 +1,41 @@ +CREATE SCHEMA adv_lock_permission; +SET search_path to adv_lock_permission; +-- do not cache any connections, we change some settings and don't want old ones cached +SET citus.max_cached_conns_per_worker TO 0; +CREATE ROLE user_1 WITH LOGIN; +CREATE TABLE reference_table_1 (A int); +SELECT create_reference_table('reference_table_1'); + create_reference_table +--------------------------------------------------------------------- + +(1 row) + +CREATE TABLE reference_table_2 (A int); +SELECT create_reference_table('reference_table_2'); + create_reference_table +--------------------------------------------------------------------- + +(1 row) + +GRANT USAGE ON SCHEMA adv_lock_permission TO user_1; +GRANT SELECT ON reference_table_1 TO user_1; +GRANT INSERT, UPDATE ON reference_table_2 TO user_1; +SET ROLE user_1; +-- do not cache any connections, we change some settings and don't want old ones cached +SET citus.max_cached_conns_per_worker TO 0; +SET search_path to adv_lock_permission; +INSERT INTO reference_table_2 SELECT * FROM reference_table_1; +ERROR: permission denied for table reference_table_1 +CONTEXT: while executing command on localhost:xxxxx +SET ROLE postgres; +-- do not cache any connections, we change some settings and don't want old ones cached +SET citus.max_cached_conns_per_worker TO 0; +-- change the role so that it can skip permission checks +ALTER ROLE user_1 SET citus.skip_advisory_lock_permission_checks TO on; +SET ROLE user_1; +SET citus.max_cached_conns_per_worker TO 0; +INSERT INTO reference_table_2 SELECT * FROM reference_table_1; +SET ROLE postgres; +SET client_min_messages TO ERROR; +DROP SCHEMA adv_lock_permission CASCADE; +DROP ROLE user_1; diff --git a/src/test/regress/multi_schedule b/src/test/regress/multi_schedule index a92da42fd..ef64e7657 100644 --- a/src/test/regress/multi_schedule +++ b/src/test/regress/multi_schedule @@ -86,7 +86,7 @@ test: multi_agg_type_conversion multi_count_type_conversion recursive_relation_p test: multi_partition_pruning single_hash_repartition_join unsupported_lateral_subqueries test: multi_join_pruning multi_hash_pruning intermediate_result_pruning test: multi_null_minmax_value_pruning cursors -test: modification_correctness +test: modification_correctness adv_lock_permission test: multi_query_directory_cleanup test: multi_task_assignment_policy multi_cross_shard test: multi_utility_statements diff --git a/src/test/regress/sql/adv_lock_permission.sql b/src/test/regress/sql/adv_lock_permission.sql new file mode 100644 index 000000000..2528fdc39 --- /dev/null +++ b/src/test/regress/sql/adv_lock_permission.sql @@ -0,0 +1,42 @@ +CREATE SCHEMA adv_lock_permission; +SET search_path to adv_lock_permission; + +-- do not cache any connections, we change some settings and don't want old ones cached +SET citus.max_cached_conns_per_worker TO 0; + +CREATE ROLE user_1 WITH LOGIN; + +CREATE TABLE reference_table_1 (A int); +SELECT create_reference_table('reference_table_1'); + +CREATE TABLE reference_table_2 (A int); +SELECT create_reference_table('reference_table_2'); + +GRANT USAGE ON SCHEMA adv_lock_permission TO user_1; +GRANT SELECT ON reference_table_1 TO user_1; +GRANT INSERT, UPDATE ON reference_table_2 TO user_1; + +SET ROLE user_1; + +-- do not cache any connections, we change some settings and don't want old ones cached +SET citus.max_cached_conns_per_worker TO 0; +SET search_path to adv_lock_permission; + +INSERT INTO reference_table_2 SELECT * FROM reference_table_1; + +SET ROLE postgres; +-- do not cache any connections, we change some settings and don't want old ones cached +SET citus.max_cached_conns_per_worker TO 0; + +-- change the role so that it can skip permission checks +ALTER ROLE user_1 SET citus.skip_advisory_lock_permission_checks TO on; + +SET ROLE user_1; + +SET citus.max_cached_conns_per_worker TO 0; +INSERT INTO reference_table_2 SELECT * FROM reference_table_1; + +SET ROLE postgres; +SET client_min_messages TO ERROR; +DROP SCHEMA adv_lock_permission CASCADE; +DROP ROLE user_1;