【问题标题】:SQLAlchemy verify SSL connectionSQLAlchemy 验证 SSL 连接
【发布时间】:2019-08-11 12:53:30
【问题描述】:

我想验证 SQLAlchemy 在使用 create_engine 连接到 PostgreSQL 数据库时设置的 SSL 连接。例如,如果我有以下 Python 3 代码:

from sqlalchemy import create_engine

conn_string = "postgresql+psycopg2://myuser:******@someserver:5432/somedb"

conn_args = {
    "sslmode": "verify-full",
    "sslrootcert": "/etc/ssl/certs/ca-certificates.crt",
}

engine = create_engine(conn_string, connect_args=conn_args)

我知道我可以打印engine.__dict__ 的内容,但它不包含有关它用于连接的 SSL 设置(TLS 版本、密码套件等)的任何信息:

{
    '_echo': False,
    'dialect': <sqlalchemy.dialects.postgresql.psycopg2.PGDialect_psycopg2 object at 0x7f988a217978>,
    'dispatch': <sqlalchemy.event.base.ConnectionEventsDispatch object at 0x7f988938e788>,
    'engine': Engine(postgresql+psycopg2://myuser:******@someserver:5432/somedb),
    'logger': <Logger sqlalchemy.engine.base.Engine (DEBUG)>,
    'pool': <sqlalchemy.pool.impl.QueuePool object at 0x7f988a238c50>,
    'url': postgresql+psycopg2://myuser:******@someserver:5432/somedb
}

我知道我可以做类似SELECT * FROM pg_stat_ssl; 的事情,但是 SQLAlchemy 引擎是否将此类信息存储为类属性/方法?

谢谢!

【问题讨论】:

    标签: python python-3.x postgresql ssl sqlalchemy


    【解决方案1】:

    我不使用 postgres,所以希望这适用于你。

    SQLAlchemy 获取您在 url 中提供的信息并将其传递到也在 url 中指定的底层 dbapi 库,在您的情况下是 psycopg2。

    您的engine 实例仅在需要时连接到数据库,sqlalchemy 只是将连接信息传递给 url 中指定的驱动程序,该驱动程序返回 sqlalchemy 使用的连接。

    原谅这是mysql,但对你来说应该基本相同:

    >>> engine
    Engine(mysql+mysqlconnector://test:***@localhost/test)
    >>> conn = engine.connect()
    >>> conn
    <sqlalchemy.engine.base.Connection object at 0x000001614ACBE2B0>
    >>> conn.connection
    <sqlalchemy.pool._ConnectionFairy object at 0x000001614BF08630>
    >>> conn.connection.connection
    <mysql.connector.connection_cext.CMySQLConnection object at 0x000001614AB7E1D0>
    

    调用engine.connect() 会返回一个sqlalchemy.engine.base.Connection 实例,该实例具有一个connection property,其文档字符串显示:

    由此连接管理的底层 DB-API 连接。

    但是,您可以从上面看到它实际上返回了一个 sqlalchemy.pool._ConnectionFairy 对象,该对象来自它的文档字符串:

    代理一个 DBAPI 连接...

    这是连接精灵的__init__() 方法,您可以看到它有一个connection 属性,它是实际的底层dbapi 连接。

    def __init__(self, dbapi_connection, connection_record, echo):
        self.connection = dbapi_connection
        self._connection_record = connection_record
        self._echo = echo
    

    关于 dbapi 连接对象上可用的信息,这取决于该特定驱动程序的实现。例如 psycopg2 连接对象有一个info 属性:

    一个ConnectionInfo 对象公开有关本机 libpq 的信息 连接。

    那个info对象有ssl_in_use等属性:

    如果连接使用 SSL,则为 True,否则为 False。

    还有ssl_attribute:

    返回有关连接的 SSL 相关信息。

    因此,您无需深入挖掘即可了解实际的数据库连接以了解实际情况。

    另外,如果你想确保所有客户端连接都是ssl,你可以随时force them to

    【讨论】:

    • 你好最后一个链接是强制PostgreSQL客户端使用SSL,我们如何强制MySQL客户端使用ssl? (具体使用 Python 代码)
    • @Cecilia 你看过--ssl-mode吗?如何通过 python 配置将取决于您的驱动程序。如果是 mysqlclient,ssl-modeconnect() 函数的关键字参数。
    • @SuperShot 嗨,谢谢,我使用sqlalchemy.create_engine() 连接数据库,我应该使用ssl-mode 吗?我提出了一个使用wireshark验证TLS的单独问题:stackoverflow.com/questions/68160487/… 任何帮助将不胜感激,谢谢。
    • 继续上面的评论-(我的驱动是MySQL)
    【解决方案2】:

    下面是 SuperShoot 的详细说明:

    >>> from sqlalchemy import create_engine
    >>> db_string = "postgresql+psycopg2://myuser:******@someserver:5432/somedb"
    >>> db = create_engine(db_string)
    >>> conn = db.connect()
    >>> conn.connection.connection.info.ssl_in_use
    

    如果使用 SSL,应该返回 True。

    【讨论】:

    • 嗨,最后一行给了我错误AttributeError: 'builtin_function_or_method' object has no attribute 'ssl_in_use',有没有办法可以查看它使用的是哪个 TLS 版本?我想验证连接是否使用TLSv1.2
    【解决方案3】:

    如果有人正在寻找 PostgreSQLpg8000,请参阅 pg8000 docs

    对于 SSL 默认值,它是:

    import sqlalchemy
    
    sqlalchemy.create_engine(url, connect_args={'ssl_context':True})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-30
      • 1970-01-01
      • 1970-01-01
      • 2019-08-06
      • 1970-01-01
      • 2014-03-21
      相关资源
      最近更新 更多