You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.7 KiB
114 lines
3.7 KiB
14 years ago
|
#!/usr/bin/python
|
||
|
|
||
|
import os, sys, string, random, syslog, grp, errno, re
|
||
|
from ceo import ceo_pb2, members, conf
|
||
|
import MySQLdb
|
||
|
|
||
|
CONFIG_FILE = '/etc/csc/mysql.cf'
|
||
|
|
||
|
cfg = {}
|
||
|
|
||
|
def configure():
|
||
|
string_fields = ['mysql_admin_username', 'mysql_admin_password']
|
||
|
|
||
|
# read configuration file
|
||
|
cfg_tmp = conf.read(CONFIG_FILE)
|
||
|
|
||
|
# verify configuration
|
||
|
conf.check_string_fields(CONFIG_FILE, string_fields, cfg_tmp)
|
||
|
|
||
|
# update the current configuration with the loaded values
|
||
|
cfg.update(cfg_tmp)
|
||
|
|
||
|
def response_message(response, status, message):
|
||
|
priority = syslog.LOG_ERR if status else syslog.LOG_INFO
|
||
|
syslog.syslog(priority, message)
|
||
|
msg = response.messages.add()
|
||
|
msg.status = status
|
||
|
msg.message = message
|
||
|
return status
|
||
|
|
||
|
def random_password():
|
||
|
chars = string.letters + string.digits
|
||
|
return ''.join(random.choice(chars) for i in xrange(20))
|
||
|
|
||
|
def get_ceo_user():
|
||
|
user = os.environ.get('CEO_USER')
|
||
|
if not user:
|
||
|
raise Exception("environment variable CEO_USER not set");
|
||
|
return user
|
||
|
|
||
|
def check_group(user, group):
|
||
|
try:
|
||
|
return user in grp.getgrnam(group).gr_mem
|
||
|
except KeyError:
|
||
|
return False
|
||
|
|
||
|
def check_auth(remote_user, mysql_user, response):
|
||
|
if remote_user == mysql_user:
|
||
|
return response_message(response, 0, 'user %s creating database for self' % remote_user)
|
||
|
club = members.get(mysql_user)
|
||
|
if 'club' in club.get('objectClass', []):
|
||
|
if check_group(remote_user, mysql_user):
|
||
|
return response_message(response, 0, 'user %s is in club group %s' % (remote_user, mysql_user))
|
||
|
else:
|
||
|
return response_message(response, errno.EPERM, 'denied, user %s is not in club group %s' % (remote_user, mysql_user))
|
||
|
if check_group(remote_user, 'syscom'):
|
||
|
return response_message(response, 0, 'user %s is on systems committee' % remote_user)
|
||
|
else:
|
||
|
return response_message(response, errno.EPERM, 'denied, you may not create databases for other members')
|
||
|
|
||
|
def mysql_createdb(remote_user, mysql_user, response):
|
||
|
if check_auth(remote_user, mysql_user, response):
|
||
|
return
|
||
|
|
||
|
response.password = random_password()
|
||
|
|
||
|
if not re.match('^[a-zA-Z0-9-]+$', mysql_user):
|
||
|
response_message(response, errno.EINVAL, 'invalid characters in username %s' % mysql_user)
|
||
|
return
|
||
|
|
||
|
if not re.match('^[a-zA-Z0-9-]+$', response.password):
|
||
|
response_message(response, errno.EINVAL, 'invalid characters in password %s' % response.password)
|
||
|
return
|
||
|
|
||
|
try:
|
||
|
connection = MySQLdb.Connect(user=cfg['mysql_admin_username'], passwd=cfg['mysql_admin_password'])
|
||
|
cursor = connection.cursor()
|
||
|
cursor.execute("GRANT ALL PRIVILEGES ON `%s`.* TO `%s`@`localhost` IDENTIFIED BY '%s'"
|
||
|
% (mysql_user, mysql_user, response.password))
|
||
|
cursor.execute("CREATE DATABASE IF NOT EXISTS `%s`" % mysql_user)
|
||
|
cursor.close()
|
||
|
connection.close()
|
||
|
|
||
|
response_message(response, 0, 'successfully created database %s' % mysql_user)
|
||
|
except MySQLdb.MySQLError, e:
|
||
|
response_message(response, 1, 'exception occured creating database: %s' % e)
|
||
|
|
||
|
|
||
|
def mysql_op():
|
||
|
input = sys.stdin.read()
|
||
|
|
||
|
request = ceo_pb2.AddMySQLUser()
|
||
|
request.ParseFromString(input)
|
||
|
|
||
|
remote_user = get_ceo_user()
|
||
|
mysql_user = request.username
|
||
|
|
||
|
response = ceo_pb2.AddMySQLUserResponse()
|
||
|
response_message(response, 0, 'mysql create db=%s by %s' % (mysql_user, remote_user))
|
||
|
|
||
|
mysql_createdb(remote_user, mysql_user, response)
|
||
|
|
||
|
sys.stdout.write(response.SerializeToString())
|
||
|
|
||
|
def main():
|
||
|
configure()
|
||
|
members.configure()
|
||
|
members.connect_anonymous()
|
||
|
syslog.openlog('op-mysql', syslog.LOG_PID, syslog.LOG_DAEMON)
|
||
|
mysql_op()
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
main()
|