From 670e46c3092832368c733840a2ffe8b04bb13be1 Mon Sep 17 00:00:00 2001 From: usmannasir Date: Sun, 11 Feb 2024 14:42:16 +0500 Subject: [PATCH] bug fix: use paramiko for ssh operations --- backup/backupManager.py | 1 + .../templates/backup/backupDestinations.html | 2 +- backup/templates/backup/backupSchedule.html | 2 +- plogical/IncScheduler.py | 58 +++++++++++++++---- plogical/backupUtilities.py | 1 + requirments.txt | 20 ++++--- 6 files changed, 63 insertions(+), 21 deletions(-) diff --git a/backup/backupManager.py b/backup/backupManager.py index 5b565349e..13a85be36 100755 --- a/backup/backupManager.py +++ b/backup/backupManager.py @@ -1754,6 +1754,7 @@ class BackupManager: except: pass + nbj.config = json.dumps(config) nbj.save() diff --git a/backup/templates/backup/backupDestinations.html b/backup/templates/backup/backupDestinations.html index fc4742c8f..6d8bd87be 100755 --- a/backup/templates/backup/backupDestinations.html +++ b/backup/templates/backup/backupDestinations.html @@ -12,7 +12,7 @@

{% trans "Set up Backup Destinations" %} - {% trans "Remote Backups" %} diff --git a/backup/templates/backup/backupSchedule.html b/backup/templates/backup/backupSchedule.html index 69788cede..c525dbfed 100755 --- a/backup/templates/backup/backupSchedule.html +++ b/backup/templates/backup/backupSchedule.html @@ -12,7 +12,7 @@

{% trans "Schedule Backup" %} - {% trans "Remote Backups" %} diff --git a/plogical/IncScheduler.py b/plogical/IncScheduler.py index 77d6c7ed2..445722b20 100644 --- a/plogical/IncScheduler.py +++ b/plogical/IncScheduler.py @@ -1,6 +1,9 @@ #!/usr/local/CyberCP/bin/python import os.path import sys + +import paramiko + sys.path.append('/usr/local/CyberCP') os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings") import django @@ -509,6 +512,7 @@ class IncScheduler(multi.Thread): destinationConfig = json.loads(backupjob.owner.config) currentTime = time.strftime("%m.%d.%Y_%H-%M-%S") + print(destinationConfig['type']) if destinationConfig['type'] == 'local': @@ -620,18 +624,51 @@ Automatic backup failed for %s on %s. backupjob.config = json.dumps(jobConfig) backupjob.save() else: - - if jobConfig[IncScheduler.frequency] == type: - - import subprocess - import shlex + print(jobConfig[IncScheduler.frequency]) finalPath = '%s/%s' % (destinationConfig['path'].rstrip('/'), currentTime) - command = "ssh -o StrictHostKeyChecking=no -p " + destinationConfig[ - 'port'] + " -i /root/.ssh/cyberpanel " + destinationConfig['username'] + "@" + \ - destinationConfig[ - 'ip'] + " mkdir -p %s" % (finalPath) - subprocess.call(shlex.split(command)) + + # import subprocess + # import shlex + # command = "ssh -o StrictHostKeyChecking=no -p " + destinationConfig[ + # 'port'] + " -i /root/.ssh/cyberpanel " + destinationConfig['username'] + "@" + \ + # destinationConfig[ + # 'ip'] + " mkdir -p %s" % (finalPath) + # subprocess.call(shlex.split(command)) + + ### improved paramiko code + private_key_path = '/root/.ssh/cyberpanel' + + # Create an SSH client + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + # Load the private key + private_key = paramiko.RSAKey.from_private_key_file(private_key_path) + + # Connect to the server using the private key + try: + ssh.connect(destinationConfig['ip'], port=int(destinationConfig['port']), username=destinationConfig['username'], pkey=private_key) + except BaseException as msg: + NormalBackupJobLogs(owner=backupjob, status=backupSchedule.INFO, + message=f'Failed to make sftp connection {str(msg)}').save() + print(str(msg)) + continue + # Execute the command to create the remote directory + command = f'mkdir -p {finalPath}' + stdin, stdout, stderr = ssh.exec_command(command) + + # Wait for the command to finish and check for any errors + stdout.channel.recv_exit_status() + error_message = stderr.read().decode('utf-8') + print(error_message) + if error_message: + NormalBackupJobLogs(owner=backupjob, status=backupSchedule.INFO, + message=f'Error while creating directory on remote server {error_message.strip()}').save() + continue + else: + pass + ### Check if an old job prematurely killed, then start from there. # try: @@ -1550,5 +1587,6 @@ def main(): ib.join() + if __name__ == "__main__": main() diff --git a/plogical/backupUtilities.py b/plogical/backupUtilities.py index df134ce2d..7338567e2 100755 --- a/plogical/backupUtilities.py +++ b/plogical/backupUtilities.py @@ -1316,6 +1316,7 @@ class backupUtilities: return [1, "None"] + except paramiko.AuthenticationException: return [0, 'Authentication failed. [sendKey]'] except paramiko.SSHException as e: diff --git a/requirments.txt b/requirments.txt index 9bf6d5d9e..88efcb3dd 100755 --- a/requirments.txt +++ b/requirments.txt @@ -5,16 +5,17 @@ Babel==2.8.0 backports.ssl-match-hostname==3.7.0.1 bcrypt==3.2.0 beautifulsoup4==4.9.3 -boto3==1.18.26 -botocore==1.21.26 +boto3==1.34.39 +botocore==1.34.39 cachetools==4.1.1 certifi==2020.11.8 cffi==1.14.3 chardet==3.0.4 +charset-normalizer==2.0.12 cloudflare==2.8.13 ConfigArgParse==1.2.3 configobj==5.0.6 -cryptography==3.2.1 +cryptography==42.0.2 decorator==4.4.2 Django==3.1.3 docker==4.3.1 @@ -44,10 +45,9 @@ MarkupSafe==1.1.1 mock==4.0.2 mysqlclient==2.0.1 oauthlib==3.1.0 -paramiko==2.7.2 +paramiko==3.4.0 parsedatetime==2.6 pbr==5.5.1 -pysftp pexpect==4.8.0 prettytable==1.0.1 protobuf==3.13.0 @@ -58,20 +58,22 @@ pyasn1==0.4.8 pyasn1-modules==0.2.8 pycparser==2.20 pygpgme==0.3 -PyNaCl==1.4.0 -pyOpenSSL==19.1.0 +PyNaCl==1.5.0 +pyOpenSSL==24.0.0 pyotp==2.4.1 pyRFC3339==1.1 +pysftp==0.2.9 python-dateutil==2.8.1 pytz==2020.4 pyudev==0.22.0 pyxattr==0.7.1 +PyYAML==6.0.1 requests==2.26.0 requests-file==1.5.1 requests-oauthlib==1.3.0 requests-toolbelt==0.9.1 rsa==4.6 -s3transfer==0.5.0 +s3transfer==0.10.0 six==1.15.0 soupsieve==2.0.1 sqlparse==0.4.2 @@ -81,4 +83,4 @@ uritemplate==3.0.1 urllib3==1.26.5 validators==0.18.1 wcwidth==0.2.5 -websocket-client==0.57.0 +websocket-client==0.57.0 \ No newline at end of file