Discussion:
scripts/func-change-password
Seth Vidal
2011-06-02 01:38:26 UTC
Permalink
scripts/func-change-password | 178 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 178 insertions(+)

New commits:
commit 931c9106cdf1fb75423d405544d129b524752dd3
Author: Seth Vidal <skvidal-rxtnV0ftBwyoClj4AeEUq9i2O/***@public.gmane.org>
Date: Wed Jun 1 21:38:16 2011 -0400

add func-change-password to scripts

diff --git a/scripts/func-change-password b/scripts/func-change-password
new file mode 100755
index 0000000..87f33a4
--- /dev/null
+++ b/scripts/func-change-password
@@ -0,0 +1,178 @@
+#!/usr/bin/python -tt
+# seth vidal
+# Copyright 2011, Red Hat, Inc
+##
+## This software may be freely redistributed under the terms of the GNU
+## general public license.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+import sys
+import func.overlord.client
+from func.overlord.scripts import errorprint
+
+from optparse import OptionParser
+from func.utils import is_error
+import crypt
+import getpass
+import tempfile
+import os
+import time
+
+def parse_args(args):
+ parser = OptionParser(version = "1.0")
+ parser.set_usage("func-change-password username")
+ parser.add_option('--host', default=[], action='append',
+ help="hosts to act on, defaults to ALL")
+ parser.add_option('--timeout', default=300, type='int',
+ help='set the wait timeout for func commands')
+ parser.add_option('--forks', default=40, type='int',
+ help='set the number of forks to start up')
+ parser.add_option('--grep-options', default='-n', dest='grep_options',
+ help='set options to pass to grep "-r -i" for example')
+ parser.add_option('--hosts-from-file', default=None, dest="hostfile",
+ help="read list of hosts from this file, if '-' read from stdin")
+ (opts, args) = parser.parse_args(args)
+
+
+ if opts.hostfile:
+ hosts = []
+ if opts.hostfile == '-':
+ hosts = sys.stdin.readlines()
+ else:
+ hosts = open(opts.hostfile, 'r').readlines()
+
+ for hn in hosts:
+ hn = hn.strip()
+ if hn.startswith('#'):
+ continue
+ hn = hn.replace('\n', '')
+ opts.host.append(hn)
+
+
+ return opts, args, parser
+
+def main():
+ opts, args, parser = parse_args(sys.argv[1:])
+
+ if len(args) < 1:
+ print parser.format_help()
+ sys.exit(1)
+
+
+ hosts ='*'
+ if opts.host:
+ hosts = ';'.join(opts.host)
+
+ username = args[0]
+
+ print "Changing password on hosts for %s" % username
+ password = 'new'
+ password_re = 'new1'
+ while password != password_re:
+ # take the password for the user
+ password = getpass.getpass()
+ password_re = getpass.getpass("Confirm Password: ")
+ if password != password_re:
+ print "Passwords do not match!"
+ print "Trying again"
+ if password == '' or password_re == '':
+ print "Empty, aborting"
+ sys.exit(1)
+
+ # generate salt
+ salt = '$6$' + ''.join(map(lambda x:'./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'[ord(x)%64], os.urandom(16)))
+
+ # generate crypt
+ crypted = crypt.crypt(password, salt)
+ # write to tempfile
+ (pw_fd, pw_tmp) = tempfile.mkstemp(prefix='fcp', text=True)
+ pw_fo = os.fdopen(pw_fd, 'w')
+ pw_str = '%s:%s\n' % (username, crypted)
+ pw_fo.write(pw_str)
+ pw_fo.flush()
+ pw_fo.close()
+
+ # send to hosts to specific location
+ fc = func.overlord.client.Client(hosts, timeout=opts.timeout, nforks=opts.forks)
+ source = pw_tmp
+ dest = "/root/fcp-%s" % time.strftime("%s")
+ print 'Sending changes to hosts'
+ results = fc.local.copyfile.send(source, dest)
+ # check results # copyfile fucking sucks - this needs something USEFUL
+ # any failures - take those out of the hosts and make a new fc connection
+
+ # run chpasswd on the hosts sending that file to it
+ print "Changing passwords"
+ results = fc.command.run('cat %s | /usr/sbin/chpasswd -e' % dest)
+ # check results #
+ changed_on = []
+ errors = {}
+ for (hn, output) in results.items():
+ if is_error(output) or output[0] == 127:
+
+ msg = 'Error: '
+ for item in output[1:3]:
+ if type(item) == type(''):
+ msg += ' %s' % item
+ msg += '\n'
+ errors[hn] = msg
+ continue
+
+ if output[0] != 0:
+ msg = 'Error: %s %s\n' % (output[0], output[1])
+ errors[hn] = msg
+ continue
+
+ changed_on.append(hn)
+
+ # clean up
+ # rm the file from the hosts and rm it locally
+ print "Cleaning up"
+
+ os.unlink(pw_tmp)
+ results = fc.command.run('/bin/rm -f %s' % dest)
+ for (hn, output) in results.items():
+ if is_error(output) or output[0] == 127:
+ msg = 'Error: '
+ for item in output[1:3]:
+ if type(item) == type(''):
+ msg += ' %s' % item
+ msg += '\n'
+ if msg == errors[hn]:
+ continue
+ else:
+ errors[hn] += msg
+ continue
+
+ if output[0] != 0:
+ msg = 'Error: %s %s\n' % (output[0], output[1])
+ if msg == errors[hn]:
+ continue
+ else:
+ errors[hn] += msg
+ continue
+
+
+ print "Password for %s changed on:" % username
+ for hn in sorted(changed_on):
+ print ' %s' % hn
+
+ print "\n\nErrors from: "
+ for hn in errors:
+ print ' %s' % hn
+ print ' %s' % errors[hn]
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt, e:
+ print "Exiting on user interrupt"
+ sys.exit(1)
+
+
+
+

Loading...