I want to write a fast-API endpoint with functionality that gets .ppk file and converts it to .pem to get connect to SFTP to download some files using Python without storing them in the local system.
If I use a direct .pem file, it helps connect to SFTP and download the file but need to know how to do with .ppk file.
Tried to run the command using subprocess and store data with extension .pem in tempfile but still tempfile stays empty after executing the subprocess.Popen.
the .ppk file required password.
Running the below command convert to .pem file by asking Enter passphrase to load key:
puttygen "/home/ubuntu/Music/SFTP_Private_Key.ppk" -O private-openssh -o "/home/ubuntu/Music/SFTP_Private_Key_convert.pem"
I like to get the functionality in python. Anything, I missed here!!!... Thanks in advance. Below is my code.
import paramiko
import tempfile
import subprocess
import shlex
use_host = 'testfile.random.com'
use_port = 22
use_username = 'tester123'
use_password = '1234567890'
use_ppk_path = '/home/ubuntu-test/Music/SFTP_Private_Key.ppk'
use_temp_pem_file = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix=".pem")
use_pem_path = use_temp_pem_file.name
use_cmd = f'puttygen "{use_ppk_path}" -O private-openssh -o "{use_pem_path}" --old-passphrase "{use_password}"'
use_process = subprocess.Popen(
use_cmd,
shell=True,
stdin=subprocess.PIPE
)
use_process.communicate(input=use_password.encode())
if use_process.returncode != 0:
print(f"Error executing command: {use_cmd}")
print(f"Command returned non-zero exit status: {use_process.returncode}")
print(f"Error output-stderr:\n{use_process.stderr}")
print(f"Error output-stdout:\n{use_process.stdout}")
with open(use_pem_path, 'r') as use_f:
use_f.seek(0)
use_file_contents = use_f.read()
print('file_contents', use_file_contents)
use_ssh = paramiko.SSHClient()
use_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
private_key = paramiko.RSAKey.from_private_key_file(filename=use_pem_path)
use_ssh.connect(use_host, port=use_port, username=use_username, password=use_password, key_filename=private_key)
use_sftp = use_ssh.open_sftp()
Tried command like
> f'puttygen "{use_ppk_path}" -O private-openssh -o "{use_pem_path}" --old-passphrase "{use_password}"'
> f'puttygen "{use_ppk_path}" -O private-openssh -o "{use_pem_path}" -P "{use_password}"'
> f'puttygen "{use_ppk_path}" -O private-openssh -o "{use_pem_path}"' #last command ask password in separate window while code execution, which can't do in live session.
Errors:
use_f.read() is empty always.
private_key = paramiko.RSAKey.from_private_key_file(filename=use_pem_path) ----> paramiko.ssh_exception.SSHException: not a valid RSA private key file
Checked with tempfile_path as-well, still content in file is empty.
use_temp_pem_file = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix=".pem")
use_pem_path = use_temp_pem_file.name
use_cmd = f'puttygen "{use_ppk_path}" -O private-openssh -o "{use_pem_path}"'
try:
with open(use_temp_pem_file, 'r') as use_f:
for line in use_f:
print(line)
use_f.seek(0)
use_file_contents = use_f.read()
except:
use_file_contents = ""
print('file_contents', use_file_contents)
Tried:
# with open(use_temp_pem_file, 'r') as use_f:
use_temp_pem_file.seek(0)
use_file_contents = use_temp_pem_file.read()
print('file_contents', use_file_contents)
# Still its empty values
Error-Message: TypeError: expected str, bytes or os.PathLike object, not _TemporaryFileWrapper
I have found this code snippet, http://www.example-code.com/python/ssh_ppk_to_pem.asp but I am not sure if it is a good idea to use the -chilkat- library . and Its free or not
found the answer. use pexpect instead of subprocess. doc-here
child = pexpect.spawn(f'puttygen "{use_ppk_path}" -O private-openssh -o "{use_pem_path}"')
child.expect('Enter passphrase to load key:')
child.sendline(use_password)
use_temp_pem_file.seek(0)
use_file_contents = use_temp_pem_file.read()