From 96afc3f46283acbe25cd239ec348b8e614dc909b Mon Sep 17 00:00:00 2001 From: Maykel Moya Date: Thu, 16 May 2013 03:27:30 +0200 Subject: [PATCH 1/2] Add support for crypted passwords to password lookup Added new parameter 'encrypt' with same semantics from that of vars_prompt. When encryption is requested a random salt will be generated and stored along the password in the form: ' salt='. Also store passwords with an ending '\n' for easier looking at files with console tools. File content was being already rstripped so this is harmless. --- docsite/latest/rst/playbooks2.rst | 9 +++ lib/ansible/runner/lookup_plugins/password.py | 76 +++++++++++++++---- 2 files changed, 71 insertions(+), 14 deletions(-) diff --git a/docsite/latest/rst/playbooks2.rst b/docsite/latest/rst/playbooks2.rst index db48b32d72..ba1a0cca49 100644 --- a/docsite/latest/rst/playbooks2.rst +++ b/docsite/latest/rst/playbooks2.rst @@ -537,6 +537,15 @@ This length can be changed by passing an extra parameter:: target=/tmp/{{ client }}_{{ tier }}_{{ role }}_backup.sql with_password: credentials/{{ client }}/{{ tier }}/{{ role }}/mysqlpassword length=15 + (...) + + # create an user with a given password + - user: name=guestuser + state=present + uid=5000 + password={{ item }} + with_password: credentials/{{ hostname }}/userpassword encrypt=sha256_crypt + Setting the Environment (and Working With Proxies) `````````````````````````````````````````````````` diff --git a/lib/ansible/runner/lookup_plugins/password.py b/lib/ansible/runner/lookup_plugins/password.py index 6b44e77b32..768b64a32e 100644 --- a/lib/ansible/runner/lookup_plugins/password.py +++ b/lib/ansible/runner/lookup_plugins/password.py @@ -1,5 +1,6 @@ # (c) 2012, Daniel Hokka Zakrisson # (c) 2013, Javie Candeira +# (c) 2013, Maykel Moya # # This file is part of Ansible # @@ -20,16 +21,23 @@ from ansible import utils, errors import os import errno import random -from string import ascii_uppercase, ascii_lowercase, digits +from string import ascii_letters, digits class LookupModule(object): LENGTH = 20 - def __init__(self, length=None, basedir=None, **kwargs): + def __init__(self, length=None, encrypt=None, basedir=None, **kwargs): self.basedir = basedir + def random_salt(self): + salt_chars = ascii_letters + digits + './' + salt = [] + for _ in range(8): + salt.append(random.choice(salt_chars)) + return ''.join(salt) + def run(self, terms, inject=None, **kwargs): terms = utils.listify_lookup_plugin_terms(terms, self.basedir, inject) @@ -40,16 +48,26 @@ class LookupModule(object): # you can't have escaped spaces in yor pathname params = term.split() relpath = params[0] - length = LookupModule.LENGTH - # get non-default length parameter if specified - if len(params) > 1: - try: - name, length = params[1].split('=') - assert(name.startswith("length")) - length = int(length) - except (ValueError, AssertionError) as e: - raise errors.AnsibleError(e) + paramvals = { + 'length': LookupModule.LENGTH, + 'encrypt': None, + } + + # get non-default parameters if specified + try: + for param in params[1:]: + name, value = param.split('=') + assert(name in paramvals) + if name == 'length': + paramvals[name] = int(value) + else: + paramvals[name] = value + except (ValueError, AssertionError) as e: + raise errors.AnsibleError(e) + + length = paramvals['length'] + encrypt = paramvals['encrypt'] # get password or create it if file doesn't exist path = utils.path_dwim(self.basedir, relpath) @@ -57,11 +75,41 @@ class LookupModule(object): pathdir = os.path.dirname(path) if not os.path.isdir(pathdir): os.makedirs(pathdir) - chars = ascii_uppercase + ascii_lowercase + digits + ".,:-_" + chars = ascii_letters + digits + ".,:-_" password = ''.join(random.choice(chars) for _ in range(length)) + if encrypt is not None: + salt = self.random_salt() + content = '%s salt=%s' % (password, salt) + else: + content = password with open(path, 'w') as f: - f.write(password) - ret.append(open(path).read().rstrip()) + f.write(content + '\n') + else: + content = open(path).read().rstrip() + sep = content.find(' ') + + if sep >= 0: + password = content[:sep] + salt = content[sep+1:].split('=')[1] + else: + password = content + salt = None + + # crypt requested, add salt if missing + if (encrypt is not None and not salt): + salt = self.random_salt() + content = '%s salt=%s' % (password, salt) + with open(path, 'w') as f: + f.write(content + '\n') + # crypt not requested, remove salt if present + elif (encrypt is None and salt): + with open(path, 'w') as f: + f.write(password + '\n') + + if encrypt: + password = utils.do_encrypt(password, encrypt, salt=salt) + + ret.append(password) return ret From 45f5447f9f888cffe4a0be8b1797e4c07c613392 Mon Sep 17 00:00:00 2001 From: Maykel Moya Date: Thu, 16 May 2013 18:49:35 +0200 Subject: [PATCH 2/2] Fix name in copyright --- lib/ansible/runner/lookup_plugins/password.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ansible/runner/lookup_plugins/password.py b/lib/ansible/runner/lookup_plugins/password.py index 768b64a32e..a09ca4071e 100644 --- a/lib/ansible/runner/lookup_plugins/password.py +++ b/lib/ansible/runner/lookup_plugins/password.py @@ -1,5 +1,5 @@ # (c) 2012, Daniel Hokka Zakrisson -# (c) 2013, Javie Candeira +# (c) 2013, Javier Candeira # (c) 2013, Maykel Moya # # This file is part of Ansible