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

I am looking to hear some best practices ...

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

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

Edit: added generosity to encourage more discussion and find out what more people consider best practice.

+48
git version-control svn passwords config
Nov 22 '10 at 7:22
source share
13 answers

There is no single "silver bullet", and all this will greatly depend on the details.

First of all, I believe that it is best to separate the entire source code from the configuration in a separate repository. Thus, the source code remains the source code, but its installation or deployment (with configuration, passwords, etc.) is all the rest. Thus, you will decisively separate the tasks of the developers from the tasks of sysadmins and you will be able to eventually create two excellent teams that do what is good for them.

When you have a separate source code repository + deployment repository, your best next bet is considering deployment options. The best way that I see here is to use the deployment procedures typical of the selected OS (i.e. creating standalone packages for the selected OS in the way that the OS operators do).

For example, Red Hat or Debian packaging procedures typically mean grabbing tarball software from an external site (which will export sources from your VCS source code), unpacking, compiling, and preparing packages ready for deployment. Deployment itself ideally means simply executing a quick and simple command that will install packages, such as rpm -U package.rpm , dpkg --install package.deb or apt-get dist-upgrade (given that your built-in packages are sent to the repository where apt-get can find them).

Obviously, in order to make it work this way, you will need to provide all configuration files for all system components in a fully operational state, including all addresses and credentials.

To get a brief overview, consider a typical “small maintenance” situation: one PHP application deployed on n application servers running apache / mod_php to access MySQL servers. All of these servers (or virtual containers that really don't matter) are on a secure private network. To simplify this example, suppose that for all real Internet connections there is a cluster of k http accelerators / reverse proxies (for example, nginx / lighttpd / apache) that have a very light configuration (only internal IP addresses for forwarding).

What do we need for them to be plugged in and fully working?

  • MySQL servers: setting IP addresses / host names, setting up databases, providing usernames and passwords.
  • PHP application: configure IP addresses / hostnames, create a configuration file that displays the IP addresses of MySQL servers, logins, passwords and databases.

Note that there are 2 different types of data here: IPs / hostnames are something fixed, you probably want to assign them once and for all. Logics and passwords (and even database names), on the other hand, are solely for the purpose of connecting here - to make sure that MySQL really supports our PHP application. So, my recommendations here are to separate these two “types”:

  • "Permanent" information, such as IP addresses, must be stored in some VCS (other than the VCS source code)
  • “Temporary” information, such as passwords between two applications, should never be stored, but generated when creating deployment packages.

The last and most difficult question remains here: how to create deployment packages? Several methods are available, 2 main methods:

  • Exported source code from VCS1 + "persistent" configuration from building VCS2 + script from VCS3 = packages
  • The source code is in VCS1; VCS2 is a distributed version control (for example, git or hg) that essentially contains plugs of VCS1 + + configuration information that build scripts can generate. I personally like this approach better, it is much shorter and ultimately easier to use, but the learning curve can be a little steeper, especially for admins who have to master git or hg for this.

In the above example, I would create packages such as:

  • my-application-php - which will depend on mod_php, apache and will include a generated file of type /etc/my-php-application/config.inc.php , which will include IP addresses / MySQL database names and password / password generated as md5(current source code revision + salt) . This package will be installed on each of the n application servers. Ideally, it should be able to install on a clean installed OS and make a fully functioning cluster of node applications without any manual action.
  • my-application-mysql - which will depend on the MySQL server and will include a post-install script that:
    • starts the MySQL server and ensures that it starts automatically when the OS starts
    • connects to MySQL server
    • checks for an existing database
    • if no - creates a database, loads it with contents and creates a login with a password (the same usernames and passwords as those generated in /etc/my-php-application/config.inc.php using the md5 algorithm)
    • if so, it connects to the database, applies migration to bring it to the new version, kills all old logins / passwords and recreates a new login / password pair (again, generated using the md5 method (version + salt))

Ultimately, this should be useful for updating your deployment using a single command, such as generate-packages && ssh-all apt-get dist-upgrade . In addition, you do not store passwords between applications anywhere, and they are updated with each update.

This pretty simple example illustrates the many methods you can use here, but ultimately, you decide which solution is better here and which one is crowded. If you write more detailed information here or as a separate issue, I will be happy to try to sort it out in detail.

+25
Nov 30 '10 at 22:34
source share

Leaving aside that passwords should never be stored in plain text anywhere (except for someone from the skull or a locked vault that is accessible only to the CEO, CFO and CIO (and at the same time requiring all three keys)), should store everything in the original management that is required to build your product.

This means not only your source, but even specifications for build machines, compiler options, compilers themselves, etc.

If we could find a way to test physical equipment, we would do it too :-)

Everything that can be reproduced by the assembly process itself, or anything to run, and not to create software (for example, your passwords), usually does not belong to the control source, but some stores will do this for their executable files, generated documents etc. so that they can quickly get the specific version to install.

