Move some code
[mspang/pyceo.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 'club' in club.get('objectClass', []):
33         if check_group(remote_user, mysql_user):
34             return response_message(response, 0, 'user %s is in club group %s' % (remote_user, mysql_user))
35         else:
36             return response_message(response, errno.EPERM, 'denied, user %s is not in club group %s' % (remote_user, mysql_user))
37     if 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, you may not create databases for other members')
41
42 def mysql_createdb(remote_user, mysql_user, response):
43     if check_auth(remote_user, mysql_user, response):
44         return
45
46     response.password = random_password()
47
48     if not re.match('^[a-zA-Z0-9-]+$', mysql_user):
49         response_message(response, errno.EINVAL, 'invalid characters in username %s' % mysql_user)
50         return
51
52     if not re.match('^[a-zA-Z0-9-]+$', response.password):
53         response_message(response, errno.EINVAL, 'invalid characters in password %s' % response.password)
54         return
55
56     try:
57         connection = MySQLdb.Connect(user=cfg['mysql_admin_username'], passwd=cfg['mysql_admin_password'])
58         cursor = connection.cursor()
59         cursor.execute("GRANT ALL PRIVILEGES ON `%s`.* TO `%s`@`localhost` IDENTIFIED BY '%s'"
60                        % (mysql_user, mysql_user, response.password))
61         cursor.execute("CREATE DATABASE IF NOT EXISTS `%s`" % mysql_user)
62         cursor.close()
63         connection.close()
64
65         response_message(response, 0, 'successfully created database %s' % mysql_user)
66     except MySQLdb.MySQLError, e:
67         response_message(response, 1, 'exception occured creating database: %s' % e)
68
69
70 def mysql_op():
71     input = sys.stdin.read()
72
73     request = ceo_pb2.AddMySQLUser()
74     request.ParseFromString(input)
75
76     remote_user = get_ceo_user()
77     mysql_user = request.username
78
79     response = ceo_pb2.AddMySQLUserResponse()
80     response_message(response, 0, 'mysql create db=%s by %s' % (mysql_user, remote_user))
81
82     mysql_createdb(remote_user, mysql_user, response)
83
84     sys.stdout.write(response.SerializeToString())
85
86 def main():
87     configure()
88     members.configure()
89     members.connect_anonymous()
90     syslog.openlog('op-mysql', syslog.LOG_PID, syslog.LOG_DAEMON)
91     mysql_op()
92
93 if __name__ == '__main__':
94     main()