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