如何在我的版本控制系统中安全地保存我的密钥和密码?

Chr*_* W. 131 python git django version-control

我在我的版本控制系统中保留了开发和生产服务器的主机名和端口等重要设置.但我知道将秘密(如私钥和数据库密码)保存在VCS存储库中是不好的做法.

但是密码 - 就像任何其他设置一样 - 似乎应该是版本化的.那么保持密码版本控制的正确方法什么?

我想这将涉及将秘密保存在他们自己的"秘密设置"文件中,并对该文件进行加密和版本控制.但是什么技术呢?以及如何正确地做到这一点?还有更好的办法吗?


我一般都会问这个问题,但在我的具体实例中,我想使用gitgithub存储Django/Python站点的密钥和密码.

此外,当我使用git推/拉时,理想的解决方案会做一些神奇的事情 - 例如,如果加密的密码文件发生更改,则会运行一个脚本,要求输入密码并将其解密到位.


编辑:为清楚起见,我正在询问在哪里存储的生产秘密.

dgh*_*dgh 98

您仍然希望加密敏感设置文件,同时仍然在版本控制中维护文件.正如您所提到的,最好的解决方案是Git会在您推送它们时透明地加密某些敏感文件,以便在本地(即在任何拥有您的证书的计算机上)您可以使用设置文件,但Git或Dropbox或任何人在VC下存储文件无法以纯文本格式读取信息.

推/拉期间透明加密/解密教程

这个要点https://gist.github.com/873637显示了如何使用Git的涂抹/清除过滤器驱动程序和openssl来透明地加密推送文件的教程.你只需要做一些初始设置.

它的工作原理摘要

您基本上将创建一个.gitencrypt包含3个bash脚本的文件夹,

clean_filter_openssl 
smudge_filter_openssl 
diff_filter_openssl 
Run Code Online (Sandbox Code Playgroud)

Git用于解密,加密和支持Git diff.在这些脚本中定义了主密码和盐(固定!),您必须确保实际上不会推送.gitencrypt.示例clean_filter_openssl脚本:

#!/bin/bash

SALT_FIXED=<your-salt> # 24 or less hex characters
PASS_FIXED=<your-passphrase>

openssl enc -base64 -aes-256-ecb -S $SALT_FIXED -k $PASS_FIXED
Run Code Online (Sandbox Code Playgroud)

类似于smudge_filter_open_ssldiff_filter_oepnssl.见Gist.

具有敏感信息的repo应该有一个.gitattribute文件(未加密并包含在repo中),该文件引用.gitencrypt目录(其中包含Git透明地加密/解密项目所需的所有内容)以及本地计算机上存在的目录.

.gitattribute 内容:

* filter=openssl diff=openssl
[merge]
    renormalize = true
Run Code Online (Sandbox Code Playgroud)

最后,您还需要将以下内容添加到您的.git/config文件中

[filter "openssl"]
    smudge = ~/.gitencrypt/smudge_filter_openssl
    clean = ~/.gitencrypt/clean_filter_openssl
[diff "openssl"]
    textconv = ~/.gitencrypt/diff_filter_openssl
Run Code Online (Sandbox Code Playgroud)

现在,当您将包含敏感信息的存储库推送到远程存储库时,文件将被透明加密.从具有.gitencrypt目录(包含密码)的本地计算机中提取时,文件将被透明地解密.

笔记

我应该注意,本教程没有描述仅加密敏感设置文件的方法.这将透明地加密推送到远程VC主机的整个存储库并解密整个存储库,以便在本地完全解密.要实现所需的行为,可以将一个或多个项目的敏感文件放在一个sensitive_settings_repo中.如果您确实需要敏感文件位于同一个存储库中,您可以研究这种透明加密技术如何与Git子模块协同工作http://git-scm.com/book/en/Git-Tools-Submodules.

如果攻击者可以访问许多加密的存储库/文件,那么使用固定密码短语理论上可能会导致暴力漏洞.IMO,这个概率非常低.如本教程底部的注释所述,不使用固定密码短语将导致不同计算机上的本地版本的repo始终显示"git status"发生了更改.


Col*_*nic 52

Heroku推动使用环境变量进行设置和密钥:

处理此类配置变量的传统方法是将它们放在源代码下 - 在某种属性文件中.这是一个容易出错的过程,对于开源应用来说尤其复杂,因为开源应用通常需要使用特定于应用的配置来维护单独的(和私有的)分支.

更好的解决方案是使用环境变量,并将密钥保留在代码之外.在传统主机上或在本地工作,您可以在bashrc中设置环境变量.在Heroku上,您使用配置变量.

使用Foreman和.env文件Heroku提供了令人羡慕的工具链来导出,导入和同步环境变量.


就个人而言,我认为将密钥与代码一起保存是错误的.它与源代码控制基本上不一致,因为密钥用于代码的外部服务.一个好处是开发人员可以克隆HEAD并运行应用程序而无需任何设置.但是,假设开发人员签出了代码的历史修订版.他们的副本将包括去年的数据库密码,因此应用程序将在今天的数据库中失败.

