带有 ssh 隧道的 django 数据库

问题描述 投票:0回答:2

有没有一种Python本机方法可以通过ssh隧道将django连接到数据库?我见过有人在主机中使用 ssh 端口转发,但我更喜欢一个可以轻松容器化的解决方案。

python django ssh-tunnel
2个回答
13
投票

非常无缝。

要求:

sshtunnel
https://github.com/pahaz/sshtunnel

  1. 在 django
    settings.py
    中,在 django DB 设置块之前创建一个 ssh 隧道:
from sshtunnel import SSHTunnelForwarder

# Connect to a server using the ssh keys. See the sshtunnel documentation for using password authentication
ssh_tunnel = SSHTunnelForwarder(
    SERVER_IP,
    ssh_private_key=PATH_TO_SSH_PRIVATE_KEY,
    ssh_private_key_password=SSH_PRIVATE_KEY_PASSWORD,
    ssh_username=SSH_USERNAME,
    remote_bind_address=('localhost', LOCAL_DB_PORT_ON_THE_SERVER),
)
ssh_tunnel.start()
  1. 然后在
    settings.py
    中添加数据库信息块。在这里,我添加了一个默认的本地数据库和我们使用 ssh 隧道连接到的远程数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.contrib.gis.db.backends.postgis',
        'HOST': NORMAL_DB_HOST,
        'PORT': NORMAL_DB_PORT,
        'NAME': NORMAL_DB_NAME,
        'USER': NORMAL_DB_USER,
        'PASSWORD': NORMAL_DB_PASSWORD,
    },
    'shhtunnel_db': {
        'ENGINE': 'django.contrib.gis.db.backends.postgis',
        'HOST': 'localhost',
        'PORT': ssh_tunnel.local_bind_port,
        'NAME': REMOTE_DB_DB_NAME,
        'USER': REMOTE_DB_USERNAME,
        'PASSWORD': REMOTE_DB_PASSWORD,
    },
}

就是这样。现在,可以使用

$ python manage.py migrate --database=shhtunnel_db
等命令迁移到远程数据库,或者使用
Models.objects.all().using('shhtunnel_db')

等行从 python 代码中调用数据库

额外: 就我而言,远程数据库是由其他人创建的,我只想读取它。为了避免编写模型并停用模型管理器,我使用以下 django 命令从数据库获取模型 [src]:

python manage.py inspectdb

0
投票

是的,可以使用

sshtunnel
等库建立 SSH 隧道,随后修改 Django 的
settings.py
文件以在定义
DATABASES
之前使用此连接。您需要通过将 hostport 的值更改为 SSH 隧道绑定分配的值来实现此目的。

这是一个可用于通过 SSH 隧道测试数据库连接的脚本:

import os
import atexit
import pyodbc
from sshtunnel import SSHTunnelForwarder

ssh_tunnel = None


DB_DRIVER = ""

SSH_HOST = ""
SSH_PORT = ""
SSH_USER = ""
SSH_PASSWORD = ""

SSH_DB_NAME = ""
SSH_DB_USERNAME = ""
SSH_DB_PASSWORD = ""
SSH_DB_HOST = ""
SSH_DB_PORT = ""


try:
    ssh_tunnel = SSHTunnelForwarder(
        (SSH_HOST, int(SSH_PORT)),
        ssh_username=SSH_USER,
        ssh_password=SSH_PASSWORD,
        remote_bind_address=(SSH_DB_HOST, int(SSH_DB_PORT)),
        local_bind_address=("127.0.0.1", 0),
    )
    ssh_tunnel.start()

    if ssh_tunnel.is_active:
        print(f"SSH tunnel established: Local bind at {ssh_tunnel.local_bind_host}:{ssh_tunnel.local_bind_port}")

        conn_str = (
            f"DRIVER={DB_DRIVER};"
            f"SERVER={ssh_tunnel.local_bind_host},{ssh_tunnel.local_bind_port};"
            f"DATABASE={SSH_DB_NAME};"
            f"UID={SSH_DB_USERNAME};"
            f"PWD={SSH_DB_PASSWORD};"
        )

        try:
            conn = pyodbc.connect(conn_str, timeout=30)
             print("Connection successful!")
            conn.close()

        except pyodbc.Error as e:
            print(f"Connection error: {e}")
    else:
        print("SSH tunnel could not be established.")
except Exception as e:
    print(f"Error attempting to establish SSH tunnel: {e}")


def close_sshtunnel():
    global ssh_tunnel
    if ssh_tunnel and ssh_tunnel.is_active:
        ssh_tunnel.stop()
        print("SSH tunnel closed.")

atexit.register(close_sshtunnel)
© www.soinside.com 2019 - 2024. All rights reserved.