summaryrefslogtreecommitdiff
path: root/lib/ansible/plugins/lookup/password.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/plugins/lookup/password.py')
-rw-r--r--lib/ansible/plugins/lookup/password.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/lib/ansible/plugins/lookup/password.py b/lib/ansible/plugins/lookup/password.py
new file mode 100644
index 0000000000..2e7633a067
--- /dev/null
+++ b/lib/ansible/plugins/lookup/password.py
@@ -0,0 +1,148 @@
+# (c) 2012, Daniel Hokka Zakrisson <daniel@hozac.com>
+# (c) 2013, Javier Candeira <javier@candeira.com>
+# (c) 2013, Maykel Moya <mmoya@speedyrails.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import errno
+import string
+import random
+
+from string import ascii_letters, digits
+
+from ansible import constants as C
+from ansible.errors import AnsibleError
+from ansible.plugins.lookup import LookupBase
+from ansible.utils.encrypt import do_encrypt
+
+DEFAULT_LENGTH = 20
+
+class LookupModule(LookupBase):
+
+ def random_password(self, length=DEFAULT_LENGTH, chars=C.DEFAULT_PASSWORD_CHARS):
+ '''
+ Return a random password string of length containing only chars.
+ NOTE: this was moved from the old ansible utils code, as nothing
+ else appeared to use it.
+ '''
+
+ password = []
+ while len(password) < length:
+ new_char = os.urandom(1)
+ if new_char in chars:
+ password.append(new_char)
+
+ return ''.join(password)
+
+ def random_salt(self):
+ salt_chars = ascii_letters + digits + './'
+ return self.random_password(length=8, chars=salt_chars)
+
+ def run(self, terms, variables, **kwargs):
+
+ ret = []
+
+ if not isinstance(terms, list):
+ terms = [ terms ]
+
+ for term in terms:
+ # you can't have escaped spaces in yor pathname
+ params = term.split()
+ relpath = params[0]
+
+ paramvals = {
+ 'length': DEFAULT_LENGTH,
+ 'encrypt': None,
+ 'chars': ['ascii_letters','digits',".,:-_"],
+ }
+
+ # 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)
+ 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']
+ encrypt = paramvals['encrypt']
+ use_chars = paramvals['chars']
+
+ # get password or create it if file doesn't exist
+ path = self._loader.path_dwim(relpath)
+ if not os.path.exists(path):
+ pathdir = os.path.dirname(path)
+ if not os.path.isdir(pathdir):
+ try:
+ os.makedirs(pathdir, mode=0o700)
+ except OSError as 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("'",'')
+ 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:
+ os.chmod(path, 0o600)
+ 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:
+ os.chmod(path, 0o600)
+ f.write(content + '\n')
+ # crypt not requested, remove salt if present
+ elif (encrypt is None and salt):
+ with open(path, 'w') as f:
+ os.chmod(path, 0o600)
+ f.write(password + '\n')
+
+ if encrypt:
+ password = do_encrypt(password, encrypt, salt=salt)
+
+ ret.append(password)
+
+ return ret
+