git 服务器/数据库配置文件(包括密码)是否应该存储在源代码管理中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4243174/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 04:45:57  来源:igfitidea点击:

Should server/database config files, including passwords, be stored in source control?

svngitversion-controlpasswordsconfig

提问by philfreo

I'm looking to hear some best practices...

我想听听一些最佳实践...

Assuming a web application that interacts with a few different production servers (databases, etc.)... should the configuration files that include database passwords be stored in source control (e.g., git, svn)?

假设一个 web 应用程序与几个不同的生产服务器(数据库等)交互......包含数据库密码的配置文件是否应该存储在源代码管理中(例如,git、svn)?

If not, what's the best way to keep track of server database (or other related) passwords that your application needs access to?

如果没有,跟踪您的应用程序需要访问的服务器数据库(或其他相关)密码的最佳方法是什么?

Edit:added a bounty to encourage more discussion and to hear what more people consider best practice.

编辑:添加赏金以鼓励更多讨论并听取更多人认为最佳实践的内容。

采纳答案by GreyCat

There's no single "silver bullet" answer here and it would all greatly depend on details.

这里没有单一的“银弹”答案,这在很大程度上取决于细节。

First of all, I consider best practice to separate all source code from configuration in separate repository. So, source code remains source code, but it's installation or deployment (with configuration, passwords, etc) is the whole other thing. This way you'll firmly separate developers' tasks from sysadmins' tasks and can ultimately build 2 distinct teams doing what's they're good at.

首先,我认为最佳实践是将所有源代码与单独存储库中的配置分开。所以,源代码仍然是源代码,但它的安装或部署(带有配置、密码等)是另一回事。通过这种方式,您可以将开发人员的任务与系统管理员的任务牢固地分开,并最终可以建立 2 个不同的团队,做他们擅长的事情。

When you have separate source code repository + deployment repository, your best next bet is considering deployment options. Best way I see here is using deployment procedures typical for a chosen OS (i.e. building autonomous packages for a chosen OS the way that OS's maintainers do).

当您拥有单独的源代码存储库 + 部署存储库时,您最好的下一个选择是考虑部署选项。我在这里看到的最好方法是使用所选操作系统的典型部署程序(即,按照操作系统维护人员的方式为所选操作系统构建自治包)。

For example, Red Hat or Debian packaging procedures usually mean grabbing a tarball of software from external site (that would be exporting sources from your source code VCS), unpacking it, compiling and preparing packages ready for deployment. Deployment itself should ideally mean just doing a quick & simple command that would install the packages, such as rpm -U package.rpm, dpkg --install package.debor apt-get dist-upgrade(given that your built packages go to a repository where apt-get would be able to find them).

例如,Red Hat 或 Debian 打包程序通常意味着从外部站点获取软件 tarball(即从源代码 VCS 导出源代码)、解包、编译和准备准备部署的包。理想情况下,部署本身应该意味着只执行一个快速简单的命令来安装软件包,例如rpm -U package.rpm,dpkg --install package.debapt-get dist-upgrade(假设您构建的软件包转到 apt-get 能够找到它们的存储库)。

Obviously, to get it working this way, you'll have to supply all configuration files for all components of a system in a fully working state, including all addresses and credentials.

显然,要使其以这种方式工作,您必须为处于完全工作状态的系统的所有组件提供所有配置文件,包括所有地址和凭据。

To get more concise, let's consider a typical "small service" situation: one PHP application deployed across napplication servers running apache / mod_php, accessing mMySQL servers. All these servers (or virtual containers, that doesn't really matter) reside in a protected private network. To make this example easier, let's assume that all real internet connectivity is fronted by a cluster of khttp accelerators / reverse proxies (such as nginx / lighttpd / apache) which have very easy configuration (just internal IPs to forward to).

