How do I connect to an AWS mysql database in python3? - mysql

I can connect to mysql using cli like this:
mysql -u cwaugh -p******** -h example.com mydb
However, when I try to use python3 with the same parameters, I get an error: mysql.connector.errors.ProgrammingError: 1045 (28000): Access denied for user 'cwaugh'#'xxx.xxx.xxx.xxx' (with my ip where the x should be)
My code for python looks like this:
import mysql.connector
import datetime
thinknode = mysql.connector.connect(
host = "example.com",
user = "cwaugh",
passwd = "********",
db = "mydb")
The credentials also work in javascript, but only if I used ssl: "Amazon RDS" when I created the connection (the database is on AWS RDS).
What do I need to do to connect from python? I can connect from other applications on this same computer, so I can rule out AWS Security Groups and MySQL host limits. This seems to only happen with python. Does this have something to do with ssl like it did with javascript?

You need to add the ssl_ca argument to the mysql.connector.connect function. Eg.
thinknode = mysql.connector.connect(
host = "example.com",
user = "cwaugh",
passwd = "********",
db = "mydb",
ssl_ca = "./rds-combined-ca-bundle.pem")
I'm not sure why javascript wass able to use "Amazon RDS", and it would be a lot easier if python did too, but it doesn't.

Related

SSL integration with Cloud SQL instance based MySQL

I enabled SSL in a MySQL Cloud SQL instance. In order to connect to the instance , I downloaded the necessary certficates and can connect fine using mysql command. The CloudSQL instance is running with Private IP on a sharedVPC network .
$ mysql -h 192.168.0.3 --ssl-ca=server-ca.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem -u testuser -p
Enter password:
Now to test connectivity from a code to connect to SQL instance I deployed the following in Cloud Functions
import pymysql
from sqlalchemy import create_engine
def sql_connect(request):
engine = create_engine('mysql+pymysql://testuser:<password>#192.168.0.3/mysql',echo=True)
tab = engine.execute('show databases;')
return str([t[0] for t in tab])
It shows "Access Denied" error as shown below
Error: function terminated. Recommended action: inspect logs for termination reason. Additional troubleshooting documentation can be found at https://cloud.google.com/functions/docs/troubleshooting#logging Details:
(pymysql.err.OperationalError) (1045, "Access denied for testuser'#'192.168.60.4' (using password: YES)")
When I disable SSL it works fine as shown below
['information_schema', 'mysql', 'performance_schema', 'sys', 'testdb']
A) To enable SSL in code I did the following
ssl_args = {'sslrootcert':'server-ca.pem','sslcert':'client-cert.pem','sslkey':'client-key.pem'}
engine = create_engine('mysql+pymysql://testuser:<password>#192.168.0.3/mysql',echo=True,connect_args=ssl_args)
but it is failing with below error
__init__() got an unexpected keyword argument 'sslrootcert'
B) Also tried disabling ssl=False in code but it is failing with below error
Invalid argument(s) 'ssl' sent to create_engine(), using configuration MySQLDialect_pymysql/QueuePool/Engine
UPDATE:
Changed the code for SSL as follows:
ssl_args = {'ssl': {'ca':'./server-ca.pem', 'cert':'./client-cert.pem', 'key':'./client-key.pem'}}
Uploaded the certs to cloud function source
Added 0.0.0.0/0 as authorized networks in CloudSQL to allow connecting from Cloud functions
Now seeing the following error
"Can't connect to MySQL server on 'X.X.X.181' ([SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for 'X.X.X.181'. (_ssl.c:1091))") . However can connect using the same certificates using `mysql` command
Need help to resolve both A) fixing the error as observed so that the code is integrated with SSL and B) Modify code so that it does not uses SSL
Use ssl_ca for the root, ssl_cert for the cert and ssl_key for the key
ssl_args = {'ssl_ca':'server-ca.pem','ssl_cert':'client-cert.pem','ssl_key':'client-key.pem'}
engine = create_engine('mysql+pymysql://testuser:<password>#192.168.0.3/mysql',echo=True,connect_args=ssl_args)
Use SSL parameter in the form ssl = {"ssl":{"ca":"server-ca.pem"}} within the connect function
from pymysql import connect
from sqlalchemy import create_engine
import os
SQLALCHEMY_DATABASE_URI='mysql+pymysql://testuser:<password>#192.168.0.3/mysql?ssl_ca=server-ca.pem'
engine = create_engine(SQLALCHEMY_DATABASE_URI)
args, kwargs = engine.dialect.create_connect_args(engine.url)
# Create connection to the DB
db_conn = connect(kwargs["host"], kwargs["user"], kwargs["passwd"], kwargs["db"], ssl = {"ssl":{"ca":kwargs["ssl"]["ca"]}})
cursor = db_conn.cursor()
# Execute query
cursor.execute("show tables")
cursor.fetchall()

R using RMariaDB unable to connect with .mylogin.cnf

I'm developing a script in RStudio which connects to local MySQL Server using the R package RMariaDB (not RMySQL - for other reasons though the outcome is the same).
I can both connect via storing the password in the script like:
localuserpassword <- "password"
all_projectsDb <- dbConnect(RMariaDB::MariaDB(), user='user', password=localuserpassword, dbname='projects', host='localhost')
or by way of a .my.cnf using credentials:
[client]
[mygroup]
host=127.0.0.1
user=user
password=password
port=3306
database=projects
and R code as
settingsfile = '/Users/oscar_w/.my.cnf'
all_projectsDb <- dbConnect(RMariaDB::MariaDB(), default.file = settingsfile, group="mygroup", dbname = 'projects')
The above work just fine but if I want to connect with .mylogin.cnf created in mysql_config_editor and looks like
[client]
[mygroup]
user = user
password = *****
host = 127.0.0.1
port = 3306
with the R script code like
# define location of config file
settingsfile = '/Users/oscar_w/.mylogin.cnf'
all_projectsDb <- dbConnect(RMariaDB::MariaDB(), default.file = settingsfile, group="mygroup", dbname = 'projects', password = NULL, user = NULL)
I get the error
Error: Failed to connect: Access denied for user 'root'#'localhost' (using password: NO)
I have tried various combinations of arguments expressing null or otherwise. And have entered my password with mysql_config_editor with double quotes around it. In https://cran.r-project.org/web/packages/RMariaDB/RMariaDB.pdf it specifies the use of .mylogin.cnf but I cannot find a way to make it work. Does anyone know a solution to this or has the same issue? Thanks
It looks like you're trying to log in both with and without a password, which isn't allowed. The RMariaDB documentation says that if the password argument is NULL or omitted, only users without a password can log in.

Cloud SQL Access denied

import webapp2
import MySQLdb
import os
class MainPage(webapp2.RequestHandler):
def get(self):
if (os.getenv('SERVER_SOFTWARE') and
os.getenv('SERVER_SOFTWARE').startswith('Google App Engine/')):
db = MySQLdb.connect(unix_socket='/cloudsql/fluent-outlet-604:test-db' , db='guestbook', user='root',passwd='root')
# connect to the cloud SQL
else:
db = MySQLdb.connect(host='173.194.248.221', port=3306, db='guestbook', user='root',passwd='root')
cursor = db.cursor()
cursor.execute('SELECT guestName, content, entryID FROM entries')
data = cursor.fetchall()
db.close()
self.response.write(data)
application = webapp2.WSGIApplication([
('/',MainPage),
],debug=True)
when i deploy this app to the app engine i gain error says
"(1045, "Access denied for user 'root'#'localhost' (using password: YES)")
I had the same problem, and solved it.
This problem is on Google Cloud SQL.
In the prompt console, re-start Cloud SQL like below,
gcloud sql instances --project [app engine project name] restart [sql instance name]
You should not specify the root password (even if you have set), when connecting from AppEngine.
Remove the passwd param from line 9 of your code so that it looks like:
db = MySQLdb.connect(unix_socket='/cloudsql/fluent-outlet-604:test-db' , db='guestbook', user='root')
The example code in this article also shows this.
I saw this problem when I didn't specify the hostname in the database URI:
SQLALCHEMY_DATABASE_URI = (
'mysql+pymysql://<user-name>:<password>#/<database-name>'
'?unix_socket=/cloudsql/<connection_name>'
Changing it to the following fixed it:
SQLALCHEMY_DATABASE_URI = (
'mysql+pymysql://<user-name>:<password>#<host-name>/<database-name>'
'?unix_socket=/cloudsql/{connection_name}'

Ruby SSH MySQL Sequel (or DataMapper) remote connection with keys using Net::SSH gem

How would I connect to my VPS based MySQL database remotely (from a cloud based app) using the Ruby Net::SSH or Net::SSH::Gateway gems and key, not password, authentication?
And then connect to the database with Sequel or DataMapper. I'm assuming that after I manage to get the SSH connection working, I would just setup a Sequel/DM connection to 'sql_user#localhost:3306/database'.
I did locate a couple of similar question here, but they all use password authentication, not keys, and only demonstrate executing raw commands to query the database.
UPDATE: I just cannot seem to get this (Net::SSH with key manager) to work.
UPDATE2: Alright I have managed to get authorization when logging in from a computer that has authorized keys stored in the users local .ssh folder, with the following (port is my custom SQL port on the VPS):
sql_gate = Net::SSH::Gateway.new('192.xxx.xxx.xx','sqluser', port: 26000)
However, I will not be able to create a .ssh folder in the app's VM, so I need to somehow pass the path and filename (I will be creating a public key just for SQL access for specified user) as an option ... but haven't been able to figure out how.
UPDATE: Just need to figure out DataMapper access now. Current code being tested (remote_user_sql is my Ubuntu user, sql_user is the MySQL database user with localhost/127.0.0.1 privileges):
require 'net/ssh/gateway'
require 'data_mapper'
require 'dm-mysql-adapter'
class User
include DataMapp......
.
.
end
ssh_gate = Net::SSH::Gateway.new('192.n.n.n','remote_user_sql', {port: 25000, keys: ["sql_rsa"], keys_only: true})
port = ssh_gate.open('localhost',3306,3307)
child = fork do
DataMapper.setup(:default, {
adapter: 'mysql',
database: 'sql_test',
username: 'sql_user',
password: 'passwd',
host: 'localhost',
port: port})
DataMapper.auto_upgrade!
exit
end
puts "child: #{child}"
Process.wait
ssh_gate.close(port)
My solution, in two parts:
Well I have figured how to make the Net::SSH::Gateway gem using a specified keyfile, and then connect to the VPS through ssh via a port other than 22:
Part 1: Net::SSH::Gateway key authentication
First you must generate the keyfiles you want to use, copy the .pub to the remove server and append it to the ~/.ssh/authorized_keys file (cat sql_rsa.pub >> authorized_keys), and then make sure user_sql (the user I created on the VPS to be used only for this purpose) has been added to AllowUsers list in sshd_config. Make note of port used for ssh (25000 for this example) and use the following code to establish the connection:
ssh_gate = Net::SSH::Gateway.new('192.n.n.n','user_sql', {port: 25000, keys: ["sql_rsa"], keys_only: true})
That will read the keyfile sql_rsa in the same directory as script file, then create a new ssh gateway for 'user_sql'#'192.n.n.n' on port 25000.
I can successfully execute raw shell commands on the remove VPS with:
ssh_gate.exec("ls -la")
To close:
ssh_gate.shutdown!
Unfortunately I am still having problems using DataMapper (do-mysql-adapter) to use the gateway. I will update this answer if I figure that part out, but at least the first half of the problem has been solved.
These are the errors that DataMapper::Logger has reported:
When 127.0.0.1 was used:
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) (code: 2002, sql state: HY000, query: , uri: )
When localhost was used:
Access denied for user 'user_sql'#'localhost' (using password: YES) (code: 1045, sql state: 28000, query: , uri: )
When the VPS hostname was used:
Unknown MySQL server host 'hostname' (25) (code: 2005, sql state: HY000, query: , uri: )
UPDATE (No success yet): So far the only way I can access the remote MySQL database is by using Net::SSH::Gateway to establish a gateway, and then use the .sshmethod to open a new Net::SSH connection over that gateway, like so:
ssh_gate.ssh('192.n.n.n','user_sql',{port: 25000, keys: ["sql_rsa"], keys_only: true}) do |ssh|
ssh.exec("mysql -u sql_user -p'passwd' -h localhost -P 3306 -e 'SELECT DATABASE();'")
end
In other words, I can only execute SQL commands using the mysql command line. I cannot figure out how to get Sequel or DataMapper to use the gateway to connect.
Part 2: DataMapper/Sequel/mysql2 connection through Net::SSH::Gateway
Make sure your MySQL server is bound to 127.0.0.1 in /etc/mysql/my.cnf, setup your connection - DataMapper example:
DataMapper.setup(:default, {
adapter: 'mysql',
database: 'DATABASE',
username: 'username',
password: 'passwd',
host: '127.0.0.1',
port: 3307}) # local port being forwarded via Net::SSH:Gateway
Followed by any class table definitions and DataMapper.finalize if required. Note that DataMapper doesn't actually connect to the remote MySQL server until either an auto_upgrade!, auto_migrate!, or query is executed, so no need to create the forwarded port yet.
Then create a new Net::SSH::Gateway, and then whenever you need DataMapper/Sequel to access the remote database, just open a port for the process, like so:
port = ssh_gate.open('127.0.0.1',3306,3307)
child = fork do
DataMapper.auto_upgrade! # DM call that accesses MySQL server
exit
end
Process.wait
ssh_gate.close(port)
You may want to put the Net::SSH::Gateway/.open code in a begin..ensure..end block, ensure'ing the port closure and gateway shutdown.
I had to use a fork and Process.wait to establish the connection, without it the method just hangs.

How do you use SQLCMD to login to SQL Server Express, user no password set

I installed SQL Server 2012 Express and I'm learning from a book on SQL Server administration. My task is to write a batch file to copy data from a table and export it to an Excel spreadsheet.
I've got the instance name right and my username but log in fails because of password. When I enter Management Studio and click connect I see my username but password is blank, I successfully connect to my databases this way. How do I set a password for my account? I think I can't log in using SQLCMD because I don't have this set. My username is the same as my windows username, using the password that I log on to windows with doesn't work.
SQLCMD -S CRAIG-PC\SQLExpress -U CRAIG-PC\Craig -P *********
-d AdventureWorks
-Q "SELECT * FROM Sales.SalesOrderDetail" -o C:\ExportDir\export.csv
This is the command in the batch file that I'm trying to connect and query the database. If I take out -P ******* SQL Server is waiting for a password. If I don't use a username or password connection is refused.
Remote connections are enabled using tcp, but this is a local install.
Use the '-E' switch to make your connection a trusted (Window's authentication) one, then you don't need user name and password at all (provided you have sufficient rights on your machine)
http://technet.microsoft.com/en-us/library/ms162773.aspx
Note in my python code below, I don't implement the user or password.
Hope that helps
_query = "CREATE DATABASE %s ON (FILENAME = '%s'), (FILENAME = '%s') FOR ATTACH;" %(_database, mdffilepath, logfilepath)
command_process = SubP.Popen(['sqlcmd','-b', '-E',
'-S', _server,
'-d', 'master',
'-q', _query],
stdin = SubP.PIPE,
stdout = SubP.PIPE,
stderr = SubP.STDOUT,
shell = True)
_stdOut, _stdError = command_process.communicate()
Check the name of the database, ie "AdventureWorks" should be "AdventureWorks2012"
sounds like you are using windows authentication you can remove the -u and -p. when those are not provided sqlcmd will use windows authentication.