|
1 | 1 | # -*- coding: utf-8 -*- |
2 | | -import paramiko |
3 | | -import threading |
4 | | -import time |
5 | | -import os |
6 | | -from socket import timeout |
7 | | -from assets.tasks import admin_file |
8 | | -from channels.generic.websocket import WebsocketConsumer |
9 | | -from assets.models import ServerAssets, AdminRecord |
10 | | -from django.conf import settings |
| 2 | +from utils.ssh import MySSH |
11 | 3 | from utils.crypt_pwd import CryptPwd |
12 | | -from conf.logger import fort_logger |
| 4 | +from assets.models import ServerAssets |
13 | 5 |
|
14 | 6 |
|
15 | | -class MyThread(threading.Thread): |
16 | | - def __init__(self, chan): |
17 | | - super(MyThread, self).__init__() |
18 | | - self.chan = chan |
19 | | - self._stop_event = threading.Event() |
20 | | - self.start_time = time.time() |
21 | | - self.current_time = time.strftime(settings.TIME_FORMAT) |
22 | | - self.stdout = [] |
23 | | - |
24 | | - def stop(self): |
25 | | - self._stop_event.set() |
26 | | - |
27 | | - def run(self): |
28 | | - while not self._stop_event.is_set() or not self.chan.chan.exit_status_ready(): |
29 | | - time.sleep(0.1) |
30 | | - try: |
31 | | - data = self.chan.chan.recv(1024) |
32 | | - if data: |
33 | | - str_data = data.decode('utf-8', 'ignore') |
34 | | - self.chan.send(str_data) |
35 | | - self.stdout.append([time.time() - self.start_time, 'o', str_data]) |
36 | | - except timeout: |
37 | | - self.chan.send('\n由于长时间没有操作,连接已断开!', close=True) |
38 | | - self.stdout.append([time.time() - self.start_time, 'o', '\n由于长时间没有操作,连接已断开!']) |
39 | | - break |
40 | | - |
41 | | - def record(self): |
42 | | - record_path = os.path.join(settings.MEDIA_ROOT, 'admin_ssh_records', self.chan.scope['user'].username, |
43 | | - time.strftime('%Y-%m-%d')) |
44 | | - if not os.path.exists(record_path): |
45 | | - os.makedirs(record_path, exist_ok=True) |
46 | | - record_file_name = '{}.{}.cast'.format(self.chan.host_ip, time.strftime('%Y%m%d%H%M%S')) |
47 | | - record_file_path = os.path.join(record_path, record_file_name) |
48 | | - |
49 | | - header = { |
50 | | - "version": 2, |
51 | | - "width": self.chan.width, |
52 | | - "height": self.chan.height, |
53 | | - "timestamp": round(self.start_time), |
54 | | - "title": "Demo", |
55 | | - "env": { |
56 | | - "TERM": os.environ.get('TERM'), |
57 | | - "SHELL": os.environ.get('SHELL', '/bin/bash') |
58 | | - }, |
59 | | - } |
60 | | - |
61 | | - admin_file.delay(record_file_path, self.stdout, header) |
62 | | - |
63 | | - login_status_time = time.time() - self.start_time |
64 | | - if login_status_time >= 60: |
65 | | - login_status_time = '{} m'.format(round(login_status_time / 60, 2)) |
66 | | - elif login_status_time >= 3600: |
67 | | - login_status_time = '{} h'.format(round(login_status_time / 3660, 2)) |
68 | | - else: |
69 | | - login_status_time = '{} s'.format(round(login_status_time)) |
70 | | - |
71 | | - try: |
72 | | - AdminRecord.objects.create( |
73 | | - admin_login_user=self.chan.scope['user'], |
74 | | - admin_server=self.chan.host_ip, |
75 | | - admin_remote_ip=self.chan.remote_ip, |
76 | | - admin_start_time=self.current_time, |
77 | | - admin_login_status_time=login_status_time, |
78 | | - admin_record_file=record_file_path.split('media/')[1] |
79 | | - ) |
80 | | - except Exception as e: |
81 | | - fort_logger.error('数据库添加用户操作记录失败,原因:{}'.format(e)) |
82 | | - |
83 | | - |
84 | | -class SSHConsumer(WebsocketConsumer): |
| 7 | +class SSHConsumer(MySSH): |
85 | 8 | def __init__(self, *args, **kwargs): |
86 | 9 | super(SSHConsumer, self).__init__(*args, **kwargs) |
87 | | - self.ssh = paramiko.SSHClient() |
88 | 10 | self.server = ServerAssets.objects.select_related('assets').get(id=self.scope['path'].split('/')[3]) |
89 | | - self.host_ip = self.server.assets.asset_management_ip |
90 | | - self.width = 150 |
91 | | - self.height = 30 |
92 | | - self.t1 = MyThread(self) |
93 | | - self.remote_ip = self.scope['query_string'].decode('utf8') |
94 | | - self.chan = None |
95 | | - |
96 | | - def connect(self): |
97 | | - if self.scope["user"].is_anonymous: |
98 | | - self.close(code=1007) |
99 | | - else: |
100 | | - self.accept() |
101 | | - |
102 | | - username = self.server.username |
103 | | - try: |
104 | | - self.ssh.load_system_host_keys() |
105 | | - self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) |
106 | | - self.ssh.connect(self.host_ip, int(self.server.port), username, |
107 | | - CryptPwd().decrypt_pwd(self.server.password), timeout=5) |
108 | | - except Exception as e: |
109 | | - fort_logger.error('用户{}通过webssh连接{}失败!原因:{}'.format(username, self.host_ip, e)) |
110 | | - self.send('用户{}通过webssh连接{}失败!原因:{}'.format(username, self.host_ip, e)) |
111 | | - self.close() |
112 | | - self.chan = self.ssh.invoke_shell(term='xterm', width=self.width, height=self.height) |
113 | | - # 设置如果3分钟没有任何输入,就断开连接 |
114 | | - self.chan.settimeout(60 * 3) |
115 | | - self.t1.setDaemon(True) |
116 | | - self.t1.start() |
117 | | - |
118 | | - def receive(self, text_data=None, bytes_data=None): |
119 | | - self.chan.send(text_data) |
120 | | - |
121 | | - def disconnect(self, close_code): |
122 | | - try: |
123 | | - self.t1.record() |
124 | | - self.t1.stop() |
125 | | - finally: |
126 | | - self.ssh.close() |
| 11 | + self.ip = self.server.assets.asset_management_ip |
| 12 | + self.port = self.server.port |
| 13 | + self.username = self.server.username |
| 14 | + self.password = CryptPwd().decrypt_pwd(self.server.password) |
0 commit comments