在Python中使用私钥通过SSH连接并查询Mongo数据库

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

我有一个代码文件

mongo.py
,如下所示,将n查询mongo与
username
host
password
及其工作连接起来,但是我如何使用ssh
address
username
和身份验证方法连接到ssh
private_key 
private_key
在另一个文件中

这是我的示例

config
与 ssh:

sql_local = {'mongomdm':{'host':'xx.xxx.xxx.xx', 'user':'aaa', 'pkey':'/Users/satu/dua/tiga/config/settings/googlecloud_dev_rsa'}}

我已经准备好了一些参考资料,应该像这样导入库吗?

from paramiko import SSHClient, AutoAddPolicy, RSAKey
from paramiko.auth_handler import AuthenticationException
from scp import SCPClient, SCPException
from io import StringIO

这是我的代码文件

mongo.py

import csv                                                                              
import pandas as pd
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
import config.config as cfg
import config.modules.common as comm
from bson.objectid import ObjectId

class mongoFunc:
def __init__(self):
    self.types = 'mongodb'
    self.host = cfg.sql_local[self.types]['host']
    self.user = cfg.sql_local[self.types]['user']
    self.password = cfg.sql_local[self.types]['password']
    self.uri = 'mongodb://{user}:{password}@{host}'.format(user = self.user, password = self.password, host = self.host)

def connection(self):
    try:
        client= MongoClient(self.uri)
        client.server_info()
        print('Connection Established')
    except ConnectionFailure as err:
        raise(err)
    return client

def get_collection(self, client, database, collection):
    self.client= client
    self.database= database
    self.collection= collection

    db= self.client[self.database]
    return db[self.collection]

def get_query(self,id_data= None,start_date=None,end_date=None,query=None):
    self.id = ObjectId(id_data)
    self.start_date = start_date
    self.end_date = end_date
    self.query = query
    
    if self.end_date:
        script= {'date':{'$gt':self.start_date,'$lte':self.end_date}}
    if self.end_date is None:
        script= {'date':{'$gt':self.start_date}}
    if self.id:
        script = {'_id':{'$gt':self.id}}
    if self.query:
        script.update(self.query)
    return script

def get_data_to_pandas(self, database, collection, query, skip, limit=None):
    self.database = database
    self.collection = collection
    self.query = query
    self.limit = limit
    self.skip = skip

    self.client = self.connection()
    self.collection = self.get_collection(self.client,self.database,self.collection)

    if limit:   
        cursor = self.collection.find(self.query).skip(self.skip).limit(self.limit)
    if not limit :
        cursor = collection.find(self.query).skip(self.skip)
    df = pd.DataFrame(list(cursor))
    return df

编辑:

def connection(self):
    try:
        print('Establishing SSH Connection')
        self.client = paramiko.SSHClient()
        self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        if (self.password == ''):
            private_key = paramiko.RSAKey.from_private_key_file(self.pkey)
            self.client.connect(hostname=self.host, port=self.port, username=self.user, pkey=private_key, allow_agent=False,look_for_keys=False)
            print("Connected to the server"),self.host
        else:
            self.client.connect(hostname=self.host, port=self.port, username=self.user, password=self.password, allow_agent=False,look_for_keys=False)    
            print("Connected to the server"),self.host
    except paramiko.AuthenticationException:
        print("Authentication failed, please verify your credentials")
        result_flag = False
    except paramiko.SSHException as sshException:
        print("Could not establish SSH connection: %s") % sshException
        result_flag = False
    else:
        result_flag = True
    return result_flag

