Skip to content

Commit d5efb1f

Browse files
committed
Merge pull request puppetlabs#665 from bmjen/squash-620
Support granting permission on sequences.
2 parents d6435e4 + c9ffadd commit d5efb1f

File tree

3 files changed

+138
-9
lines changed

3 files changed

+138
-9
lines changed

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,39 @@ If provided, this will install the given package prior to activating the extensi
646646
####`package_ensure`
647647
By default, the package specified with `package_name` will be installed when the extension is activated, and removed when the extension is deactivated. You can override this behavior by setting the `ensure` value for the package.
648648

649+
###Resource: postgresql::server::grant
650+
This defined type manages grant based access privileges for roles. Consult the PostgreSQL documentation for `grant` for more information.
651+
652+
####`namevar`
653+
Used to uniquely identify this resource, but functionality not used during grant.
654+
655+
####`db`
656+
Database of object which you are granting access on.
657+
658+
####`role`
659+
Role or user whom you are granting access for.
660+
661+
####`privilege`
662+
The privilege you are granting. Can be `ALL`, `ALL PRIVILEGES` or
663+
`object_type` dependent string.
664+
665+
####`object_type`
666+
The type of object you are granting privileges on. Can be `DATABASE`,
667+
`SCHEMA`, `SEQUENCE`, `ALL SEQUENCES IN SCHEMA`, `TABLE` or `ALL
668+
TABLES IN SCHEMA`.
669+
670+
####`object_name`
671+
Object of type `object_type` on which to grant access.
672+
673+
####`psql_db`
674+
Database to execute the grant against. This should not ordinarily be changed from the default, which is `postgres`.
675+
676+
####`psql_user`
677+
OS user for running `psql`. Defaults to the default user for the module, usually `postgres`.
678+
679+
####`port`
680+
Port to use when connecting. Default to 'undef' which generally defaults to 5432 depending on your PostgreSQL packaging.
681+
649682
###Resource: postgresql::server::pg\_hba\_rule
650683
This defined type allows you to create an access rule for `pg_hba.conf`. For more details see the [PostgreSQL documentation](http://www.postgresql.org/docs/8.2/static/auth-pg-hba-conf.html).
651684

manifests/server/grant.pp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@
3434
#'FUNCTION',
3535
#'PROCEDURAL LANGUAGE',
3636
'SCHEMA',
37-
#'SEQUENCE',
37+
'SEQUENCE',
38+
'ALL SEQUENCES IN SCHEMA',
3839
'TABLE',
3940
'ALL TABLES IN SCHEMA',
4041
#'TABLESPACE',
4142
#'VIEW',
4243
)
4344
# You can use ALL TABLES IN SCHEMA by passing schema_name to object_name
45+
# You can use ALL SEQUENCES IN SCHEMA by passing schema_name to object_name
4446

