在git存储库中处理密码的最佳实践是什么?

我有一个小Bash脚本,我用它来访问twitter,并在某些情况下弹出咆哮通知。用脚本存储密码的最佳方法是什么?

我想将这个脚本提交到git回购,并使其在GitHub上可用,但我想知道在这样做的时候,保持我的登录名/密码私密性的最佳方法是什么。目前,密码存储在脚本本身中。我不能在我推送之前删除它,因为所有旧的提交都会包含密码。在没有密码的情况下进行开发是行不通的。我想我应该将密码存储在一个外部配置文件中,但我想在尝试整合之前,我应该检查一下是否有既定的方法来处理这个问题。

122997 次浏览

实现这一点的典型方法是从配置文件中读取密码信息。如果您的配置文件名为foobar.config,那么您将向存储库提交一个名为foobar.config.example的文件,其中包含示例数据。要运行你的程序,你需要用你的真正的密码数据创建一个名为foobar.config的本地(不跟踪)文件。

要从以前的提交中过滤掉你现有的密码,请参阅GitHub的帮助页面删除敏感数据

什么格雷格说,但我要补充的是,签入文件foobar.config-TEMPLATE是一个好主意。

它应该包含示例名称、密码或其他配置信息。那就很明显什么才是真正的傻瓜了。config应该包含,而不必在所有代码中查找必须在foobar.config中显示哪些值以及它们应该具有什么格式。

通常配置值可以是不明显的,如数据库连接字符串和类似的东西。

如果您正在使用ruby on rails,费加罗宝石非常好,简单,可靠。它在生产环境中也没有什么令人头痛的因素。

一种方法是使用环境变量设置密码(或API密钥)。 所以这个密码不受修改控制。< / p >

使用Bash,您可以使用来设置环境变量

export your_env_variable='your_password'

这种方法可以用于持续集成服务,如特拉维斯,你的代码(没有密码)存储在GitHub存储库可以由Travis执行(你的密码是使用环境变量设置)。

使用Bash,你可以使用以下命令获取环境变量的值:

echo "$your_env_variable"

使用Python,你可以使用以下命令获取环境变量的值:

import os
print(os.environ['your_env_variable'])

PS:注意这可能有点冒险(但这是一种相当常见的做法)https://www.bleepingcomputer.com/news/security/javascript-packages-caught-stealing-environment-variables/

PS2:这篇名为“如何安全地储存API密钥”dev.to文章可能会很有趣。

可以使用HashiCorp库来保护、存储和控制对令牌、密码、证书、API密钥等的访问。

Ansible特别有一个“Vault"功能(与HashiCorp产品无关)用于加密静止的秘密。

下面是我使用的一个技巧:

我在我的主文件夹中创建了一个名为: .config < / p >

在这个文件夹中,我放置了我想外部化密码和密钥的任何数量的配置文件。

我通常使用反向域名语法,例如:

com.example.databaseconfig

然后在bash脚本中我这样做:

#!/bin/bash
source $HOME/.config/com.example.databaseconfig ||exit 1

如果无法加载配置文件,|| exit 1将导致脚本退出。

我在bash、python和ant脚本中使用了这种技术。

我很偏执,认为.gitignore文件不够健壮,无法防止无意签入。此外,没有任何监控机制,所以即使发生了签入,也没有人会发现如何处理它。

如果一个特定的应用程序需要一个以上的文件,我创建子文件夹而不是一个单一的文件。

根据您的具体问题,可以以不同的方式处理存储库中的密码。

1. 不要这样做。

避免这样做的方法包括在一些回复- .gitignore, config。例子中,等

或2。使存储库仅对授权的人访问

即允许知道密码的人。chmod和用户组出现在脑海中;还有一些问题,比如如果你在外部托管存储库或服务器,Github或AWS员工是否应该被允许查看内容?

或3。加密敏感数据(回复的目的)

如果您想将包含敏感信息(如密码)的配置文件存储在公共位置,则需要对其进行加密。这些文件可以在从存储库中恢复时解密,甚至可以直接从其加密形式中使用。

下面是使用加密配置数据的javascript解决方案示例。

