将.ppk文件使用Python和临时文件转换为.pem文件。

huangapple go评论61阅读模式
英文:

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()

huangapple
  • 本文由 发表于 2023年6月19日 00:49:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76501623.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定