X-Git-Url: https://git.decadent.org.uk/gitweb/?p=dak.git;a=blobdiff_plain;f=dak%2Fimport_users_from_passwd.py;h=ed121398fe43ece4320a65dc4d6a214c3d1c4835;hp=e28afa98b4e0f396e2041a124fc5ca240aa6af69;hb=17c5cab4eb8d5181ec7a81267a4e2e6b43c0fc65;hpb=30413cf0ff7bc21b8d2b8b4346406357fe55dc19 diff --git a/dak/import_users_from_passwd.py b/dak/import_users_from_passwd.py index e28afa98..ed121398 100755 --- a/dak/import_users_from_passwd.py +++ b/dak/import_users_from_passwd.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -# Sync PostgreSQL users with system users -# Copyright (C) 2001, 2002 James Troup -# $Id: julia,v 1.9 2003-01-02 18:12:50 troup Exp $ +""" Sync PostgreSQL users with system users """ +# Copyright (C) 2001, 2002, 2006 James Troup # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -30,18 +29,20 @@ ################################################################################ -import pg, pwd, sys -import utils +import pwd +import grp +import sys +import re import apt_pkg -################################################################################ +from daklib.config import Config +from daklib.dbconn import * +from daklib import utils -Cnf = None -projectB = None ################################################################################ def usage (exit_code=0): - print """Usage: julia [OPTION]... + print """Usage: dak import-users-from-passwd [OPTION]... Sync PostgreSQL's users with system users. -h, --help show this help and exit @@ -53,69 +54,83 @@ Sync PostgreSQL's users with system users. ################################################################################ def main (): - global Cnf, projectB - - Cnf = utils.get_conf() + cnf = Config() - Arguments = [('n', "no-action", "Julia::Options::No-Action"), - ('q', "quiet", "Julia::Options::Quiet"), - ('v', "verbose", "Julia::Options::Verbose"), - ('h', "help", "Julia::Options::Help")] + Arguments = [('n', "no-action", "Import-Users-From-Passwd::Options::No-Action"), + ('q', "quiet", "Import-Users-From-Passwd::Options::Quiet"), + ('v', "verbose", "Import-Users-From-Passwd::Options::Verbose"), + ('h', "help", "Import-Users-From-Passwd::Options::Help")] for i in [ "no-action", "quiet", "verbose", "help" ]: - if not Cnf.has_key("Julia::Options::%s" % (i)): - Cnf["Julia::Options::%s" % (i)] = "" + if not cnf.has_key("Import-Users-From-Passwd::Options::%s" % (i)): + cnf["Import-Users-From-Passwd::Options::%s" % (i)] = "" - arguments = apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv) - Options = Cnf.SubTree("Julia::Options") + arguments = apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv) + Options = cnf.subtree("Import-Users-From-Passwd::Options") if Options["Help"]: usage() elif arguments: - utils.warn("julia takes no non-option arguments.") + utils.warn("dak import-users-from-passwd takes no non-option arguments.") usage(1) - projectB = pg.connect(Cnf["DB::Name"], Cnf["DB::Host"], int(Cnf["DB::Port"])) - valid_gid = int(Cnf.get("Julia::ValidGID","")) + session = DBConn().session() + valid_gid = cnf.get("Import-Users-From-Passwd::ValidGID", "") + if valid_gid: + debiangrp = grp.getgrnam(valid_gid).gr_mem + else: + debiangrp = [] passwd_unames = {} for entry in pwd.getpwall(): uname = entry[0] - gid = entry[3] - if valid_gid and gid != valid_gid: + if uname not in debiangrp: if Options["Verbose"]: - print "Skipping %s (GID %s != Valid GID %s)." % (uname, gid, valid_gid) + print "Skipping %s (Not in group %s)." % (uname, valid_gid) continue passwd_unames[uname] = "" postgres_unames = {} - q = projectB.query("SELECT usename FROM pg_user") - ql = q.getresult() - for i in ql: + q = session.execute("SELECT usename FROM pg_user") + for i in q.fetchall(): uname = i[0] postgres_unames[uname] = "" known_postgres_unames = {} - for i in Cnf.get("Julia::KnownPostgres","").split(","): + for i in cnf.get("Import-Users-From-Passwd::KnownPostgres","").split(","): uname = i.strip() known_postgres_unames[uname] = "" keys = postgres_unames.keys() keys.sort() for uname in keys: - if not passwd_unames.has_key(uname)and not known_postgres_unames.has_key(uname): - print "W: %s is in Postgres but not the passwd file or list of known Postgres users." % (uname) + if not passwd_unames.has_key(uname) and not known_postgres_unames.has_key(uname): + print "I: Deleting %s from Postgres, no longer in passwd or list of known Postgres users" % (uname) + q = session.execute('DROP USER "%s"' % (uname)) keys = passwd_unames.keys() keys.sort() + safe_name = re.compile('^[A-Za-z0-9]+$') for uname in keys: if not postgres_unames.has_key(uname): if not Options["Quiet"]: print "Creating %s user in Postgres." % (uname) if not Options["No-Action"]: - q = projectB.query('CREATE USER "%s"' % (uname)) + if safe_name.match(uname): + # NB: I never figured out how to use a bind parameter for this query + # XXX: Fix this as it looks like a potential SQL injection attack to me + # (hence the safe_name match we do) + try: + q = session.execute('CREATE USER "%s"' % (uname)) + session.commit() + except Exception as e: + utils.warn("Could not create user %s (%s)" % (uname, str(e))) + session.rollback() + else: + print "NOT CREATING USER %s. Doesn't match safety regex" % uname + + session.commit() ####################################################################################### if __name__ == '__main__': main() -