|
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