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

I would like to commit this script to the git repo and make it available on GitHub, but I'm wondering what the best way to keep my login/password private while doing this is. Currently, the password is stored in the script itself. I can't remove it right before I push because all the old commits will contain the password. Developing without a password isn't an option. I imagine that I should be storing the password in an external config file, but I thought I'd check to see if there was an established way to handle this before I tried and put something together.


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

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


Greg说的,但我想补充的是,签入文件foobar.config-TEMPLATE是个好主意。

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

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


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


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

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

export your_env_variable='your_password'

这种方法可以与Travis这样的持续集成服务一起使用,你存储在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 Vault来保护、存储和控制对令牌、密码、证书、API密钥等的访问。

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


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

我在我的主文件夹中创建了一个名为: config

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

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

com.example.databaseconfig

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

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

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

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

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

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


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

1. 不要这样做。

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

.gitignore:存储在服务器等,而不是Git(弱解决方案) 环境变量:https://stackoverflow.com/a/30664318/3070485 配置。例如:https://stackoverflow.com/a/2397905/3070485 命令行参数:程序启动时手动输入密码

或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);

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

注意,放置一个文件配置。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');

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

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

将每个配置项放在单独的行中(例如上面的Hello和Goodbye), 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)

Is there any possibility to tell github to track the file under a different name? Example: Locally, I have a file passwords.config with real passwords, and sample-passwords.config with stubs. However, in public repo, I'd like to have only passwords.config with content from sample-passwords.config and real passwords.config ignored. I know .gitignore, which can hide my passwords.config, but I don't know is there any solution to rename sample-passwords.config while commiting to remote public repo. Of course, I'd like to avoid situation, when my local repo tracks renamed file as if something changed in git status.