使用上面的Heroku方法,开发人员可以查看去年的应用程序,使用今天的密钥配置它,并在今天的数据库中成功运行它.

  • 因此,如果在bashrc中设置了环境变量,并且您正在部署新服务器,那么创建bashrc的是什么?这不仅仅是将密码从源代码仓库中移出并进入部署配置吗?(大概也是在源代码回购中,或者在自己的回购中?) (10认同)
  • 对不起,我的评论含糊不清,但那是因为我真的很困惑.我喜欢这个答案的观点,但从未完全理解它.如果我正在部署到几个不同的环境,每个环境包含多个主机,也许包含几种类型的主机,那么显然我需要自动创建将存在于每个主机上的.bashrc文件以设置其环境变量.所以答案是说我应该有一个*second*repo,与我的源代码分开,其中包含在部署时将成为.bashrc环境变量的所有设置? (3认同)

Sam*_*ane 16

我认为最干净的方法是使用环境变量.例如,您不必处理.dist文件,生产环境中的项目状态将与本地计算机相同.

如果你有兴趣,我建议你阅读The Twelve-Factor App的配置章节,其他章节.

  • 似乎环境变量是使用秘密设置运行应用程序的好方法......但它仍然无法回答在哪里*保持*这些设置的问题. (6认同)
  • @Samy:如果你自动部署了? (4认同)
  • @Samy我仍然不明白如何设置环境变量.12因素应用程序页面也没有说清楚(除非你在Heroku上,我当前的项目不是.)我们是说生成脚本需要询问中央配置存储"我是机器X,请给我我的配置数据",并响应应该设置的环境变量的值.在这种情况下,我不认为*你需要一个生成的脚本了.我在这里疯狂地猜测,我正在咆哮着正确的树吗? (3认同)
  • 您通常应该为每个应用程序提供自述文件.在那里,指定应设置哪些环境变量,每次部署项目时,只需按照步骤设置每个环境变量即可.您还可以使用许多`export MY_ENV_VAR =`创建一个shell脚本,在部署时,只需使用正确的值和`source`填充它.如果通过*keep*你的意思是设置的版本,你不应该首先这样做. (2认同)

sch*_*eck 10

一个选项是将项目绑定的凭据放入加密容器(TrueCrypt或Keepass)并推送它.

更新以下评论的答案:

有趣的问题btw.我刚刚发现这个:github.com/shadowhand/git-encrypt看起来非常有希望进行自动加密

  • 有趣的问题btw.我刚刚发现这个:https://github.com/shadowhand/git-encrypt看起来非常有希望进行自动加密. (7认同)

tik*_*tak 9

我建议使用配置文件,不要对它们进行版本控制.

但是,您可以对文件进行版本示例.

我没有看到共享开发设置的任何问题.根据定义,它应该不包含有价值的数据.


Chr*_* W. 7

BlackBox最近由StackExchange发布,虽然我还没有使用它,但它似乎正好解决了这个问题,并支持这个问题所要求的功能.

https://github.com/StackExchange/blackbox上的描述:

安全地将秘密存储在VCS仓库(即Git或Mercurial)中.这些命令使您可以轻松地对GPG中的特定文件进行加密,以便在存储库中"静态加密".但是,当您需要查看或编辑脚本并将其解密以供在生产中使用时,脚本可以轻松解密它们.


Chr*_* W. 6

自从提出这个问题以来,我已经找到了一个解决方案,我在与小团队开发小型应用程序时使用了这个解决方案.

混帐隐窝

git-crypt使用GPG在名称与某些模式匹配时透明地加密文件.对于intance,如果你添加到你的.gitattributes文件......

*.secret.* filter=git-crypt diff=git-crypt
Run Code Online (Sandbox Code Playgroud)

...然后一个文件config.secret.json将始终通过加密推送到远程存储库,但在本地文件系统上保持未加密状态.

如果我想在您的仓库中添加一个新的GPG密钥(一个人),可以解密受保护的文件,然后运行git-crypt add-gpg-user <gpg_user_key>.这会创建一个新的提交.新用户将能够解密后续提交.


Hed*_*ide 5

我一般都会问这个问题,但在我的具体实例中,我想使用git和github存储Django/Python站点的密钥和密码.

不,只是不要,即使它是你的私人回购,你永远不打算分享,不要.

您应该创建一个local_settings.py,将它放在VCS上忽略,并在settings.py中执行类似的操作

from local_settings import DATABASES, SECRET_KEY
DATABASES = DATABASES

SECRET_KEY = SECRET_KEY
Run Code Online (Sandbox Code Playgroud)

如果你的秘密设置是多才多艺的,我很想说你做错了什么

  • 但我仍然需要在某个地方跟踪那些秘密*.例如,keypass或其他东西,对吧? (8认同)