Я хочу написать конечную точку быстрого API с функциональностью, которая получает файл .ppk и преобразует его в .pem, чтобы подключиться к SFTP для загрузки некоторых файлов с помощью Python без сохранения их в локальной системе.
Если я использую прямой файл .pem, это помогает подключиться к SFTP и загрузить файл, но мне нужно знать, что делать с файлом .ppk.
Пытался запустить команду с помощью подпроцесса и сохранить данные с расширением .pem в tempfile, но после выполнения subprocess.Popen tempfile остается пустым.
для файла .ppk требуется пароль.
Запустив приведенную ниже команду, преобразуйте ее в файл .pem, попросив ввести кодовую фразу для загрузки ключа:
puttygen "/home/ubuntu/Music/SFTP_Private_Key.ppk" -O private-openssh -o "/home/ubuntu/Music/SFTP_Private_Key_convert.pem"
Мне нравится получать функциональность в python. Ничего, я тут пропустил!!!... Заранее спасибо. Ниже мой код.
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()
Пробовал команду вроде
> 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.
Ошибки:
use_f.read() всегда пуст.
private_key = paramiko.RSAKey.from_private_key_file(filename=use_pem_path) ----> paramiko.ssh_exception.SSHException: недействительный файл закрытого ключа RSA
Также проверено с помощью tempfile_path, все еще содержимое в файле пусто.
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)
Пытался:
# 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
Сообщение об ошибке: TypeError: ожидаемый объект str, bytes или os.PathLike, не _TemporaryFileWrapper
Я нашел этот фрагмент кода, http://www.example-code.com/python/ssh_ppk_to_pem.asp но я не уверен, что это хорошая идея - использовать библиотеку -chilkat-. и это бесплатно или нет
Я не думаю, что open(use_temp_pem_file) может работать. Я имел в виду, что вы должны попытаться сделать use_temp_pem_file.read.
use_temp_pem_file.read() дает пустую строку. Обновляет вопрос. @МартинПрикрыл
В вашем новом примере кода отсутствует какой-либо контекст. Вы use_temp_pem_file.seek(0) перед прочтением?
обновленный код с use_temp_pem_file.seek(0), но он все еще пуст. Правильно ли выполнено выполнение команды с subprocess.run...? что-нибудь пропустил?





нашел ответ. используйте pexpect вместо подпроцесса. док-здесь
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()
Попробуйте вызвать
use_temp_pem_file.flush. + Хотя не лучше ли вам читать изuse_temp_pem_file, а не пытаться открыть его (снова) по его имени?