def host_executor(host, pkey, command): try: cli = SSH(host.hostname, host.port, host.username, pkey=pkey) exit_code, out = cli.exec_command(command) return exit_code == 0, out.decode() except Exception as e: return False, f'异常信息:{e}'
def check_user_password(request): """ 判断远程登陆用户名和密码是否准确 """ if request.method == "POST": try: data = dict() post_data = json.loads(str(request.body, encoding='utf-8')) info = { "hostname": post_data["hostname"], "username": post_data["username"], "password": post_data["password"], "port": post_data["port"] } ssh = SSH(**info) ssh.get_client() data["status"] = "success" data['result'] = info except paramiko.ssh_exception.NoValidConnectionsError: data["status"] = "fail" data["result"] = u"端口未开放或路由不可达,请重试或关闭!" except paramiko.ssh_exception.AuthenticationException: data["status"] = "fail" data["result"] = u"用户名或密码不准确,请重试或关闭!" except socket.error as err: data["status"] = "fail" data["result"] = u"连接超时,请重试或关闭!" return json_response(data)
def host_executor(q, host, pkey, command): exit_code, out, now = -1, None, time.time() try: cli = SSH(host.hostname, host.port, host.username, pkey=pkey) exit_code, out = cli.exec_command(command) finally: q.put((host.id, exit_code, round(time.time() - now, 3), out.decode() if out else None))
def host_executor(host, pkey, command): try: cli = SSH(host.hostname, host.port, host.username, pkey=pkey) exit_code, out = cli.exec_command(command) if exit_code == 0: return True, out or '检测状态正常' else: return False, out or f'退出状态码:{exit_code}' except Exception as e: return False, f'异常信息:{e}'
def valid_ssh(hostname, port, username, password=None, pkey=None, with_expect=True): try: private_key = AppSetting.get('private_key') public_key = AppSetting.get('public_key') except KeyError: private_key, public_key = SSH.generate_key() AppSetting.set('private_key', private_key, 'ssh private key') AppSetting.set('public_key', public_key, 'ssh public key') if password: _cli = SSH(hostname, port, username, password=str(password)) _cli.add_public_key(public_key) if pkey: private_key = pkey try: cli = SSH(hostname, port, username, private_key) cli.ping() except BadAuthenticationType: if with_expect: raise TypeError('该主机不支持密钥认证,请参考官方文档,错误代码:E01') return False except AuthenticationException: if password and with_expect: raise ValueError('密钥认证失败,请参考官方文档,错误代码:E02') return False return True
class Job: def __init__(self, hostname, port, username, pkey, command, token=None, **kwargs): self.ssh_cli = SSH(hostname, port, username, pkey) self.key = f'{hostname}:{port}' self.command = command self.token = token self.rds_cli = None def _send(self, message, with_expire=False): if self.rds_cli is None: self.rds_cli = get_redis_connection() self.rds_cli.lpush(self.token, json.dumps(message)) if with_expire: self.rds_cli.expire(self.token, 300) def send(self, data): message = {'key': self.key, 'type': 'info', 'data': data} self._send(message) def send_system(self, data): message = {'key': self.key, 'type': 'system', 'data': data} self._send(message) def send_error(self, data): message = {'key': self.key, 'type': 'error', 'data': data} self._send(message) def send_status(self, code): message = {'key': self.key, 'status': code} self._send(message, True) def run(self): if not self.token: return self.ssh_cli.exec_command(self.command) self.send_system('### Executing') code = -1 try: for code, out in self.ssh_cli.exec_command_with_stream( self.command): self.send(out) except socket.timeout: code = 130 self.send_error('### Time out') except Exception as e: code = 131 self.send_error(f'{e}') finally: self.send_status(code)
def host_executor(q, host, pkey, command): exit_code, out, now = -1, None, time.time() try: cli = SSH(host.hostname, host.port, host.username, pkey=pkey) exit_code, out = cli.exec_command(command) out = out.decode() if out else None except AuthenticationException: out = 'ssh authentication fail' except socket.error as e: out = f'network error {e}' finally: q.put((host.id, exit_code, round(time.time() - now, 3), out))
def __init__(self, hostname, port, username, pkey, command, token=None, **kwargs): self.ssh_cli = SSH(hostname, port, username, pkey) self.key = f'{hostname}:{port}' self.command = command self.token = token self.rds_cli = None
def valid_ssh(hostname, port, username, password, with_expect=True): try: private_key = AppSetting.get('private_key') #定义私钥公钥 public_key = AppSetting.get('public_key') except KeyError: #错误检查 private_key, public_key = SSH.generate_key() AppSetting.set('private_key', private_key, 'ssh private key') AppSetting.set('public_key', public_key, 'ssh public key') cli = SSH(hostname, port, username, private_key) if password: _cli = SSH(hostname, port, username, password=str(password)) code, out = _cli.exec_command('mkdir -p -m 700 ~/.ssh && \ echo %r >> ~/.ssh/authorized_keys && \ chmod 600 ~/.ssh/authorized_keys' % public_key) if code != 0: raise Exception(f'add public key error: {out!r}') try: cli.ping() except BadAuthenticationType: if with_expect: raise TypeError('该主机不支持密钥认证,请参考官方文档,错误代码:E01') return False except AuthenticationException: if password and with_expect: raise ValueError('密钥认证失败,请参考官方文档,错误代码:E02') return False return True
def _init(self): self.send(bytes_data=b'Connecting ...\r\n') host = self.ssh_info_dict.get("ip") if not host: self.send(text_data='Unknown host\r\n') self.close() try: self.ssh = SSH(hostname=host, username=self.ssh_info_dict["username"], password=self.ssh_info_dict["password"], port=self.ssh_info_dict["port"]).get_client() except Exception as e: self.send(bytes_data=f'Exception: {e}\r\n'.encode()) self.close() self.chan = self.ssh.invoke_shell(term='xterm') self.chan.transport.set_keepalive(30) Thread(target=self.loop_read).start()
def get_ssh_key(cls): public_key = cls.get_default('public_key') private_key = cls.get_default('private_key') if not private_key or not public_key: private_key, public_key = SSH.generate_key() cls.set('private_key', private_key) cls.set('public_key', public_key) return private_key, public_key
def post(self, request): form, error = JsonParser( Argument('id', type=int, required=False), Argument('group_ids', type=list, filter=lambda x: len(x), help='请选择主机分组'), Argument('name', help='请输主机名称'), Argument('username', handler=str.strip, help='请输入登录用户名'), Argument('hostname', handler=str.strip, help='请输入主机名或IP'), Argument('port', type=int, help='请输入SSH端口'), Argument('pkey', required=False), Argument('desc', required=False), Argument('password', required=False), ).parse(request.body) if error is None: password = form.pop('password') private_key, public_key = AppSetting.get_ssh_key() try: if form.pkey: private_key = form.pkey elif password: with SSH(form.hostname, form.port, form.username, password=password) as ssh: ssh.add_public_key(public_key) with SSH(form.hostname, form.port, form.username, private_key) as ssh: ssh.ping() except BadAuthenticationType: return json_response(error='该主机不支持密钥认证,请参考官方文档,错误代码:E01') except AuthenticationException: if password: return json_response(error='密钥认证失败,请参考官方文档,错误代码:E02') return json_response('auth fail') group_ids = form.pop('group_ids') other = Host.objects.filter(name=form.name).first() if other and (not form.id or other.id != form.id): return json_response(error=f'已存在的主机名称【{form.name}】') if form.id: Host.objects.filter(pk=form.id).update(is_verified=True, **form) host = Host.objects.get(pk=form.id) else: host = Host.objects.create(created_by=request.user, is_verified=True, **form) _sync_host_extend(host, ssh=ssh) host.groups.set(group_ids) response = host.to_view() response['group_ids'] = group_ids return json_response(response) return json_response(error=error)
def __init__(self, key, name, hostname, port, username, pkey, command, interpreter, token=None): self.ssh = SSH(hostname, port, username, pkey) self.key = key self.command = self._handle_command(command, interpreter) self.token = token self.rds_cli = None self.env = dict(SPUG_HOST_ID=str(self.key), SPUG_HOST_NAME=name, SPUG_HOST_HOSTNAME=hostname, SPUG_SSH_PORT=str(port), SPUG_SSH_USERNAME=username, SPUG_INTERPRETER=interpreter)
def _get_ssh(kwargs, pkey=None, private_key=None, public_key=None, password=None): try: ssh = SSH(pkey=pkey or private_key, **kwargs) ssh.get_client() return ssh except AuthenticationException as e: if password: with SSH(password=str(password), **kwargs) as ssh: ssh.add_public_key(public_key) return _get_ssh(kwargs, private_key) raise e
def valid_ssh(hostname, port, username, password): try: private_key = AppSetting.get('private_key') public_key = AppSetting.get('public_key') except KeyError: private_key, public_key = SSH.generate_key() AppSetting.set('private_key', private_key, 'ssh private key') AppSetting.set('public_key', public_key, 'ssh public key') if password: cli = SSH(hostname, port, username, password=str(password)) code, out = cli.exec_command('mkdir -p -m 700 ~/.ssh && \ echo %r >> ~/.ssh/authorized_keys && \ chmod 600 ~/.ssh/authorized_keys' % public_key) if code != 0: raise Exception(f'add public key error: {out!r}') else: cli = SSH(hostname, port, username, private_key) try: cli.ping() except AuthenticationException: return False return True
class SSHConsumer(WebsocketConsumer): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) kwargs = self.scope['url_route']['kwargs'] ssh_infos = kwargs['id'] ssh_infos = aes_decode(conf_data['AES_KEY'], ssh_infos) ssh_infos = ssh_infos.split("&") self.ssh_info_dict = dict() for i in ssh_infos: i = i.split("=") self.ssh_info_dict[i[0]] = i[1] self.chan = None self.ssh = None def loop_read(self): while True: data = self.chan.recv(32 * 1024) if not data: self.close(3333) break self.send(bytes_data=data) def receive(self, text_data=None, bytes_data=None): data = text_data or bytes_data if data: data = json.loads(data) print("receive:", data) resize = data.get('resize') if resize and len(resize) == 2: self.chan.resize_pty(*resize) else: print("send:", data['data']) self.chan.send(data['data']) def disconnect(self, code): self.chan.close() self.ssh.close() def connect(self): self.accept() self._init() def _init(self): self.send(bytes_data=b'Connecting ...\r\n') host = self.ssh_info_dict.get("ip") if not host: self.send(text_data='Unknown host\r\n') self.close() try: self.ssh = SSH(hostname=host, username=self.ssh_info_dict["username"], password=self.ssh_info_dict["password"], port=self.ssh_info_dict["port"]).get_client() except Exception as e: self.send(bytes_data=f'Exception: {e}\r\n'.encode()) self.close() self.chan = self.ssh.invoke_shell(term='xterm') self.chan.transport.set_keepalive(30) Thread(target=self.loop_read).start()
class Job: def __init__(self, key, name, hostname, port, username, pkey, command, interpreter, token=None): self.ssh = SSH(hostname, port, username, pkey) self.key = key self.command = self._handle_command(command, interpreter) self.token = token self.rds_cli = None self.env = dict(SPUG_HOST_ID=str(self.key), SPUG_HOST_NAME=name, SPUG_HOST_HOSTNAME=hostname, SPUG_SSH_PORT=str(port), SPUG_SSH_USERNAME=username, SPUG_INTERPRETER=interpreter) def _send(self, message, with_expire=False): if self.rds_cli is None: self.rds_cli = get_redis_connection() self.rds_cli.lpush(self.token, json.dumps(message)) if with_expire: self.rds_cli.expire(self.token, 300) def _handle_command(self, command, interpreter): if interpreter == 'python': attach = 'INTERPRETER=python\ncommand -v python3 &> /dev/null && INTERPRETER=python3' return f'{attach}\n$INTERPRETER << EOF\n# -*- coding: UTF-8 -*-\n{command}\nEOF' return command def send(self, data): message = {'key': self.key, 'data': data} self._send(message) def send_status(self, code): message = {'key': self.key, 'status': code} self._send(message, True) def run(self): if not self.token: with self.ssh: return self.ssh.exec_command(self.command, self.env) self.send('\r\n\x1b[36m### Executing ...\x1b[0m\r\n') code = -1 try: with self.ssh: for code, out in self.ssh.exec_command_with_stream( self.command, self.env): self.send(out) except socket.timeout: code = 130 self.send('\r\n\x1b[31m### Time out\x1b[0m') except Exception as e: code = 131 self.send(f'\r\n\x1b[31m### Exception {e}\x1b[0m') raise e finally: self.send_status(code)
def get_ssh(self, pkey=None, default_env=None): pkey = pkey or self.private_key return SSH(self.hostname, self.port, self.username, pkey, default_env=default_env)
def get_ssh(self, pkey=None): pkey = pkey or AppSetting.get('private_key') return SSH(self.hostname, self.port, self.username, pkey)