【问题标题】:Keep Secret Keys Out保留密钥
【发布时间】:2013-01-25 00:22:55
【问题描述】:

local_settings.py 反模式的原因之一是把 SECRET_KEY, AWS 设置文件中的键等值有问题:

  • 秘密通常应该是这样的:秘密!将它们保存在版本控制中意味着 拥有存储库访问权限的每个人都可以访问它们。

我的问题是如何将所有密钥保密?

【问题讨论】:

  • 已接受的答案因抄袭而被删除,但我将@neuronet 的贡献(试图纠正问题)放入下面的社区 wiki。
  • 从标题中删除 'with environment variables' 将问题从原始 Q 中改变得足够大,以至于它可能不应该完成。

标签: python django settings


【解决方案1】:

这是一种与 Heroku 上的部署兼容的方法:

  1. 创建一个名为 .env 的 gitignored 文件,其中包含:

    export DJANGO_SECRET_KEY = 'replace-this-with-the-secret-key'

  2. 然后编辑 settings.py 以删除实际的 SECRET_KEY 并添加它:

    SECRET_KEY = os.environ['DJANGO_SECRET_KEY']

  3. 然后当你想在本地运行开发服务器时,使用:

    source .env
    python manage.py runserver

  4. 当您最终部署到 Heroku 时,转到您的应用设置选项卡并将 DJANGO_SECRET_KEY 添加到 Config Vars。

【讨论】:

  • 我必须删除“=”周围的空格才能使其正常工作:export DJANGO_SECRET_KEY='replace-this-with-the-secret-key'
  • 我还必须删除“=”周围的空格才能使其正常工作:export DJANGO_SECRET_KEY='replace-this-with-the-secret-key'
【解决方案2】:

您可能需要使用 os.environ.get("SOME_SECRET_KEY")

【讨论】:

  • 应该是os.environ.get("SOME_SECRET_KEY")
【解决方案3】:

最初的问题是关于如何在环境变量中保密。这在Two Scoops of Django 一书中进行了广泛的讨论。下面是他们所说的摘要,然后是关于使用这种技术的警告。

从 1.11 版的第 48 页(第 5.3 节)开始:

Django(和 Python)支持的每个操作系统都提供 轻松创建环境变量。

以下是使用环境变量作为密钥的好处:

  • 设置中的机密允许您毫不犹豫地将每个设置文件存储在版本控制中。你所有的 Python 代码 确实应该存储在版本控制中,包括您的设置。
  • 不是每个开发人员都维护自己的复制粘贴版本的 local_settings.py.example 用于开发,而是每个人都共享 相同的版本控制设置/local.py。
  • 系统管理员无需修改包含 Python 代码的文件即可快速部署项目。
  • 大多数平台即服务建议使用环境变量进行配置,并具有用于设置和 管理他们。

在下一页,本书继续:

在开始设置环境变量之前,您应该拥有 以下:

  • 一种管理您要存储的秘密信息的方法。
  • 非常了解 bash 设置如何在服务器上工作,或者愿意将您的项目托管在平台即服务中。

他们描述了如何在本地和生产环境中设置环境变量(以 Heroku 为例——您需要检查您是否使用不同的主机,这只是一种可能性):

如何在本地设置环境变量
导出 SOME_SECRET_KEY=1c3-cr3am-15-yummy

如何在生产环境中设置环境变量
heroku 配置:设置 SOME_SECRET_KEY=1c3-cr3am-15-yummy

最后,在第 52 页,他们给出了如何访问密钥的说明。例如,您可以将下面的前两行放在您的设置文件中,以替换默认放置在那里的原始密钥字符串:

>>> import os
>>> os.environ['SOME_SECRET_KEY'] 
'1c3-cr3am-15-yummy'

这个 sn-p 只是获取 SOME_SECRET_KEY 环境的值 来自操作系统的变量并将其保存到 Python 变量中 称为 SOME_SECRET_KEY。

遵循此模式意味着所有代码都可以保留在版本控制中, 并且所有的秘密都是安全的。

请注意,这在某些情况下不起作用,例如,如果您使用的是 Apache 服务器。要处理这种模式不起作用的情况,您应该查看他们书中的第 5.4 节(“当您无法使用环境变量时”)。在这种情况下,他们建议使用机密文件。

截至 2017 年底,这种在环境变量中存储机密的技术是两勺和十二因素应用程序设计模式中推荐的最佳实践。在 Django 文档中也推荐它。但是,存在一些安全风险:如果某些开发人员或某些代码可以访问您的系统,他们将可以访问您的环境变量,并且可能会无意(或有意)将它们公开。这一点是由 Michael Reinsch 在这里提出的:
http://movingfast.io/articles/environment-variables-considered-harmful/

