从Google Cloud Platform的Secret Manager读取django_settings不起作用



在我的笔记本电脑上本地运行命令python manage.py makemigrations时,我在控制台上得到以下错误:

(mywebsite) C:UsersSanderPycharmProjectsmywebsite>python manage.py makemigrations
Invalid line: echo DATABASE_URL=postgres://myuser:mypassword@//cloudsql/mywebsite:europe-west6:mywebsite-db/mydb > .env
Invalid line: echo GS_BUCKET_NAME=mybucket >> .env
Invalid line: echo SECRET_KEY=$(cat /dev/urandom | LC_ALL=C tr -dc '[:alpha:]'| fold -w 50 | head -n

请注意,echo [... etc. ...] > .env指令实际上是我在Google Cloud Platform的secret Manager上配置的一个秘密的内容,当我按照Google Cloud Platform的说明在Google Cloud Run上部署我的Django网站时。

现在我知道这些echo [... etc. ...] > .env指令应该创建一个文件。env与变量DATABASE_URL, GS_BUCKET_NAME和SECRET_KEY在其中,但它没有,当然,因为它报告错误"无效行:…"相反。

我找到了这个StackOverflow答案,说明这些bash指令(echo [... etc. ...] > .env)根本不能由python执行,我可以通过从shell脚本运行它们来简单地在本地执行它们,所以执行这个create-env-file.sh工作:

DATABASE_URL=postgres://myuser:mypassword@//cloudsql/mywebsite:europe-we
st6:mywebsite-db/mydb > .env
GS_BUCKET_NAME=mybucket >> .env
echo SECRET_KEY=$(cat /dev/urandom | LC_ALL=C tr -dc '[:alpha:]'| fold -w 50 | head -n

然而,这会生成一个本地。env文件,显然,在将网站移动到生产之前,我想确认与秘密管理器一起工作的流程。,因为如果我保留.env文件并将其上传到生产环境中,那么仍然使用秘密管理器就没有意义了,它不再是必需的了。

当观察后面实际运行的代码时,这一点也变得非常清楚:

import io
import os
from pathlib import Path
import environ
import google.auth
from google.cloud import secretmanager
if os.path.isfile(env_file):
# Use a local secret file, if provided
env.read_env(env_file)
elif os.environ.get("GOOGLE_CLOUD_PROJECT", None):
# Pull secrets from Secret Manager
project_id = os.environ.get("GOOGLE_CLOUD_PROJECT")
client = secretmanager.SecretManagerServiceClient()
settings_name = os.environ.get("SETTINGS_NAME", "django_settings")
name = f"projects/{project_id}/secrets/{settings_name}/versions/latest"
payload = client.access_secret_version(name=name).payload.data.decode("UTF-8")
env.read_env(io.StringIO(payload))
else:
raise Exception("No local .env or GOOGLE_CLOUD_PROJECT detected. No secrets found.")

我调试了该代码,问题是在env.read_env(io.StringIO(payload))的执行中,因为有效负载包含预期的内容(echo [... etc. ...] > .env行)。

我看到了使用Google的秘密管理器的优势,但我开始认为要么是Django Cloud Run教程提供的秘密内容有问题,要么是代码解析并将其保存为环境变量。

我在Windows本地运行,使用以下库(我的requirements.txt的内容):

django
# For integrating with Google Cloud Platform:
django-storages[google]>=1.12
django-environ>=0.8.1
psycopg2-binary>=2.9.1
gunicorn>=20.1.0
google-cloud-secret-manager>=2.7.2

这显然是由两个原因引起的:

  • 在settings.py中,使用env.read_env(io.StringIO(payload))将秘密内容加载到环境变量中,如问题所述。read_env()函数显然做了以下工作:

    # ...
    for line in content.splitlines():
    m1 = re.match(r'A(?:export )?([A-Za-z_0-9]+)=(.*)Z', line)
    if m1:
    # ...
    elif not line or line.startswith('#'):
    # ignore warnings for empty line-breaks or comments
    pass
    else:
    logger.warning('Invalid line: %s', line)
    # ...
    

    因为秘密内容的行以"echo &quot开头,所以这些行被标记为无效(你可以在https://regex101.com上尝试一下)并且命令python manage.py makemigrations因此崩溃并产生该错误。

  • 当编辑payload之前,它进入env.read_env(io.StringIO(payload)),使它不再以echo开始(解决上面的问题),也因为正则表达式匹配,也删除> .env>> .env在最后,第三行也会导致问题:SECRET_KEY=$(cat /dev/urandom | LC_ALL=C tr -dc '[:alpha:]'| fold -w 50 | head -n。读取/dev/urandom生成伪随机的SECRET_KEY是Windows上的问题,/dev/urandom只存在于linux操作系统。

所以看起来这个秘密应该在Google Cloud Run的基于linux的生产服务器上工作,而不是在运行Windows的本地计算机上,如果像部署Django网站的说明那样执行。

对于本地运行,创建一个.env文件,可以通过运行问题(*)中提到的create-env-file.sh脚本,或者在与settings.py:

相同的文件夹中手动创建.env文件。
DATABASE_URL=postgres://myuser:mypassword@//cloudsql/mywebsite:europe-west6:mywebsite-db/mydb
GS_BUCKET_NAME=mybucket
SECRET_KEY=some1279Long30String5You7Create2Yourself8136

(*)/dev/urandom确实对我有用,因为当我在PyCharm的终端窗口上执行create-env_file.sh时,我的计算机上打开了一个新的Git Bash终端,可能是因为在我的计算机上这是执行shell文件的注册程序。

相关内容

  • 没有找到相关文章

最新更新