lxd-project/sshim_patch.py

134 lines
4.9 KiB
Python
Raw Normal View History

2022-11-23 19:18:40 +00:00
from sshim import *
import paramiko
import os
import uuid
import lxd_interface
import threading
import logging
2022-11-28 19:25:39 +00:00
import select
2022-11-26 23:06:01 +00:00
import time
2022-11-26 23:48:22 +00:00
import inspect
2022-11-26 22:24:31 +00:00
logger = logging.getLogger(__name__)
2022-11-29 18:23:11 +00:00
def check_channel_request(self, kind, channel_id):
logger.debug(f"Client requested {kind}")
if kind in ('session', 'sftp'):
return paramiko.OPEN_SUCCEEDED
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_channel_shell_request(self, channel):
2022-11-28 19:25:39 +00:00
logger.debug("Check channel shell request: %s" % channel.get_id())
2022-11-29 18:23:11 +00:00
self.runner.set_shell_channel(channel)
return True
2022-11-29 18:54:09 +00:00
def check_channel_subsystem_request(self, channel, name):
if name == 'sftp':
self.runner.set_sftp_channel(channel)
return True
else:
return False
2022-11-23 19:18:40 +00:00
def check_auth_none(self, username):
2022-11-28 19:56:50 +00:00
if username == os.environ["SSH_USERNAME"]:
return paramiko.AUTH_PARTIALLY_SUCCESSFUL
return paramiko.AUTH_FAILED
2022-11-23 19:18:40 +00:00
def check_auth_password(self, username, password):
2022-11-28 19:55:27 +00:00
logger.debug(f"{username} just tried to connect")
if username == os.environ["SSH_USERNAME"] and password == os.environ["SSH_PASSWORD"]:
2022-11-29 18:23:11 +00:00
self.runner = Runner(self, self.transport)
self.runner.start()
2022-11-23 19:18:40 +00:00
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
def check_auth_publickey(self, username, key):
return paramiko.AUTH_FAILED
class Runner(threading.Thread):
2022-11-29 18:23:11 +00:00
def __init__(self, client, transport: paramiko.Transport):
self.instance_name = "instance-" + str(uuid.uuid4())
2022-11-29 19:53:08 +00:00
threading.Thread.__init__(self, name=f'sshim.Runner {self.instance_name}')
2022-11-25 16:08:10 +00:00
self.instance_password = str(uuid.uuid4()) # TODO: secure password generation
self.daemon = True
self.client = client
2022-11-29 18:23:11 +00:00
self.transport = transport
2022-11-29 18:54:09 +00:00
# self.transport.set_subsystem_handler('sftp', handler=paramiko.SFTPServer)
2022-11-29 18:23:11 +00:00
self.shell_channel = None
self.sftp_channel = None
def run(self) -> None:
2022-11-26 23:06:01 +00:00
vm_ip = lxd_interface.create_instance(self.instance_name, self.instance_password)['address']
2022-11-25 16:08:10 +00:00
with paramiko.SSHClient() as ssh_client:
2022-11-26 23:06:01 +00:00
ssh_client.set_missing_host_key_policy(paramiko.WarningPolicy)
ssh_client.connect(vm_ip, username='root', password=self.instance_password)
2022-11-29 18:23:11 +00:00
client_shell_channel = ssh_client.invoke_shell()
client_sftp_channel = ssh_client.open_sftp().get_channel()
2022-11-26 23:06:01 +00:00
while True:
2022-11-29 18:23:11 +00:00
if self.shell_channel is not None:
r, w, e = select.select([client_shell_channel, self.shell_channel], [], [])
if self.shell_channel in r:
x = self.shell_channel.recv(1024)
if len(x) == 0:
2022-11-29 19:53:08 +00:00
self.shell_channel.close()
2022-11-29 19:22:27 +00:00
self.shell_channel = None
2022-11-29 19:53:08 +00:00
continue
2022-11-29 18:23:11 +00:00
client_shell_channel.send(x)
if client_shell_channel in r:
x = client_shell_channel.recv(1024)
if len(x) == 0:
2022-11-29 19:53:08 +00:00
self.shell_channel.close()
2022-11-29 19:22:27 +00:00
self.shell_channel = None
2022-11-29 19:53:08 +00:00
continue
2022-11-29 18:23:11 +00:00
self.shell_channel.send(x)
2022-11-29 19:22:27 +00:00
if self.sftp_channel is not None: # TODO: move this to function
2022-11-29 18:23:11 +00:00
r, w, e = select.select([client_sftp_channel, self.sftp_channel], [], [])
if self.sftp_channel in r:
x = self.sftp_channel.recv(1024)
if len(x) == 0:
2022-11-29 19:53:08 +00:00
self.sftp_channel.close()
2022-11-29 19:22:27 +00:00
self.sftp_channel = None
2022-11-29 19:53:08 +00:00
continue
2022-11-29 18:23:11 +00:00
client_sftp_channel.send(x)
if client_sftp_channel in r:
x = client_sftp_channel.recv(1024)
if len(x) == 0:
2022-11-29 19:53:08 +00:00
self.sftp_channel.close()
2022-11-29 19:22:27 +00:00
self.sftp_channel = None
2022-11-29 19:53:08 +00:00
continue
2022-11-29 18:23:11 +00:00
self.sftp_channel.send(x)
if self.transport.is_active() is False:
break
2022-11-28 19:38:07 +00:00
lxd_interface.destroy_instance(self.instance_name)
2022-11-29 18:23:11 +00:00
def set_shell_channel(self, channel):
self.shell_channel = channel
self.shell_channel.settimeout(None)
2022-11-29 18:54:09 +00:00
def set_sftp_channel(self, channel):
2022-11-29 18:23:11 +00:00
self.sftp_channel = channel
self.sftp_channel.settimeout(None)
2022-11-23 19:18:40 +00:00
2022-11-29 18:54:09 +00:00
Handler.check_channel_request = check_channel_request
Handler.check_channel_shell_request = check_channel_shell_request
2022-11-29 18:54:09 +00:00
Handler.check_channel_subsystem_request = check_channel_subsystem_request
2022-11-23 19:18:40 +00:00
Handler.check_auth_none = check_auth_none
Handler.check_auth_password = check_auth_password
Handler.check_auth_publickey = check_auth_publickey
Handler.enable_auth_gssapi = paramiko.server.ServerInterface.enable_auth_gssapi
Handler.get_allowed_auths = paramiko.server.ServerInterface.get_allowed_auths