# coding: utf-8 # 服务器端每5分钟更改密码,申请的时候管理服务器从服务器端获取token(time + server license) # 主机名md5[15:] + 用户名md5[15:] + timetoken md5[15:] + server uuid md5 的md5值[15:].upper() # 服务器端主动上报token至集中管理服务器并记录,每台服务器记录一条,每次都修改上一次的记录,当服务器端更改密码的程序出故障时,使用数据库记录的最后一次token # 平台登录申请使用google authenticator加password认证 import time import logging import logging.config import socket import MySQLdb import hashlib import subprocess from config import Config import redis import base64 import string import random class PWDManager(object): def __init__(self, user): """ Dy token Manager """ self.t = int(time.time()) self.hostname = socket.gethostname() self.loginuser = user self.serverid = subprocess.Popen(['dmidecode -s system-uuid'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read().strip() logging.config.fileConfig("logging.conf") self.logger = logging.getLogger("Main") self.conn = MySQLdb.connect(user=decodestr(Config.dbuser), passwd=decodestr(Config.dbpasswd), host=decodestr(Config.dbhost), port=int(decodestr(Config.dbport))) self.cursor = self.conn.cursor() self.redis_conn = redis.StrictRedis(host=decodestr(Config.redishost), port=int(decodestr(Config.redisport)), db=0) @property def tokengenerate(self): try: token_hostname = hashlib.md5(self.hostname).hexdigest()[10:] token_loginuser = hashlib.md5(self.loginuser).hexdigest()[10:] token_unix_time = hashlib.md5(str(int(self.t) / 300)).hexdigest()[10:] #token_serverid = hashlib.md5(self.serverid).hexdigest()[10:] token = hashlib.md5(token_hostname + token_loginuser + token_unix_time).hexdigest()[10:].upper() token, rd = self.recodepw(token) self.rd = '&'.join([str(x) for x in rd]) self.logger.info('token created success.') self.token = token return token except Exception, e: self.logger.error("generate token faild!") self.logger.debug(e) @property def modifypwd(self): p1 = subprocess.Popen(['echo', self.token], stdout=subprocess.PIPE) p2 = subprocess.Popen(['passwd', '--stdin', self.loginuser], stdin=p1.stdout, stdout=subprocess.PIPE) result = p2.communicate() if result[-1]: self.logger.error(result[-1]) return else: self.logger.debug("change security token success.") return True @property def reporter(self): result = True # database try: self.cursor.execute('select id from %s.token_info where host="%s"' % (decodestr(Config.dbname), self.hostname)) token_id = self.cursor.fetchone() if not token_id: self.cursor.execute('insert into %s.token_info(host,time,rd_list) VALUES ("%s",%s,%s)' % ( decodestr(Config.dbname), self.hostname, self.t, self.rd)) self.conn.commit() else: self.cursor.execute( 'update %s.token_info set time = %s,rd_list=%s where host = "%s"' % ( decodestr(Config.dbname), self.t, self.rd, self.hostname )) self.conn.commit() self.logger.debug("update database scuess!") except Exception, e: self.logger.error("update database faild!") self.logger.debug(e) result = False #redis try: redis_set_t = self.redis_conn.set(self.hostname, self.t) redis_set_rd = self.redis_conn.set(self.hostname + 'rd', self.rd) if not redis_set_t and not redis_set_rd : result = False except Exception, e: self.logger.error("update redis faild!") self.logger.debug(e) result = False if result: self.logger.debug("update redis scuess!") return result def recodepw(self,token): spec_case = [x for x in '~!@#$%^&*()_+{}<>-='] + [x for x in string.lowercase] rd = random.sample(range(22),12) reset_token = '' for x in range(len(token)): if x in rd: w = spec_case[x] else: w = token[x] reset_token += w return reset_token, rd def decodestr(s): dns = s[5:].replace(s[-12:-4], '') + '==' return base64.decodestring(dns) # if __name__ == '__main__': # for user in users: # Agent = PWDManager(user) # token = Agent.tokengenerate # if token: # rep = Agent.reporter # if rep: # Agent.modifypwd # else: # continue # else: # continue # ~!@#$%^&*()_+{}<>-= 对应range(11,30) # a-z 对应 range(30,56)