为Python模块存储系统级数据库连接密码

0 投票
2 回答
1278 浏览
提问于 2025-04-15 18:10

我写了一个Python模块,这个模块需要连接MySQL数据库。现在,这个连接的详细信息(比如主机、数据库名、用户名和密码)都存储在/etc/mymodule.conf这个文件里,而且是明文的,这显然不是个好主意。

据说,/etc/mymodule.conf这个文件是在模块安装后由超级用户(root用户)来编辑的,因为这个模块和它的数据库可能会被Unix系统上的所有用户使用。

那么,我应该怎么安全地存储密码呢?

2 个回答

1

为什么不创建一个默认的MySQL用户账户,并限制它的权限呢?你可以设置这个账户只能读取特定的数据库。你还可以限制这个默认用户只能执行SELECT操作,也就是只能查询数据,而不能进行INSERT(插入)、UPDATE(更新)或DELETE(删除)。具体应该设置哪些权限,当然要根据你的实际情况来决定。

关于如何限制或授予权限的语法,可以参考这里: http://dev.mysql.com/doc/refman/5.1/en/grant.html

通过创建一个默认的、权限受限的MySQL用户,你可能就可以把密码放在一个普通的文本文件里,这样也不会有什么问题。

同时,如果你在模块的连接函数中添加userpassword作为可选参数,那么权限更高的用户就可以提供自己的密码,以便能够以更高的权限与数据库进行交互。

当然,这其实是在质疑你最初提问的前提。如果这个方向不可行,可以随意忽略!:)

祝好,
unutbu

4

你的限制条件设定了一个非常棘手的问题:系统中的每个用户都必须能够访问那个密码(因为这是用户访问数据库的唯一方式)……但他们又不能访问(除了在运行那个脚本的时候,显然是在没有像 python -i 这样的交互式会话的情况下,这种会话允许他们在连接调用之前设置断点并查看内存,所以他们肯定能看到密码)。

你可以写一个守护进程,让它以root身份运行(这样可以读取mymodule.conf文件,而这个文件只能root可读),并接受请求,某种方式验证请求来自一个“良好”的进程(即正在运行特定模块而不是交互式的进程),然后才提供密码。这种方法比较脆弱,主要是因为需要判断一个进程在关键执行点是否可能设置了断点。

另外,你可以进一步提高技术难度,让守护进程返回的不是密码,而是一个可以被包装成符合DB-API标准的打开的套接字;一些Unix系统允许在不相关的进程之间发送打开的文件描述符(这是这种方法的前提)——当然,你还需要大幅修改基于MySQL的DB API,以允许围绕一个已经打开的套接字而不是新创建的套接字打开连接。需要注意的是,一个经过验证的请求进程如果是交互式的,仍然可以获取连接对象,并发送完全任意的请求——技术上他们看不到密码,但这并不能让人安心。所以这里所需的大量工作可能并不值得。

因此,下一个可能的架构是通过验证守护进程来调解所有数据库交互:一个进程会“登录”到守护进程,经过验证后,如果一切正常,就获得一个代理连接到(例如)一个暴露数据库连接和功能的XMLRPC服务器(守护进程可能会在从仅root可读的文件中读取密码后,立即为每个这样的代理进程分叉,并立即降低权限,这主要是出于安全考虑)。

与之前的替代方案相比,这种方法的好处在于,除了可能更容易实现外,代理还可以查看即将发送到MySQL数据库的每个SQL请求,并能够验证和审查这些请求(大概是基于默认拒绝的原则,出于一般安全原则),从而严重限制一个“恶意”客户端进程(在交互式调试器中运行)可能造成的损害……希望如此;-)。

是的,这里没有简单的解决方案——但你的限制条件所带来的问题远非简单,几乎是自相矛盾的不可能性;-)。顺便说一下,这个问题并不特别与Python有关,基本上是关于选择一个安全的架构,接近于“画圆”的困难,关于访问权限的矛盾限制!-)

撰写回答