为了更简洁,让我们考虑一个典型的“小服务”情况:一个 PHP 应用程序部署在运行 apache/mod_php 的n 个应用程序服务器上,访问m 个MySQL 服务器。所有这些服务器(或虚拟容器,这并不重要)都驻留在受保护的专用网络中。为了让这个例子更简单,让我们假设所有真实的互联网连接都由k 个http 加速器/反向代理(例如 nginx/lighttpd/apache)组成,它们具有非常简单的配置(只是要转发到的内部 IP)。

What do we have for them to be connected and fully working?

我们有什么东西可以让他们连接起来并充分工作?

  • MySQL servers: set up IPs/hostnames, set up databases, provide logins & passwords
  • PHP application: set up IPs/hostnames, create configuration file that will mention MySQL servers IPs, logins, passwords & databases
  • MySQL 服务器:设置 IP/主机名、设置数据库、提供登录名和密码
  • PHP 应用程序:设置 IP/主机名,创建将提及 MySQL 服务器 IP、登录名、密码和数据库的配置文件

Note that there are 2 different "types" of information here: IPs/hostnames is something fixed, you'd likely want to assign them once and for all. Logins & passwords (and even database names), on the other hand, are purely for connectivity purposes here - to make sure for MySQL that it's really our PHP application connecting to it. So, my recommendations here would be splitting these 2 "types":

请注意,这里有 2 种不同的“类型”信息:IP/主机名是固定的,您可能希望一劳永逸地分配它们。另一方面,登录名和密码(甚至数据库名称)在这里纯粹是为了连接目的 - 确保 MySQL 确实是我们的 PHP 应用程序连接到它。所以,我在这里的建议是将这两种“类型”分开:

  • "Permanent" information, such as IPs, should be stored in some VCS (different from source code VCS)
  • "Transient" information, such as passwords between 2 applications, should be never stored, but generated during generation of deployment packages.
  • “永久”信息,例如IP,应该存储在一些VCS中(与源代码VCS不同)
  • “瞬态”信息,例如 2 个应用程序之间的密码,不应存储,而是在生成部署包期间生成。

The last and the toughest question remains here: how to create deployment packages? There are multiple techniques available, 2 main ways are:

最后一个也是最棘手的问题仍然存在:如何创建部署包?有多种技术可用,两种主要方法是:

  • Exported source code from VCS1 + "permanent" configuration from VCS2 + building script from VCS3 = packages
  • Source code is in VCS1; VCS2 is a distributed version control (like git or hg) which essentially contains "forks" of VCS1 + configuration information + building scripts which can generate . I personally like this approach better, it's much shorter and ultimately easier to use, but learning curve may be a bit steeper, especially for admin guys who'll have to master git or hg for it.
  • 从 VCS1 导出的源代码 + 从 VCS2 的“永久”配置 + 从 VCS3 的构建脚本 = 包
  • 源代码在 VCS1 中;VCS2 是一个分布式版本控制(如 git 或 hg),它本质上包含 VCS1 + 配置信息 + 构建脚本的“分支”,可以生成 . 我个人更喜欢这种方法,它更短,最终更容易使用,但学习曲线可能有点陡峭,尤其是对于必须掌握 git 或 hg 的管理员。

For an example above, I'd create packages like:

