def posix_shell(chan,user_obj,bind_host_obj,cmd_caches,log_recording): import select oldtty = termios.tcgetattr(sys.stdin) try: tty.setraw(sys.stdin.fileno()) tty.setcbreak(sys.stdin.fileno()) chan.settimeout(0.0) cmd = '' tab_key = False while True: r, w, e = select.select([chan, sys.stdin], [], []) if chan in r: try: x = u(chan.recv(1024)) if tab_key: if x not in ('\x07' , '\r\n'): #print('tab:',x) cmd += x tab_key = False if len(x) == 0: sys.stdout.write('\r\n*** EOF\r\n') break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in r: x = sys.stdin.read(1) if '\r' != x: cmd +=x else: print('cmd->:',cmd) log_item = models.AuditLog(user_id=user_obj.id, bind_host_id=bind_host_obj.id, action_type='cmd', cmd=cmd , date=datetime.datetime.now() ) cmd_caches.append(log_item) cmd = '' if len(cmd_caches)>=10: log_recording(user_obj,bind_host_obj,cmd_caches) cmd_caches = [] if '\t' == x: tab_key = True if len(x) == 0: break chan.send(x) finally: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
def write_logs(user_obj, bind_host_obj, log_recording): while True: item = redis_log.brpop(log_2_redis, 1) # 如果"log_2_redis"中没有数据, 等待1秒 if item: json_2_dic = json.loads(item[1].decode(), encoding="utf-8") log_item = models.AuditLog(user_id=user_obj.id, bind_host_id=bind_host_obj.id, action_type=json_2_dic.get( "action_type", "cmd"), cmd=json_2_dic.get("cmd", None), date=json_2_dic.get("date", None)) log_recording(log_item)
def store_aduit_log(user_profile_obj, bind_host_obj, cmd): ''' :param user_obj: 登录远程计算机的用户对象 :param bind_host_obj: 远程计算机对象 :param cmd: 用户对象执行的命令字符串 :return: ''' aduitLog_obj = models.AuditLog(user_profile_id=user_profile_obj.id, bind_host_id=bind_host_obj.id, cmd=cmd, date=datetime.datetime.now()) session.add(aduitLog_obj) session.commit()
def ssh_login(user_obj, bind_host_obj, mysql_engine, log_recording): # now, connect and use paramiko Client to negotiate SSH2 across the connection try: client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.WarningPolicy()) print('*** Connecting...') #client.connect(hostname, port, username, password) #连接远程机器。 client.connect( bind_host_obj.host.ip, #远程主机的ip bind_host_obj.host.port, #远程主机的端口 bind_host_obj.remote_user.username, #远程主机的远程用户 bind_host_obj.remote_user.password, #远程主机的远程用户密码 timeout=30) #命令缓存队列 cmd_caches = [] #创建通道。 chan = client.invoke_shell() print(repr(client.get_transport())) #连接上了远程主机 print('*** Here we go!\n') #往命令缓存队列中,记录一条日志。 cmd_caches.append( models.AuditLog( user_id=user_obj.id, #堡垒机用户的id bind_host_id=bind_host_obj.id, #远程主机 action_type='login', #动作类型登入,也可以写登出。 cmd=u"登入远程主机。", date=datetime.datetime.now() #日期 )) #把命令缓存写入数据库。 #缺点是,如果断开或者重启,命令缓存的数据就丢失了。 log_recording(user_obj, bind_host_obj, cmd_caches) #调用interactive进行处理。 interactive.interactive_shell(chan, user_obj, bind_host_obj, cmd_caches, log_recording) chan.close() client.close() except Exception as e: print('*** Caught exception: %s: %s' % (e.__class__, e)) traceback.print_exc() try: client.close() except: pass sys.exit(1)
def ssh_login(user_obj, bind_host_obj, mysql_engine, log_recording): # now, connect and use paramiko Client to negotiate SSH2 across the connection try: client = paramiko.SSHClient() # create SSHClient object client.load_system_host_keys() # 加载用户的.ssh密钥文件 client.set_missing_host_key_policy( paramiko.WarningPolicy()) # 允许连接不在know_hosts文件中的主机 print('*** Connecting...') # client.connect(hostname, port, username, password) client.connect(bind_host_obj.host.ip, bind_host_obj.host.port, bind_host_obj.remote_user.username, bind_host_obj.remote_user.password, timeout=30) # cmd_caches = [] chan = client.invoke_shell( ) # Start an interactive shell session on the SSH server. print(repr(client.get_transport())) print('*** Here we go!\n') log_item = models.AuditLog( user_id=user_obj.id, bind_host_id=bind_host_obj.id, action_type='login', date=datetime.datetime.now()) # 设定AuditLog表中各字段值 log_recording(log_item) interactive.interactive_shell(chan, user_obj, bind_host_obj, log_recording) chan.close() client.close() except Exception as e: print('*** Caught exception: %s: %s' % (e.__class__, e)) traceback.print_exc() try: client.close() except: pass sys.exit(1)
def ssh_login(user_obj, bind_host_obj, mysql_engine, log_recording): # now, connect and use paramiko Client to negotiate SSH2 across the connection try: client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.WarningPolicy()) print('*** Connecting...') #client.connect(hostname, port, username, password) client.connect(bind_host_obj.host.ip, bind_host_obj.host.port, bind_host_obj.remote_user.username, bind_host_obj.remote_user.password, timeout=30) cmd_caches = [] # 命令缓存 (为了不丢失,可以写入队列或者Redis,写入Redis最好) chan = client.invoke_shell() # print(repr(client.get_transport())) print('*** Here we go!\n') cmd_caches.append( models.AuditLog(user_id=user_obj.id, bind_host_id=bind_host_obj.id, action_type='login', date=datetime.datetime.now())) log_recording(user_obj, bind_host_obj, cmd_caches) interactive.interactive_shell( chan, user_obj, bind_host_obj, cmd_caches, log_recording) # 调paramiko的interactive方法 进行交互 chan.close() client.close() except Exception as e: print('*** Caught exception: %s: %s' % (e.__class__, e)) traceback.print_exc() try: client.close() except: pass sys.exit(1)
def ssh_login(user_obj, bind_host_obj, mysql_engine, log_recording): ''' ssh登陆 :param user_obj: :param bind_host_obj: :param mysql_engine: 连接数据库 :param log_recording: 写日志记录 :return: ''' # now, connect and use paramiko Client to negotiate SSH2 across the connection try: client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.WarningPolicy()) print('*** Connecting...') client.connect(bind_host_obj.host.ip, bind_host_obj.host.port, bind_host_obj.remote_user.username, bind_host_obj.remote_user.password, timeout=30) cmd_caches = [] chan = client.invoke_shell() # print(repr(client.get_transport())) print('*** Here we go!\n') # 连接redis pool = redis.ConnectionPool(host='192.168.84.66', port=6379) # 传一个命令列表给redis user_record = [ user_obj.id, bind_host_obj.id, 'login', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) ] r = redis.Redis(connection_pool=pool) # 用用户名做key前缀,避免冲突 key_name = str(user_obj.username) + '_login' r.lpush(key_name, user_record) interactive.interactive_shell(chan, user_obj, bind_host_obj, cmd_caches, log_recording) chan.close() client.close() # 数据库写入操作 login_record = r.lrange(key_name, 0, -1) login_redis_record = login_record[0].decode().replace('[', '').replace( ']', '').split(',') log_item = models.AuditLog(user_id=login_redis_record[0], bind_host_id=login_redis_record[1], action_type='login', cmd='login', date=login_redis_record[3].replace("'", '')) cmd_caches.append(log_item) log_recording(user_obj, bind_host_obj, cmd_caches) user_record_cmd = user_obj.username + '_user_record' cmd_redis_record = r.lrange(user_record_cmd, 0, -1) for i in cmd_redis_record: cmd_caches = [] v = i.decode().replace('[', '').replace(']', '').split(',') v2 = v[3].replace("'", '') # print(v[0], v[1], v[2], v[3], v[4]) log_item = models.AuditLog(user_id=v[0], bind_host_id=v[1], action_type='cmd', cmd=v2, date=v[4].replace("'", '')) cmd_caches.append(log_item) log_recording(user_obj, bind_host_obj, cmd_caches) # 当退出的时候将redis的值写入到数据库并且清空redis logout_caches = [] logout_caches.append( models.AuditLog(user_id=user_obj.id, bind_host_id=bind_host_obj.id, action_type='logout', cmd='logout', date=datetime.datetime.now())) log_recording(user_obj, bind_host_obj, logout_caches) # 清空keys r.delete(key_name) r.delete(user_record_cmd) except Exception as e: print('*** Caught exception: %s: %s' % (e.__class__, e)) traceback.print_exc() try: client.close() except: pass sys.exit(1)
def posix_shell(chan,user_obj,bind_host_obj,cmd_caches,log_recording): ''' :param chan: 通道 :param user_obj: 堡垒机用户对象 :param bind_host_obj: 后端主机对象 :param cmd_caches: 命令缓存列表 :param log_recording: 日志记录模块。 :return: ''' import select oldtty = termios.tcgetattr(sys.stdin) try: tty.setraw(sys.stdin.fileno()) tty.setcbreak(sys.stdin.fileno()) chan.settimeout(0.0) cmd = '' #标记tab键的标识符。 tab_key = False while True: r, w, e = select.select([chan, sys.stdin], [], []) if chan in r:#socket中有数据进入。 try: x = u(chan.recv(1024)) if tab_key:#用户按下了tab键。 if x not in ('\x07' , '\r\n'): #print('tab:',x) cmd += x#把远程主机补全的命令也加到命令字符串中。 tab_key = False#把标志位设置位false。 if len(x) == 0:#断开了 sys.stdout.write('\r\n*** EOF\r\n') break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in r:#按下键盘 x = sys.stdin.read(1) if '\r' != x:#如果不是换行键,就加入命令变量中。 cmd +=x else:#是换行键,说明输入了一条命令。 print('cmd->:',cmd)#打印此行命令。 #生成数据库对象。 log_item = models.AuditLog(user_id=user_obj.id, bind_host_id=bind_host_obj.id, action_type='cmd', cmd=cmd , date=datetime.datetime.now() ) #加入到命令缓存列表中。 cmd_caches.append(log_item) #把cmd字符串变量清空。 cmd = '' if len(cmd_caches)>=10:#每满10个命令,就保存到数据库中。 log_recording(user_obj,bind_host_obj,cmd_caches) cmd_caches = [] if '\t' == x:#用户按下了tab键。 tab_key = True#标志设置为true. if len(x) == 0:#断开连接了。 break chan.send(x)#把输入的数据发送到远程主机。 finally: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)