def get_collection(self, client, database, collection):
    self.client= client
    self.database= database
    self.collection= collection

    db= self.client[self.database]
    return db[self.collection]`

我收到错误:

line 64, in get_collection
    db= self.client[self.database]
TypeError: 'bool' object is not subscriptable

我该怎么办?

python mongodb ssh pymongo paramiko
4个回答
2
投票

这对我有用。我检查了上面的 paramiko 示例,但不明白并发现了这个。 我从这里获取了代码并根据我的需要进行了一些修改。

def data_call(collection_name, query={}):
    from sshtunnel import SSHTunnelForwarder
    import pymongo

    MONGO_HOST = 'HOST' 
    SERVER_USER   = 'server_user'
    PRIVATE_KEY ='pem.txt'

    MONGO_USER='user_mongo'
    MONGO_PASS ='pass_mongo'

    MONGO_DB = "db"

    # define ssh tunnel
    server = SSHTunnelForwarder(
        MONGO_HOST,
        ssh_username=SERVER_USER,
        ssh_pkey=PRIVATE_KEY,
        remote_bind_address=('127.0.0.1', 27017)
    )

    # start ssh tunnel
    server.start()

    connection = pymongo.MongoClient('127.0.0.1', server.local_bind_port)
    db = connection[MONGO_DB]

    data = db[collection_name].find(query)
    return data

2
投票

除非 MongoClient 模块本身支持 SSH 隧道(我不知道),否则您必须显式实现端口转发。

修改使用 Python Paramiko 的嵌套 SSH 进行数据库隧道的代码,您将得到如下代码:

ssh_client = paramiko.SSHClient() # ... ssh_client.connect(hostname=ssh_hostname, username=ssh_username, key_filename=ssh_key) transport = ssh_client.get_transport() dest_addr = (mongo_host, mongo_port) local_unique_port = 4000 # any unused local port local_host = 'localhost' local_addr = (local_host, local_unique_port) channel = transport.open_channel("direct-tcpip", dest_addr, local_addr) self.uri = 'mongodb://{user}:{password}@{local_host}:{port}'. format(user=mongo_user, password=mongo_password, local_host=local_host, port=local_unique_port)
如果 Mongo 数据库运行在 SSH 服务器本身上,那么它通常只会侦听环回接口。在这种情况下,

mongo_host

 应设置为 
localhost


关于 PostgreSQL 的同样问题:使用 Paramiko 设置 SSH 隧道来访问 PostgreSQL


0
投票
只是改进了一些实际上对我有帮助的其他答案

添加了行 db.authenticate(MONGO_USER, MONGO_PASS)

回忆:“在 MONGO 上进行授权!!!”

并转换为 pandas 数据框,如果它对任何人有用(对我来说是)

from sshtunnel import SSHTunnelForwarder import pymongo import pandas as pd def data_call(collection_name, query={}): MONGO_HOST = 'ip.add.res' SERVER_USER = 'user' PRIVATE_KEY = 'PATH TO/id_rsa' MONGO_USER = 'mongouser' MONGO_PASS = 'mongopass' MONGO_DB = "dbname" # define ssh tunnel server = SSHTunnelForwarder( MONGO_HOST, ssh_username=SERVER_USER, ssh_pkey=PRIVATE_KEY, remote_bind_address=('127.0.0.1', dbport) ) # start ssh tunnel server.start() connection = pymongo.MongoClient('localhost', server.local_bind_port) db = connection[MONGO_DB] db.authenticate(MONGO_USER, MONGO_PASS) data = pd.DataFrame(list(db[collection_name].find(query))).drop(columns=['_id']) return data
    

0
投票
在您的连接信息中:

sql_local = { 'mongomdm': { 'host':'xx.xxx.xxx.xx', 'user':'aaa', 'pkey':'/Users/satu/dua/tiga/config/settings/googlecloud_dev_rsa'}}
您可以

pip install ssh-pymongo

,然后:

from ssh_pymongo import MongoSession session = MongoSession('xx.xxx.xxx.xx', user='aaa', key='/Users/satu/dua/tiga/config/settings/googlecloud_dev_rsa', uri='mongodb://{mongo-user}:{mongo-password}@{host}:{local-port}' ) db = session.connection['db-name']
更多信息请参阅另一篇文章:

如何使用 pymongo 连接远程 mongodb .

© www.soinside.com 2019 - 2024. All rights reserved.