对于上面的示例,我将创建如下包:

  • my-application-php- which would depend on mod_php, apache and would include generated file like /etc/my-php-application/config.inc.phpthat will include MySQL database IPs/hostnames and login / password generated as md5(current source code revision + salt). This package would be installed on every of napplication servers. Ideally, it should be able install on a cleanly installed OS and make a fully working application cluster node without any manual activity.
  • my-application-mysql- which would depend on MySQL-server and would include post-install script that:
    • starts MySQL server and makes sure it will start automatically on OS start
    • connects to MySQL server
    • checks if required database exists
    • if no - creates the database, bootstraps it with contents and creates login with password (the same logins & passwords as generated in /etc/my-php-application/config.inc.php, using md5 algorithm)
    • if yes - connects to the database, applies migrations to bring it up to the new version, kills all older logins / passwords and recreates the new login/password pair (again, generated using md5(revision + salt) method)
  • my-application-php- 这将取决于 mod_php、apache 并且将包含生成的文件,例如/etc/my-php-application/config.inc.php将包含 MySQL 数据库 IP/主机名和登录名/密码生成为md5(current source code revision + salt). 该软件包将安装在n 个应用程序服务器中的每一个上。理想情况下,它应该能够安装在干净安装的操作系统上,并在没有任何手动操作的情况下创建一个完全工作的应用程序集群节点。
  • my-application-mysql- 这将取决于 MySQL-server 并且将包括安装后脚本:
    • 启动 MySQL 服务器并确保它会在操作系统启动时自动启动
    • 连接到 MySQL 服务器
    • 检查所需的数据库是否存在
    • 如果没有 - 创建数据库,使用内容引导它并使用密码创建登录名(与 中生成的登录名和密码相同/etc/my-php-application/config.inc.php,使用 md5 算法)
    • 如果是 - 连接到数据库,应用迁移以将其升级到新版本,删除所有旧的登录名/密码并重新创建新的登录名/密码对(再次,使用 md5(revision + salt) 方法生成)

Ultimately, it should bring the benefit of upgrading your deployment using single command like generate-packages && ssh-all apt-get dist-upgrade. Also, you do not store inter-applications passwords anywhere and they get regenerated on every update.

