Fix auth for mysql database creation
[public/pyceo-broken.git] / src / op-mysql
1 #!/usr/bin/python
2
3 import os, sys, string, random, syslog, grp, errno, re
4 from ceo import ceo_pb2, members, conf, ops
5 from ceo.ops import response_message, get_ceo_user, check_group
6 import MySQLdb
7
8 CONFIG_FILE = '/etc/csc/mysql.cf'
9
10 cfg = {}
11
12 def configure():
13     string_fields = ['mysql_admin_username', 'mysql_admin_password']
14
15     # read configuration file
16     cfg_tmp = conf.read(CONFIG_FILE)
17
18     # verify configuration
19     conf.check_string_fields(CONFIG_FILE, string_fields, cfg_tmp)
20
21     # update the current configuration with the loaded values
22     cfg.update(cfg_tmp)
23
24 def random_password():
25     chars = string.letters + string.digits
26     return ''.join(random.choice(chars) for i in xrange(20))
27
28 def check_auth(remote_user, mysql_user, response):
29     if remote_user == mysql_user:
30         return response_message(response, 0, 'user %s creating database for self' % remote_user)
31     club = members.get(mysql_user)
32     if not club:
33         return response_message(response, errno.EPERM, 'user %s does not exist' % mysql_user)
34     if 'club' in club.get('objectClass', []):
35         if check_group(remote_user, mysql_user):
36             return response_message(response, 0, 'user %s is in club group %s' % (remote_user, mysql_user))
37         elif check_group(remote_user, 'syscom'):
38             return response_message(response, 0, 'user %s is on systems committee' % remote_user)
39         else:
40             return response_message(response, errno.EPERM, 'denied, user %s is not in club group %s' % (remote_user, mysql_user))
41     else:
42         if check_group(remote_user, 'syscom'):
43             return response_message(response, 0, 'user %s is on systems committee' % remote_user)
44         else:
45             return response_message(response, errno.EPERM, 'denied, you may not create databases for other members')
46
47 def mysql_createdb(remote_user, mysql_user, response):
48     if check_auth(remote_user, mysql_user, response):
49         return
50
51     response.password = random_password()
52
53     if not re.match('^[a-zA-Z0-9-]+$', mysql_user):
54         response_message(response, errno.EINVAL, 'invalid characters in username %s' % mysql_user)
55         return
56
57     if not re.match('^[a-zA-Z0-9-]+$', response.password):
58         response_message(response, errno.EINVAL, 'invalid characters in password %s' % response.password)
59         return
60
61     try:
62         connection = MySQLdb.Connect(user=cfg['mysql_admin_username'], passwd=cfg['mysql_admin_password'])
63         cursor = connection.cursor()
64         cursor.execute("GRANT ALL PRIVILEGES ON `%s`.* TO `%s`@`localhost` IDENTIFIED BY '%s'"
65                        % (mysql_user, mysql_user, response.password))
66         cursor.execute("CREATE DATABASE IF NOT EXISTS `%s`" % mysql_user)
67         cursor.close()
68         connection.close()
69
70         response_message(response, 0, 'successfully created database %s' % mysql_user)
71     except MySQLdb.MySQLError, e:
72         response_message(response, 1, 'exception occured creating database: %s' % e)
73
74
75 def mysql_op():
76     input = sys.stdin.read()
77
78     request = ceo_pb2.AddMySQLUser()
79     request.ParseFromString(input)
80
81     remote_user = get_ceo_user()
82     mysql_user = request.username
83
84     response = ceo_pb2.AddMySQLUserResponse()
85     response_message(response, 0, 'mysql create db=%s by %s' % (mysql_user, remote_user))
86
87     mysql_createdb(remote_user, mysql_user, response)
88
89     sys.stdout.write(response.SerializeToString())
90
91 def main():
92     configure()
93     members.configure()
94     members.connect_anonymous()
95     syslog.openlog('op-mysql', syslog.LOG_PID, syslog.LOG_DAEMON)
96     mysql_op()
97
98 if __name__ == '__main__':
99     main()