Created
May 2, 2017 00:17
-
-
Save HackersZone/0793310e405b4bd4b9ad7881a9a21be8 to your computer and use it in GitHub Desktop.
Create .htpasswd file with htpasswd.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python | |
| # -*- coding: utf-8 -*- | |
| # | |
| # Copyright (C) 2008-2013 Edgewall Software | |
| # Copyright (C) 2008 Eli Carter | |
| # All rights reserved. | |
| # | |
| # This software is licensed as described in the file COPYING, which | |
| # you should have received as part of this distribution. The terms | |
| # are also available at http://trac.edgewall.com/license.html. | |
| # | |
| # This software consists of voluntary contributions made by many | |
| # individuals. For the exact contribution history, see the revision | |
| # history and logs, available at http://trac.edgewall.org/. | |
| import argparse | |
| import getpass | |
| import sys | |
| from trac.util import salt | |
| from trac.util.compat import crypt, wait_for_file_mtime_change | |
| from trac.util.text import printerr | |
| if crypt is None: | |
| printerr("The crypt module is not found. Install the passlib package " | |
| "from PyPI.", newline=True) | |
| sys.exit(1) | |
| def ask_pass(): | |
| pass1 = getpass.getpass('New password: ') | |
| pass2 = getpass.getpass('Re-type new password: ') | |
| if pass1 != pass2: | |
| printerr("htpasswd: password verification error") | |
| sys.exit(1) | |
| return pass1 | |
| class HtpasswdFile(object): | |
| """A class for manipulating htpasswd files.""" | |
| def __init__(self, filename, create=False): | |
| self.entries = [] | |
| self.filename = filename | |
| if not create: | |
| self.load() | |
| def load(self): | |
| """Read the htpasswd file into memory.""" | |
| self.entries = [] | |
| with open(self.filename, 'r') as f: | |
| for line in f: | |
| username, pwhash = line.split(':') | |
| entry = [username, pwhash.rstrip()] | |
| self.entries.append(entry) | |
| def save(self): | |
| """Write the htpasswd file to disk""" | |
| wait_for_file_mtime_change(self.filename) | |
| with open(self.filename, 'w') as f: | |
| f.writelines("%s:%s\n" % (entry[0], entry[1]) | |
| for entry in self.entries) | |
| def update(self, username, password): | |
| """Replace the entry for the given user, or add it if new.""" | |
| pwhash = crypt(password, salt()) | |
| matching_entries = [entry for entry in self.entries | |
| if entry[0] == username] | |
| if matching_entries: | |
| matching_entries[0][1] = pwhash | |
| else: | |
| self.entries.append([username, pwhash]) | |
| def delete(self, username): | |
| """Remove the entry for the given user.""" | |
| self.entries = [entry for entry in self.entries | |
| if entry[0] != username] | |
| def main(): | |
| """ | |
| %(prog)s [-c] passwordfile username | |
| %(prog)s -b[c] passwordfile username password | |
| %(prog)s -D passwordfile username\ | |
| """ | |
| parser = argparse.ArgumentParser(usage=main.__doc__) | |
| parser.add_argument('-b', action='store_true', dest='batch', | |
| help="batch mode; password is passed on the command " | |
| "line IN THE CLEAR") | |
| parser_group = parser.add_mutually_exclusive_group() | |
| parser_group.add_argument('-c', action='store_true', dest='create', | |
| help="create a new htpasswd file, overwriting " | |
| "any existing file") | |
| parser_group.add_argument('-D', action='store_true', dest='delete_user', | |
| help="remove the given user from the password " | |
| "file") | |
| parser.add_argument('passwordfile', help=argparse.SUPPRESS) | |
| parser.add_argument('username', help=argparse.SUPPRESS) | |
| parser.add_argument('password', nargs='?', help=argparse.SUPPRESS) | |
| args = parser.parse_args() | |
| password = args.password | |
| if args.delete_user: | |
| if password is not None: | |
| parser.error("too many arguments") | |
| else: | |
| if args.batch and password is None: | |
| parser.error("too few arguments") | |
| elif not args.batch and password is not None: | |
| parser.error("too many arguments") | |
| try: | |
| passwdfile = HtpasswdFile(args.passwordfile, create=args.create) | |
| except EnvironmentError: | |
| printerr("File not found.") | |
| sys.exit(1) | |
| else: | |
| if args.delete_user: | |
| passwdfile.delete(args.username) | |
| else: | |
| if password is None: | |
| password = ask_pass() | |
| passwdfile.update(args.username, password) | |
| passwdfile.save() | |
| if __name__ == '__main__': | |
| main() |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
chmod 755 /usr/local/bin/htpasswd.py
I want to create the password file /var/www/www.example.com/.htpasswd now and store the user falko in it (you can give the password file any name you like - it's not necessary to name it .htpasswd; I just named it .htpasswd because that's the way password files are named under Apache):
htpasswd.py -c -b /var/www/www.example.com/.htpasswd falko falkossecret
Please replace falkossecret with a password for the user falko. Please note that the -c switch makes that the file is created from scratch; if it didn't exist before, it will be created; if it existed before, it will be overwritten with a new one, and all users from the old file will be lost! Therefore, if you want to add another user without deleting all existing users, use the htpasswd.py command without the -c switch:
htpasswd.py -b /var/www/www.example.com/.htpasswd till tillssecret
The last command adds the user till to /var/www/www.example.com/.htpasswd so that we now have the users falko and till in it.