]> git.decadent.org.uk Git - dak.git/blob - dak/import_users_from_passwd.py
Remove files that are (no longer) generated
[dak.git] / dak / import_users_from_passwd.py
1 #!/usr/bin/env python
2
3 """ Sync PostgreSQL users with system users """
4 # Copyright (C) 2001, 2002, 2006  James Troup <james@nocrew.org>
5
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 ################################################################################
21
22 # <aj> ARRRGGGHHH
23 # <aj> what's wrong with me!?!?!?
24 # <aj> i was just nice to some mormon doorknockers!!!
25 # <Omnic> AJ?!?!
26 # <aj> i know!!!!!
27 # <Omnic> I'm gonna have to kick your ass when you come over
28 # <Culus> aj: GET THE HELL OUT OF THE CABAL! :P
29
30 ################################################################################
31
32 import pwd
33 import grp
34 import sys
35 import re
36 import apt_pkg
37
38 from daklib.config import Config
39 from daklib.dbconn import *
40 from daklib import utils
41
42 ################################################################################
43
44 def usage (exit_code=0):
45     print """Usage: dak import-users-from-passwd [OPTION]...
46 Sync PostgreSQL's users with system users.
47
48   -h, --help                 show this help and exit
49   -n, --no-action            don't do anything
50   -q, --quiet                be quiet about what is being done
51   -v, --verbose              explain what is being done"""
52     sys.exit(exit_code)
53
54 ################################################################################
55
56 def main ():
57     cnf = Config()
58
59     Arguments = [('n', "no-action", "Import-Users-From-Passwd::Options::No-Action"),
60                  ('q', "quiet", "Import-Users-From-Passwd::Options::Quiet"),
61                  ('v', "verbose", "Import-Users-From-Passwd::Options::Verbose"),
62                  ('h', "help", "Import-Users-From-Passwd::Options::Help")]
63     for i in [ "no-action", "quiet", "verbose", "help" ]:
64         if not cnf.has_key("Import-Users-From-Passwd::Options::%s" % (i)):
65             cnf["Import-Users-From-Passwd::Options::%s" % (i)] = ""
66
67     arguments = apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv)
68     Options = cnf.subtree("Import-Users-From-Passwd::Options")
69
70     if Options["Help"]:
71         usage()
72     elif arguments:
73         utils.warn("dak import-users-from-passwd takes no non-option arguments.")
74         usage(1)
75
76     session = DBConn().session()
77     valid_gid = cnf.get("Import-Users-From-Passwd::ValidGID", "")
78     if valid_gid:
79         debiangrp = grp.getgrnam(valid_gid).gr_mem
80     else:
81         debiangrp = []
82
83     passwd_unames = {}
84     for entry in pwd.getpwall():
85         uname = entry[0]
86         if uname not in debiangrp:
87             if Options["Verbose"]:
88                 print "Skipping %s (Not in group %s)." % (uname, valid_gid)
89             continue
90         passwd_unames[uname] = ""
91
92     postgres_unames = {}
93     q = session.execute("SELECT usename FROM pg_user")
94     for i in q.fetchall():
95         uname = i[0]
96         postgres_unames[uname] = ""
97
98     known_postgres_unames = {}
99     for i in cnf.get("Import-Users-From-Passwd::KnownPostgres","").split(","):
100         uname = i.strip()
101         known_postgres_unames[uname] = ""
102
103     keys = postgres_unames.keys()
104     keys.sort()
105     for uname in keys:
106         if not passwd_unames.has_key(uname) and not known_postgres_unames.has_key(uname):
107             print "I: Deleting %s from Postgres, no longer in passwd or list of known Postgres users" % (uname)
108             q = session.execute('DROP USER "%s"' % (uname))
109
110     keys = passwd_unames.keys()
111     keys.sort()
112     safe_name = re.compile('^[A-Za-z0-9]+$')
113     for uname in keys:
114         if not postgres_unames.has_key(uname):
115             if not Options["Quiet"]:
116                 print "Creating %s user in Postgres." % (uname)
117             if not Options["No-Action"]:
118                 if safe_name.match(uname):
119                     # NB: I never figured out how to use a bind parameter for this query
120                     # XXX: Fix this as it looks like a potential SQL injection attack to me
121                     #      (hence the safe_name match we do)
122                     try:
123                         q = session.execute('CREATE USER "%s"' % (uname))
124                         session.commit()
125                     except Exception as e:
126                         utils.warn("Could not create user %s (%s)" % (uname, str(e)))
127                         session.rollback()
128                 else:
129                     print "NOT CREATING USER %s.  Doesn't match safety regex" % uname
130
131     session.commit()
132
133 #######################################################################################
134
135 if __name__ == '__main__':
136     main()