#!/usr/bin/env python
-# Sync PostgreSQL users with system users
-# Copyright (C) 2001, 2002 James Troup <james@nocrew.org>
-# $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 <james@nocrew.org>
# 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
################################################################################
-import pg, pwd, sys;
-import utils;
-import apt_pkg;
+import pwd
+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
################################################################################
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.ParseCommandLine(cnf.Cnf, Arguments, sys.argv)
+ Options = cnf.SubTree("Import-Users-From-Passwd::Options")
if Options["Help"]:
- usage();
+ usage()
elif arguments:
- utils.warn("julia takes no non-option arguments.");
- usage(1);
+ 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 = int(cnf.get("Import-Users-From-Passwd::ValidGID",""))
- passwd_unames = {};
+ passwd_unames = {}
for entry in pwd.getpwall():
- uname = entry[0];
- gid = entry[3];
+ uname = entry[0]
+ gid = entry[3]
if valid_gid and gid != valid_gid:
if Options["Verbose"]:
- print "Skipping %s (GID %s != Valid GID %s)." % (uname, gid, valid_gid);
- continue;
- passwd_unames[uname] = "";
-
- postgres_unames = {};
- q = projectB.query("SELECT usename FROM pg_user");
- ql = q.getresult();
- for i in ql:
- uname = i[0];
- postgres_unames[uname] = "";
-
- known_postgres_unames = {};
- for i in Cnf.get("Julia::KnownPostgres","").split(","):
- uname = i.strip();
- known_postgres_unames[uname] = "";
+ print "Skipping %s (GID %s != Valid GID %s)." % (uname, gid, valid_gid)
+ continue
+ passwd_unames[uname] = ""
+
+ postgres_unames = {}
+ 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("Import-Users-From-Passwd::KnownPostgres","").split(","):
+ uname = i.strip()
+ known_postgres_unames[uname] = ""
keys = postgres_unames.keys()
- keys.sort();
+ 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();
+ 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);
+ 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)
+ q = session.execute('CREATE USER "%s"' % (uname))
+ else:
+ print "NOT CREATING USER %s. Doesn't match safety regex" % uname
+
+ session.commit()
#######################################################################################
if __name__ == '__main__':
main()
-