From 3408de156ab089e9f05c912d52869fee20fa5fc8 Mon Sep 17 00:00:00 2001 From: Victor Fauth Date: Sat, 16 Feb 2019 21:44:10 +0000 Subject: [PATCH] etcd3: Support authentication (#44383) * etcd3: Support authentication * etcd3: Comment argument check * etcd3: Fixed wrong var names * etcd3: Added in 2.8 instead of 2.7 --- lib/ansible/modules/clustering/etcd3.py | 68 ++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/lib/ansible/modules/clustering/etcd3.py b/lib/ansible/modules/clustering/etcd3.py index 5ffaee152ce..5eee442412c 100644 --- a/lib/ansible/modules/clustering/etcd3.py +++ b/lib/ansible/modules/clustering/etcd3.py @@ -45,8 +45,37 @@ options: - the state of the value for the key. - can be present or absent required: true + user: + description: + - The etcd user to authenticate with. + version_added: '2.8' + password: + description: + - The password to use for authentication. + - Required if I(user) is defined. + version_added: '2.8' + ca_cert: + description: + - The Certificate Authority to use to verify the etcd host. + - Required if I(client_cert) and I(client_key) are defined. + version_added: '2.8' + client_cert: + description: + - PEM formatted certificate chain file to be used for SSL client authentication. + - Required if I(client_key) is defined. + version_added: '2.8' + client_key: + description: + - PEM formatted file that contains your private key to be used for SSL client authentication. + - Required if I(client_cert) is defined. + version_added: '2.8' + timeout: + description: + - The socket level timeout in seconds. + version_added: '2.8' author: - Jean-Philippe Evrard (@evrardjp) + - Victor Fauth (@vfauth) """ EXAMPLES = """ @@ -57,6 +86,24 @@ EXAMPLES = """ host: "localhost" port: 2379 state: "present" + +# Authenticate using user/password combination with a timeout of 10 seconds +- etcd3: + key: "foo" + value: "baz3" + state: "present" + user: "someone" + password: "password123" + timeout: 10 + +# Authenticate using TLS certificates +- etcd3: + key: "foo" + value: "baz3" + state: "present" + ca_cert: "/etc/ssl/certs/CA_CERT.pem" + client_cert: "/etc/ssl/certs/cert.crt" + client_key: "/etc/ssl/private/key.pem" """ RETURN = ''' @@ -93,6 +140,12 @@ def run_module(): host=dict(type='str', default='localhost'), port=dict(type='int', default=2379), state=dict(type='str', required=True, choices=['present', 'absent']), + user=dict(type='str'), + password=dict(type='str', no_log=True), + ca_cert=dict(type='path'), + client_cert=dict(type='path'), + client_key=dict(type='path'), + timeout=dict(type='int'), ) # seed the result dict in the object @@ -110,15 +163,26 @@ def run_module(): # supports check mode module = AnsibleModule( argument_spec=module_args, - supports_check_mode=True + supports_check_mode=True, + required_together=[['client_cert', 'client_key'], ['user', 'password']], ) + # It is possible to set `ca_cert` to verify the server identity without + # setting `client_cert` or `client_key` to authenticate the client + # so required_together is enough + # Due to `required_together=[['client_cert', 'client_key']]`, checking the presence + # of either `client_cert` or `client_key` is enough + if module.params['ca_cert'] is None and module.params['client_cert'] is not None: + module.fail_json(msg="The 'ca_cert' parameter must be defined when 'client_cert' and 'client_key' are present.") + result['key'] = module.params.get('key') + module.params['cert_cert'] = module.params.pop('client_cert') + module.params['cert_key'] = module.params.pop('client_key') if not HAS_ETCD: module.fail_json(msg=missing_required_lib('etcd3'), exception=ETCD_IMP_ERR) - allowed_keys = ['host', 'port', 'ca_cert', 'cert_key', 'cert_cert', + allowed_keys = ['host', 'port', 'ca_cert', 'cert_cert', 'cert_key', 'timeout', 'user', 'password'] # TODO(evrardjp): Move this back to a dict comprehension when python 2.7 is # the minimum supported version