1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

Add tls parameter to redis module (#4207)

* Add tls parameter to redis module

* Rename changelog fragment to match PR

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>

* Port redis module to redis auth module util

* Update changelogs/fragments/4207-add-redis-tls-support.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/modules/database/misc/redis.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Undo reuse of redis auth doc fragment

* Use doc fragment.

Co-authored-by: Julian Faude <julian.faude@zweiacht.de>
Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
jcharlytown 2022-03-11 06:54:38 +01:00 committed by GitHub
parent 10ca62905f
commit 9a74ace1e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 60 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- redis - add authentication parameters ``login_user``, ``tls``, ``validate_certs``, and ``ca_certs`` (https://github.com/ansible-collections/community.general/pull/4207).

View file

@ -27,20 +27,20 @@ except ImportError:
HAS_CERTIFI_PACKAGE = False HAS_CERTIFI_PACKAGE = False
def fail_imports(module): def fail_imports(module, needs_certifi=True):
errors = [] errors = []
traceback = [] traceback = []
if not HAS_REDIS_PACKAGE: if not HAS_REDIS_PACKAGE:
errors.append(missing_required_lib('redis')) errors.append(missing_required_lib('redis'))
traceback.append(REDIS_IMP_ERR) traceback.append(REDIS_IMP_ERR)
if not HAS_CERTIFI_PACKAGE: if not HAS_CERTIFI_PACKAGE and needs_certifi:
errors.append(missing_required_lib('certifi')) errors.append(missing_required_lib('certifi'))
traceback.append(CERTIFI_IMPORT_ERROR) traceback.append(CERTIFI_IMPORT_ERROR)
if errors: if errors:
module.fail_json(errors=errors, traceback='\n'.join(traceback)) module.fail_json(errors=errors, traceback='\n'.join(traceback))
def redis_auth_argument_spec(): def redis_auth_argument_spec(tls_default=True):
return dict( return dict(
login_host=dict(type='str', login_host=dict(type='str',
default='localhost',), default='localhost',),
@ -50,7 +50,7 @@ def redis_auth_argument_spec():
), ),
login_port=dict(type='int', default=6379), login_port=dict(type='int', default=6379),
tls=dict(type='bool', tls=dict(type='bool',
default=True), default=tls_default),
validate_certs=dict(type='bool', validate_certs=dict(type='bool',
default=True default=True
), ),
@ -58,6 +58,30 @@ def redis_auth_argument_spec():
) )
def redis_auth_params(module):
login_host = module.params['login_host']
login_user = module.params['login_user']
login_password = module.params['login_password']
login_port = module.params['login_port']
tls = module.params['tls']
validate_certs = 'required' if module.params['validate_certs'] else None
ca_certs = module.params['ca_certs']
if tls and ca_certs is None:
ca_certs = str(certifi.where())
if tuple(map(int, redis_version.split('.'))) < (3, 4, 0) and login_user is not None:
module.fail_json(
msg='The option `username` in only supported with redis >= 3.4.0.')
params = {'host': login_host,
'port': login_port,
'password': login_password,
'ssl_ca_certs': ca_certs,
'ssl_cert_reqs': validate_certs,
'ssl': tls}
if login_user is not None:
params['username'] = login_user
return params
class RedisAnsible(object): class RedisAnsible(object):
'''Base class for Redis module''' '''Base class for Redis module'''
@ -66,28 +90,8 @@ class RedisAnsible(object):
self.connection = self._connect() self.connection = self._connect()
def _connect(self): def _connect(self):
login_host = self.module.params['login_host']
login_user = self.module.params['login_user']
login_password = self.module.params['login_password']
login_port = self.module.params['login_port']
tls = self.module.params['tls']
validate_certs = 'required' if self.module.params['validate_certs'] else None
ca_certs = self.module.params['ca_certs']
if tls and ca_certs is None:
ca_certs = str(certifi.where())
if tuple(map(int, redis_version.split('.'))) < (3, 4, 0) and login_user is not None:
self.module.fail_json(
msg='The option `username` in only supported with redis >= 3.4.0.')
params = {'host': login_host,
'port': login_port,
'password': login_password,
'ssl_ca_certs': ca_certs,
'ssl_cert_reqs': validate_certs,
'ssl': tls}
if login_user is not None:
params['username'] = login_user
try: try:
return Redis(**params) return Redis(**redis_auth_params(self.module))
except Exception as e: except Exception as e:
self.module.fail_json(msg='{0}'.format(str(e))) self.module.fail_json(msg='{0}'.format(str(e)))
return None return None

