def setUp(self): self._cluster = "cluster" self._username = "******" self._password = "******" self._fakeConnection = FakeMysqlConnection() self._fakeCursor = FakeMysqlCursor() self._logPasswords = True echoAccessLevel = mysql_query_tool.QAL_ALL queryAccessLevel = mysql_query_tool.QAL_ALL mysql_query_tool.MySQLdb.connect = mock.MagicMock( return_value=self._fakeConnection) self._mysqlQueryTool = mysql_query_tool.MysqlQueryTool( self._cluster, self._username, self._password, echoAccessLevel, queryAccessLevel, self._logPasswords) self._mysqlQueryTool.getCursor = mock.MagicMock( return_value=self._fakeCursor)
def start(autoGrantConfig, echoOnly, logPasswords, destructive, passwordReset, revert, userList, groupList, clusterList): restoreName = '' restorePath = '' mysqlBackupTool = _getMysqlBackupTool(echoOnly, logPasswords) pruneBeforeDate = mysqlBackupTool.getPruneBeforeFromTimeDelta( datetime.timedelta(days=30)) mysqlBackupTool.pruneBefore(pruneBeforeDate) if revert is not False: if revert is None: # default we use the last backup restoreName = mysqlBackupTool.getLastBackup() else: # default we use the last backup restoreName = revert backupDir = mysql_backup_tool.DEFAULT_BACKUP_DIR if restoreName is not None and 0 < len(restoreName): restorePath = os.path.join(backupDir, restoreName) if os.path.isdir(restorePath): revertUser = autoGrantConfig.getMysqlRevertUsername() revertPass = autoGrantConfig.getMysqlRevertPassword() mysqlBackupTool = _getMysqlBackupTool(echoOnly, logPasswords) for cluster in autoGrantConfig.getDbClusters(): logger.info("reverting %s", cluster) echoAccessLevel = mysql_query_tool.QAL_ALL queryAccessLevel = mysql_query_tool.QAL_ALL if echoOnly: queryAccessLevel = mysql_query_tool.QAL_NONE mysqlConn = mysql_query_tool.MysqlQueryTool(cluster, revertUser, revertPass, echoAccessLevel, queryAccessLevel, logPasswords) mysqlBackupTool.restoreFromMySQLDumpList(cluster, revertUser, revertPass, restoreName, [("mysql", "user")]) mysqlConn.queryFlushPrivileges() else: logger.error("No backup was found under %s", backupDir) else: ldapUrl = autoGrantConfig.getLdapURL() ldapUsernameBase = autoGrantConfig.getLdapUsernameBase() ldapPassword = autoGrantConfig.getLdapPassword() ldapGroupDict = {} if ldapUrl is None or ldapUsernameBase is None or ldapPassword is None: logger.warning("missing one of ldapUrl:%s ldapUsernameBase:%s or ldapPassword:%s [%s]", str(ldapUrl), str(ldapUsernameBase), str(ldapPassword), "this will disable ldap integration") else: ldapQueryTool = ldap_query_tool.LdapQueryTool(ldapUrl, ldapUsernameBase, ldapPassword) ldapGroupDesc = autoGrantConfig.getLdapGroupDesc() ldapGroupDict = ldapQueryTool.queryLDAP(ldapGroupDesc) groupDict = makeGroupDict(autoGrantConfig, ldapGroupDict) if userList is not None: userList = userList.split(",") if groupList is not None: for group in groupList.split(","): if userList is None: userList = [] userList += groupDict[group] logger.debug("groupDict:\n"+pprint.pformat(groupDict)) userDict = makeUserDict(autoGrantConfig, groupDict, userList) logger.debug("userDict:\n"+pprint.pformat(userDict)) grantDict = makeGrantDict(autoGrantConfig, userDict, clusterList) logger.debug("grantDict:\n"+pprint.pformat(grantDict)) grantAccess(autoGrantConfig, grantDict, echoOnly, logPasswords, destructive, passwordReset)
def grantAccess(autoGrantConfig, grantDict, echoOnly, logPasswords, destructive, passwordReset): """ This is the function that grants revokes and drops users Before adding any additional logica we should consider splitting this function to avoid it getting too unweildy NOTE: if destructive is False Revokes and Drop Users will be omitted """ newUserDict = {} mysqlBackupTool = _getMysqlBackupTool(echoOnly, logPasswords) backupName = mysqlBackupTool.getCurrentTimeBackup() grantUser = autoGrantConfig.getMysqlGrantsUsername() grantPass = autoGrantConfig.getMysqlGrantsPassword() # determine access levels from echoOnly and destructive echoAccessLevel = mysql_query_tool.QAL_READ_WRITE if destructive or passwordReset: echoAccessLevel = mysql_query_tool.QAL_READ_WRITE_DELETE queryAccessLevel = echoAccessLevel if echoOnly: queryAccessLevel = mysql_query_tool.QAL_READ defaultCluster = grantDict.keys()[0] for cluster in grantDict.keys(): mysqlBackupTool.performMySQLDumpList(cluster, grantUser, grantPass, backupName, [("mysql", "user")]) logger.debug("backup saved") mysqlConn = mysql_query_tool.MysqlQueryTool(cluster, grantUser, grantPass, echoAccessLevel, queryAccessLevel, logPasswords) logger.debug("connection created") for userAtHost in grantDict[cluster].keys(): logger.debug("working on %s", userAtHost) userPart, hostPart = (x.strip("'") for x in userAtHost.split('@')) mysqlConn.beginTransaction() passwordHash = mysqlConn.getPasswordHash(userPart, hostPart) userExists = (passwordHash is not None) if passwordReset and userExists: mysqlConn.dropUser(userAtHost) userExists = False passwordHash = None if userExists: logger.debug("CACHING PASSWORD HASH %s FOR %s ACCOUNT ON %s" % (passwordHash, userAtHost, cluster)) updateMysqlUser(newUserDict, userAtHost, mysqlConn, passwordHash, None) else: logger.debug("NEED TO CREATE USER: %s", userAtHost) updateMysqlUser(newUserDict, userAtHost, mysqlConn, generateRandomPassword(), cluster) grantDeltaDict = {} try: for grant in grantDict[cluster][userAtHost]: dbTable = grant['db_table'] privileges = grant['privileges'] grantDeltaDict = mysqlConn.getGrantDeltaDict(userAtHost, dbTable, privileges) if 0 < len(grantDeltaDict['grants']): mysqlConn.queryGrant(userAtHost, grantDeltaDict['grants'], dbTable) if 0 < len(grantDeltaDict['revokes']): mysqlConn.queryRevoke(userAtHost, grantDeltaDict['revokes'], dbTable) mysqlConn.queryFlushPrivileges() mysqlConn.commitTransaction() except Exception as e: mysqlConn.rollbackTransaction() message = e.message + ": An exception occured when trying to grant:[%s] and revoke:[%s] to %s on %s" % (",".join(grantDeltaDict['grants']), ",".join(grantDeltaDict['revokes']), userAtHost, cluster) raise GrantException(message) if destructive and not passwordReset: # remove non defined users allMysqlUsers = mysqlConn.findAllUsers() usersToDrop = findUsersToDrop(autoGrantConfig, allMysqlUsers, grantDict[cluster].keys()) for userToDropWithHost in usersToDrop: mysqlConn.dropUser(userToDropWithHost) mysqlConn.closeConnection() if echoOnly is False: sendEmailNotifications(autoGrantConfig, newUserDict, defaultCluster)