英文:
Convert .ppk file to .pem with tempfile using python
问题
我想编写一个快速的FastAPI端点,具有将.ppk文件转换为.pem文件的功能,以便使用Python连接到SFTP并下载一些文件,而不将它们存储在本地系统中。
如果我使用直接的.pem文件,它可以帮助连接到SFTP并下载文件,但我需要知道如何处理.ppk文件。
尝试使用subprocess运行命令,并将数据存储在临时文件中,但在执行subprocess.Popen后,临时文件仍然为空。
.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}"' # 最后一个命令在代码执行时会在单独的窗口中要求密码,无法在实时会话中执行。
错误:
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)
# 仍然是空值
错误消息:TypeError: 期望 str、bytes 或 os.PathLike 对象,而不是 _TemporaryFileWrapper
我找到了这个代码片段:http://www.example-code.com/python/ssh_ppk_to_pem.asp,但我不确定是否可以使用-chilkat-库。它是否免费?
【注意】请注意,上述代码示例中包含了处理密码的部分,这可能不够安全。在实际应用中,建议采用更安全的方式来处理密码,如从安全存储中获取密码或使用其他安全措施。
英文:
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
答案1
得分: 1
发现答案。使用 pexpect 而不是 subprocess。 文档在这里。
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()
英文:
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()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论