View file

@ -13,6 +13,8 @@ module: redis
short_description: Various redis commands, replica and flush short_description: Various redis commands, replica and flush
description: description:
- Unified utility to interact with redis instances. - Unified utility to interact with redis instances.
extends_documentation_fragment:
- community.general.redis
options: options:
command: command:
description: description:
@ -22,20 +24,15 @@ options:
- C(replica) sets a redis instance in replica or master mode. (C(slave) is an alias for C(replica).) - C(replica) sets a redis instance in replica or master mode. (C(slave) is an alias for C(replica).)
choices: [ config, flush, replica, slave ] choices: [ config, flush, replica, slave ]
type: str type: str
login_password: tls:
description: default: false
- The password used to authenticate with (usually not used) version_added: 4.6.0
type: str login_user:
login_host: version_added: 4.6.0
description: validate_certs:
- The host running the database version_added: 4.6.0
default: localhost ca_certs:
type: str version_added: 4.6.0
login_port:
description:
- The port to connect to
default: 6379
type: int
master_host: master_host:
description: description:
- The host of the master instance [replica command] - The host of the master instance [replica command]
@ -144,6 +141,8 @@ else:
from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.common.text.formatters import human_to_bytes from ansible.module_utils.common.text.formatters import human_to_bytes
from ansible.module_utils.common.text.converters import to_native from ansible.module_utils.common.text.converters import to_native
from ansible_collections.community.general.plugins.module_utils.redis import (
fail_imports, redis_auth_argument_spec, redis_auth_params)
import re import re
@ -175,29 +174,28 @@ def flush(client, db=None):
# Module execution. # Module execution.
def main(): def main():
module = AnsibleModule( redis_auth_args = redis_auth_argument_spec(tls_default=False)
argument_spec=dict( module_args = dict(
command=dict(type='str', choices=['config', 'flush', 'replica', 'slave']), command=dict(type='str', choices=['config', 'flush', 'replica', 'slave']),
login_password=dict(type='str', no_log=True),
login_host=dict(type='str', default='localhost'),
login_port=dict(type='int', default=6379),
master_host=dict(type='str'), master_host=dict(type='str'),
master_port=dict(type='int'), master_port=dict(type='int'),
replica_mode=dict(type='str', default='replica', choices=['master', 'replica', 'slave'], aliases=["slave_mode"]), replica_mode=dict(type='str', default='replica', choices=['master', 'replica', 'slave'],
aliases=["slave_mode"]),
db=dict(type='int'), db=dict(type='int'),
flush_mode=dict(type='str', default='all', choices=['all', 'db']), flush_mode=dict(type='str', default='all', choices=['all', 'db']),
name=dict(type='str'), name=dict(type='str'),
value=dict(type='str') value=dict(type='str'),
), )
module_args.update(redis_auth_args)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True, supports_check_mode=True,
) )
if not redis_found: fail_imports(module, module.params['tls'])
module.fail_json(msg=missing_required_lib('redis'), exception=REDIS_IMP_ERR)
redis_params = redis_auth_params(module)
login_password = module.params['login_password']
login_host = module.params['login_host']
login_port = module.params['login_port']
command = module.params['command'] command = module.params['command']
if command == "slave": if command == "slave":
command = "replica" command = "replica"
@ -219,7 +217,7 @@ def main():
module.fail_json(msg='In replica mode master port must be provided') module.fail_json(msg='In replica mode master port must be provided')
# Connect and check # Connect and check
r = redis.StrictRedis(host=login_host, port=login_port, password=login_password) r = redis.StrictRedis(**redis_params)
try: try:
r.ping() r.ping()
except Exception as e: except Exception as e:
@ -270,7 +268,7 @@ def main():
module.fail_json(msg="In db mode the db number must be provided") module.fail_json(msg="In db mode the db number must be provided")
# Connect and check # Connect and check
r = redis.StrictRedis(host=login_host, port=login_port, password=login_password, db=db) r = redis.StrictRedis(db=db, **redis_params)
try: try:
r.ping() r.ping()
except Exception as e: except Exception as e:
@ -301,7 +299,7 @@ def main():
except ValueError: except ValueError:
value = module.params['value'] value = module.params['value']
r = redis.StrictRedis(host=login_host, port=login_port, password=login_password) r = redis.StrictRedis(**redis_params)
try: try:
r.ping() r.ping()