Skip to content

Commit f9f18d0

Browse files
Support grants and revokes on foreign tables (ansible-collections#725)
* Support grants on foreign tables in postgresql_privs module * Adds tests for granting and revoking foreign tables * Adds changelog fragment * Updates documentation to reference foreign table support * typo * Update plugins/modules/postgresql_privs.py --------- Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
1 parent 19f3901 commit f9f18d0

File tree

4 files changed

+124
-4
lines changed

4 files changed

+124
-4
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
minor_changes:
3+
- postgresql_privs - adds support for granting and revoking privileges on foreign tables
4+
(https://github.com/ansible-collections/community.postgresql/issues/724).

plugins/modules/postgresql_privs.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
- The C(type) choice is available since Ansible version 2.10.
4848
- The C(procedure) is supported since collection version 1.3.0 and PostgreSQL 11.
4949
- The C(parameter) is supported since collection version 3.1.0 and PostgreSQL 15.
50+
- The C(table) is inclusive of foreign tables since collection version 3.6.0.
5051
type: str
5152
default: table
5253
choices: [ database, default_privs, foreign_data_wrapper, foreign_server, function,
@@ -549,11 +550,11 @@ def get_all_tables_in_schema(self, schema):
549550
query = """SELECT relname
550551
FROM pg_catalog.pg_class c
551552
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
552-
WHERE nspname = %s AND relkind in ('r', 'v', 'm', 'p')"""
553+
WHERE nspname = %s AND relkind in ('r', 'v', 'm', 'p', 'f')"""
553554
self.execute(query, (schema,))
554555
else:
555556
query = ("SELECT relname FROM pg_catalog.pg_class "
556-
"WHERE relkind in ('r', 'v', 'm', 'p')")
557+
"WHERE relkind in ('r', 'v', 'm', 'p', 'f')")
557558
self.execute(query)
558559
return [t["relname"] for t in self.cursor.fetchall()]
559560

@@ -621,12 +622,12 @@ def get_table_acls(self, schema, tables):
621622
query = """SELECT relacl::text
622623
FROM pg_catalog.pg_class c
623624
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
624-
WHERE nspname = %s AND relkind in ('r','p','v','m') AND relname = ANY (%s)
625+
WHERE nspname = %s AND relkind in ('r','p','v','m','f') AND relname = ANY (%s)
625626
ORDER BY relname"""
626627
self.execute(query, (schema, tables))
627628
else:
628629
query = ("SELECT relacl::text FROM pg_catalog.pg_class "
629-
"WHERE relkind in ('r','p','v','m') AND relname = ANY (%s) "
630+
"WHERE relkind in ('r','p','v','m','f') AND relname = ANY (%s) "
630631
"ORDER BY relname")
631632
self.execute(query)
632633
return [t["relacl"] for t in self.cursor.fetchall()]

tests/integration/targets/postgresql_privs/tasks/main.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@
1717
# Tests default_privs with target_role:
1818
- include_tasks: test_target_role.yml
1919
when: postgres_version_resp.stdout is version('9.4', '>=')
20+
21+
# Tests involving foreign tables:
22+
- include_tasks: postgresql_privs_foreign_tables.yml
23+
when: postgres_version_resp.stdout is version('9.4', '>=')
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#
2+
# Test settings privileges for foreign tables
3+
#
4+
- name: Create db
5+
become_user: "{{ pg_user }}"
6+
become: true
7+
postgresql_db:
8+
name: "{{ db_name }}"
9+
state: "present"
10+
login_user: "{{ pg_user }}"
11+
12+
- name: Create some tables on the db
13+
become_user: "{{ pg_user }}"
14+
become: true
15+
shell: echo "create table test_table1 (field text);" | psql {{ db_name }}
16+
17+
- vars:
18+
db_password: 'secretù' # use UTF-8
19+
block:
20+
- name: Create a user with some permissions on the db
21+
become_user: "{{ pg_user }}"
22+
become: true
23+
postgresql_user:
24+
name: "{{ db_user1 }}"
25+
encrypted: 'true'
26+
password: "md5{{ (db_password ~ db_user1) | hash('md5')}}"
27+
db: "{{ db_name }}"
28+
login_user: "{{ pg_user }}"
29+
30+
- name: Install foreign data wrapper extension
31+
become: yes
32+
become_user: "{{ pg_user }}"
33+
postgresql_query:
34+
login_db: "{{ db_name }}"
35+
query: "CREATE EXTENSION IF NOT EXISTS postgres_fdw"
36+
37+
- name: Create foreign server
38+
become: yes
39+
become_user: "{{ pg_user }}"
40+
postgresql_query:
41+
login_db: "{{ db_name }}"
42+
query: "CREATE SERVER IF NOT EXISTS self FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'localhost',dbname '{{ db_name }}')"
43+
44+
- name: Create user mapping
45+
become: yes
46+
become_user: "{{ pg_user }}"
47+
postgresql_query:
48+
login_db: "{{ db_name }}"
49+
query: "CREATE USER MAPPING IF NOT EXISTS FOR CURRENT_USER SERVER self OPTIONS (user '{{ pg_user }}')"
50+
51+
- name: Create foreign table
52+
become: yes
53+
become_user: "{{ pg_user }}"
54+
postgresql_query:
55+
login_db: "{{ db_name }}"
56+
query: "CREATE FOREIGN TABLE IF NOT EXISTS foreign_table1 (field text) SERVER self OPTIONS (table_name 'test_table1')"
57+
58+
- name: Grant a single privilege on foreign table
59+
become_user: "{{ pg_user }}"
60+
become: true
61+
postgresql_privs:
62+
state: "present"
63+
roles: "{{ db_user1 }}"
64+
privs: "INSERT"
65+
objs: "foreign_table1"
66+
login_db: "{{ db_name }}"
67+
login_user: "{{ pg_user }}"
68+
trust_input: false
69+
70+
- name: Check that permissions were added (foreign_table1)
71+
become_user: "{{ pg_user }}"
72+
become: true
73+
postgresql_query:
74+
login_db: '{{ db_name }}'
75+
query: "select privilege_type from information_schema.role_table_grants where grantee='{{ db_user1 }}' and table_name='foreign_table1'"
76+
register: result_table1
77+
78+
- assert:
79+
that:
80+
- result_table1.rowcount == 1
81+
- result_table1.query_result[0]['privilege_type'] == 'INSERT'
82+
83+
- name: Revoke privileges on foreign table
84+
become_user: "{{ pg_user }}"
85+
become: true
86+
postgresql_privs:
87+
state: "absent"
88+
roles: "{{ db_user1 }}"
89+
privs: "INSERT"
90+
objs: "foreign_table1"
91+
db: "{{ db_name }}"
92+
login_user: "{{ pg_user }}"
93+
trust_input: false
94+
register: result
95+
96+
- name: Check that ansible reports it changed the user
97+
assert:
98+
that:
99+
- result is changed
100+
101+
- name: Check that permissions were revoked (foreign_table1)
102+
become_user: "{{ pg_user }}"
103+
become: true
104+
postgresql_query:
105+
login_db: '{{ db_name }}'
106+
query: "select privilege_type from information_schema.role_table_grants where grantee='{{ db_user1 }}' and table_name='foreign_table1'"
107+
register: result_table1
108+
109+
- assert:
110+
that:
111+
- result_table1.rowcount == 0

0 commit comments

Comments
 (0)