"""RabbitMQAdmin module serves for the management of the internal RabbitMQ users database. It uses rabbitmqctl command. Only the user with the right permissions can execute those commands. """ from __future__ import print_function from __future__ import absolute_import from __future__ import division import re from DIRAC import S_OK, S_ERROR import errno from DIRAC.Core.Utilities import Subprocess def executeRabbitmqctl(arg, *argv): """Executes RabbitMQ administration command. It uses rabbitmqctl command line interface. For every command the -q argument ("quit mode") is used, since in some cases the output must be processed, so we don't want any additional informations printed. Args: arg(str): command recognized by the rabbitmqctl. argv: optional list of string parameters. :rtype: S_OK or S_ERROR :type argv: python:list """ command = ["sudo", "/usr/sbin/rabbitmqctl", "-q", arg] + list(argv) timeOut = 30 result = Subprocess.systemCall(timeout=timeOut, cmdSeq=command) if not result["OK"]: return S_ERROR(errno.EPERM, "%r failed to launch" % command) errorcode, cmd_out, cmd_err = result["Value"] if errorcode: # No idea what errno code should be used here. # Maybe we should define some specific for rabbitmqctl return S_ERROR( errno.EPERM, "%r failed, status code: %s stdout: %r stderr: %r" % (command, errorcode, cmd_out, cmd_err) ) return S_OK(cmd_out) def addUserWithoutPassword(user): """Adds user to the internal RabbitMQ database and clears its password. This should be done for all users, that will be using SSL authentication. They do not need any password. """ ret = addUser(user) if not ret["OK"]: return ret return clearUserPassword(user) def addUser(user, password="password"): """Adds user to the internal RabbitMQ database Function also sets user password. User still cannot access to any resources, without having permissions set. """ return executeRabbitmqctl("add_user", user, password) def deleteUser(user): """Removes the user from the internal RabbitMQ database.""" return executeRabbitmqctl("delete_user", user) def getAllUsers(): """Returns all existing users in the internal RabbitMQ database. :returns: S_OK with a list of all users :rtype: S_OK """ ret = executeRabbitmqctl("list_users") if not ret["OK"]: return ret users = ret["Value"] users = users.split("\n") # the rabbitMQ user list is given in the format: # user_name [usr_tag] # I remove [usr_tag] part. # Also only non-empty users are proceeded further. # Empty users can appear, cause every new line was # treated as a new user. users = [re.sub(r"\\t\[\w*\]$", "", u) for u in users if u] return S_OK(users) def setUserPermission(user): return executeRabbitmqctl("set_permissions", "-p", "/", user, '".*"', '".*"', '".*"') def clearUserPassword(user): """Clears users password for the internal RabbitMQ database. User with no password cannot enter the RabbitMQ website interface but still can connect via SSL if given permission. """ return executeRabbitmqctl("clear_password", user) def setUsersPermissions(users): successful = {} failed = {} for u in users: ret = setUserPermission(u) if ret["OK"]: successful[u] = ret["Value"] else: print("Problem with permissions:%s" % ret["Message"]) failed[u] = "Permission not set because of:%s" % ret["Message"] return S_OK({"Successful": successful, "Failed": failed}) def addUsersWithoutPasswords(users): successful = {} failed = {} for u in users: ret = addUserWithoutPassword(u) if ret["OK"]: successful[u] = ret["Value"] else: print("Problem with adding user:%s" % ret["Message"]) failed[u] = "User not added" return S_OK({"Successful": successful, "Failed": failed}) def addUsers(users): """Adds users to the RabbitMQ internal database.""" successful = {} failed = {} for u in users: ret = addUser(u) if ret["OK"]: successful[u] = ret["Value"] else: print("Problem with adding user:%s" % ret["Message"]) failed[u] = "User not added" return S_OK({"Successful": successful, "Failed": failed}) def deleteUsers(users): """Deletes users from the RabbitMQ internal database.""" successful = {} failed = {} for u in users: ret = deleteUser(u) if ret["OK"]: successful[u] = ret["Value"] else: print("Problem with adding user:%s" % ret["Message"]) failed[u] = "User not added" return S_OK({"Successful": successful, "Failed": failed})