+18
Nov 22 '10 at 7:28
source share

Passwords should not be stored in the original control. At all. Ever. See How To Keep Secrets Secret

Passwords, server names, etc. are part of the deployment configuration performed by the server administrator. It is necessary to document this procedure and control the documented procedure.

Alternatively, you can configure the deployment using a script that will be run by sysadmin to execute the configuration, and during the execution of the script, it will ask sysadmin to provide the necessary information. Again, this script should be kept in version control.

Everything else except the server configuration must be in the source control.

Saving the server configuration in the source control is usually a bad idea, because it interferes with deployment and can cause minor disasters (for example, when someone does not understand that their test version, deployed from the source control, is exchanging data with a live service) .

Always save these configuration files outside the website.

Trusted connections can be an option that allows known IP addresses to connect to services by configuring this service.

+11
Nov 25 2018-10-25
source share

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

Think about the situation when your server fails, the backups turn out to be bad, and you need to return this server. I think that you and your client (or boss) will definitely agree that having everything you need to deploy a site in source control is a big plus.

If you want to create easily deployable packages from your sources using continuous integration (another best practice), you will have to put the configuration files in the source code.

Also think that in most cases, developers who have access to a control source cannot directly access the production database server. Production passwords are useless to them.

If the wrong people got access to your sources, they still need to access the production server in order to harm the passwords. Thus, if your production environment is properly protected, the security risks of passwords in source management are very limited.

+6
Nov 22 '10 at 8:07
source share

I think this issue is more about ownership of information, trust and organization. You have to ask yourself, what part of your organization would you trust so that your system passwords are protected from disclosure and misuse?

I was in organizations where they were held by people responsible for business. In others, they were delegated to a task force that also owned processes around creation and use, etc.

Most importantly, your organization clearly defines who should have access to system passwords. After that, you can choose the appropriate technical solutions for password protection.

+3
Nov 26 '10 at 11:37
source share

No. The production password must be configured directly on the server. You must create deployment instructions for the deployment team / person to modify the correct properties file during deployment.

+1
Nov 22 '10 at 7:27
source share

I found that using the build script (Phing in my case) was the best way to enter passwords.

+1
Nov 29 '10 at 9:38
source share

In my Subversion repositories for PHP, configuration files containing passwords are checked as config.php.sample with hints about what should be provided, and for using scripts, you need config.php in the same place.

The repository is configured to ignore config.php for this directory in order to avoid "accidental" additions or checks.

+1
Nov 30 '10 at 21:20
source share

An example configuration file, of course, I would put them under version control. But usually this is not with real world access data such as server addresses or passwords. Something like

 # program.conf
 #
 # mysql option for $ myprog.
 #
 # SERVER_ADDR = 127.0.0.1
 # SERVER_USER = mysql
 # SERVER_PASSWD = abcdef
+1
Nov 30 '10 at 22:40
source share

Problems with passwords in the source code:

  • hard to vary from one deployment to another (I don't want to change the source code during production)
  • increased chance of accidentally distorting the database during development
  • security issue (in most stores there is no reason for code / developers to know prod passwords).
  • changed password requires redistribution

What I found works best with configuration validation, which uses mixed standard defaults and placeholders for specific deployment data. Our applications are always looking for a system configuration that allows you to override any variable. This allows the production machine to have a configuration suitable for its deployment.

Note. When I work as an administrator, I always manage configurations separately from the code (for good reason).

+1
Dec 01 '10 at 17:14
source share

I would always rule out vital configuration files containing passwords or other access data (e.g. for databases), this is purely best practice. In addition, this source and version control usually serve more than one user, and not all of them work with the same database or even with the same server configuration (domains, etc.), and for this configuration files must remain excluded from it a whole lot.

0
Dec 01 '10 at
source share

Without the proper build process, I use this strategy (for PHP applications):

  • Make the folder /etc/companyname
  • Place two files in it:

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

Now your application configuration file will look something like this:

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

In this case, the environment determines the credentials used, and you can move the code between the pre-configured environments (and manage some parameters using $env ). Of course, this can be done using server environment variables, but this: a) is easier to configure and b) does not provide credentials for each script on the server (it will not appear in a debug debugging unwanted file, for example phpinfo() ).

To simplify reading outside of PHP, you can make JSON credential files or something else and just put up with a tiny performance hit (APC will not cache them).

0
Feb 29 '12 at 17:06
source share

I prefer having a local_settings file next to the main settings . This local_settings should not be added to the repository, but I will add sample.local_setting to the repository to show the structure of this file.

At run time, if there is a local setting, its values ​​will override the values ​​of the main settings file.

For example in python:

settings.py:

 log='error.log' db=lambda:None db.host='localhost' db.user='' db.password='' try: import local_settings except ImportError: pass 

local_settings.py:

 from settings import * db.user='abcd' db.password='1234' 
0
Feb 05 '14 at 7:14
source share



All Articles