diff --git a/changelogs/fragments/264-postgresql_idx_add_trust_input_parameter.yml b/changelogs/fragments/264-postgresql_idx_add_trust_input_parameter.yml new file mode 100644 index 0000000000..0b056831b6 --- /dev/null +++ b/changelogs/fragments/264-postgresql_idx_add_trust_input_parameter.yml @@ -0,0 +1,2 @@ +minor_changes: +- postgresql_idx - add the ``trust_input`` parameter (https://github.com/ansible-collections/community.general/pull/264). diff --git a/plugins/modules/database/postgresql/postgresql_idx.py b/plugins/modules/database/postgresql/postgresql_idx.py index 507af2a32e..2efdd17ef1 100644 --- a/plugins/modules/database/postgresql/postgresql_idx.py +++ b/plugins/modules/database/postgresql/postgresql_idx.py @@ -114,6 +114,11 @@ options: - Mutually exclusive with I(concurrent=yes) type: bool default: no + trust_input: + description: + - If C(no), check whether values of some parameters are potentially dangerous. + type: bool + default: yes seealso: - module: postgresql_table @@ -258,6 +263,7 @@ except ImportError: pass from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.general.plugins.module_utils.database import check_input from ansible_collections.community.general.plugins.module_utils.postgres import ( connect_to_db, exec_sql, @@ -360,7 +366,8 @@ class Index(object): self.exists = False return False - def create(self, tblname, idxtype, columns, cond, tblspace, storage_params, concurrent=True, unique=False): + def create(self, tblname, idxtype, columns, cond, tblspace, + storage_params, concurrent=True, unique=False): """Create PostgreSQL index. Return True if success, otherwise, return False. @@ -391,12 +398,9 @@ class Index(object): if concurrent: query += ' CONCURRENTLY' - query += ' %s' % self.name + query += ' "%s"' % self.name - if self.schema: - query += ' ON %s.%s ' % (self.schema, tblname) - else: - query += 'public.%s ' % tblname + query += ' ON "%s"."%s" ' % (self.schema, tblname) query += 'USING %s (%s)' % (idxtype, columns) @@ -404,7 +408,7 @@ class Index(object): query += ' WITH (%s)' % storage_params if tblspace: - query += ' TABLESPACE %s' % tblspace + query += ' TABLESPACE "%s"' % tblspace if cond: query += ' WHERE %s' % cond @@ -438,9 +442,9 @@ class Index(object): query += ' CONCURRENTLY' if not schema: - query += ' public.%s' % self.name + query += ' "public"."%s"' % self.name else: - query += ' %s.%s' % (schema, self.name) + query += ' "%s"."%s"' % (schema, self.name) if cascade: query += ' CASCADE' @@ -475,6 +479,7 @@ def main(): storage_params=dict(type='list', elements='str'), cascade=dict(type='bool', default=False), schema=dict(type='str'), + trust_input=dict(type='bool', default=True), ) module = AnsibleModule( argument_spec=argument_spec, @@ -493,6 +498,13 @@ def main(): storage_params = module.params["storage_params"] cascade = module.params["cascade"] schema = module.params["schema"] + session_role = module.params["session_role"] + trust_input = module.params["trust_input"] + + if not trust_input: + # Check input for potentially dangerous elements: + check_input(module, idxname, session_role, schema, table, columns, + tablespace, storage_params, cond) if concurrent and cascade: module.fail_json(msg="Concurrent mode and cascade parameters are mutually exclusive") diff --git a/tests/integration/targets/postgresql_idx/tasks/postgresql_idx_initial.yml b/tests/integration/targets/postgresql_idx/tasks/postgresql_idx_initial.yml index 19de216f2a..095165c59b 100644 --- a/tests/integration/targets/postgresql_idx/tasks/postgresql_idx_initial.yml +++ b/tests/integration/targets/postgresql_idx/tasks/postgresql_idx_initial.yml @@ -3,17 +3,20 @@ become: true shell: psql postgres -U "{{ pg_user }}" -t -c "CREATE TABLE test_table (id int, story text);" ignore_errors: true + - name: postgresql_idx - drop test tablespace called ssd if exists become_user: '{{ pg_user }}' become: true shell: psql postgres -U "{{ pg_user }}" -t -c "DROP TABLESPACE IF EXISTS ssd;" ignore_errors: true + - name: postgresql_idx - drop dir for test tablespace become: true file: path: /mnt/ssd state: absent ignore_errors: true + - name: postgresql_idx - create dir for test tablespace become: true file: @@ -22,22 +25,26 @@ owner: '{{ pg_user }}' mode: '0755' ignore_errors: true + - name: postgresql_idx - create test tablespace called ssd become_user: '{{ pg_user }}' become: true shell: psql postgres -U "{{ pg_user }}" -t -c "CREATE TABLESPACE ssd LOCATION '/mnt/ssd';" ignore_errors: true register: tablespace + - name: postgresql_idx - create test schema become_user: '{{ pg_user }}' become: true shell: psql postgres -U "{{ pg_user }}" -t -c "CREATE SCHEMA foo;" ignore_errors: true + - name: postgresql_idx - create table in non-default schema become_user: '{{ pg_user }}' become: true shell: psql postgres -U "{{ pg_user }}" -t -c "CREATE TABLE foo.foo_table (id int, story text);" ignore_errors: true + - name: postgresql_idx - create btree index in check_mode become_user: '{{ pg_user }}' become: true @@ -50,6 +57,7 @@ check_mode: true register: result ignore_errors: true + - assert: that: - result is changed @@ -61,6 +69,7 @@ - result.storage_params == [] - result.schema == '' - result.query == '' + - name: postgresql_idx - check nothing changed after the previous step become_user: '{{ pg_user }}' become: true @@ -69,9 +78,11 @@ login_user: '{{ pg_user }}' query: SELECT 1 FROM pg_indexes WHERE indexname = 'test0_idx' register: result + - assert: that: - result.rowcount == 0 + - name: postgresql_idx - create btree index concurrently become_user: '{{ pg_user }}' become: true @@ -81,8 +92,10 @@ table: test_table columns: id, story idxname: test0_idx + trust_input: no register: result ignore_errors: true + - assert: that: - result is changed @@ -93,7 +106,8 @@ - result.tblspace == '' - result.storage_params == [] - result.schema == 'public' - - result.query == 'CREATE INDEX CONCURRENTLY test0_idx ON public.test_table USING BTREE (id, story)' + - result.query == 'CREATE INDEX CONCURRENTLY "test0_idx" ON "public"."test_table" USING BTREE (id, story)' + - name: postgresql_idx - check the index exists after the previous step become_user: '{{ pg_user }}' become: true @@ -102,9 +116,11 @@ login_user: '{{ pg_user }}' query: SELECT 1 FROM pg_indexes WHERE indexname = 'test0_idx' register: result + - assert: that: - result.rowcount == 1 + - name: postgresql_idx - try to create existing index again become_user: '{{ pg_user }}' become: true @@ -116,6 +132,7 @@ idxname: test0_idx register: result ignore_errors: true + - assert: that: - result is not changed @@ -127,6 +144,7 @@ - result.storage_params == [] - result.schema == 'public' - result.query == '' + - name: postgresql_idx - create btree index - non-default schema, tablespace, storage parameter become_user: '{{ pg_user }}' become: true @@ -141,9 +159,11 @@ idxname: foo_test_idx tablespace: ssd storage_params: fillfactor=90 + trust_input: no register: result ignore_errors: true when: tablespace.rc == 0 + - assert: that: - result is changed @@ -154,8 +174,9 @@ - result.tblspace == 'ssd' - result.storage_params == [ "fillfactor=90" ] - result.schema == 'foo' - - result.query == 'CREATE INDEX CONCURRENTLY foo_test_idx ON foo.foo_table USING BTREE (id,story) WITH (fillfactor=90) TABLESPACE ssd' + - result.query == 'CREATE INDEX CONCURRENTLY "foo_test_idx" ON "foo"."foo_table" USING BTREE (id,story) WITH (fillfactor=90) TABLESPACE "ssd"' when: tablespace.rc == 0 + - name: postgresql_idx - create brin index not concurrently become_user: '{{ pg_user }}' become: true @@ -169,8 +190,10 @@ columns: id idxname: test_brin_idx concurrent: false + trust_input: no register: result ignore_errors: true + - assert: that: - result is changed @@ -181,8 +204,9 @@ - result.tblspace == '' - result.storage_params == [] - result.schema == 'public' - - result.query == 'CREATE INDEX test_brin_idx ON public.test_table USING brin (id)' + - result.query == 'CREATE INDEX "test_brin_idx" ON "public"."test_table" USING brin (id)' when: postgres_version_resp.stdout is version('9.5', '>=') + - name: postgresql_idx - create index with condition become_user: '{{ pg_user }}' become: true @@ -193,8 +217,10 @@ columns: id idxname: test1_idx cond: id > 1 AND id != 10 + trust_input: no register: result ignore_errors: true + - assert: that: - result is changed @@ -205,7 +231,8 @@ - result.tblspace == '' - result.storage_params == [] - result.schema == 'public' - - result.query == 'CREATE INDEX CONCURRENTLY test1_idx ON public.test_table USING BTREE (id) WHERE id > 1 AND id != 10' + - result.query == 'CREATE INDEX CONCURRENTLY "test1_idx" ON "public"."test_table" USING BTREE (id) WHERE id > 1 AND id != 10' + - name: postgresql_idx - create unique index become_user: '{{ pg_user }}' become: true @@ -216,8 +243,10 @@ columns: story idxname: test_unique0_idx unique: true + trust_input: no register: result ignore_errors: true + - assert: that: - result is changed @@ -228,7 +257,8 @@ - result.tblspace == '' - result.storage_params == [] - result.schema == 'public' - - result.query == 'CREATE UNIQUE INDEX CONCURRENTLY test_unique0_idx ON public.test_table USING BTREE (story)' + - result.query == 'CREATE UNIQUE INDEX CONCURRENTLY "test_unique0_idx" ON "public"."test_table" USING BTREE (story)' + - name: postgresql_idx - avoid unique index with type different of btree become_user: '{{ pg_user }}' become: true @@ -243,10 +273,12 @@ type: brin register: result ignore_errors: true + - assert: that: - result is not changed - result.msg == 'Only btree currently supports unique indexes' + - name: postgresql_idx - drop index from specific schema cascade in check_mode become_user: '{{ pg_user }}' become: true @@ -258,10 +290,12 @@ cascade: true state: absent concurrent: false + trust_input: yes check_mode: true register: result ignore_errors: true when: tablespace.rc == 0 + - assert: that: - result is changed @@ -270,6 +304,7 @@ - result.schema == 'foo' - result.query == '' when: tablespace.rc == 0 + - name: postgresql_idx - check the index exists after the previous step become_user: '{{ pg_user }}' become: true @@ -279,10 +314,12 @@ query: SELECT 1 FROM pg_indexes WHERE indexname = 'foo_test_idx' AND schemaname = 'foo' register: result when: tablespace.rc == 0 + - assert: that: - result.rowcount == 1 when: tablespace.rc == 0 + - name: postgresql_idx - drop index from specific schema cascade become_user: '{{ pg_user }}' become: true @@ -297,14 +334,16 @@ register: result ignore_errors: true when: tablespace.rc == 0 + - assert: that: - result is changed - result.name == 'foo_test_idx' - result.state == 'absent' - result.schema == 'foo' - - result.query == 'DROP INDEX foo.foo_test_idx CASCADE' + - result.query == 'DROP INDEX "foo"."foo_test_idx" CASCADE' when: tablespace.rc == 0 + - name: postgresql_idx - check the index doesn't exist after the previous step become_user: '{{ pg_user }}' become: true @@ -314,10 +353,12 @@ query: SELECT 1 FROM pg_indexes WHERE indexname = 'foo_test_idx' and schemaname = 'foo' register: result when: tablespace.rc == 0 + - assert: that: - result.rowcount == 0 when: tablespace.rc == 0 + - name: postgresql_idx - try to drop not existing index become_user: '{{ pg_user }}' become: true @@ -329,6 +370,7 @@ state: absent register: result ignore_errors: true + - assert: that: - result is not changed