1
2
3 """ Sync PostgreSQL users with system users """
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import pwd
23 import grp
24 import sys
25 import re
26 import apt_pkg
27
28 from daklib.config import Config
29 from daklib.dbconn import *
30 from daklib import utils
31
32
33
34
36 print("""Usage: dak import-users-from-passwd [OPTION]...
37 Sync PostgreSQL's users with system users.
38
39 -h, --help show this help and exit
40 -n, --no-action don't do anything
41 -q, --quiet be quiet about what is being done
42 -v, --verbose explain what is being done""")
43 sys.exit(exit_code)
44
45
46
47
49 cnf = Config()
50
51 Arguments = [('n', "no-action", "Import-Users-From-Passwd::Options::No-Action"),
52 ('q', "quiet", "Import-Users-From-Passwd::Options::Quiet"),
53 ('v', "verbose", "Import-Users-From-Passwd::Options::Verbose"),
54 ('h', "help", "Import-Users-From-Passwd::Options::Help")]
55 for i in ["no-action", "quiet", "verbose", "help"]:
56 key = "Import-Users-From-Passwd::Options::%s" % i
57 if key not in cnf:
58 cnf[key] = ""
59
60 arguments = apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv)
61 Options = cnf.subtree("Import-Users-From-Passwd::Options")
62
63 if Options["Help"]:
64 usage()
65 elif arguments:
66 utils.warn("dak import-users-from-passwd takes no non-option arguments.")
67 usage(1)
68
69 session = DBConn().session()
70 valid_gid = cnf.get("Import-Users-From-Passwd::ValidGID", "")
71 if valid_gid:
72 debiangrp = grp.getgrnam(valid_gid).gr_mem
73 else:
74 debiangrp = []
75
76 passwd_unames = {}
77 for entry in pwd.getpwall():
78 uname = entry[0]
79 if uname not in debiangrp:
80 if Options["Verbose"]:
81 print("Skipping %s (Not in group %s)." % (uname, valid_gid))
82 continue
83 passwd_unames[uname] = ""
84
85 postgres_unames = {}
86 q = session.execute("SELECT usename FROM pg_user")
87 for i in q.fetchall():
88 uname = i[0]
89 postgres_unames[uname] = ""
90
91 known_postgres_unames = {}
92 for i in cnf.get("Import-Users-From-Passwd::KnownPostgres", "").split(","):
93 uname = i.strip()
94 known_postgres_unames[uname] = ""
95
96 for uname in sorted(postgres_unames):
97 if uname not in passwd_unames and uname not in known_postgres_unames:
98 print("I: Deleting %s from Postgres, no longer in passwd or list of known Postgres users" % (uname))
99 q = session.execute('DROP USER "%s"' % (uname))
100
101 safe_name = re.compile('^[A-Za-z0-9]+$')
102 for uname in sorted(passwd_unames):
103 if uname not in postgres_unames:
104 if not Options["Quiet"]:
105 print("Creating %s user in Postgres." % (uname))
106 if not Options["No-Action"]:
107 if safe_name.match(uname):
108
109
110
111 try:
112 q = session.execute('CREATE USER "%s"' % (uname))
113 session.commit()
114 except Exception as e:
115 utils.warn("Could not create user %s (%s)" % (uname, str(e)))
116 session.rollback()
117 else:
118 print("NOT CREATING USER %s. Doesn't match safety regex" % uname)
119
120 session.commit()
121
122
123
124
125 if __name__ == '__main__':
126 main()
127