From 70edc1b2018487ac782a7af720ca6c76cb99ef01 Mon Sep 17 00:00:00 2001 From: Andreas Ntaflos Date: Mon, 23 Mar 2026 22:55:01 +0100 Subject: [PATCH] Properly quote role name in default_privileges type Like in many other places in this module we need to ensure that user-supplied identifiers, such as role names, database names, etc. are quoted in SQL queries, because they may contain characters such as the hyphen that the SQL standard considers illegal unless the identifier is surrounded by double quotes. The `unless` clause in the default_privileges defined type constructs an SQL query to check if the ALTER DEFAULT PRIVILEGES grant is already applied, but this SQL query does not quote the role name. This leads to server-side errors when trying to run the query if the role name contains a character like the hyphen. In this example the role name is `monitoring-user`: Could not evaluate: Error evaluating 'unless' clause, returned pid 891642 exit 1: 'ERROR: unrecognized key word: "monitoring" LINE 1: ...amespace AS n ON da.defaclnamespace = n.oid WHERE 'monitori... ^ HINT: ACL key word must be "group" or "user". ' This change fixes the SQL query for the `unless` clause and contains updated spec tests. Fixes #1665 --- manifests/server/default_privileges.pp | 4 +-- .../defines/server/default_privileges_spec.rb | 36 ++++++++++++++++--- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/manifests/server/default_privileges.pp b/manifests/server/default_privileges.pp index 815abaebbd..b3b10cd012 100644 --- a/manifests/server/default_privileges.pp +++ b/manifests/server/default_privileges.pp @@ -145,8 +145,8 @@ } $_unless = $ensure ? { - 'absent' => "SELECT 1 WHERE NOT EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '%s=%s%s' = ANY (defaclacl)%s and defaclobjtype = '%s')", # lint:ignore:140chars - default => "SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '%s=%s%s' = ANY (defaclacl)%s and defaclobjtype = '%s')", # lint:ignore:140chars + 'absent' => "SELECT 1 WHERE NOT EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '\"%s\"=%s%s' = ANY (defaclacl)%s and defaclobjtype = '%s')", # lint:ignore:140chars + default => "SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '\"%s\"=%s%s' = ANY (defaclacl)%s and defaclobjtype = '%s')", # lint:ignore:140chars } $unless_cmd = sprintf($_unless, $role, $_check_privilege, $_check_target_role, $_check_schema, $_check_type) diff --git a/spec/defines/server/default_privileges_spec.rb b/spec/defines/server/default_privileges_spec.rb index fc88ac10fb..b0e8784d82 100644 --- a/spec/defines/server/default_privileges_spec.rb +++ b/spec/defines/server/default_privileges_spec.rb @@ -92,7 +92,33 @@ # rubocop:disable Layout/LineLength expect(subject).to contain_postgresql_psql('default_privileges:test') .with_command('ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO "test"') - .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=arwdDxt' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r')") + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '\"test\"=arwdDxt' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r')") + # rubocop:enable Layout/LineLength + end + end + + context 'supported privilege and a role name with a hyphen' do + let :params do + { + db: 'test', + role: 'test-foo', + privilege: 'all', + object_type: 'tables' + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_postgresql__server__default_privileges('test') } + + it do + # rubocop:disable Layout/LineLength + expect(subject).to contain_postgresql_psql('default_privileges:test') + .with_command('ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO "test-foo"') + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '\"test-foo\"=arwdDxt' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r')") # rubocop:enable Layout/LineLength end end @@ -163,7 +189,7 @@ class { 'postgresql::server': } # rubocop:disable Layout/LineLength expect(subject).to contain_postgresql_psql('default_privileges:test') .with_command('ALTER DEFAULT PRIVILEGES GRANT ALL ON SCHEMAS TO "test"') - .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=UC' = ANY (defaclacl) AND nspname IS NULL and defaclobjtype = 'n')") + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '\"test\"=UC' = ANY (defaclacl) AND nspname IS NULL and defaclobjtype = 'n')") # rubocop:enable Layout/LineLength end end @@ -282,7 +308,7 @@ class { 'postgresql::server': } # rubocop:disable Layout/LineLength expect(subject).to contain_postgresql_psql('default_privileges:test') .with_command('ALTER DEFAULT PRIVILEGES IN SCHEMA my_schema GRANT ALL ON TABLES TO "test"') - .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=arwdDxt' = ANY (defaclacl) AND nspname = 'my_schema' and defaclobjtype = 'r')") + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '\"test\"=arwdDxt' = ANY (defaclacl) AND nspname = 'my_schema' and defaclobjtype = 'r')") # rubocop:enable Layout/LineLength end end @@ -309,7 +335,7 @@ class { 'postgresql::server': } # rubocop:disable Layout/LineLength expect(subject).to contain_postgresql_psql('default_privileges:test') .with_command('ALTER DEFAULT PRIVILEGES GRANT ALL ON TABLES TO "test"') - .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=arwdDxt' = ANY (defaclacl) AND nspname IS NULL and defaclobjtype = 'r')") + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '\"test\"=arwdDxt' = ANY (defaclacl) AND nspname IS NULL and defaclobjtype = 'r')") # rubocop:enable Layout/LineLength end end @@ -367,7 +393,7 @@ class {'postgresql::server':} # rubocop:disable Layout/LineLength expect(subject).to contain_postgresql_psql('default_privileges:test') .with_command('ALTER DEFAULT PRIVILEGES FOR ROLE target IN SCHEMA public GRANT ALL ON TABLES TO "test"') - .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=arwdDxt/target' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r')") + .with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da LEFT JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '\"test\"=arwdDxt/target' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r')") # rubocop:enable Layout/LineLength end end