当由 systemd 启动 mod_wsgi 下的 flask 应用程序时,与 postgresql 的数据库连接被拒绝

当由 systemd 启动 mod_wsgi 下的 flask 应用程序时,与 postgresql 的数据库连接被拒绝

我遇到了一个奇怪的问题,我试图运行一个 Flask 应用程序(https://github.com/pyfarm/pyfarm-master) 在 CentOS 7 下的 Apache 下 mod_wsgi 无法连接到本地 postgresql 服务器 - 但前提是该 apache 已使用 systemctl 从 systemd 启动。如果我/usr/sbin/httpd -DFOREGROUND在命令行上手动使用 apache(systemd 说它使用的相同命令),则一切正常。

Apache、Postgresql 和 mod_wsgi 几乎未作任何改动,都是来自 CentOS 存储库或 EPEL 的默认安装。Pyfarm-core 和 pyfarm-master 已在 pip 的帮助下安装。

除了将基于主机的身份验证设置为“信任”所有本地主机之外,postgresql 配置与默认配置没有变化:

# "local" is for Unix domain socket connections only
local   all             all                                     trust
# IPv4 local connections:
host    all             all             127.0.0.1/32            trust
# IPv6 local connections:
host    all             all             ::1/128                 trust

之后,我创建了一个用户和数据库

CREATE USER pyfarm WITH PASSWORD 'pyfarmpw';
CREATE DATABASE pyfarm WITH OWNER pyfarm;

之后我可以使用 psql 以用户 pyfarm 身份登录数据库 pyfarm。

Apache 也几乎与默认配置没有太大变化。我唯一更改的是添加了一个新文件,/etc/httpd/conf.d/pyfarm.conf内容如下:

<VirtualHost *>
  ServerName pyfarm.produktion.local
  ServerAlias pyfarm

  SetEnv PYFARM_APP_INSTANCE True
  SetEnv PYFARM_SECRET_KEY 2qgsd4hHaalvAn7
  SetEnv PYFARM_CONFIG Prod
  SetEnv PYFARM_DB_PREFIX ""
  SetEnv PYFARM_DATABASE_URI postgresql+psycopg2://pyfarm:[email protected]/pyfarm
  SetEnv TDB_DRIVER psycopg2 

  WSGIScriptAlias / /var/www/pyfarm/pyfarm.wsgi

  DocumentRoot /var/www/pyfarm

  <Directory /var/www/pyfarm>
      Order allow,deny
      Allow from all
  </Directory>
</VirtualHost>

(这些配置文件里的密码和密钥并不是很重要,无论如何都会被改变……)

该文件引用/var/www/pyfarm/pyfarm.wsgi,如下所示:

import os

def application(environ, start_response):
     for key in environ:
         if key.startswith("PYFARM_") or key.startswith("TDB_"):
             os.environ[key] = environ[key]

     from pyfarm.master.entrypoints import app as application_

     return application_(environ, start_response)

(它需要非常复杂,因为否则应用程序将看不到 apache 中设置的环境变量。)

完成这些步骤后,从应用程序访问任何实际上不需要数据库的页面都可以正常工作,但是,一旦我尝试访问需要数据库的页面,就会收到 500 返回代码,并且在 Apache 的 error_log 中出现以下错误:

[Thu Jul 03 18:01:20.099007 2014] [:info] [pid 18094] mod_wsgi (pid=18094): Initializing Python.
[Thu Jul 03 18:01:20.106601 2014] [:info] [pid 18094] mod_wsgi (pid=18094): Attach interpreter ''.
[Thu Jul 03 18:01:20.116951 2014] [:error] [pid 18080] \x1b[31m2014-07-03 18:01:20 ERROR    - pyfarm.master   - Exception on /api/v1/agents/ [GET]
[Thu Jul 03 18:01:20.116964 2014] [:error] [pid 18080] Traceback (most recent call last):
[Thu Jul 03 18:01:20.116968 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
[Thu Jul 03 18:01:20.116971 2014] [:error] [pid 18080]     response = self.full_dispatch_request()
[Thu Jul 03 18:01:20.116974 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
[Thu Jul 03 18:01:20.116977 2014] [:error] [pid 18080]     rv = self.handle_user_exception(e)
[Thu Jul 03 18:01:20.116989 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
[Thu Jul 03 18:01:20.116993 2014] [:error] [pid 18080]     reraise(exc_type, exc_value, tb)
[Thu Jul 03 18:01:20.116996 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
[Thu Jul 03 18:01:20.116999 2014] [:error] [pid 18080]     rv = self.dispatch_request()
[Thu Jul 03 18:01:20.117001 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
[Thu Jul 03 18:01:20.117005 2014] [:error] [pid 18080]     return self.view_functions[rule.endpoint](**req.view_args)
[Thu Jul 03 18:01:20.117007 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/flask/views.py", line 84, in view
[Thu Jul 03 18:01:20.117010 2014] [:error] [pid 18080]     return self.dispatch_request(*args, **kwargs)
[Thu Jul 03 18:01:20.117013 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/flask/views.py", line 149, in dispatch_request
[Thu Jul 03 18:01:20.117016 2014] [:error] [pid 18080]     return meth(*args, **kwargs)
[Thu Jul 03 18:01:20.117019 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/pyfarm/master/api/agents.py", line 412, in get
[Thu Jul 03 18:01:20.117021 2014] [:error] [pid 18080]     for host in query:
[Thu Jul 03 18:01:20.117024 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2405, in __iter__
[Thu Jul 03 18:01:20.117027 2014] [:error] [pid 18080]     return self._execute_and_instances(context)
[Thu Jul 03 18:01:20.117030 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2418, in _execute_and_instances
[Thu Jul 03 18:01:20.117033 2014] [:error] [pid 18080]     close_with_result=True)
[Thu Jul 03 18:01:20.117037 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2409, in _connection_from_session
[Thu Jul 03 18:01:20.117040 2014] [:error] [pid 18080]     **kw)
[Thu Jul 03 18:01:20.117043 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 846, in connection
[Thu Jul 03 18:01:20.117046 2014] [:error] [pid 18080]     close_with_result=close_with_result)
[Thu Jul 03 18:01:20.117048 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 850, in _connection_for_bind
[Thu Jul 03 18:01:20.117051 2014] [:error] [pid 18080]     return self.transaction._connection_for_bind(engine)
[Thu Jul 03 18:01:20.117054 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 315, in _connection_for_bind
[Thu Jul 03 18:01:20.117057 2014] [:error] [pid 18080]     conn = bind.contextual_connect()
[Thu Jul 03 18:01:20.117060 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1737, in contextual_connect
[Thu Jul 03 18:01:20.117063 2014] [:error] [pid 18080]     self.pool.connect(),
[Thu Jul 03 18:01:20.117065 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/pool.py", line 332, in connect
[Thu Jul 03 18:01:20.117068 2014] [:error] [pid 18080]     return _ConnectionFairy._checkout(self)
[Thu Jul 03 18:01:20.117071 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/pool.py", line 630, in _checkout
[Thu Jul 03 18:01:20.117074 2014] [:error] [pid 18080]     fairy = _ConnectionRecord.checkout(pool)
[Thu Jul 03 18:01:20.117076 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/pool.py", line 433, in checkout
[Thu Jul 03 18:01:20.117079 2014] [:error] [pid 18080]     rec = pool._do_get()
[Thu Jul 03 18:01:20.117082 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/pool.py", line 949, in _do_get
[Thu Jul 03 18:01:20.117085 2014] [:error] [pid 18080]     return self._create_connection()
[Thu Jul 03 18:01:20.117091 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/pool.py", line 278, in _create_connection
[Thu Jul 03 18:01:20.117094 2014] [:error] [pid 18080]     return _ConnectionRecord(self)
[Thu Jul 03 18:01:20.117097 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/pool.py", line 404, in __init__
[Thu Jul 03 18:01:20.117099 2014] [:error] [pid 18080]     self.connection = self.__connect()
[Thu Jul 03 18:01:20.117102 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/pool.py", line 530, in __connect
[Thu Jul 03 18:01:20.117105 2014] [:error] [pid 18080]     connection = self.__pool._creator()
[Thu Jul 03 18:01:20.117108 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/engine/strategies.py", line 95, in connect
[Thu Jul 03 18:01:20.117111 2014] [:error] [pid 18080]     connection_invalidated=invalidated
[Thu Jul 03 18:01:20.117113 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/util/compat.py", line 189, in raise_from_cause
[Thu Jul 03 18:01:20.117116 2014] [:error] [pid 18080]     reraise(type(exception), exception, tb=exc_tb)
[Thu Jul 03 18:01:20.117119 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/engine/strategies.py", line 89, in connect
[Thu Jul 03 18:01:20.117122 2014] [:error] [pid 18080]     return dialect.connect(*cargs, **cparams)
[Thu Jul 03 18:01:20.117125 2014] [:error] [pid 18080]   File "/usr/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 376, in connect
[Thu Jul 03 18:01:20.117127 2014] [:error] [pid 18080]     return self.dbapi.connect(*cargs, **cparams)
[Thu Jul 03 18:01:20.117130 2014] [:error] [pid 18080]   File "/usr/lib64/python2.7/site-packages/psycopg2/__init__.py", line 164, in connect
[Thu Jul 03 18:01:20.117133 2014] [:error] [pid 18080]     conn = _connect(dsn, connection_factory=connection_factory, async=async)
[Thu Jul 03 18:01:20.117136 2014] [:error] [pid 18080] OperationalError: (OperationalError) could not connect to server: Permission denied
[Thu Jul 03 18:01:20.117138 2014] [:error] [pid 18080] \tIs the server running on host "127.0.0.1" and accepting
[Thu Jul 03 18:01:20.117141 2014] [:error] [pid 18080] \tTCP/IP connections on port 5432?
[Thu Jul 03 18:01:20.117144 2014] [:error] [pid 18080]  None None\x1b[39m

但是,当我使用 停止 apachesystemctl stop httpd.service并使用 重新启动它时/usr/sbin/httpd -DFOREGROUND,一切都正常运行,包括需要数据库访问的页面。

当 Apache 像这样运行时,我可以看到应用程序在中创建并使用数据库连接tcpdump -i lo。当从 systemd 启动 Apache 时,在 tcpdump 中看不到这样的连接,甚至没有 SYN 数据包。

显然,每次都手动启动 Apache 并不是一个长期的解决方案。有人知道这里出了什么问题吗?也许是某种特定于 systemd 的功能限制阻止某些服务建立出站 TCP 连接?

答案1

启用 SELinux 后,Web 服务器(以及在其中运行的进程,例如 mod_wsgi,以及在 EL 7 上,类似的服务器进程甚至与 Web 服务器分开运行)不允许建立传出网络连接,除非您明确允许它们这样做,例如使用 SELinux 布尔值。

为了解决该问题,请设置布尔值以允许与数据库的网络连接:

setsebool -P httpd_can_network_connect_db 1

相关内容