【问题标题】:What is the best practice for dealing with passwords in git repositories?在 git 存储库中处理密码的最佳实践是什么?
【发布时间】:2011-01-24 18:21:40
【问题描述】:

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

我想将此脚本提交到 git 存储库并在 GitHub 上提供,但我想知道在执行此操作时保持我的登录名/密码私有的最佳方法是什么。目前,密码存储在脚本本身中。我无法在推送之前将其删除,因为所有旧提交都将包含密码。没有密码的开发不是一种选择。我想我应该将密码存储在外部配置文件中,但我想在尝试将某些东西放在一起之前,我会先检查一下是否有既定的方法来处理这个问题。

【问题讨论】:

    标签: git bash security github passwords


    【解决方案1】:

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

    要从以前的提交中过滤掉您现有的密码,请参阅Removing sensitive data 上的 GitHub 帮助页面。

    【讨论】:

    • 顺便说一句,您可以将示例 foobar.config 添加到 repo,然后将 foobar.config 添加到 .ignore 文件。这样,示例 foobar.config 将在克隆时出现,并且您的实际密码不会添加到存储库中。
    • @Mr_Chimp:.gitignore 文件不适用于已在存储库中的跟踪文件。例如,git add -u 将添加一个已更改的文件,即使它已经在 .gitignore 中。
    • 作为补充,这里有一个有趣的链接,以防您不小心添加了配置文件并且想从 git 历史记录中删除它:help.github.com/articles/remove-sensitive-data
    • 您将如何与您的团队共享这些密码?一件事是拥有一个本地副本(未提交到 repo),另一件事是与更大的团队共享它,甚至使用自动工具(用于部署等)
    • 我和@dangonfast 有同样的问题。对于大型团队来说,这似乎并不实用。
    【解决方案2】:

    Greg said 什么,但我要补充一点,签入文件 foobar.config-TEMPLATE 是个好主意。

    它应该包含示例名称、密码或其他配置信息。那么真正的 foobar.config 应该包含什么就非常明显了,而无需查看所有代码,哪些值必须存在于 foobar.config 中,以及它们应该具有什么格式。

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

    【讨论】:

      【解决方案3】:

      如果您在 Rails 上使用 ruby​​,那么 Figaro gem 非常好、简单且可靠。它对生产环境的头痛系数也很低。

      【讨论】:

      • 您能否详细介绍一下该 gem 的功能?这样一来,它可以(可能)被视为适用于多种语言的“实践”。
      • medium.com/@MinimalGhost/… 有一个概述,它基本上似乎管理从配置文件中拉取东西
      【解决方案4】:

      一种方法是使用环境变量设置密码(或 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:这篇标题为"How to securely store API keys"dev.to 文章可能会很有趣。

      【讨论】:

      【解决方案5】:

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

      Ansible 还专门有一个 "Vault" feature(与 HashiCorp 产品无关)用于加密静态机密。

      【讨论】:

      • 与仅创建示例配置文件相比,我发现 Ansible Vault 确实过于复杂。
      • @icc97 是的,这很可悲。但是我们需要提到这种可能性。在我看来,对于比为单用户环境存储少量密码更复杂的任务,最好从一开始就使用专门的解决方案。
      • 为了帮助未来的读者:Vault 和 Ansible Vault 是完全不同的不相关项目,但名称相似
      【解决方案6】:

      这是我使用的一种技术:

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

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

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

      com.example.databaseconfig

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

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

      || exit 1 会导致脚本在无法加载配置文件时退出。

      我将该技术用于 bash、python 和 ant 脚本。

      我很偏执,不认为 .gitignore 文件足够强大以防止无意签入。另外,没有任何监控它,所以如果确实发生了签到,没有人会发现来处理它。

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

      【讨论】:

        【解决方案7】:

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

        1。不要这样做。

        一些回复中涵盖了避免这样做的方法 - .gitignore、config.example 等

        或 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 即可恢复加密的配置文件。

        请注意,将文件 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');
        

        您可以使用类似这样的方式解密具有加密值的配置文件。

        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 也将能够更好地管理合并和樱桃挑选等。

        但是,您越想对敏感信息进行版本控制更改,您就越倾向于安全存储库解决方案 (2) 并远离加密信息 (3) 解决方案。

        【讨论】:

          【解决方案8】:

          信任但验证。

          .gitignore 中,这将从存储库中排除“安全”目录:

          secure/
          

          但我分享@Michael Potter 的偏执狂。因此,为了验证 .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)
          

          【讨论】:

            猜你喜欢
            • 2018-07-27
            • 1970-01-01
            • 2012-04-28
            • 2011-03-21
            • 2011-05-27
            • 2014-12-18
            • 1970-01-01
            • 2015-09-21
            • 1970-01-01
            相关资源
            最近更新 更多