Make granting on ALL TABLES IN SCHEMA idempotent
Define a proper SELECT statement to feed into Postgresql_psql's `unless` parameter that checks if there are any tables in the specified schema for which the specified role *does not* have the specified privilege. Only then allow the GRANT statement to be executed. For details see comments. Note that this, too, suffers from the problem that there is no feasible way to check if a role has ALL PRIVILEGES on a table in plain SQL. By terrible convention the INSERT privilege represents ALL PRIVILEGES here.
This commit is contained in:
parent
4dbf624b2a
commit
dbbb7aa2b3
1 changed files with 41 additions and 5 deletions
|
@ -75,10 +75,45 @@ define postgresql::server::grant (
|
|||
$on_db = $db
|
||||
}
|
||||
'ALL TABLES IN SCHEMA': {
|
||||
validate_string($_privilege, 'SELECT', 'INSERT', 'UPDATE', 'REFERENCES',
|
||||
'ALL', 'ALL PRIVILEGES')
|
||||
$unless_function = false # There is no way to test it simply
|
||||
validate_string($_privilege,'SELECT','INSERT','UPDATE','DELETE',
|
||||
'TRUNCATE','REFERENCES','TRIGGER','ALL','ALL PRIVILEGES')
|
||||
$unless_function = 'custom'
|
||||
$on_db = $db
|
||||
|
||||
$schema = $object_name
|
||||
|
||||
# Again there seems to be no easy way in plain SQL to check if ALL
|
||||
# PRIVILEGES are granted on a table. By convention we use INSERT
|
||||
# here to represent ALL PRIVILEGES (truly terrible).
|
||||
$custom_privilege = $_privilege ? {
|
||||
'ALL' => 'INSERT',
|
||||
'ALL PRIVILEGES' => 'INSERT',
|
||||
default => $_privilege,
|
||||
}
|
||||
|
||||
# This checks if there is a difference between the tables in the
|
||||
# specified schema and the tables for which the role has the specified
|
||||
# privilege. It uses the EXCEPT clause which computes the set of rows
|
||||
# that are in the result of the first SELECT statement but not in the
|
||||
# result of the second one. It then counts the number of rows from this
|
||||
# operation. If this number is zero then the role has the specified
|
||||
# privilege for all tables in the schema and the whole query returns a
|
||||
# single row, which satisfies the `unless` parameter of Postgresql_psql.
|
||||
# If this number is not zero then there is at least one table for which
|
||||
# the role does not have the specified privilege, making it necessary to
|
||||
# execute the GRANT statement.
|
||||
$custom_unless = "SELECT 1 FROM (
|
||||
SELECT table_name
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema='${schema}'
|
||||
EXCEPT DISTINCT
|
||||
SELECT table_name
|
||||
FROM information_schema.role_table_grants
|
||||
WHERE grantee='${role}'
|
||||
AND table_schema='${schema}'
|
||||
AND privilege_type='${custom_privilege}'
|
||||
) P
|
||||
HAVING count(P.table_name) = 0"
|
||||
}
|
||||
default: {
|
||||
fail("Missing privilege validation for object type ${_object_type}")
|
||||
|
@ -103,8 +138,9 @@ define postgresql::server::grant (
|
|||
}
|
||||
|
||||
$_unless = $unless_function ? {
|
||||
false => undef,
|
||||
default => "SELECT 1 WHERE ${unless_function}('${role}',
|
||||
false => undef,
|
||||
'custom' => $custom_unless,
|
||||
default => "SELECT 1 WHERE ${unless_function}('${role}',
|
||||
'${_granted_object}', '${unless_privilege}')",
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue