使用 SQLAlchemy 连接到 Amazon Aurora

Posted

技术标签:

【中文标题】使用 SQLAlchemy 连接到 Amazon Aurora【英文标题】:Connecting to Amazon Aurora using SQLAlchemy 【发布时间】:2018-03-01 21:51:34 【问题描述】:

我正在尝试使用 SSL 连接通过 SQLAlchemy 连接到 Amazon Aurora,将 IAM 角色指定为数据库用户帐户,并将身份验证令牌指定为密码,如 [AWS 文档] 中所述 (http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html#UsingWithRDS.IAMDBAuth.Connecting)

这些是我遵循的步骤。

wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem

export LIBmysql_ENABLE_CLEARTEXT_PLUGIN=1

aws rds generate-db-auth-token --hostname 'datadbcluster-1.cluster-xxxxxxxxxxxx.us-west-2.rds.amazonaws.com' --port 3306 --username dt_analyst --region us-west-2 > /home/ubuntu/dt_analyst.pem

mysql -h datadbinstance2nd. xxxxxxxxxxxx.us-west-2.rds.amazonaws.com--ssl-ca /home/ubuntu/rds-combined-ca-bundle.pem -u dt_analyst --ssl-verify-server-cert --enable-cleartext-plugin -p'<token>'

我确认我可以使用 mysql 客户端通过 SSL 进行连接。

但我想使用 sqlalchemy 而不是 mysql 客户端进行连接。以下代码是根据互联网上的十几条建议编译而成的,但只会产生以下错误。

'sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (1045, "Access denied for user...")'

我的代码如下。

import boto3

client = boto3.client('rds', region_name='us-west-2')

dialect='mysql'
user = ‘dt_analyst’
host = 'datadbcluster-1.cluster-xxxxxxxxxxxx.us-west-2.rds.amazonaws.com'
port = 3306
data = ‘datadb’
region='us-west-2'

token = client.generate_db_auth_token(host,port,user,region)
host1 = 'datadbinstance2nd. xxxxxxxxxxxx.us-west-2.rds.amazonaws.com'
conn_str = '%s://%s:%s@%s:%d/%s'%(dialect,user,token,host1,port,data)
conn_str += '?ssl_key=%s'%token
conn_str += '&ssl_cert=’/home/ubuntu/rds-combined-ca-bundle.pem'

ssl_args = 
    'ssl': 
        'ca_cert': '/home/ubuntu/rds-combined-ca-bundle.pem',
        'sslmode': 'require',
        'verify_ssl_cert': True
    


engine = create_engine(conn_str,connect_args=ssl_args, echo=True)

【问题讨论】:

您的互动对我来说看起来不错,因此我建议您联系 AWS Support。如果你能弄清楚,请分享!谢谢。 代码 sn-p 有一处遗漏:create_engine 来自哪里。我将其追踪到sqlalchemy.create_engine,它将connect_args 作为kwarg 转发到底层PyMySQLmysqlclient 连接器库。 【参考方案1】:

我的回答有三点:

IAM 角色

这里没有提到一个步骤:您需要分配一个 IAM 角色,让您的客户有权连接到 RDS。

“客户端”是指任何 AWS 资源正在运行此问题中的代码。可以是 lambda 函数,也可以是 EC2 实例,或者其他东西。不管它是什么,它都有一个 ARN,并且必须允许它执行 rds-db:connect 操作。

URL 引用连接字符串

那么 RDS 凭据可能存在问题。如果密码包含 URL 中不允许的字符,您可能必须在 URL 中引用密码。

Python 3:passwd = urllib.parse.quote(rds_password) Python 2:passwd = urllib.quote(rds_password)

RDS 临时凭证

最后,您的 RDS 数据库可能需要临时凭据。此代码示例展示了如何获取这些:

# get RDS config, often done through environment variables
import os

rds_host = os.environ.get("RDS_HOST")  
rds_port = os.environ.get("RDS_PORT")
rds_username = os.environ.get("RDS_USER")   

# get temp credential
import boto3

temp_passwd = boto3.client('rds').generate_db_auth_token(
    DBHostname=rds_host,
    Port=rds_port,
    DBUsername=rds_username 
)

rds_credentials = 'user': rds_username, 'passwd': temp_passwd

把它放在一起:

def create_sqlalchemy_engine(self):
    conn_str = f"protocol://rds_host:rds_port/database"

    kw = dict()
    kw.update(rds_credentials)
    # kw.update('ssl': 'ca': /path/to/pem-file.pem)  # MySQL
    # kw.update('sslmode': 'verify-full', 'sslrootcert /path/to/pem-file.pem)  # PostgreSQL

    return create_engine(conn_str, connect_args=kw)

我将用户和密码参数从连接字符串移到connect_args。这消除了对 URL 引用的需要。

另请参阅:https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html

【讨论】:

以上是关于使用 SQLAlchemy 连接到 Amazon Aurora的主要内容,如果未能解决你的问题,请参考以下文章

使用 sqlalchemy 连接到本地 postgresql

使用 SQLAlchemy 连接到 Oracle 数据库

使用 sqlalchemy 和 pyodbc 连接到 SQL Server 2012

使用 Flask-SQLAlchemy 连接到 MSSQL 数据库

无法在 Windows 机器上使用 sqlalchemy 连接到本地 mysql 数据库

使用 sqlalchemy 连接到 mysql 并查询