Skip to content

Commit 6aaa1cf

Browse files
committed
Support setting default_privileges on all schemas
The Postgres default is for the absent specification of a schema name when altering default privileges to apply to all schemas. Support that behaviour, but keep the current default behaviour for an unset schema parameter.
1 parent c768dec commit 6aaa1cf

File tree

3 files changed

+129
-11
lines changed

3 files changed

+129
-11
lines changed

manifests/server/default_privileges.pp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# @param db Specifies the database to which you are granting access.
77
# @param object_type Specify target object type: 'FUNCTIONS', 'ROUTINES', 'SEQUENCES', 'TABLES', 'TYPES'.
88
# @param privilege Specifies comma-separated list of privileges to grant. Valid options: depends on object type.
9-
# @param schema Target schema. Defaults to 'public'.
9+
# @param schema Target schema. Defaults to 'public'. Can be set to '' to apply to all schemas.
1010
# @param psql_db Defines the database to execute the grant against. This should not ordinarily be changed from the default.
1111
# @param psql_user Specifies the OS user for running psql. Default value: The default user for the module, usually 'postgres'.
1212
# @param psql_path Specifies the OS user for running psql. Default value: The default user for the module, usually 'postgres'.
@@ -52,11 +52,11 @@
5252
case $ensure {
5353
default: {
5454
# default is 'present'
55-
$sql_command = 'ALTER DEFAULT PRIVILEGES%s IN SCHEMA %s GRANT %s ON %s TO "%s"'
55+
$sql_command = 'ALTER DEFAULT PRIVILEGES%s%s GRANT %s ON %s TO "%s"'
5656
$unless_is = true
5757
}
5858
'absent': {
59-
$sql_command = 'ALTER DEFAULT PRIVILEGES%s IN SCHEMA %s REVOKE %s ON %s FROM "%s"'
59+
$sql_command = 'ALTER DEFAULT PRIVILEGES%s%s REVOKE %s ON %s FROM "%s"'
6060
$unless_is = false
6161
}
6262
}
@@ -80,6 +80,14 @@
8080
$_check_target_role = ''
8181
}
8282

83+
if $schema != '' {
84+
$_schema = " IN SCHEMA $schema"
85+
$_check_schema = " AND nspname = '$schema'"
86+
} else {
87+
$_schema = ''
88+
$_check_schema = ' AND nspname IS NULL'
89+
}
90+
8391
## Munge the input values
8492
$_object_type = upcase($object_type)
8593
$_privilege = upcase($privilege)
@@ -138,12 +146,12 @@
138146
}
139147

140148
$_unless = $ensure ? {
141-
'absent' => "SELECT 1 WHERE NOT EXISTS (SELECT * FROM pg_default_acl AS da JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '%s=%s%s' = ANY (defaclacl) AND nspname = '%s' and defaclobjtype = '%s')",
142-
default => "SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE '%s=%s%s' = ANY (defaclacl) AND nspname = '%s' and defaclobjtype = '%s')"
149+
'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')",
150+
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')"
143151
}
144152

145-
$unless_cmd = sprintf($_unless, $role, $_check_privilege, $_check_target_role, $schema, $_check_type)
146-
$grant_cmd = sprintf($sql_command, $_target_role, $schema, $_privilege, $_object_type, $role)
153+
$unless_cmd = sprintf($_unless, $role, $_check_privilege, $_check_target_role, $_check_schema, $_check_type)
154+
$grant_cmd = sprintf($sql_command, $_target_role, $_schema, $_privilege, $_object_type, $role)
147155

