From dbab5f6dd3fda53a5b6015dfdcae96c325d74bac Mon Sep 17 00:00:00 2001 From: Joerg Jaspert Date: Fri, 13 Feb 2009 21:41:20 +0100 Subject: [PATCH] add-user add an OLD OLD script from bpo to git, used to "create" new users on that archive. Signed-off-by: Joerg Jaspert --- dak/add_user.py | 251 +++++++++++++++++++++++++++++++++++++++ dak/dak.py | 2 + daklib/regexes.py | 9 ++ templates/add-user.added | 18 +++ 4 files changed, 280 insertions(+) create mode 100755 dak/add_user.py create mode 100644 templates/add-user.added diff --git a/dak/add_user.py b/dak/add_user.py new file mode 100755 index 00000000..fd06a72b --- /dev/null +++ b/dak/add_user.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python + +""" +Add a user to to the uid/maintainer/fingerprint table and +add his key to the GPGKeyring + +@contact: Debian FTP Master +@copyright: 2004, 2009 Joerg Jaspert +@license: GNU General Public License version 2 or later +""" + +################################################################################ +# wow, sounds like it'll be a big step up.. configuring dak on a +# new machine even scares me :) +################################################################################ + +# You don't want to read this script if you know python. +# I know what I say. I dont know python and I wrote it. So go and read some other stuff. + +import commands +import pg +import re +import sys +import time +import os +import apt_pkg +from daklib import database +from daklib import logging +from daklib import queue +from daklib import utils +from daklib.regexes import re_gpg_fingerprint, re_user_address, re_user_mails, re_user_name + +################################################################################ + +Cnf = None +projectB = None +Logger = None +Upload = None +Subst = None + +################################################################################ + +def usage(exit_code=0): + print """Usage: add-user [OPTION]... +Adds a new user to the dak databases and keyrings + + -k, --key keyid of the User + -u, --user userid of the User + -c, --create create a system account for the user + -h, --help show this help and exit.""" + sys.exit(exit_code) + +################################################################################ +# Stolen from userdir-ldap +# Compute a random password using /dev/urandom. +def GenPass(): + # Generate a 10 character random string + SaltVals = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/." + Rand = open("/dev/urandom") + Password = "" + for i in range(0,15): + Password = Password + SaltVals[ord(Rand.read(1)[0]) % len(SaltVals)] + return Password + +# Compute the MD5 crypted version of the given password +def HashPass(Password): + import crypt + # Hash it telling glibc to use the MD5 algorithm - if you dont have + # glibc then just change Salt = "$1$" to Salt = "" + SaltVals = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/." + Salt = "$1$" + Rand = open("/dev/urandom") + for x in range(0,10): + Salt = Salt + SaltVals[ord(Rand.read(1)[0]) % len(SaltVals)] + Pass = crypt.crypt(Password,Salt) + if len(Pass) < 14: + raise "Password Error", "MD5 password hashing failed, not changing the password!" + return Pass + +################################################################################ + +def createMail(login, passwd, keyid, keyring): + import GnuPGInterface + + message= """ + +Additionally there is now an account created for you. + +""" + message+= "\nYour password for the login %s is: %s\n" % (login, passwd) + + gnupg = GnuPGInterface.GnuPG() + gnupg.options.armor = 1 + gnupg.options.meta_interactive = 0 + gnupg.options.extra_args.append("--no-default-keyring") + gnupg.options.extra_args.append("--always-trust") + gnupg.options.extra_args.append("--no-secmem-warning") + gnupg.options.extra_args.append("--keyring=%s" % keyring) + gnupg.options.recipients = [keyid] + proc = gnupg.run(['--encrypt'], create_fhs=['stdin', 'stdout']) + proc.handles['stdin'].write(message) + proc.handles['stdin'].close() + output = proc.handles['stdout'].read() + proc.handles['stdout'].close() + proc.wait() + return output + +################################################################################ + +def main(): + global Cnf, projectB + keyrings = None + + Cnf = daklib.utils.get_conf() + + Arguments = [('h',"help","Add-User::Options::Help"), + ('c',"create","Add-User::Options::Create"), + ('k',"key","Add-User::Options::Key", "HasArg"), + ('u',"user","Add-User::Options::User", "HasArg"), + ] + + for i in [ "help", "create" ]: + if not Cnf.has_key("Add-User::Options::%s" % (i)): + Cnf["Add-User::Options::%s" % (i)] = "" + + apt_pkg.ParseCommandLine(Cnf, Arguments, sys.argv) + + Options = Cnf.SubTree("Add-User::Options") + if Options["help"]: + usage() + + projectB = pg.connect(Cnf["DB::Name"], Cnf["DB::Host"], int(Cnf["DB::Port"])) + daklib.database.init(Cnf, projectB) + + if not keyrings: + keyrings = Cnf.ValueList("Dinstall::GPGKeyring") + +# Ignore the PGP keyring for download of new keys. Ignore errors, if key is missing it will +# barf with the next commands. + cmd = "gpg --no-secmem-warning --no-default-keyring %s --recv-keys %s" \ + % (daklib.utils.gpg_keyring_args(keyrings), Cnf["Add-User::Options::Key"]) + (result, output) = commands.getstatusoutput(cmd) + + cmd = "gpg --with-colons --no-secmem-warning --no-auto-check-trustdb --no-default-keyring %s --with-fingerprint --list-key %s" \ + % (daklib.utils.gpg_keyring_args(keyrings), + Cnf["Add-User::Options::Key"]) + (result, output) = commands.getstatusoutput(cmd) + m = re_gpg_fingerprint.search(output) + if not m: + print output + daklib.utils.fubar("0x%s: (1) No fingerprint found in gpg output but it returned 0?\n%s" \ + % (Cnf["Add-User::Options::Key"], daklib.utils.prefix_multi_line_string(output, \ + " [GPG output:] "))) + primary_key = m.group(1) + primary_key = primary_key.replace(" ","") + + uid = "" + if Cnf.has_key("Add-User::Options::User") and Cnf["Add-User::Options::User"]: + uid = Cnf["Add-User::Options::User"] + name = Cnf["Add-User::Options::User"] + else: + u = re_user_address.search(output) + if not u: + print output + daklib.utils.fubar("0x%s: (2) No userid found in gpg output but it returned 0?\n%s" \ + % (Cnf["Add-User::Options::Key"], daklib.utils.prefix_multi_line_string(output, " [GPG output:] "))) + uid = u.group(1) + n = re_user_name.search(output) + name = n.group(1) + +# Look for all email addresses on the key. + emails=[] + for line in output.split('\n'): + e = re_user_mails.search(line) + if not e: + continue + emails.append(e.group(2)) + + + print "0x%s -> %s <%s> -> %s -> %s" % (Cnf["Add-User::Options::Key"], name, emails[0], uid, primary_key) + + prompt = "Add user %s with above data (y/N) ? " % (uid) + yn = daklib.utils.our_raw_input(prompt).lower() + + if yn == "y": +# Create an account for the user? + summary = "" + if Cnf.FindB("Add-User::CreateAccount") or Cnf["Add-User::Options::Create"]: + password = GenPass() + pwcrypt = HashPass(password) + if Cnf.has_key("Add-User::GID"): + cmd = "sudo /usr/sbin/useradd -g users -m -p '%s' -c '%s' -G %s %s" \ + % (pwcrypt, name, Cnf["Add-User::GID"], uid) + else: + cmd = "sudo /usr/sbin/useradd -g users -m -p '%s' -c '%s' %s" \ + % (pwcrypt, name, uid) + (result, output) = commands.getstatusoutput(cmd) + if (result != 0): + daklib.utils.fubar("Invocation of '%s' failed:\n%s\n" % (cmd, output), result) + try: + summary+=createMail(uid, password, Cnf["Add-User::Options::Key"], Cnf["Dinstall::GPGKeyring"]) + except: + summary="" + daklib.utils.warn("Could not prepare password information for mail, not sending password.") + +# Now add user to the database. + projectB.query("BEGIN WORK") + uid_id = daklib.database.get_or_set_uid_id(uid) + projectB.query('CREATE USER "%s"' % (uid)) + projectB.query("COMMIT WORK") +# The following two are kicked out in rhona, so we don't set them. kelly adds +# them as soon as she installs a package with unknown ones, so no problems to expect here. +# Just leave the comment in, to not think about "Why the hell aren't they added" in +# a year, if we ever touch uma again. +# maint_id = daklib.database.get_or_set_maintainer_id(name) +# projectB.query("INSERT INTO fingerprint (fingerprint, uid) VALUES ('%s', '%s')" % (primary_key, uid_id)) + +# Lets add user to the email-whitelist file if its configured. + if Cnf.has_key("Dinstall::MailWhiteList") and Cnf["Dinstall::MailWhiteList"] != "": + file = daklib.utils.open_file(Cnf["Dinstall::MailWhiteList"], "a") + for mail in emails: + file.write(mail+'\n') + file.close() + + print "Added:\nUid:\t %s (ID: %s)\nMaint:\t %s\nFP:\t %s" % (uid, uid_id, \ + name, primary_key) + +# Should we send mail to the newly added user? + if Cnf.FindB("Add-User::SendEmail"): + mail = name + "<" + emails[0] +">" + Upload = daklib.queue.Upload(Cnf) + Subst = Upload.Subst + Subst["__NEW_MAINTAINER__"] = mail + Subst["__UID__"] = uid + Subst["__KEYID__"] = Cnf["Add-User::Options::Key"] + Subst["__PRIMARY_KEY__"] = primary_key + Subst["__FROM_ADDRESS__"] = Cnf["Dinstall::MyEmailAddress"] + Subst["__HOSTNAME__"] = Cnf["Dinstall::MyHost"] + Subst["__SUMMARY__"] = summary + new_add_message = daklib.utils.TemplateSubst(Subst,Cnf["Dir::Templates"]+"/add-user.added") + daklib.utils.send_mail(new_add_message) + + else: + uid = None + + +####################################################################################### + +if __name__ == '__main__': + main() + diff --git a/dak/dak.py b/dak/dak.py index a08f20e0..981a31a9 100755 --- a/dak/dak.py +++ b/dak/dak.py @@ -171,6 +171,8 @@ def init(): "Generate statistics"), ("bts-categorize", "Categorize uncategorized bugs filed against ftp.debian.org"), + ("add-user", + "Add a user to the archive"), ] return functionality diff --git a/daklib/regexes.py b/daklib/regexes.py index b94c53b3..96f6c8e9 100755 --- a/daklib/regexes.py +++ b/daklib/regexes.py @@ -7,6 +7,7 @@ Central repository of regexes for dak @contact: Debian FTP Master @copyright: 2001, 2002, 2003, 2004, 2005, 2006 James Troup @copyright: 2009 Mark Hymers +@copyright: 2009 Joerg Jaspert @license: GNU General Public License version 2 or later """ @@ -97,3 +98,11 @@ re_build_dep_arch = re.compile(r"\[[^]]+\]") # From dak/transitions.py re_broken_package = re.compile(r"[a-zA-Z]\w+\s+\-.*") + +# From dak/add_user.py +re_gpg_fingerprint = re.compile(r"^fpr:+(.*):$", re.MULTILINE); +# The next one is dirty +re_user_address = re.compile(r"^pub:.*<(.*)@.*>.*$", re.MULTILINE); +re_user_mails = re.compile(r"^(pub|uid):[^rdin].*<(.*@.*)>.*$", re.MULTILINE); +re_user_name = re.compile(r"^pub:.*:(.*)<.*$", re.MULTILINE); + diff --git a/templates/add-user.added b/templates/add-user.added new file mode 100644 index 00000000..1a934912 --- /dev/null +++ b/templates/add-user.added @@ -0,0 +1,18 @@ +From: __FROM_ADDRESS__ +To: __NEW_MAINTAINER__ +Subject: Account on __HOSTNAME__ activated + +Hi __UID__, + +your account on __HOSTNAME__ has just been activated. You are now able +to upload packages there, using dput or dupload as you wish. +The gpg-key you need to sign your packages with is key 0x__KEYID__ +with the fingerprint __PRIMARY_KEY__. + +__SUMMARY__ + +This message was generated automatically; if you believe that there is +a problem with it please contact the archive administrators by mailing +__ADMIN_ADDRESS__. + +__DISTRO__ distribution maintenance software -- 2.39.5