在使用uWSGI进行部署时,如何使用getpass向Flask应用程序提供输入?

时间:2013-09-12 15:21:05

标签: python flask uwsgi gunicorn

我有一个Flask应用程序,它有一些加密组件。具体来说,磁盘上有一个加密的密钥,必须在内存中解密才能在Flask应用程序进程中使用。为了解密密钥,在应用程序运行时,系统会提示用户输入带有getpass的密码。

这适用于app.run()和单个前台Flask WSGI服务器。我们遇到的问题是,当使用uWSGI进行部署时,uWSGI控制器不允许stdin。

理想情况下,我们希望发生的情况类似于当您使用SSL重新启动或启动Apache或Nginx时 - 在服务分叉之前它会在stdin上提示输入密码。

任何帮助将不胜感激!

更新

虽然我们仍然希望使用uWSGI,但由于gunicorn的前叉选项,我们已经转向了gunicorn。此解决方案仍然不理想,特别是因为我们无法添加像UPSTART这样的监控服务。基本上,我们之前运行的脚本使用read将密码设置为环境变量,并将该环境变量传递给gunicorn应用程序。

#!/bin/bash

NAME="baz"                                  # Name of the application
APPDIR=/var/apps/baz                        # Application project directory
SOCKFILE=/var/apps/baz/gunicorn.sock        # Using a socket
BIND="127.0.0.1:8000"                       # Using a port
USER="www-data"                             # User to run as
GROUP="www-data"                            # Group to run as
WORKERS=1                                   # How many worker processes

echo "Starting $NAME"

# Collect the passphrase
read -s -p "Enter $NAME passphrase: " PASSPHRASE
echo ""

# Activate the virtual environment
source /var/venvs/baz/bin/activate
export BAZ_SETTINGS="baz.conf.Config"
export BAZ_PASSPHRASE=$PASSPRHASE

# Start Gunicorn
exec gunicorn $NAME:app \
    --user $USER --group $GROUP \
    --bind $BIND \
    --workers $WORKERS \
    --chdir $APPDIR \
    --env BAZ_PASSPHRASE=$PASSPHRASE \
    --daemon

这或多或少是教程Setting up Django with Nginx, Gunicorn, virtualenv, supervisor and PostgreSQL中使用的脚本 - 修改后用于阅读密码并与Flask一起使用。

我们已经检查过以确保BAZ_PASSPHRASE环境变量在任何环境中都不存在,但这仍然感觉有点吱吱作响,所以我们仍然感谢任何评论,特别是关于uWSGI。

2 个答案:

答案 0 :(得分:1)

只需添加--honour-stdin即可禁用将文件描述符0重新映射到/dev/null

如果您致电--daemonize,您将失去控制终端,因此您必须在使用--daemonize2

读取输入后推迟守护进程

答案 1 :(得分:0)

TL; DR:使用FIFO代替STDIN提供输入

#!/bin/sh

FIFO=/tmp/.appfifo
rm -f ${FIFO}
mkfifo ${FIFO}
cat > ${FIFO} # decryt password | /etc/init.d/app start

exec gunicorn $NAME:app \
    --user $USER --group $GROUP \
    --bind $BIND \
    --workers $WORKERS \
    --chdir $APPDIR \
    --env ENCRYPTED_CFG=/etc/app.encrypted.cfg
    --daemon

以及代码中的某个地方

get_password(file(os.getenv('ENCRYPTED_CFG'),'r').read())