Python 使用uWSGI部署时,如何使用getpass向Flask应用程序提供输入?
我有一个Flask应用程序,它有一些加密组件。具体来说,磁盘上有一个加密的密钥,必须在内存中未加密,以便在Flask应用程序进程中使用。为了解除密钥加密,当应用程序运行时,系统会提示用户使用getpass输入密码短语 这对于Python 使用uWSGI部署时,如何使用getpass向Flask应用程序提供输入?,python,flask,uwsgi,gunicorn,Python,Flask,Uwsgi,Gunicorn,我有一个Flask应用程序,它有一些加密组件。具体来说,磁盘上有一个加密的密钥,必须在内存中未加密,以便在Flask应用程序进程中使用。为了解除密钥加密,当应用程序运行时,系统会提示用户使用getpass输入密码短语 这对于app.run()和单个WSGI服务器非常有效。我们遇到的问题是,当使用uWSGI部署时,uWSGI控制器不允许stdin 理想情况下,我们希望发生的事情与使用SSL重新启动或启动Apache或Nginx时类似——在服务分叉之前,它会提示在stdin上输入密码 任何帮助都将不
app.run()
和单个WSGI服务器非常有效。我们遇到的问题是,当使用uWSGI部署时,uWSGI控制器不允许stdin
理想情况下,我们希望发生的事情与使用SSL重新启动或启动Apache或Nginx时类似——在服务分叉之前,它会提示在stdin上输入密码
任何帮助都将不胜感激
更新
尽管我们仍然希望使用uWSGI,但由于gunicorn的pre-fork选项,我们已经迁移到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
这或多或少是教程中使用的脚本-修改后用于阅读密码短语和与Flask一起使用
我们已经检查过,以确保BAZ_PASSPHRASE
环境变量在任何环境中都不存在,但这仍然感觉有点吱吱作响,因此我们仍然希望您提供任何意见,特别是关于uWSGI。只需添加--honor stdin
它将禁用文件描述符0到/dev/null
的重新映射
如果您调用
--daemonize
您将失去控制终端,因此您必须在使用--daemonize2
TL读取输入后推迟daemonization;DR:使用FIFO而不是标准输入提供输入
#!/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
#!/垃圾箱/垃圾箱
FIFO=/tmp/.appfifo
rm-f${FIFO}
mkfifo${FIFO}
cat>${FIFO}#decryt password |/etc/init.d/app start
exec gunicorn$NAME:应用程序\
--用户$user--组$group\
--bind$bind\
--工人$工人\
--chdir$APPDIR\
--env ENCRYPTED_CFG=/etc/app.ENCRYPTED.CFG
--守护进程
在代码的某个地方
get_password(file(os.getenv('ENCRYPTED_CFG'),'r').read())
获取密码(文件(os.getenv('ENCRYPTED_CFG'),'r').read())
我们确实试过了——我会在周一回复你,告诉你它不起作用的原因,然后我会重新评估这场争论到底发生了什么。一个主要的问题是,服务器可能实际上从stdin中的服务器读取请求。在uWSGI分叉子烧瓶进程之前,我们需要一种可移植的方式来提供stdin。此外,今天我们将测试添加--《不一定会跟随你》上发布的聊天中的守护进程honor stdin,-honor stdin是允许工作人员管理stdin的正确选项,但请确保不要“守护”uWSGI,因为它将失去控制终端。我不了解gunicorn的fork前部分,因为uWSGI允许您选择何时调用fork()(-懒惰应用程序具有与gunicorn相同的行为)。我已经更新了答案,以澄清daemonization行为。好吧,我买这个-说这更多是为了日志记录,但现在看来它已经起作用了。