最终,它应该带来使用单个命令(如generate-packages && ssh-all apt-get dist-upgrade. 此外,您不会在任何地方存储应用程序间密码,它们会在每次更新时重新生成。

This fairly simple example illustrates a lot of methods you can employ here - but, ultimately, it's up to you to decide which solution is better here and which one is overkill. If you'll put more details here or as a separate question, I'll gladly try to get into details.

这个相当简单的示例说明了您可以在此处使用的许多方法 - 但最终,由您决定哪种解决方案在这里更好,哪个解决方案过大。如果您将在此处或作为单独的问题提供更多详细信息,我将很乐意尝试深入了解细节。

回答by paxdiablo

Leaving aside the point that passwords should never be stored in plain text anywhere(other than someone's cranium or a locked vault accessible only to the CEO, CFO and CIO (and needing all three keys at once)), you should store everything into source control that's required to buildyour product.

撇开密码永远不应该以纯文本形式存储在任何地方的观点(除了某人的头骨或只有 CEO、CFO 和 CIO 才能访问的锁定保险库(并且同时需要所有三个密钥)),您应该将所有内容存储到源代码控制中这是构建您的产品所必需的。

That means not just your source, but even the specifications for the build machines, compiler options, the compilers themselves and so on.

这不仅意味着您的源代码,还意味着构建机器的规范、编译器选项、编译器本身等等。

If we could find a way to check in the physical hardware, we'd do that too :-)

如果我们能找到一种方法来检查物理硬件,我们也会这样做:-)

Everything that can be reproduced by the build process itself, or anything for runningrather than building the software (such as your passwords) does not generally belong under source control but some shops will do that for their executables, generated docs and so on, just so that they can quickly get a specific release out for installation.

构建过程本身可以复制的所有内容,或用于运行而不是构建软件的任何内容(例如您的密码)通常不属于源代码管理,但有些商店会为他们的可执行文件、生成的文档等执行此操作,只是以便他们可以快速获取特定版本进行安装。

回答by Richard Harrison

Passwords should not be stored in source control. At all. Ever. See How to keep secrets secret

密码不应存储在源代码管理中。在所有。曾经。看看如何保守秘密

Passwords, servernames, etc. are part of the deployment configuration as performed by the server administrator. It is essential to document this procedure and place the documented procedure under control.

密码、服务器名称等是服务器管理员执行的部署配置的一部分。必须记录此程序并将文件化程序置于控制之下。

Alternatively the deployment configuration could be performed by a script that the sysadmin would run to perform the configuration, and during the script execution it would ask the sysadmin to provide the required information. Again this script must be kept in version control.

或者,部署配置可以由系统管理员运行以执行配置的脚本执行,并且在脚本执行期间它会要求系统管理员提供所需的信息。同样,此脚本必须保留在版本控制中。

Everything else, apart from server configuration mustbe in source control.

除了服务器配置之外,其他一切都必须在源代码管理中。

Storing server configuration in source control is generally a bad idea because it gets in the way of deployments and can cause small disasters (e.g. when someone doesn't realise that their test version deployed from source control is communicating with a live service).

在源代码管理中存储服务器配置通常是一个坏主意,因为它会妨碍部署并可能导致小灾难(例如,当有人没有意识到从源代码管理部署的测试版本正在与实时服务通信时)。

Always keep these configuration files outside of the webroot.

始终将这些配置文件保存在 webroot 之外。

Trusted connections may be an option, allowing known IP addresses to connect to services by configuration of that service..

可信连接可能是一个选项,允许已知 IP 地址通过该服务的配置连接到服务。

回答by Marnix van Valen

In general, I agree with paxdiablo: put everything you possibly can under source control. That includes production configuration files with database credentials.

总的来说,我同意 paxdiablo:将所有可能的东西置于源代码控制之下。这包括具有数据库凭据的生产配置文件。

Think about the situation where your server crashes, the backups turn out to be bad and you need to get that server back up. I think you and your customer (or boss) would definitely agree that having everything needed to deploy the site in source control is a big plus.

想想您的服务器崩溃的情况,备份结果很糟糕,您需要备份该服务器。我认为您和您的客户(或老板)肯定会同意在源代码控制中部署站点所需的一切是一个很大的优势。

If you want to build easily deployable packages from your sources using continuous integration (another best practice) you'll have to put the configuration files under source control.

如果您想使用持续集成(另一个最佳实践)从源代码构建易于部署的包,则必须将配置文件置于源代码控制之下。

Also consider that in most cases the devs that have source control access cannot access the production database server directly. The production passwords are useless to them.

还要考虑在大多数情况下,具有源代码控制访问权限的开发人员无法直接访问生产数据库服务器。生产密码对他们来说毫无用处。

If the wrong people gained access to your sources, they still need to gain access to the production server in order to do harm with the passwords. So, if your production environment is properly protected, the security risks of passwords in source control are very limited.

如果错误的人获得了您的资源的访问权限,他们仍然需要获得对生产服务器的访问权限,以便对密码造成危害。因此,如果您的生产环境得到适当的保护,源代码控制中密码的安全风险是非常有限的。

回答by 8DH

I think this question is more about information ownership, trust and organization. You should ask yourself, what part of your organization would you trust to keep your system passwords safe from disclosure and misuse?

我认为这个问题更多的是关于信息所有权、信任和组织。您应该问问自己,您信任组织的哪一部分来保护您的系统密码免遭泄露和滥用?

I've been in organizations where they were kept by the people responsible for the business. In others they've been delegated to the operations team that also owned the processes around creation and usage etc.

我曾在那些由负责业务的人管理的组织中工作过。在其他情况下,他们被委派给运营团队,运营团队也拥有创建和使用等流程。

The most important thing is that it is clearly defined in your organization who should have access to system passwords. After that you can decide on appropriate technical solutions for protecting the passwords.

最重要的是,在您的组织中明确定义了谁应该有权访问系统密码。之后,您可以决定适当的技术解决方案来保护密码。

回答by Linus Kleen

In my Subversion repos for PHP, configuration files that contain passwords are checked in as config.php.samplewith hints to what has to be provided and scripts relying require a config.phpto be present at the same location.

在我的 PHP 的 Subversion 存储库中,包含密码的配置文件被检入,config.php.sample并提示必须提供的内容,并且依赖的脚本要求 aconfig.php出现在同一位置。

The repository is configured to ignore config.phpfor that directory to avoid "accidental" adds or check-ins.

存储库配置为忽略config.php该目录以避免“意外”添加或签入。

回答by user502515

Sample configurations file, sure, I would put them under version control. But usually not with realworld access data such as server addresses or passwords. More somethinglike

示例配置文件,当然,我会将它们置于版本控制之下。但通常不会使用真实世界的访问数据,例如服务器地址或密码。更多类似

# program.conf
#
# mysql option for $myprog.
#
#SERVER_ADDR=127.0.0.1
#SERVER_USER=mysql
#SERVER_PASSWD=abcdef

回答by Jinesh Parekh

No. Production password should be configured directly on the server. You should create a deployment instructions for the deployment team/person to change the right properties file during deployment.

否。生产密码应直接在服务器上配置。您应该为部署团队/人员创建部署说明,以在部署期间更改正确的属性文件。

回答by dietbuddha

Problems with passwords in source code:

源代码密码问题:

  • hard to vary from one deployment to another (I don't want to have to modify source code in production)
  • increased likelyhood of accidentally corrupting production database when doing development
  • security issue (in most shops there is no reason for code/developers to know prod passwords)
  • changed password requires redeployment
  • 很难从一个部署到另一个部署(我不想在生产中修改源代码)
  • 在进行开发时意外损坏生产数据库的可能性增加
  • 安全问题(在大多数商店中,代码/开发人员没有理由知道产品密码)
  • 更改密码需要重新部署

What I have found works the best is having a config checked in that uses mixture sane defaults and placeholders for deployment specific data. Our apps always look for a system config which allows the override of any variable. This allows the production machine to have a config appropriate for it's deployment.

我发现最有效的是检查配置,该配置使用混合理智的默认值和占位符用于部署特定数据。我们的应用程序总是寻找允许覆盖任何变量的系统配置。这允许生产机器拥有适合其部署的配置。

Note: When I function as an admin I always manage configs separately from code (for good reason).

注意:当我作为管理员时,我总是将配置与代码分开管理(有充分的理由)。

回答by Steve Clay

Without a proper build process, I'm using this strategy (for PHP apps):

没有适当的构建过程,我正在使用此策略(对于 PHP 应用程序):

  1. Make a folder /etc/companyname
  2. In it, place two files:

    <?php // env.php
    return 'prod'; 
    
    <?php // appname-prod.php
    return array(
      'db' => array( /* credentials */ ),
      /* other host-specific conf data */
    ); 
    
  3. Make both files readable only by your PHP process

  1. 制作文件夹 /etc/companyname
  2. 在其中放置两个文件:

    <?php // env.php
    return 'prod'; 
    
    <?php // appname-prod.php
    return array(
      'db' => array( /* credentials */ ),
      /* other host-specific conf data */
    ); 
    
  3. 使这两个文件只能由您的 PHP 进程读取

Now your app's config file will be something like:

现在您的应用程序的配置文件将类似于:

<?php // config.php
$env = (require "/etc/companyname/env.php");
$creds = (require "/etc/companyname/appname-{$env}.php");

With this in place, the environment defines the credentials used, and you can move code between pre-configured environments (and control some options with $env). This, of course, can be done with server environment variables, but this a) is simpler to setup and b) doesn't expose credentials to every script on the server (won't show up in a stray debugging junk like phpinfo()).

有了这个,环境定义了使用的凭据,您可以在预配置的环境之间移动代码(并使用 控制一些选项$env)。当然,这可以使用服务器环境变量来完成,但是 a) 设置起来更简单,并且 b) 不会向服务器上的每个脚本公开凭据(不会出现在像 那样的杂散调试垃圾中phpinfo())。

For easier reading outside PHP you could make the credential files JSON or something and just put up with the tiny performance hit (APC won't cache them).

为了在 PHP 之外更容易阅读,您可以制作凭证文件 JSON 或其他东西,然后忍受微小的性能损失(APC 不会缓存它们)。