【讨论】:

  • 关于安全问题:如果有人可以访问我的系统,那么无论我做什么都会有麻烦。使用环境变量似乎很流行,在 Django 文档中被推荐为可行的选项,被 Two Scoops 书推荐。只是感觉更像蟒蛇。例如,与存储不受版本控制的秘密文件相比(因此每个人都有不同的本地文件:简单胜于复杂)。几年前关于这个话题的讨论:stackoverflow.com/questions/12461484/…
  • @neuronet 你介意把这个答案拿过来,让它连贯而不是脱节吗?也感谢您发现抄袭。如果您看到更多,请告诉我。
  • 我可以在接下来的几天内试一试。我远不是这方面的专家,我刚刚在阅读 Two Scoops 书,最近在 django 中处理环境变量,偶然发现了这本书的剪切/粘贴。
【解决方案4】:

我编写了一个 getcreds() 函数,它从文件中获取密钥。我将文件保存在 www-data 可以访问的位置,因此无论我在 settings.py 中需要凭据的任何地方,我都只需调用 getcreds() 并将文件名作为参数传递。它返回文件中所有行的列表,宾果游戏我有隐藏的秘密。这是代码...

from __future__ import unicode_literals, absolute_import
import os


def getcreds(fname, project, credsroot='/var/www/creds', credsdir=None):
    """ return a list of userid and password and perhaps other data """
    if credsdir is None:
        credsdir = os.path.join(credsroot, project)
    creds = list()
    fname = os.path.join(credsdir, fname).replace("\\", "/")
    with open(fname, 'r') as f:
        for line in f:
            # remove leading/trailing whitespace and append to list
            creds.append(line.strip())
    assert creds, "The list of credentials is empty"
    return creds

【讨论】:

    【解决方案5】:

    我使用 Windows 7 和 Powershell 执行我的 Django 项目,所以对我来说设置环境变量略有不同。不过,一旦设置好,我就在我的 settings.py 文件中执行了以下操作:

    import os
    SECRET_KEY = os.environ["SOME_SECRET_KEY"]
    

    要使用 PowerShell 在 Windows 中设置环境变量,请按照以下链接中的说明进行操作:

    http://technet.microsoft.com/en-us/library/ff730964.aspx

    【讨论】:

      【解决方案6】:

      将您的 local_settings.py 数据存储在使用 GPG 加密的文件中 - 最好严格按照您解析并分配给 dict 的 key=value 行(另一种有吸引力的方法是将其作为可执行的 python,但在配置中的可执行代码文件让我颤抖)。

      有一个 python gpg 模块,所以这不是问题。从您的钥匙圈中获取您的钥匙,并使用 GPG 钥匙圈管理工具,这样您就不必一直输入您的钥匙串密码。确保您直接从加密文件中读取数据,而不仅仅是创建您读取的解密临时文件。这是失败的秘诀。

      这只是一个大纲,你必须自己构建它。

      这样,秘密数据仅保留在进程内存空间中,而不是文件或环境变量中。

      【讨论】:

      • 在其他语言中加密密钥、值文件也是一种常见的良好做法。只有对 GPG 密钥环的依赖和正确配置是我会尽量避免的。
      【解决方案7】:

      理想情况下,local_settings.py 不应签入生产/部署服务器。您可以将备份副本保存在其他地方,但不能保存在源代码管理中。

      local_settings.py可以在开发配置中签入,只是为了方便,每个开发者都需要更改。

      这能解决你的问题吗?

      【讨论】:

      • 它是比使用环境变量更好的解决方案,也是更简单的解决方案之一。我不知道为什么我们的答案在没有任何解释的情况下被否决。只需将 local_settings.py 添加到您的 .gitignore 并完成工作。你能告诉 git 将东西保存在本地仓库中而不是向上游推送吗?那会更好。 OP 没有指定他们的 VC 系统...
      • local_settings.py 如果可能会更简单,但它并非在所有情况下都有效。比如afaict,部署到Heroku时,只能使用git和环境变量中签入的内容,所以如果不想将secret_key签入git,就必须使用环境变量。
      猜你喜欢
      • 2020-09-08
      • 2014-02-01
      • 2022-01-22
      • 2016-03-14
      • 2018-01-08
      • 1970-01-01
      • 1970-01-01
      • 2020-11-10
      • 2014-12-15
      相关资源
      最近更新 更多