在Pyramid web框架中,如何将敏感设置源代码到开发.ini/ 生产.ini从外部文件?

2024-05-23 13:42:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我希望将development.iniproduction.ini置于版本控制之下,但出于安全原因,我不希望存储{}连接字符串,因为这将包含用于数据库连接的用户名和密码。在

在金字塔中,从额外的外部文件获取此设置的标准方式是什么?在

编辑 除了使用环境变量的解决方案外,我在询问#pyramid时提出了这个解决方案:

def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
# Read db password from config file outside of version control
secret_cfg = ConfigParser()
secret_cfg.read(settings['secrets'])
dbpass = secret_cfg.get("secrets", "dbpass")
settings['sqlalchemy.url'] = settings['connstr'] % (dbpass,)

Tags: 字符串config数据库secretsettings原因解决方案cfg
3条回答

金字塔中独立的ini文件的全部意义在于,您不必对它们进行版本控制,并且它们可以包含针对不同场景(开发/生产/测试)的不同设置。你的生产.ini几乎总是不应该与源代码在同一个VCS中。在

我对此进行了很多研究,并采用了很多不同的方法。然而,Pyramid非常灵活,.iniconfig解析器对您的作用非常小,似乎没有实际的答案。在

在我的场景中,我首先尝试在版本控制中使用production.example.ini在生产服务器上复制,并填写详细信息,但这变得很麻烦,因为对示例的更新没有转换为副本,因此在进行更改时必须重新创建副本。另外,我开始使用Heroku,因此不在版本控制中的文件从未进入部署中。在

然后是加密配置方法。我不喜欢这种模式。假设一个系统管理员负责维护生产环境,但他或她无法更改数据库或特定于环境的设置的位置,而不通过版本控制运行它。在环境和代码之间尽可能地分离是非常好的,这样就可以在没有版本控制修改的情况下动态地进行这些更改。在

我的最终解决方案是获得如下所示的一些值:

[app:main]

sqlalchemy.url = ${SQLALCHEMY_URL}

然后,在生产服务器上,将环境变量SQLALCHEMY_URL设置为指向数据库。这甚至允许我对登台和生产使用相同的配置文件,这很好。在

在Pyramid init中,我只是使用^{}扩展了环境变量值:

^{pr2}$

而且,如果您想使用它并自动替换设置字典中的所有环境变量,我为我的项目创建了一个小助手方法:

def expandvars_dict(settings):
    """Expands all environment variables in a settings dictionary."""
    return dict((key, os.path.expandvars(value)) for
                key, value in settings.iteritems())

在您的main应用程序入口点中如下所示:

settings = expandvars_dict(settings)

我发现这种方法可以从额外的配置和env中加载机密。在

from pyramid.config import Configurator
from paste.deploy import appconfig
from os import path

__all__ = [ "main" ]


def _load_secrets(global_config, settings):
    """ Helper to load secrets from a secrets config and
        from env (in that order).
    """
    if "drawstack.secrets" in settings:
        secrets_config = appconfig('config:' + settings["drawstack.secrets"],
                                    relative_to=path.dirname(global_config['__file__']))

        for k, v in secrets_config.items():
            if k == "here" or k == "__file__":
                continue
            settings[k] = v

    if "ENV_DB_URL" in global_config:
        settings["sqlalchemy.url"] = global_config["ENV_DB_URL"]


def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """

    _load_secrets(global_config, settings)

    config = Configurator(settings=settings)
    config.include('pyramid_jinja2')
    config.include('.models')
    config.include('.routes')
    config.scan()
    return config.make_wsgi_app()

上面的代码将从配置键drawstack.secrets的值加载任何变量,然后尝试从环境加载DB_URL。在

drawstack.secrets可以是相对于原始配置文件的,也可以是绝对的。在

相关问题 更多 >