const fs = require('fs');
const NodeRSA = require('node-rsa');


let privatekey = new NodeRSA();
privatekey.importKey(fs.readFileSync('private.key', 'utf8'));
const config = privatekey.decrypt(fs.readFileSync('config.RSA', 'utf8'), 'json');


console.log('decrypted: ', config);

Decrypted Config File

因此,只需编写几行Javascript就可以恢复加密的配置文件。

请注意,将文件config.RSA放入git存储库将有效地使其成为二进制文件,因此它将失去像git这样的许多好处,例如能够对其进行筛选更改。

解决方案可能是加密键值对或仅加密值。您可以加密所有值,例如,如果您有一个单独的敏感信息文件,或者如果您在一个文件中有所有值,则只加密敏感值。(见下文)

我上面的例子对于任何想要用它进行测试的人来说都有点无用,或者作为一个开始的例子,因为它假设存在一些RSA密钥和一个加密的配置文件config.RSA

因此,这里添加了一些额外的代码行来创建RSA密钥和一个配置文件。

const fs = require('fs');
const NodeRSA = require('node-rsa');


/////////////////////////////
// Generate some keys for testing
/////////////////////////////


const examplekey = new NodeRSA({b: 2048});


fs.writeFileSync('private.key', examplekey.exportKey('pkcs8-private'));
fs.writeFileSync('public.key', examplekey.exportKey('pkcs8-public'));


/////////////////////////////
// Do this on the Machine creating the config file
/////////////////////////////


const configToStore = {Goodbye: 'Cruel world'};


let publickey = new NodeRSA();
publickey.importKey(fs.readFileSync('public.key', 'utf8'));


fs.writeFileSync('config.RSA', publickey.encrypt(configToStore, 'base64'), 'utf8');


/////////////////////////////
// Do this on the Machine consuming the config file
/////////////////////////////


let privatekey = new NodeRSA();
privatekey.importKey(fs.readFileSync('private.key', 'utf8'));


const config = privatekey.decrypt(fs.readFileSync('config.RSA', 'utf8'), 'json');
console.log('decrypted: ', config);

只加密值

fs.writeFileSync('config.RSA', JSON.stringify(config,null,2), 'utf8');

enter image description here

您可以使用类似这样的方法对带有加密值的配置文件进行解密。

const savedconfig = JSON.parse(fs.readFileSync('config.RSA', 'utf8'));
let config = {...savedconfig};
Object.keys(savedconfig).forEach(key => {
config[key] = privatekey.decrypt(savedconfig[key], 'utf8');
});

将每个配置项放在单独的行中(例如上面的HelloGoodbye), Git将更好地识别文件中正在发生的事情,并将信息项的更改存储为差异而不是完整的文件。Git也将能够更好地管理合并和樱桃采摘等。

然而,你越想对敏感信息进行版本控制,你就越倾向于使用SAFE REPOSITORY解决方案(2),而远离加密INFO(3)解决方案。

信任,但要核实。

.gitignore中,这将从repo中排除一个“安全”目录:

secure/

但我和@迈克尔•波特一样偏执。因此,为了验证.gitignore,这里有一个Python 单元测试,如果这个“安全”目录被检入,它将发出一个喇叭。为了检查检查,也要测试一个合法的目录:

def test_github_not_getting_credentials(self):
safety_url = 'https://github.com/BobStein/fliki/tree/master/static'
danger_url = 'https://github.com/BobStein/fliki/tree/master/secure'


self.assertEqual(200, urllib.request.urlopen(safety_url).status)


with self.assertRaises(urllib.error.HTTPError):
urllib.request.urlopen(danger_url)
是否有可能告诉github以不同的名称跟踪文件? 示例:在本地,我有一个文件passwords.config,其中包含真实密码,sample-passwords.config中包含存根。然而,在公共回购中,我希望只有passwords.config,内容来自sample-passwords.config,而真正的passwords.config被忽略。 我知道.gitignore,它可以隐藏我的passwords.config,但我不知道是否有任何解决方案可以在提交远程公共回购时重命名sample-passwords.config。 当然,我想避免这种情况,当我的本地回购跟踪重命名的文件时,就好像git status中发生了什么变化