I'm trying to connect to a remote MySQL database through an SSH Tunnel and deploying my code to Streamlit. When I try to do it, I get this error:
File "/home/appuser/venv/lib/python3.9/site-packages/sshtunnel.py", line 966, in __init__
(self.ssh_password, self.ssh_pkeys) = self._consolidate_auth(
File "/home/appuser/venv/lib/python3.9/site-packages/sshtunnel.py", line 1169, in _consolidate_auth
raise ValueError('No password or public key available!')
ValueError: No password or public key available!
I've tried a lot of things, from updating my SSH keys to my server and github to changing my code.
The code I have for the SSH - MySQL section looks like this:
import MySQLdb as db
from sshtunnel import SSHTunnelForwarder
def query(q):
with SSHTunnelForwarder(
ssh_address_or_host=("host_ip"),
ssh_username=("host_username"),
ssh_pkey=("path_to_private_sshkey"),
remote_bind_address=("private_host_ip", "host_port")
) as server:
conn = db.connect(
host="localhost",
port=server.local_bind_port,
user="db_username",
passwd="db_password",
db="db_database"
)
return pd.read_sql_query(q, conn)
I appreciate any help you can give me.
conn = db.connect(host="localhost"),
port=server.local_bind_port,
user=("db_username"),
passwd=("db_password"),
db=("db_database")
Because you have a closing parentheses on the first line, only the host argument is being passed to the db.connect() function. And so the function is complaining that it doesn't have a password, username, etc.
The other lines are creating plain local variables.
Related
I have been able to sshtunnel into a remote database via the following code utilizing passwords
import sshtunnel
import mysql.connector
import numpy as np
import pandas as pd
host =""
username=""
password=""
tunnel_username=""
tunnel_password=""
with sshtunnel.SSHTunnelForwarder(
(host, 22),
ssh_username=username,
ssh_password=password,
remote_bind_address=('localhost', 3306),
local_bind_address=('0.0.0.0', 3306)
) as tunnel:
connection = mysql.connector.connect(
user= tunnel_username,
password= tunnel_password,
host='localhost',
database= database,
port=3306)
data = pd.read_sql_query(query, connection)
connection.close()
print(data)
However, circumstances have changed, and I have been forced to only connect via SSH keys (generated with PuTTYgen). With that being said, I have the private key (ppk file), but it is unclear what I need to do (or if possible) to get the following code to work again.
I have not seen an option to reference the ppk file path instead of the sshtunnel password.
Use ssh_pkey parameter of SSHTunnelForwarder constructor to provide the path to your private key file.
And you will need to convert your private key file to the OpenSSH format, as Paramiko (used by sshtunnel) does not support PuTTY key format.
See How to ssh connect through python Paramiko with ppk public key
Python 3.8
Mysql 8.0.23-0ubuntu0.20.04.1 for Linux on x86_64 ((Ubuntu))
Hi,
I want to connect to a distant mysql server using python's mysqldb connector and paramiko's sshtunnelforwarder.
I can connect to the database remotely without any problems by executing the following:
Connecting to database using mysql password authentication
server = new_ssh_server(config)
with server:
print('Connection', server.local_bind_address)
cnx = MySQLdb.connect(host = '127.0.0.1',
port = server.local_bind_port,
user = config['user'],
passwd = config['password'],
db = config['db'])
Queries work, I can read/write to database, no problem.
I would like to connect to database without supplying mysql password, by using mysql auth_socket authentication method, through ssh.
My attempts at this can be resumed by the following code:
Connecting to database using mysql auth_socket authentication
with server as tunnel:
print('Tunnel:', tunnel.local_bind_address)
cnx = MySQLdb.connect(host = 'localhost', user = 'hillbilly', password = '', db='tutut')#, unix_socket="/tmp/mysql.sock")
res = pd.read_sql('select * from users;', cnx)
print(res)
Which throws the following error:
File "connect_ssh_mysql_auth_socket.py", line 12, in <module>
cnx = MySQLdb.connect(host = 'localhost', user = 'hillbilly', password = '', db='rsotest2')#, unix_socket="/tmp/mysql.sock")
File "...../lib/python3.8/site-packages/MySQLdb/__init__.py", line 84, in Connect
return Connection(*args, **kwargs)
File "...../lib/python3.8/site-packages/MySQLdb/connections.py", line 179, in __init__
super(Connection, self).__init__(*args, **kwargs2)
MySQLdb._exceptions.OperationalError: (2002, "Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)")
I have and existing mysqld.sock on the distant server that I symlinked to /tmp/mysql.sock, but the error remains. I have also added the next line to /etc/mysql/mysql.conf.d/mysql.cnf:
socket=/run/mysqld/mysqld.sock
But I still get the same error when trying to connect remotely.
Specifying the unix_socket='/run/mysqld/mysqld.sock' to mysqldb connector (commented in Connecting to database using mysql auth_socket authentication) does not fix the issue.
I seem to misunderstand the use of mysql.sock, mysqld.sock.
I was not able to find nor create a mysql.sock socket.
Is what I am trying to do possible? I remember reading somewhere that unix sockets only work locally, does this mean it is not achievable?
Any help/explanation would be appreciated.
(EDIT AND CLOSING)
So this is not possible. Following this thread, auth_socket needs local access to the socket file (usually /tmp/mysql.sock) to run autentication tests, so not accessible through ssh tunneling.
Authentication to remote mysql server using auth_socket plugin is not possible through sshtunnel, as the plugin requires local access to the socket file. See this thread for more information.
I'm trying to connect to a server using LDAP. I've gotten the script to work on a test server that didn't use a specific port number. When trying to connect to our Dev-System, which uses a specific port I receive the following error:
File "site-packages\ldap3\core\server.py", line 117, in__init__
ldap3.core.exceptions.LDAPInvalidPortError: port must be an integer
[7836] Failed to execute script ldap_query
In the past we used python-ldap which didn't have an issue with a specified port in the ldap.initialize('LDAP://cd-dir...net/(Port)') command. The piece of code that generates the error can be seen below.
def ldap_connect(address, dn, password)
server = Server(address)
try:
conn = Connection(server, dn, password, auto_bind = True)
print('Authentication Successful')
print(conn.extend.standard.who_am_i())
except: LDAPBindError as err:
print(LDAPBindError)
ldap_connect('LDAP://cd-dir-cd-test....net:port/dc=cd...dc=com', 'user', 'password')
To solve the issue I tried taking the port number out of the address and instead put it in the following way:
server = Server(address, port = XXX)
That solved the "port must be an integer" error. However, that didn't solve the problem. The new error that I'm receiving is:
File "site-packages\ldap3\core\connection.py", line 325, in__init__
File "site-packages\ldap3\core\connection.py", line 340, in do_auto_bind
File "site-packages\ldap3\strategy\sync.py", line 56, in open
File "site-packages\ldap3\strategy\base.py", line 151, in open
ldap3.core.exceptions.LDAPSocketOpenError: invalid server address
[5976] Failed to execute script ldap_query
How can I solve this issue? Is there another way to set the port that I don't know of?
Best wishes,
You're passing an ldap:// URI to ldap_connect, but it looks like the ldap3.Server class expects an hostname or address. That is, you're currently trying to do this:
server = Server('ldap://cd-dir-cd-test.example.net:port')
When what you need is:
server = Server('cd-dir-cd-test.example.net', port=port)
And of course port must be an integer, not a string. You can use the ldap3.utils.uri.parse_uri method to extract the information you want from an ldap URI:
from ldap3 import Server, Connection
from ldap3.utils.uri import parse_uri
def ldap_connect(uri, dn, password):
parsed = parse_uri(uri)
server = Server(parsed['host'], use_ssl=parsed['ssl'], port=parsed['port'])
conn = Connection(server, dn, password, auto_bind = True)
print('Authentication Successful')
print(conn.extend.standard.who_am_i())
return conn
conn = ldap_connect('LDAP://cd-dir-cd-test....net:port/dc=cd...dc=com',
'user', 'password')
After trying to run a query on redshift, I get the following error message:
OperationalError: (psycopg2.OperationalError) server certificate for
"" does not match host name "".
I already installed the sqlalchemy-redshift package, as well as the Psycopg2 package. My code:
from sqlalchemy import create_engine
def run_query(query, connection_string):
red_engine = create_engine(connection_string)
data_set = pd.read_sql_query(query, red_engine)
return data_set
The exact same code does work on another computer, so we are sure that the login name, password and queries are correct, and the problem is specific to my computer. Any suggestions?
This worked for me in the end: we added a preferred sslmode to our code, as follows:
create_engine(connection_string, connect_args={'sslmode': 'prefer'})
I am refering to the http://api.mongodb.org/python/current/examples/authentication.html site for authentication mechanism examples. I have created a User administrator and using its credentials I created a user for my 'reporting' database. Now i need to access the same through pymongo using the username and password. I tried the following commands in python shell. Is this the right way as my authentication is failing.
from pymongo import MongoClient
client = MongoClient('localhost')
client.reporting.authenticate('reportsUser', '123456', mechanism='MONGODB-CR')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/pymongo/database.py", line 746, in authenticate
self.connection._cache_credentials(self.name, credentials)
File "/usr/lib/python2.7/dist-packages/pymongo/mongo_client.py", line 441, in _cache_credentials
auth.authenticate(credentials, sock_info, self.__simple_command)
File "/usr/lib/python2.7/dist-packages/pymongo/auth.py", line 214, in authenticate
auth_func(credentials[1:], sock_info, cmd_func)
File "/usr/lib/python2.7/dist-packages/pymongo/auth.py", line 194, in _authenticate_mongo_cr
cmd_func(sock_info, source, query)
File "/usr/lib/python2.7/dist-packages/pymongo/mongo_client.py", line 607, in __simple_command
helpers._check_command_response(response, None, msg)
File "/usr/lib/python2.7/dist-packages/pymongo/helpers.py", line 147, in _check_command_response
raise OperationFailure(msg % errmsg, code)
pymongo.errors.OperationFailure: command SON([('authenticate', 1), ('user', u'reportsUser'), ('nonce', u'f8158a24f1c61650'), ('key', u'14cea216c54b93bae20acd2e076bb785')]) failed: auth failed
As an FYI, you can use the URI string format as well. The pseudocode looks like this:
pymongo.MongoClient('mongodb://user:password#server:port/')
Here's a simple connection code block with auth:
import pymongo
conn = pymongo.MongoClient('mongodb://root:pass#localhost:27017/')
db = conn['database']
coll = db['collection']
There are more options for the query string here: http://docs.mongodb.org/manual/reference/connection-string/
Hope that helps = looks like you already have it though. Happy coding!!
Just adding more to provided solutions.
I have been using as URI connection string and credentials being provided as f string it helps to reduce number of lines. One thing to note is about special characters in password where we convert using urllib package as shown below.
import urllib.parse
from pymongo import MongoClient
host = "localhost"
port = 27017
user_name = "myuser"
pass_word = "Pass#123"
db_name = "mydb" # database name to authenticate
# if your password has '#' then you might need to escape hence we are using "urllib.parse.quote_plus()"
client = MongoClient(f'mongodb://{user_name}:{urllib.parse.quote_plus(pass_word)}#{host}:{port}/{db_name}')
It's worked for me.
Here you can connect mongodb to python by using authentication username and password.
import pymongo
DATABASE_NAME = "your_database_name"
DATABASE_HOST = "localhost"
DATABASE_USERNAME = "database_username"
DATABASE_PASSWORD = "database_password"
try:
myclient = pymongo.MongoClient( DATABASE_HOST )
myclient.test.authenticate( DATABASE_USERNAME , DATABASE_PASSWORD )
mydb = myclient[DATABASE_NAME]
print("[+] Database connected!")
except Exception as e:
print("[+] Database connection error!")
raise e
By default Mongodb uses 27017 port