【问题标题】:Is there a way to pass Python sshtunnel a key rather than a file?有没有办法将 Python sshtunnel 传递给密钥而不是文件?
【发布时间】:2020-12-10 23:06:52
【问题描述】:

我在本地使用以下库连接到完美运行的远程服务器:

https://pypi.org/project/sshtunnel/

但我需要将我的 Python 函数托管为 Google Cloud 函数。不幸的是,该库似乎只能接受文件,而不是直接作为字符串的键。这是配置:

server = SSHTunnelForwarder(
    SERVER_HOST,
    ssh_username=SSH_USERNAME,
    ssh_pkey="my_filename.pem",
    remote_bind_address=('127.0.0.1', 5412)
)

如果我尝试插入这样的内容:

SSH_KEY = """-----BEGIN RSA PRIVATE KEY-----

-----END RSA PRIVATE KEY-----"""

然后将 ssh_pkey 行修改为:

ssh_pkey=SSH_KEY

我的期望是它会起作用,但看起来图书馆不允许这样做。我在这里查看了源代码,似乎是 this 导致了这个问题。

@staticmethod
def get_keys(logger=None, host_pkey_directories=None, allow_agent=False):
    """
    Load public keys from any available SSH agent or local
    .ssh directory.
    Arguments:
        logger (Optional[logging.Logger])
        host_pkey_directories (Optional[list[str]]):
            List of local directories where host SSH pkeys in the format
            "id_*" are searched. For example, ['~/.ssh']
            .. versionadded:: 0.1.0
        allow_agent (Optional[boolean]):
            Whether or not load keys from agent
            Default: False
    Return:
        list
    """
    keys = SSHTunnelForwarder.get_agent_keys(logger=logger) \
        if allow_agent else []

    if host_pkey_directories is not None:
        paramiko_key_types = {'rsa': paramiko.RSAKey,
                              'dsa': paramiko.DSSKey,
                              'ecdsa': paramiko.ECDSAKey,
                              'ed25519': paramiko.Ed25519Key}
        for directory in host_pkey_directories or [DEFAULT_SSH_DIRECTORY]:
            for keytype in paramiko_key_types.keys():
                ssh_pkey_expanded = os.path.expanduser(
                    os.path.join(directory, 'id_{}'.format(keytype))
                )
                if os.path.isfile(ssh_pkey_expanded):
                    ssh_pkey = SSHTunnelForwarder.read_private_key_file(
                        pkey_file=ssh_pkey_expanded,
                        logger=logger,
                        key_type=paramiko_key_types[keytype]
                    )
                    if ssh_pkey:
                        keys.append(ssh_pkey)
    if logger:
        logger.info('{0} keys loaded from host directory'.format(
            len(keys))
        )

    return keys

我之前从来没有修补过任何东西,所以看看这个,我可以以某种方式手动覆盖它吗?

【问题讨论】:

  • 你考虑过/dev/fd/NN句柄吗?您可以让一个子进程控制另一端,准备写入文件的内容。
  • ...也就是说,get_keys 确实看起来非常独立,如果您愿意的话,可以随意修补。
  • 如果您使用的是 Windows,您可以创建一个 named pipe。虽然答案确实使用 Win32API 来读取文件(客户端),但在我的系统上直接调用 open(r"\\.\pipes\Foo") 似乎就足够了。
  • 这不是 Windows。我已经让它在 Ubuntu 上运行。问题是让它与 GCP Cloud 功能一起使用。

标签: python ssh-tunnel


【解决方案1】:

这就是我解决它的方法,希望它对某人有所帮助。首先,我使用 Python 打印出我的密钥文件 'temp_key.pem' 的 base64 编码密钥:

import base64
with open('temp_key.pem', 'rb') as f:
    blob = base64.b64encode(f.read())

print(blob)
for_google_cloud_function = blob.decode('utf-8')
print(for_google_cloud_function)

我使用了我的环境变量 SSH_KEY_BLOB 的输出。然后在我的 GCP Cloud Function 中添加了这个:

# decode key back into a useable form from base64
SSH_KEY_BLOB_DECODED = base64.b64decode(SSH_KEY_BLOB)
SSH_KEY = SSH_KEY_BLOB_DECODED.decode('utf-8')

# pass key to parmiko to get your pkey
pkey = paramiko.RSAKey.from_private_key(io.StringIO(SSH_KEY))

# setup your SSHTunnel like normal
server = SSHTunnelForwarder(
    remote_server_ip,
    ssh_username=SSH_USERNAME,
    ssh_pkey=pkey,
    remote_bind_address=('127.0.0.1', 27017)
)

这样,密钥就不会被硬编码,并且文件中的功能是自给自足的。它们可能是更好的方法,但这对我有用。

【讨论】:

猜你喜欢
  • 2023-04-07
  • 1970-01-01
  • 2019-10-30
  • 2020-02-20
  • 1970-01-01
  • 2021-11-19
  • 1970-01-01
  • 2020-09-20
  • 2011-02-24
相关资源
最近更新 更多