|
2 | 2 | define postgresql::server::grant (
|
3 | 3 | String $role,
|
4 | 4 | String $db,
|
5 |
| - Optional[String] $privilege = undef, |
6 |
| - String $object_type = 'database', |
7 |
| - Optional[String[1]] $object_name = undef, |
8 |
| - String $psql_db = $postgresql::server::default_database, |
9 |
| - String $psql_user = $postgresql::server::user, |
10 |
| - Integer $port = $postgresql::server::port, |
11 |
| - Boolean $onlyif_exists = false, |
12 |
| - Hash $connect_settings = $postgresql::server::default_connect_settings, |
| 5 | + Optional[String] $privilege = undef, |
| 6 | + String $object_type = 'database', |
| 7 | + Optional[String[1]] $object_name = undef, |
| 8 | + String $psql_db = $postgresql::server::default_database, |
| 9 | + String $psql_user = $postgresql::server::user, |
| 10 | + Integer $port = $postgresql::server::port, |
| 11 | + Boolean $onlyif_exists = false, |
| 12 | + Hash $connect_settings = $postgresql::server::default_connect_settings, |
| 13 | + Enum['present', 'absent'] $ensure = 'present', |
13 | 14 | ) {
|
14 | 15 |
|
| 16 | + case $ensure { |
| 17 | + 'present': { |
| 18 | + $sql_command = 'GRANT %s ON %s "%s" TO "%s"' |
| 19 | + $unless_is = true |
| 20 | + } |
| 21 | + 'absent': { |
| 22 | + $sql_command = 'REVOKE %s ON %s "%s" FROM "%s"' |
| 23 | + $unless_is = false |
| 24 | + } |
| 25 | + default: { |
| 26 | + fail("Unknown value for ensure '${ensure}'.") |
| 27 | + } |
| 28 | + } |
| 29 | + |
15 | 30 | $group = $postgresql::server::group
|
16 | 31 | $psql_path = $postgresql::server::psql_path
|
17 | 32 |
|
|
125 | 140 | # If this number is not zero then there is at least one sequence for which
|
126 | 141 | # the role does not have the specified privilege, making it necessary to
|
127 | 142 | # execute the GRANT statement.
|
128 |
| - $custom_unless = "SELECT 1 FROM ( |
129 |
| - SELECT sequence_name |
130 |
| - FROM information_schema.sequences |
131 |
| - WHERE sequence_schema='${schema}' |
132 |
| - EXCEPT DISTINCT |
133 |
| - SELECT object_name as sequence_name |
134 |
| - FROM ( |
135 |
| - SELECT object_schema, |
136 |
| - object_name, |
137 |
| - grantee, |
138 |
| - CASE privs_split |
139 |
| - WHEN 'r' THEN 'SELECT' |
140 |
| - WHEN 'w' THEN 'UPDATE' |
141 |
| - WHEN 'U' THEN 'USAGE' |
142 |
| - END AS privilege_type |
143 |
| - FROM ( |
144 |
| - SELECT DISTINCT |
145 |
| - object_schema, |
146 |
| - object_name, |
147 |
| - (regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[1] AS grantee, |
148 |
| - regexp_split_to_table((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[2],E'\\s*') AS privs_split |
149 |
| - FROM ( |
150 |
| - SELECT n.nspname as object_schema, |
151 |
| - c.relname as object_name, |
152 |
| - regexp_split_to_table(array_to_string(c.relacl,','),',') AS privs |
153 |
| - FROM pg_catalog.pg_class c |
154 |
| - LEFT JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid |
155 |
| - WHERE c.relkind = 'S' |
156 |
| - AND n.nspname NOT IN ( 'pg_catalog', 'information_schema' ) |
157 |
| - ) P1 |
158 |
| - ) P2 |
159 |
| - ) P3 |
160 |
| - WHERE grantee='${role}' |
161 |
| - AND object_schema='${schema}' |
162 |
| - AND privilege_type='${custom_privilege}' |
163 |
| - ) P |
164 |
| - HAVING count(P.sequence_name) = 0" |
| 143 | + if $ensure == 'present' { |
| 144 | + $custom_unless = "SELECT 1 FROM ( |
| 145 | + SELECT sequence_name |
| 146 | + FROM information_schema.sequences |
| 147 | + WHERE sequence_schema='${schema}' |
| 148 | + EXCEPT DISTINCT |
| 149 | + SELECT object_name as sequence_name |
| 150 | + FROM ( |
| 151 | + SELECT object_schema, |
| 152 | + object_name, |
| 153 | + grantee, |
| 154 | + CASE privs_split |
| 155 | + WHEN 'r' THEN 'SELECT' |
| 156 | + WHEN 'w' THEN 'UPDATE' |
| 157 | + WHEN 'U' THEN 'USAGE' |
| 158 | + END AS privilege_type |
| 159 | + FROM ( |
| 160 | + SELECT DISTINCT |
| 161 | + object_schema, |
| 162 | + object_name, |
| 163 | + (regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[1] AS grantee, |
| 164 | + regexp_split_to_table((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[2],E'\\s*') AS privs_split |
| 165 | + FROM ( |
| 166 | + SELECT n.nspname as object_schema, |
| 167 | + c.relname as object_name, |
| 168 | + regexp_split_to_table(array_to_string(c.relacl,','),',') AS privs |
| 169 | + FROM pg_catalog.pg_class c |
| 170 | + LEFT JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid |
| 171 | + WHERE c.relkind = 'S' |
| 172 | + AND n.nspname NOT IN ( 'pg_catalog', 'information_schema' ) |
| 173 | + ) P1 |
| 174 | + ) P2 |
| 175 | + ) P3 |
| 176 | + WHERE grantee='${role}' |
| 177 | + AND object_schema='${schema}' |
| 178 | + AND privilege_type='${custom_privilege}' |
| 179 | + ) P |
| 180 | + HAVING count(P.sequence_name) = 0" |
| 181 | + } else { |
| 182 | + # ensure == absent |
| 183 | + $custom_unless = "SELECT 1 FROM ( |
| 184 | + SELECT object_name as sequence_name |
| 185 | + FROM ( |
| 186 | + SELECT object_schema, |
| 187 | + object_name, |
| 188 | + grantee, |
| 189 | + CASE privs_split |
| 190 | + WHEN 'r' THEN 'SELECT' |
| 191 | + WHEN 'w' THEN 'UPDATE' |
| 192 | + WHEN 'U' THEN 'USAGE' |
| 193 | + END AS privilege_type |
| 194 | + FROM ( |
| 195 | + SELECT DISTINCT |
| 196 | + object_schema, |
| 197 | + object_name, |
| 198 | + (regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[1] AS grantee, |
| 199 | + regexp_split_to_table((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[2],E'\\s*') AS privs_split |
| 200 | + FROM ( |
| 201 | + SELECT n.nspname as object_schema, |
| 202 | + c.relname as object_name, |
| 203 | + regexp_split_to_table(array_to_string(c.relacl,','),',') AS privs |
| 204 | + FROM pg_catalog.pg_class c |
| 205 | + LEFT JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid |
| 206 | + WHERE c.relkind = 'S' |
| 207 | + AND n.nspname NOT IN ( 'pg_catalog', 'information_schema' ) |
| 208 | + ) P1 |
| 209 | + ) P2 |
| 210 | + ) P3 |
| 211 | + WHERE grantee='${role}' |
| 212 | + AND object_schema='${schema}' |
| 213 | + AND privilege_type='${custom_privilege}' |
| 214 | + ) P |
| 215 | + HAVING count(P.sequence_name) = 0" |
| 216 | + } |
165 | 217 | }
|
166 | 218 | 'TABLE': {
|
167 | 219 | $unless_privilege = $_privilege ? {
|
|
187 | 239 | $schema = $object_name
|
188 | 240 |
|
189 | 241 | # Again there seems to be no easy way in plain SQL to check if ALL
|
190 |
| - # PRIVILEGES are granted on a table. By convention we use INSERT |
191 |
| - # here to represent ALL PRIVILEGES (truly terrible). |
192 |
| - $custom_privilege = $_privilege ? { |
193 |
| - 'ALL' => 'INSERT', |
194 |
| - 'ALL PRIVILEGES' => 'INSERT', |
195 |
| - default => $_privilege, |
| 242 | + # PRIVILEGES are granted on a table. |
| 243 | + # There are currently 7 possible priviliges: |
| 244 | + # ('SELECT','UPDATE','INSERT','DELETE','TRIGGER','REFERENCES','TRUNCATE') |
| 245 | + # This list is consistant from Postgresql 8.0 |
| 246 | + # |
| 247 | + # There are 4 cases to cover, each with it's own distinct unless clause: |
| 248 | + # grant ALL |
| 249 | + # grant SELECT (or INSERT or DELETE ...) |
| 250 | + # revoke ALL |
| 251 | + # revoke SELECT (or INSERT or DELETE ...) |
| 252 | + |
| 253 | + if $ensure == 'present' { |
| 254 | + if $_privilege == 'ALL' or $_privilege == 'ALL PRIVILEGES' { |
| 255 | + # GRANT ALL |
| 256 | + $custom_unless = "SELECT 1 FROM |
| 257 | + ( SELECT tablename FROM pg_catalog.pg_tables |
| 258 | + WHERE schemaname = '${schema}' EXCEPT |
| 259 | + SELECT table_name FROM |
| 260 | + (SELECT table_name,count(privilege_type) FROM information_schema.role_table_grants |
| 261 | + WHERE grantee = '${role}' AND table_schema = '${schema}' |
| 262 | + AND privilege_type IN ('SELECT','UPDATE','INSERT','DELETE','TRIGGER','REFERENCES','TRUNCATE') |
| 263 | + GROUP BY table_name |
| 264 | + ) AS P WHERE P.count >= 7 |
| 265 | + ) AS TBLS HAVING TBLS.count=0" |
| 266 | + |
| 267 | + } else { |
| 268 | + # GRANT $_privilege |
| 269 | + $custom_unless = "SELECT 1 FROM |
| 270 | + ( SELECT tablename FROM pg_catalog.pg_tables |
| 271 | + WHERE schemaname = '${schema}' EXCEPT |
| 272 | + SELECT table_name FROM |
| 273 | + information_schema.role_table_grants |
| 274 | + WHERE grantee = '${role}' AND table_schema = '${schema}' AND privilege_type = '${_privilege}' |
| 275 | + ) AS TBLS HAVING TBLS.count=0" |
| 276 | + } |
| 277 | + } else { |
| 278 | + if $_privilege == 'ALL' or $_privilege == 'ALL PRIVILEGES' { |
| 279 | + # REVOKE ALL |
| 280 | + $custom_unless = "SELECT 1 FROM |
| 281 | + ( SELECT table_name FROM information_schema.role_table_grants |
| 282 | + WHERE grantee = '${role}' AND table_schema ='${schema}' |
| 283 | + ) AS TBLS HAVING TBLS.count=0" |
| 284 | + } else { |
| 285 | + # REVOKE $_privilege |
| 286 | + $custom_unless = "SELECT 1 FROM |
| 287 | + ( SELECT table_name FROM information_schema.role_table_grants |
| 288 | + WHERE grantee = '${role}' AND table_schema ='${schema}' |
| 289 | + AND privilege_type = '${_privilege}' |
| 290 | + ) AS TBLS HAVING TBLS.count=0" |
| 291 | + } |
196 | 292 | }
|
197 | 293 |
|
198 |
| - # This checks if there is a difference between the tables in the |
199 |
| - # specified schema and the tables for which the role has the specified |
200 |
| - # privilege. It uses the EXCEPT clause which computes the set of rows |
201 |
| - # that are in the result of the first SELECT statement but not in the |
202 |
| - # result of the second one. It then counts the number of rows from this |
203 |
| - # operation. If this number is zero then the role has the specified |
204 |
| - # privilege for all tables in the schema and the whole query returns a |
205 |
| - # single row, which satisfies the `unless` parameter of Postgresql_psql. |
206 |
| - # If this number is not zero then there is at least one table for which |
207 |
| - # the role does not have the specified privilege, making it necessary to |
208 |
| - # execute the GRANT statement. |
209 |
| - $custom_unless = "SELECT 1 FROM ( |
210 |
| - SELECT table_name |
211 |
| - FROM information_schema.tables |
212 |
| - WHERE table_schema='${schema}' |
213 |
| - EXCEPT DISTINCT |
214 |
| - SELECT table_name |
215 |
| - FROM information_schema.role_table_grants |
216 |
| - WHERE grantee='${role}' |
217 |
| - AND table_schema='${schema}' |
218 |
| - AND privilege_type='${custom_privilege}' |
219 |
| - ) P |
220 |
| - HAVING count(P.table_name) = 0" |
221 | 294 | }
|
222 | 295 | 'LANGUAGE': {
|
223 | 296 | $unless_privilege = $_privilege ? {
|
|
259 | 332 | $_unless = $unless_function ? {
|
260 | 333 | false => undef,
|
261 | 334 | 'custom' => $custom_unless,
|
262 |
| - default => "SELECT 1 WHERE ${unless_function}('${role}', |
263 |
| - '${_granted_object}', '${unless_privilege}')", |
| 335 | + default => "SELECT * FROM ${unless_function}('${role}', |
| 336 | + '${_granted_object}', '${unless_privilege}') WHERE ${unless_function} = ${unless_is}", |
264 | 337 | }
|
265 | 338 |
|
266 | 339 | $_onlyif = $onlyif_function ? {
|
|
269 | 342 | default => undef,
|
270 | 343 | }
|
271 | 344 |
|
272 |
| - $grant_cmd = "GRANT ${_privilege} ON ${_object_type} \"${_togrant_object}\" TO |
273 |
| - \"${role}\"" |
| 345 | + $grant_cmd = sprintf($sql_command, $_privilege, $_object_type, $_togrant_object, $role) |
| 346 | + |
274 | 347 | postgresql_psql { "grant:${name}":
|
275 | 348 | command => $grant_cmd,
|
276 | 349 | db => $on_db,
|
|
0 commit comments