https://12factor.net/config上的devops指南建议将网站秘密(数据库密码,api密钥等)放入环境变量中。与使用版本控制忽略的文本文件(JSON,XML,YAML,INI或类似文件)相比,这有什么优点?
我发现复制带有机密的配置文件比处理.bash_profile和Webserver配置中的环境变量要容易得多。我想念什么吗?
https://12factor.net/config上的devops指南建议将网站秘密(数据库密码,api密钥等)放入环境变量中。与使用版本控制忽略的文本文件(JSON,XML,YAML,INI或类似文件)相比,这有什么优点?
我发现复制带有机密的配置文件比处理.bash_profile和Webserver配置中的环境变量要容易得多。我想念什么吗?
Answers:
作者列出了他们的推理,尽管有些脱节。他们的主要论据是,很容易意外地检入配置文件,并且配置文件具有不同的格式,并且可能散布在系统中(对于安全性相关的配置,这三个参数充其量只是中等的参数,例如身份验证令牌和凭据)。
根据我自己的经验,您基本上可以选择以下三个选项,并具有各自的优点和缺点:
采用这种方法时,最好将它们与存储库本身隔离开,并确保它们不在应用程序将其内容存储在其中的区域内。
通常,这是通过从启动脚本中获取环境变量和值的列表来完成的,但是在某些情况下,它可能只是在命令行中在程序名称之前声明了它们。
hidepid
mount选项/proc
),但默认情况下未启用它们,并且无法防范拥有该进程的用户的攻击。认真地,不惜一切代价避免这种情况,它不安全,维护起来很痛苦。
Web服务器的每个子进程都将继承环境变量。那就是连接到服务器的每个会话,以及由它们产生的每个程序。这些秘密将自动显示给所有这些过程。
如果您在文本文件中保留机密,则服务器进程必须读取它们,因此每个子进程也可能读取它们。但是至少程序必须去找到它们;它们不会自动提供。您也许还可以使某些子进程在不同的帐户下运行,并使机密仅由那些帐户可读。例如,suEXEC在Apache中执行此操作。
MYVAR=foo /path/to/some/executable
)将传播限制到一个进程,并且仅限于其子进程-并且在需要的主守护程序可以擦洗/重置/修改的地方子进程的环境。
即使在环境变量或文件方面需要进行一些与安全性相关的折衷,我也不认为安全性是此建议的主要推动力。还记得12factor.net的作者还是Heroku PaaS的开发人员吗?让每个人都使用环境变量可能会大大简化他们的开发。不同的配置文件格式和位置种类繁多,因此很难完全支持它们。环境变量很容易比较。
猜测一些对话并不需要太多的想象力。
开发人员A:“啊,这个秘密的配置文件UI太混乱了!我们真的需要下拉列表在json,xml和csv之间切换吗?”
开发人员B:“哦,如果只有每个人都为应用程序配置使用环境变量,生活将会如此美好。”
开发人员A:“实际上,这样做有一些与安全性相关的理由。环境变量可能不会被意外检查到源代码管理中。”
开发人员B:“您不是使用启动守护程序的脚本或配置文件来设置环境变量吗?”
开发人员A:“不在Heroku中!我们将让他们在用户界面中键入它们。”
开发人员B:“哦,我的12factor.net域名警报刚响了。” 1个
1:来源:组成。
使用环境变量而不是配置文件的原因很多,但是最容易忽略的两个原因是带外配置的实用价值以及服务器,应用程序或组织角色之间的增强隔离。我没有给出所有可能原因的详尽列表,而是在回答中仅涉及了这两个主题,并轻轻地涉及了它们的安全性。
如果将所有机密存储在配置文件中,则必须将这些机密分发到每个服务器。这意味着将机密信息与代码一起检查到修订控制中,或者具有完全独立的机密信息库或机密分发机制。
加密您的秘密并不能真正解决问题。所有要做的就是将这个问题一举解决,因为现在您也必须担心密钥管理和分发!
简而言之,当您要将开发与操作分开时,环境变量是一种将每个服务器或每个应用程序数据移出源代码的方法。如果您已发布源代码,这尤其重要!
虽然您当然可以有一个配置文件来保存您的机密,但是如果您将机密存储在源代码中,则会遇到特殊性问题。对于每组秘密,您是否有单独的分支或存储库?您如何确保正确的机密集到达正确的服务器?还是通过使“秘密”在任何地方都是相同的(如果在一个文件中都具有可读性,则到处都是可读的)来降低安全性,从而在任何一个系统的安全控制失败时构成更大的风险?
如果要在每个服务器或每个应用程序上拥有唯一的机密,则环境变量消除了必须管理多个文件的问题。如果添加新的服务器,应用程序或角色,则不必创建新文件或更新旧文件:您只需更新相关系统的环境即可。
尽管对内核/内存/文件安全性的彻底探讨超出了此答案的范围,但值得指出的是,正确实现的每个系统环境变量的安全性不亚于“加密”机密。无论哪种情况,目标系统仍必须在某个时候将解密的机密保存在内存中才能使用它。
还值得指出的是,当值存储在给定节点上的易失性内存中时,没有磁盘上的文件可以复制和脱机攻击。通常认为这对内存中的秘密是有好处的,但是肯定不是决定性的。
与其他机密管理技术相比,环境变量的问题实际上更多地是关于安全性和可用性的权衡,而不是绝对值。你的旅费可能会改变。
就个人而言,我不建议设置环境变量,.bashrc
因为它们对于外壳程序启动的所有进程都是可见的,而是将其设置为守护程序/主管级别(init / rc脚本,systemd config),以便将它们的范围限制在需要的地方。
在由单独的团队管理操作的地方,环境变量为操作提供了一个简单的界面,以便为应用程序设置环境,而不必了解配置文件/格式和/或诉诸于其内容的处理。在多语言/多框架设置中,尤其如此,运营团队可以根据运营需求(部署简便性,可伸缩性,安全性等)选择部署系统(操作系统,主管流程)。
另一个考虑因素是CI / CD管道-代码在不同的环境中运行(即开发,测试/质量保证,分段,生产)环境细节(部署区域,数据库连接细节,凭据,IP地址,域名等)最好由专用的配置管理工具/框架进行设置,并由应用程序使用环境中的进程(在DRY中,一次写入,以任何方式运行)。传统上,开发人员倾向于管理这些运营问题,他们倾向于签入除代码之外的配置文件或模板-然后当运营需求发生变化(例如出现新的环境/部署/站点,可伸缩性/安全性)时最终会增加变通方法和其他复杂性称量体重,
对于生产,我赞成设置应用程序ENV-瓦尔在EnvironmentFile如/etc/default/myapplication.conf
由配置管理部署,并只能通过设置读取root
,使得systemd
(或任何其他为此事)可以生成一个专用下的应用非特权系统用户在私有组。用专用的用户群为后盾ops
和sudo
-这些文件不可读由世界默认。这是12因子兼容标准,支持Dev + Ops的所有优点,并具有体面安全性的所有优点,同时仍允许开发人员/测试人员在dev / qa / test环境中放入自己的EnvironmentFiles。