148156
postgresql_psql { "default_privileges:${name}":
149157
command => $grant_cmd,

spec/acceptance/server/default_privileges_spec.rb

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
# Check that the default privileges were revoked
1212
let(:check_command) do
13-
"SELECT * FROM pg_default_acl a JOIN pg_namespace b ON a.defaclnamespace = b.oid WHERE '#{user}=arwdDxt' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r';"
13+
"SELECT * FROM pg_default_acl a LEFT JOIN pg_namespace b ON a.defaclnamespace = b.oid WHERE '#{user}=arwdDxt' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r';"
1414
end
1515

1616
let(:pp_one) do
@@ -167,6 +167,67 @@ class { 'postgresql::server': }
167167
MANIFEST
168168
end
169169

170+
let(:all_schemas_check_command) do
171+
"SELECT * FROM pg_default_acl a WHERE '#{user}=arwdDxt' = ANY (defaclacl) AND defaclnamespace = 0 and defaclobjtype = 'r';"
172+
end
173+
174+
let(:pp_unset_schema) do
175+
<<-MANIFEST.unindent
176+
$db = #{db}
177+
$user = #{user}
178+
$group = #{group}
179+
$password = #{password}
180+
181+
class { 'postgresql::server': }
182+
183+
postgresql::server::role { $user:
184+
password_hash => postgresql::postgresql_password($user, $password),
185+
}
186+
187+
postgresql::server::database { $db:
188+
require => Postgresql::Server::Role[$user],
189+
}
190+
191+
# Set default privileges on tables
192+
postgresql::server::default_privileges { "alter default privileges grant all on tables to ${user}":
193+
db => $db,
194+
role => $user,
195+
privilege => 'ALL',
196+
object_type => 'TABLES',
197+
schema => '',
198+
require => Postgresql::Server::Database[$db],
199+
}
200+
MANIFEST
201+
end
202+
let(:pp_unset_schema_revoke) do
203+
<<-MANIFEST
204+
$db = #{db}
205+
$user = #{user}
206+
$group = #{group}
207+
$password = #{password}
208+
209+
class { 'postgresql::server': }
210+
211+
postgresql::server::role { $user:
212+
password_hash => postgresql::postgresql_password($user, $password),
213+
}
214+
postgresql::server::database { $db:
215+
require => Postgresql::Server::Role[$user],
216+
}
217+
218+
# Removes default privileges on tables
219+
postgresql::server::default_privileges { "alter default privileges revoke all on tables for ${user}":
220+
db => $db,
221+
role => $user,
222+
privilege => 'ALL',
223+
object_type => 'TABLES',
224+
schema => '',
225+
ensure => 'absent',
226+
require => Postgresql::Server::Database[$db],
227+
}
228+
MANIFEST
229+
end
230+
170231
it 'grants default privileges to an user' do
171232
if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.6')
172233
idempotent_apply(pp_one)
@@ -212,4 +273,27 @@ class { 'postgresql::server': }
212273
end
213274
end
214275
end
276+
277+
it 'grants default privileges on all schemas to a user' do
278+
if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.6')
279+
idempotent_apply(pp_unset_schema)
280+
281+
psql("--command=\"SET client_min_messages = 'error';#{all_schemas_check_command}\" --db=#{db}") do |r|
282+
expect(r.stdout).to match(%r{\(1 row\)})
283+
expect(r.stderr).to eq('')
284+
end
285+
end
286+
end
287+
288+
it 'revokes default privileges on all schemas for a user' do
289+
if Gem::Version.new(postgresql_version) >= Gem::Version.new('9.6')
290+
apply_manifest(pp_unset_schema, catch_failures: true)
291+
apply_manifest(pp_unset_schema_revoke, expect_changes: true)
292+
293+
psql("--command=\"SET client_min_messages = 'error';#{all_schemas_check_command}\" --db=#{db}") do |r|
294+
expect(r.stdout).to match(%r{\(0 rows\)})
295+
expect(r.stderr).to eq('')
296+
end
297+
end
298+
end
215299
end

spec/unit/defines/server/default_privileges_spec.rb

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
# rubocop:disable Layout/LineLength
113113
is_expected.to contain_postgresql_psql('default_privileges:test')
114114
.with_command('ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO "test"')
115-
.with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=arwdDxt' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r')")
115+
.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')")
116116
# rubocop:enable Layout/LineLength
117117
end
118118
end
@@ -222,7 +222,33 @@
222222
# rubocop:disable Layout/LineLength
223223
is_expected.to contain_postgresql_psql('default_privileges:test')
224224
.with_command('ALTER DEFAULT PRIVILEGES IN SCHEMA my_schema GRANT ALL ON TABLES TO "test"')
225-
.with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=arwdDxt' = ANY (defaclacl) AND nspname = 'my_schema' and defaclobjtype = 'r')")
225+
.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')")
226+
# rubocop:enable Layout/LineLength
227+
end
228+
end
229+
230+
context 'with unset schema name' do
231+
let :params do
232+
{
233+
db: 'test',
234+
role: 'test',
235+
privilege: 'all',
236+
object_type: 'tables',
237+
schema: ''
238+
}
239+
end
240+
241+
let :pre_condition do
242+
"class {'postgresql::server':}"
243+
end
244+
245+
it { is_expected.to compile.with_all_deps }
246+
it { is_expected.to contain_postgresql__server__default_privileges('test') }
247+
it do
248+
# rubocop:disable Layout/LineLength
249+
is_expected.to contain_postgresql_psql('default_privileges:test')
250+
.with_command('ALTER DEFAULT PRIVILEGES GRANT ALL ON TABLES TO "test"')
251+
.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')")
226252
# rubocop:enable Layout/LineLength
227253
end
228254
end
@@ -278,7 +304,7 @@ class {'postgresql::server':}
278304
# rubocop:disable Layout/LineLength
279305
is_expected.to contain_postgresql_psql('default_privileges:test')
280306
.with_command('ALTER DEFAULT PRIVILEGES FOR ROLE target IN SCHEMA public GRANT ALL ON TABLES TO "test"')
281-
.with_unless("SELECT 1 WHERE EXISTS (SELECT * FROM pg_default_acl AS da JOIN pg_namespace AS n ON da.defaclnamespace = n.oid WHERE 'test=arwdDxt/target' = ANY (defaclacl) AND nspname = 'public' and defaclobjtype = 'r')")
307+
.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')")
282308
# rubocop:enable Layout/LineLength
283309
end
284310
end

0 commit comments

Comments
 (0)