Use parse_kv to correctly parse parameters from password lookup

Fixes https://github.com/ansible/ansible-modules-core/issues/1968
This commit is contained in:
Toshio Kuratomi 2015-09-04 12:07:49 -07:00
parent e218bf8da9
commit c68e04c185

View file

@ -20,7 +20,6 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
import os import os
import errno
import string import string
import random import random
@ -29,10 +28,13 @@ from string import ascii_letters, digits
from ansible import constants as C from ansible import constants as C
from ansible.errors import AnsibleError from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase from ansible.plugins.lookup import LookupBase
from ansible.parsing.splitter import parse_kv
from ansible.utils.encrypt import do_encrypt from ansible.utils.encrypt import do_encrypt
from ansible.utils.path import makedirs_safe from ansible.utils.path import makedirs_safe
DEFAULT_LENGTH = 20 DEFAULT_LENGTH = 20
VALID_PARAMS = frozenset(('length', 'encrypt', 'chars'))
class LookupModule(LookupBase): class LookupModule(LookupBase):
@ -60,37 +62,36 @@ class LookupModule(LookupBase):
ret = [] ret = []
for term in terms: for term in terms:
# you can't have escaped spaces in yor pathname params = parse_kv(term)
params = term.split() if '_raw_params' in params:
relpath = params[0] relpath = params['_raw_params']
del params['_raw_params']
else:
relpath = params
paramvals = { # Check that we parsed the params correctly
'length': DEFAULT_LENGTH, if not term.startswith(relpath):
'encrypt': None, # Likely, the user had a non parameter following a parameter.
'chars': ['ascii_letters','digits',".,:-_"], # Reject this as a user typo
} raise AnsibleError('Unrecognized value after key=value parameters given to password lookup')
# get non-default parameters if specified invalid_params = frozenset(params.keys()).difference(VALID_PARAMS)
try: if invalid_params:
for param in params[1:]: raise AnsibleError('Unrecognized parameter(s) given to password lookup: %s' % ', '.join(invalid_params))
name, value = param.split('=')
assert(name in paramvals)
if name == 'length':
paramvals[name] = int(value)
elif name == 'chars':
use_chars=[]
if ",," in value:
use_chars.append(',')
use_chars.extend(value.replace(',,',',').split(','))
paramvals['chars'] = use_chars
else:
paramvals[name] = value
except (ValueError, AssertionError) as e:
raise AnsibleError(e)
length = paramvals['length'] length = int(params.get('length', DEFAULT_LENGTH))
encrypt = paramvals['encrypt'] encrypt = params.get('encrypt', None)
use_chars = paramvals['chars']
use_chars = params.get('chars', None)
if use_chars:
tmp_chars = []
if ',,' in use_chars:
tmp_chars.append(',')
tmp_chars.extend(use_chars.replace(',,', ',').split(','))
use_chars = tmp_chars
else:
# Default chars for password
use_chars = ['ascii_letters', 'digits', ".,:-_"]
# get password or create it if file doesn't exist # get password or create it if file doesn't exist
path = self._loader.path_dwim(relpath) path = self._loader.path_dwim(relpath)
@ -101,7 +102,7 @@ class LookupModule(LookupBase):
except OSError as e: except OSError as e:
raise AnsibleError("cannot create the path for the password lookup: %s (error was %s)" % (pathdir, str(e))) raise AnsibleError("cannot create the path for the password lookup: %s (error was %s)" % (pathdir, str(e)))
chars = "".join([getattr(string,c,c) for c in use_chars]).replace('"','').replace("'",'') chars = "".join(getattr(string, c, c) for c in use_chars).replace('"', '').replace("'", '')
password = ''.join(random.choice(chars) for _ in range(length)) password = ''.join(random.choice(chars) for _ in range(length))
if encrypt is not None: if encrypt is not None:
@ -118,7 +119,7 @@ class LookupModule(LookupBase):
if sep >= 0: if sep >= 0:
password = content[:sep] password = content[:sep]
salt = content[sep+1:].split('=')[1] salt = content[sep + 1:].split('=')[1]
else: else:
password = content password = content
salt = None salt = None
@ -142,4 +143,3 @@ class LookupModule(LookupBase):
ret.append(password) ret.append(password)
return ret return ret