4547
## Validate that the object type's privilege is acceptable
4648
# TODO: this is a terrible hack; if they pass "ALL" as the desired privilege,
@@ -75,6 +77,53 @@
7577
$on_db = $db
7678
$onlyif_function = undef
7779
}
80+
'SEQUENCE': {
81+
$unless_privilege = $_privilege ? {
82+
'ALL' => 'USAGE',
83+
default => $_privilege,
84+
}
85+
validate_string($unless_privilege,'USAGE','ALL','ALL PRIVILEGES')
86+
$unless_function = 'has_sequence_privilege'
87+
$on_db = $db
88+
}
89+
'ALL SEQUENCES IN SCHEMA': {
90+
validate_string($_privilege,'USAGE','ALL','ALL PRIVILEGES')
91+
$unless_function = 'custom'
92+
$on_db = $db
93+
94+
$schema = $object_name
95+
96+
$custom_privilege = $_privilege ? {
97+
'ALL' => 'USAGE',
98+
'ALL PRIVILEGES' => 'USAGE',
99+
default => $_privilege,
100+
}
101+
102+
# This checks if there is a difference between the sequences in the
103+
# specified schema and the sequences for which the role has the specified
104+
# privilege. It uses the EXCEPT clause which computes the set of rows
105+
# that are in the result of the first SELECT statement but not in the
106+
# result of the second one. It then counts the number of rows from this
107+
# operation. If this number is zero then the role has the specified
108+
# privilege for all sequences in the schema and the whole query returns a
109+
# single row, which satisfies the `unless` parameter of Postgresql_psql.
110+
# If this number is not zero then there is at least one sequence for which
111+
# the role does not have the specified privilege, making it necessary to
112+
# execute the GRANT statement.
113+
$custom_unless = "SELECT 1 FROM (
114+
SELECT sequence_name
115+
FROM information_schema.sequences
116+
WHERE sequence_schema='${schema}'
117+
EXCEPT DISTINCT
118+
SELECT object_name as sequence_name
119+
FROM information_schema.role_usage_grants
120+
WHERE object_type='SEQUENCE'
121+
AND grantee='${role}'
122+
AND object_schema='${schema}'
123+
AND privilege_type='${custom_privilege}'
124+
) P
125+
HAVING count(P.sequence_name) = 0"
126+
}
78127
'TABLE': {
79128
$unless_privilege = $_privilege ? {
80129
'ALL' => 'INSERT',

spec/unit/defines/server/grant_spec.rb

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,63 @@
1717
'test'
1818
end
1919

20-
let :params do
21-
{
22-
:db => 'test',
23-
:role => 'test',
24-
}
20+
context 'plain' do
21+
let :params do
22+
{
23+
:db => 'test',
24+
:role => 'test',
25+
}
26+
end
27+
28+
let :pre_condition do
29+
"class {'postgresql::server':}"
30+
end
31+
32+
it { is_expected.to contain_postgresql__server__grant('test') }
2533
end
2634

27-
let :pre_condition do
28-
"class {'postgresql::server':}"
35+
context 'sequence' do
36+
let :params do
37+
{
38+
:db => 'test',
39+
:role => 'test',
40+
:privilege => 'usage',
41+
:object_type => 'sequence',
42+
}
43+
end
44+
45+
let :pre_condition do
46+
"class {'postgresql::server':}"
47+
end
48+
49+
it { is_expected.to contain_postgresql__server__grant('test') }
50+
it { is_expected.to contain_postgresql_psql('grant:test').with(
51+
{
52+
'command' => "GRANT USAGE ON SEQUENCE \"test\" TO\n \"test\"",
53+
'unless' => "SELECT 1 WHERE has_sequence_privilege('test',\n 'test', 'USAGE')",
54+
}) }
2955
end
3056

31-
it { is_expected.to contain_postgresql__server__grant('test') }
57+
context 'all sequences' do
58+
let :params do
59+
{
60+
:db => 'test',
61+
:role => 'test',
62+
:privilege => 'usage',
63+
:object_type => 'all sequences in schema',
64+
:object_name => 'public',
65+
}
66+
end
67+
68+
let :pre_condition do
69+
"class {'postgresql::server':}"
70+
end
71+
72+
it { is_expected.to contain_postgresql__server__grant('test') }
73+
it { is_expected.to contain_postgresql_psql('grant:test').with(
74+
{
75+
'command' => "GRANT USAGE ON ALL SEQUENCES IN SCHEMA \"public\" TO\n \"test\"",
76+
'unless' => "SELECT 1 FROM (\n SELECT sequence_name\n FROM information_schema.sequences\n WHERE sequence_schema='public'\n EXCEPT DISTINCT\n SELECT object_name as sequence_name\n FROM information_schema.role_usage_grants\n WHERE object_type='SEQUENCE'\n AND grantee='test'\n AND object_schema='public'\n AND privilege_type='USAGE'\n ) P\n HAVING count(P.sequence_name) = 0",
77+
}) }
78+
end
3279
end

0 commit comments

Comments
 (0)