mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
postgresql_db: add trust_input parameter (#184)
This commit is contained in:
parent
764cae9f33
commit
5b1652e8fa
3 changed files with 99 additions and 14 deletions
|
@ -105,6 +105,11 @@ options:
|
||||||
- Provides additional arguments when I(state) is C(dump).
|
- Provides additional arguments when I(state) is C(dump).
|
||||||
- Cannot be used with dump-file-format-related arguments like ``--format=d``.
|
- Cannot be used with dump-file-format-related arguments like ``--format=d``.
|
||||||
type: str
|
type: str
|
||||||
|
trust_input:
|
||||||
|
description:
|
||||||
|
- If C(no), check whether values of some parameters are potentially dangerous.
|
||||||
|
type: bool
|
||||||
|
default: yes
|
||||||
seealso:
|
seealso:
|
||||||
- name: CREATE DATABASE reference
|
- name: CREATE DATABASE reference
|
||||||
description: Complete reference of the CREATE DATABASE command documentation.
|
description: Complete reference of the CREATE DATABASE command documentation.
|
||||||
|
@ -207,7 +212,10 @@ else:
|
||||||
|
|
||||||
import ansible_collections.community.general.plugins.module_utils.postgres as pgutils
|
import ansible_collections.community.general.plugins.module_utils.postgres as pgutils
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible_collections.community.general.plugins.module_utils.database import SQLParseError, pg_quote_identifier
|
from ansible_collections.community.general.plugins.module_utils.database import (
|
||||||
|
check_input,
|
||||||
|
SQLParseError,
|
||||||
|
)
|
||||||
from ansible.module_utils.six import iteritems
|
from ansible.module_utils.six import iteritems
|
||||||
from ansible.module_utils.six.moves import shlex_quote
|
from ansible.module_utils.six.moves import shlex_quote
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils._text import to_native
|
||||||
|
@ -224,18 +232,14 @@ class NotSupportedError(Exception):
|
||||||
|
|
||||||
|
|
||||||
def set_owner(cursor, db, owner):
|
def set_owner(cursor, db, owner):
|
||||||
query = 'ALTER DATABASE %s OWNER TO "%s"' % (
|
query = 'ALTER DATABASE "%s" OWNER TO "%s"' % (db, owner)
|
||||||
pg_quote_identifier(db, 'database'),
|
|
||||||
owner)
|
|
||||||
executed_commands.append(query)
|
executed_commands.append(query)
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def set_conn_limit(cursor, db, conn_limit):
|
def set_conn_limit(cursor, db, conn_limit):
|
||||||
query = "ALTER DATABASE %s CONNECTION LIMIT %s" % (
|
query = 'ALTER DATABASE "%s" CONNECTION LIMIT %s' % (db, conn_limit)
|
||||||
pg_quote_identifier(db, 'database'),
|
|
||||||
conn_limit)
|
|
||||||
executed_commands.append(query)
|
executed_commands.append(query)
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
return True
|
return True
|
||||||
|
@ -270,7 +274,7 @@ def db_exists(cursor, db):
|
||||||
|
|
||||||
def db_delete(cursor, db):
|
def db_delete(cursor, db):
|
||||||
if db_exists(cursor, db):
|
if db_exists(cursor, db):
|
||||||
query = "DROP DATABASE %s" % pg_quote_identifier(db, 'database')
|
query = 'DROP DATABASE "%s"' % db
|
||||||
executed_commands.append(query)
|
executed_commands.append(query)
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
return True
|
return True
|
||||||
|
@ -281,11 +285,11 @@ def db_delete(cursor, db):
|
||||||
def db_create(cursor, db, owner, template, encoding, lc_collate, lc_ctype, conn_limit, tablespace):
|
def db_create(cursor, db, owner, template, encoding, lc_collate, lc_ctype, conn_limit, tablespace):
|
||||||
params = dict(enc=encoding, collate=lc_collate, ctype=lc_ctype, conn_limit=conn_limit, tablespace=tablespace)
|
params = dict(enc=encoding, collate=lc_collate, ctype=lc_ctype, conn_limit=conn_limit, tablespace=tablespace)
|
||||||
if not db_exists(cursor, db):
|
if not db_exists(cursor, db):
|
||||||
query_fragments = ['CREATE DATABASE %s' % pg_quote_identifier(db, 'database')]
|
query_fragments = ['CREATE DATABASE "%s"' % db]
|
||||||
if owner:
|
if owner:
|
||||||
query_fragments.append('OWNER "%s"' % owner)
|
query_fragments.append('OWNER "%s"' % owner)
|
||||||
if template:
|
if template:
|
||||||
query_fragments.append('TEMPLATE %s' % pg_quote_identifier(template, 'database'))
|
query_fragments.append('TEMPLATE "%s"' % template)
|
||||||
if encoding:
|
if encoding:
|
||||||
query_fragments.append('ENCODING %(enc)s')
|
query_fragments.append('ENCODING %(enc)s')
|
||||||
if lc_collate:
|
if lc_collate:
|
||||||
|
@ -293,7 +297,7 @@ def db_create(cursor, db, owner, template, encoding, lc_collate, lc_ctype, conn_
|
||||||
if lc_ctype:
|
if lc_ctype:
|
||||||
query_fragments.append('LC_CTYPE %(ctype)s')
|
query_fragments.append('LC_CTYPE %(ctype)s')
|
||||||
if tablespace:
|
if tablespace:
|
||||||
query_fragments.append('TABLESPACE %s' % pg_quote_identifier(tablespace, 'tablespace'))
|
query_fragments.append('TABLESPACE "%s"' % tablespace)
|
||||||
if conn_limit:
|
if conn_limit:
|
||||||
query_fragments.append("CONNECTION LIMIT %(conn_limit)s" % {"conn_limit": conn_limit})
|
query_fragments.append("CONNECTION LIMIT %(conn_limit)s" % {"conn_limit": conn_limit})
|
||||||
query = ' '.join(query_fragments)
|
query = ' '.join(query_fragments)
|
||||||
|
@ -491,9 +495,7 @@ def do_with_password(module, cmd, password):
|
||||||
|
|
||||||
|
|
||||||
def set_tablespace(cursor, db, tablespace):
|
def set_tablespace(cursor, db, tablespace):
|
||||||
query = "ALTER DATABASE %s SET TABLESPACE %s" % (
|
query = 'ALTER DATABASE "%s" SET TABLESPACE "%s"' % (db, tablespace)
|
||||||
pg_quote_identifier(db, 'database'),
|
|
||||||
pg_quote_identifier(tablespace, 'tablespace'))
|
|
||||||
executed_commands.append(query)
|
executed_commands.append(query)
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
return True
|
return True
|
||||||
|
@ -520,6 +522,7 @@ def main():
|
||||||
conn_limit=dict(type='str', default=''),
|
conn_limit=dict(type='str', default=''),
|
||||||
tablespace=dict(type='path', default=''),
|
tablespace=dict(type='path', default=''),
|
||||||
dump_extra_args=dict(type='str', default=None),
|
dump_extra_args=dict(type='str', default=None),
|
||||||
|
trust_input=dict(type='bool', default=True),
|
||||||
)
|
)
|
||||||
|
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
|
@ -542,6 +545,12 @@ def main():
|
||||||
conn_limit = module.params['conn_limit']
|
conn_limit = module.params['conn_limit']
|
||||||
tablespace = module.params['tablespace']
|
tablespace = module.params['tablespace']
|
||||||
dump_extra_args = module.params['dump_extra_args']
|
dump_extra_args = module.params['dump_extra_args']
|
||||||
|
trust_input = module.params['trust_input']
|
||||||
|
|
||||||
|
# Check input
|
||||||
|
if not trust_input:
|
||||||
|
# Check input for potentially dangerous elements:
|
||||||
|
check_input(module, owner, conn_limit, encoding, db, template, tablespace, session_role)
|
||||||
|
|
||||||
raw_connection = state in ("dump", "restore")
|
raw_connection = state in ("dump", "restore")
|
||||||
|
|
||||||
|
|
|
@ -4,3 +4,8 @@ db_user2: 'ansible.db.user2'
|
||||||
tmp_dir: '/tmp'
|
tmp_dir: '/tmp'
|
||||||
db_session_role1: 'session_role1'
|
db_session_role1: 'session_role1'
|
||||||
db_session_role2: 'session_role2'
|
db_session_role2: 'session_role2'
|
||||||
|
|
||||||
|
# To test trust_input parameter and
|
||||||
|
# possibility to create a database with dots in its name
|
||||||
|
db_name_with_dot: 'db.name'
|
||||||
|
suspicious_db_name: '{{ db_name_with_dot }}"; --'
|
||||||
|
|
|
@ -140,6 +140,77 @@
|
||||||
- "'47' in result.stdout"
|
- "'47' in result.stdout"
|
||||||
- "'Joe Smith' in result.stdout"
|
- "'Joe Smith' in result.stdout"
|
||||||
|
|
||||||
|
############################
|
||||||
|
# 1. Test trust_input parameter
|
||||||
|
# 2. Test db name containing dots
|
||||||
|
|
||||||
|
- name: state dump/restore - create database, trust_input no
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ pg_user }}"
|
||||||
|
postgresql_db:
|
||||||
|
state: present
|
||||||
|
name: "{{ suspicious_db_name }}"
|
||||||
|
owner: "{{ db_user1 }}"
|
||||||
|
login_user: "{{ pg_user }}"
|
||||||
|
trust_input: no
|
||||||
|
register: result
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
- result.msg == 'Passed input \'{{ suspicious_db_name }}\' is potentially dangerous'
|
||||||
|
|
||||||
|
- name: state dump/restore - create database, trust_input yes explicitly
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ pg_user }}"
|
||||||
|
postgresql_db:
|
||||||
|
state: present
|
||||||
|
name: "{{ suspicious_db_name }}"
|
||||||
|
owner: "{{ db_user1 }}"
|
||||||
|
login_user: "{{ pg_user }}"
|
||||||
|
trust_input: yes
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: test state=restore to restore the database (expect changed=true)
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ pg_user }}"
|
||||||
|
postgresql_db:
|
||||||
|
name: "{{ db_name_with_dot }}"
|
||||||
|
target: "{{ db_file_name }}"
|
||||||
|
owner: "{{ db_user1 }}"
|
||||||
|
login_user: '{{(test_fixture == "user")|ternary(db_user1, pg_user)}}'
|
||||||
|
target_opts: '{{(test_fixture == "user")|ternary("-n public", omit)}}'
|
||||||
|
login_host: '{{(test_fixture == "user")|ternary("localhost", omit)}}'
|
||||||
|
login_password: '{{(test_fixture == "user")|ternary("password", omit)}}'
|
||||||
|
state: restore
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert output message restore the database
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: state dump/restore - remove databases
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ pg_user }}"
|
||||||
|
postgresql_db:
|
||||||
|
state: absent
|
||||||
|
name: "{{ db_name_with_dot }}"
|
||||||
|
owner: "{{ db_user1 }}"
|
||||||
|
login_user: "{{ pg_user }}"
|
||||||
|
trust_input: yes
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
# Clean up
|
||||||
- name: state dump/restore - remove database name
|
- name: state dump/restore - remove database name
|
||||||
postgresql_db:
|
postgresql_db:
|
||||||
name: "{{ db_name }}"
|
name: "{{ db_name }}"
|
||||||
|
|
Loading…
Reference in a new issue