¿Deben almacenarse los files de configuration del server / database, incluidas las passwords, en el control de código fuente?

Estoy buscando escuchar algunas mejores prácticas …

Suponiendo una aplicación web que interactúa con unos pocos serveres de producción diferentes (bases de datos, etc.) … ¿deberían almacenarse los files de configuration que incluyen las passwords de la database en el control de código fuente (p. Ej., Git, svn)?

De lo contrario, ¿cuál es la mejor manera de realizar un seguimiento de la database del server (u otras passwords relacionadas) a las que necesita acceder su aplicación?

Editar: se agregó una recompensa para alentar una mayor discusión y escuchar lo que más personas consideran la mejor práctica.

No hay una sola respuesta de "bala de plata" aquí y todo dependería en gran medida de los detalles.

Antes que nada, considero la mejor práctica separar todo el código fuente de la configuration en un repository separado. Entonces, el código fuente permanece como código fuente, pero su installation o deployment (con configuration, passwords, etc.) es todo lo demás. De esta forma, separará con firmeza las tareas de los desarrolladores de las tareas de los administradores de sistemas y, en última instancia, podrá crear 2 equipos distintos que harán lo que les conviene.

Cuando tiene repository de distribución de repository de código fuente separado, su mejor apuesta siguiente es considerar las opciones de implementación. La mejor forma que veo aquí es mediante el uso de procedimientos de implementación típicos para un sistema operativo elegido (es decir, crear packages autónomos para un sistema operativo elegido de la misma manera que los mantenedores del sistema operativo).

Por ejemplo, los procedimientos de empaquetado de Red Hat o Debian normalmente implican tomar un tarball de software del sitio externo (que estaría exportando fonts desde su código fuente VCS), desempaquetarlo, comstackr y preparar packages listos para la implementación. La implementación en sí misma debería significar simplemente hacer un command rápido y simple que instalaría los packages, como rpm -U package.rpm , dpkg --install package.deb o apt-get dist-upgrade (dado que los packages construidos van a un repository donde apt-get podría encontrarlos).

Obviamente, para que funcione de esta manera, deberá proporcionar todos los files de configuration de todos los componentes de un sistema en pleno funcionamiento, incluidas todas las direcciones y cnetworkingenciales.

Para ser más concisos, consideremos una situación típica de "service pequeño": una aplicación PHP implementada en n serveres de aplicaciones que ejecutan apache / mod_php, accediendo a m serveres MySQL. Todos estos serveres (o contenedores virtuales, que realmente no importan) residen en una networking privada protegida. Para simplificar este ejemplo, supongamos que toda la conectividad real de Internet está liderada por un grupo de k http aceleradores / proxies inversos (como nginx / lighttpd / apache) que tienen una configuration muy sencilla (solo IP internas para reenviar).

¿Qué tenemos para que estén conectados y funcionando completamente?

  • Servidores MySQL: configure direcciones IP / nombres de host, configure bases de datos, proporcione inicios de session y passwords
  • Aplicación PHP: configure direcciones IP / nombres de host, cree un file de configuration que mencione IP de serveres MySQL, inicios de session, passwords y bases de datos

Tenga en count que aquí hay 2 "types" de información diferentes: IP / nombres de host es algo fijo, es probable que desee asignarlos de una vez por todas. Los inicios de session y las passwords (e incluso los nombres de las bases de datos), por otro lado, son puramente para fines de conectividad aquí, para asegurarnos de que MySQL realmente se conecte a nuestra aplicación PHP. Entonces, mis recomendaciones aquí serían dividir estos 2 "types":

  • La información "permanente", como IP, debe almacenarse en algunos VCS (diferente del código fuente VCS)
  • La información "transitoria", como las passwords entre 2 aplicaciones, nunca debe almacenarse, sino generarse durante la generación de packages de implementación.

La última y más difícil pregunta queda aquí: ¿cómo crear packages de implementación? Hay varias técnicas disponibles, 2 forms principales son:

  • Código fuente exportado de VCS1 + configuration "permanente" de VCS2 + script de creación de VCS3 = packages
  • El código fuente está en VCS1; VCS2 es un control de versión distribuida (como git o hg) que esencialmente contiene "horquillas" de información de configuration VCS1 + + scripts de construcción que pueden generar. Personalmente, me gusta este enfoque, es mucho más corto y, en última instancia, más fácil de usar, pero la curva de aprendizaje puede ser un poco más pronunciada, especialmente para los chicos de administración que tendrán que dominar git o hg por ello.

Para un ejemplo anterior, crearía packages como:

  • my-application-php – que dependería de mod_php, apache e includeía un file generado como /etc/my-php-application/config.inc.php que includeá las bases de datos de MySQL IP / hostnames y login / password generados como md5(current source code revision + salt) . Este package se instalaría en cada uno de los n serveres de aplicaciones. Idealmente, debería ser capaz de instalarse en un sistema operativo limpio instalado y crear un nodo de clúster de aplicación totalmente funcional sin ninguna actividad manual.
  • my-application-mysql – que dependería del server MySQL e includeía un script posterior a la installation que:
    • inicia el server MySQL y se asegura de que se inicie automáticamente en el inicio del SO
    • se conecta al server MySQL
    • comtesting si la database requerida existe
    • si no, crea la database, la inicia con los contenidos y crea un inicio de session con contraseña (los mismos inicios de session y passwords que se generaron en /etc/my-php-application/config.inc.php , utilizando el algorithm md5)
    • En caso afirmativo, se conecta a la database, aplica migraciones para llevarla a la nueva versión, elimina todas las passwords / inicios de session anteriores y recrea el nuevo par de inicio de session / contraseña (nuevamente, generado mediante el método md5 (revisión + sal))

En última instancia, debería brindar el beneficio de actualizar su implementación mediante un solo command como generate-packages && ssh-all apt-get dist-upgrade . Además, no almacena passwords entre aplicaciones en ningún lugar y se regeneran en cada actualización.

Este ejemplo bastante simple ilustra una gran cantidad de methods que puede emplear aquí, pero, en última instancia, depende de usted decidir qué solución es mejor aquí y cuál es excesiva. Si va a poner más detalles aquí o como una pregunta separada, gustosamente trataré de entrar en detalles.

Dejando de lado el punto de que las passwords nunca deben almacenarse en text plano en cualquier lugar (que no sea el cráneo de alguien o una bóveda bloqueada accesible solo para el CEO, CFO y CIO (y necesita las tres keys a la vez)), debe almacenar todo en control de origen eso es necesario para build su producto.

Eso significa no solo su fuente, sino incluso las especificaciones para las máquinas de compilation, las opciones del comstackdor, los propios comstackdores, etc.

Si pudiéramos encontrar una manera de verificar el hardware físico, lo haríamos también 🙂

Todo lo que puede ser reproducido por el process de compilation, o cualquier cosa para ejecutar en lugar de build el software (como sus passwords) generalmente no pertenece al control de código fuente, pero algunas tiendas lo harán por sus ejecutables, documentos generados y demás, solo para que puedan get rápidamente un lanzamiento específico para la installation.

Las passwords no deben almacenarse en el control de fuente. En absoluto. Nunca. Vea Cómo mantener secretos en secreto

Las passwords, nombres de server, etc. son parte de la configuration de implementación realizada por el administrador del server. Es esencial documentar este procedimiento y colocar el procedimiento documentado bajo control.

Alternativamente, la configuration de implementación podría ser realizada por un script que el administrador del sistema ejecutaría para realizar la configuration, y durante la ejecución del script le pediría a la administración del sistema que proporcionara la información requerida. De nuevo, este script debe mantenerse en control de versión.

Todo lo demás, aparte de la configuration del server, debe estar en control de fuente.

Almacenar la configuration del server en el control de fuente generalmente es una mala idea porque obstaculiza las implementaciones y puede causar pequeños desastres (por ejemplo, cuando alguien no se da count de que su versión de testing implementada desde el control de origen se está comunicando con un service en vivo).

Mantenga siempre estos files de configuration fuera de la raíz web.

Las conexiones confiables pueden ser una opción, permitiendo que las direcciones IP conocidas se conecten a los services mediante la configuration de ese service.

  • Cuando se ejecuta en Windows usa authentication integrada. Consulte Cómo asegurar el acceso a los datos
  • MySQL configura para permitir conexiones de localhost y para no requerir una contraseña. Vea el Paso 7: Proteger un server MySQL en Windows
  • PostgreSQL puede usar ~ / .pgpass .

En general, estoy de acuerdo con paxdiablo: pon todo lo que puedas bajo el control de la fuente. Eso incluye files de configuration de producción con cnetworkingenciales de database.

Piense en la situación en la que su server falla, las copys de security resultan ser malas y necesita volver a hacer ese server. Creo que usted y su cliente (o jefe) definitivamente estarían de acuerdo en que tener todo lo necesario para implementar el sitio en el control de la fuente es una gran ventaja.

Si desea crear packages fácilmente implementables a partir de sus fonts mediante la continuous integration (otra práctica recomendada), deberá colocar los files de configuration bajo el control de la fuente.

Tenga en count también que, en la mayoría de los casos, los desarrolladores que tienen acceso de control de origen no pueden acceder directamente al server de la database de producción. Las passwords de producción son inútiles para ellos.

Si las personas equivocadas obtuvieron acceso a sus fonts, aún necesitan get acceso al server de producción para dañar las passwords. Por lo tanto, si su entorno de producción está protegido adecuadamente, los riesgos de security de las passwords en el control de la fuente son muy limitados.

Creo que esta pregunta es más sobre propiedad de la información, confianza y organización. Debería preguntarse: ¿en qué parte de su organización confiaría para mantener las passwords de su sistema a salvo de la divulgación y el uso indebido?

He estado en organizaciones donde fueron custodiados por las personas responsables del negocio. En otros, han sido delegates en el equipo de operaciones que también poseía los processs en torno a la creación y el uso, etc.

Lo más importante es que esté claramente definido en su organización quién debería tener acceso a las passwords del sistema. Después de eso, puede decidir sobre soluciones técnicas apropiadas para proteger las passwords.

No. La contraseña de producción debe configurarse directamente en el server. Debe crear instrucciones de implementación para el equipo / persona de implementación para cambiar el file de properties correcto durante la implementación.

Descubrí que usar una secuencia de commands de compilation (Phing en mi caso) era la mejor forma de ingresar passwords.

En mis repositorys de Subversion para PHP, los files de configuration que contienen passwords se registran como config.php.sample con sugerencias sobre lo que debe proporcionarse y los scripts que dependen requieren que config.php esté presente en la misma location.

El repository está configurado para ignorar config.php para ese directory para evitar agregaciones o loggings "accidentales".

Ejemplo de file de configuraciones, seguro, las pondría bajo control de versiones. Pero generalmente no con datos de acceso en el mundo real como direcciones de server o passwords. Más como algo

 # program.conf
 #
 # mysql opción para $ myprog.
 #
 # SERVER_ADDR = 127.0.0.1
 # SERVER_USER = mysql
 # SERVER_PASSWD = abcdef

Problemas con las passwords en el código fuente:

  • difícil de variar de una implementación a otra (no quiero tener que modificar el código fuente en producción)
  • probabilidad aumentada de corromper accidentalmente la database de producción al hacer el desarrollo
  • problema de security (en la mayoría de las tiendas no hay ninguna razón para que el código / los desarrolladores conozcan las passwords de los productos)
  • la contraseña cambiada requiere networkingespliegue

Lo que he encontrado funciona lo mejor es tener una configuration activada que utiliza los valores pnetworkingeterminados de la combinación de las strings y los marcadores de position para los datos específicos de la implementación. Nuestras aplicaciones siempre buscan una configuration de sistema que permita anular cualquier variable. Esto permite que la máquina de producción tenga una configuration adecuada para su implementación.

Nota: Cuando funciono como administrador, siempre administro las configuraciones por separado del código (por una buena razón).

Siempre excluiría los files de configuration vitales que contienen passwords u otros detalles de acceso (como para las bases de datos), es puramente la mejor práctica. Además de eso, el control de fuente y versión sirve generalmente a más de un usuario y no todos trabajan con los mismos detalles de database o incluso con la misma configuration de server (dominios, etc.) y para este propósito los files de configuration deben permanecer excluidos del mucho.

Sin un process de compilation adecuado, estoy usando esta estrategia (para aplicaciones PHP):

  1. Crear una carpeta /etc/companyname
  2. En él, coloca dos files:

     <?php // env.php return 'prod'; 
     <?php // appname-prod.php return array( 'db' => array( /* cnetworkingentials */ ), /* other host-specific conf data */ ); 
  3. Haga que ambos files sean legibles solo por su process PHP

Ahora el file de configuration de su aplicación será algo así como:

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

Con esto en su lugar, el entorno define las cnetworkingenciales utilizadas, y puede mover el código entre entornos preconfigurados (y controlar algunas opciones con $env ). Esto, por supuesto, se puede hacer con las variables de entorno del server, pero esto a) es más fácil de configurar y b) no expone las cnetworkingenciales a cada script en el server (no se mostrará en una basura de phpinfo() errores como phpinfo() )

Para facilitar la lectura fuera de PHP, puede crear los files de cnetworkingenciales JSON o algo así y simplemente aguantar el pequeño golpe de performance (APC no los almacenará en caching).

Prefiero tener un file local_settings junto al file de configuration principal. Esta local_settings no se debe agregar al repository, pero agregaré un sample.local_setting al repository para mostrar la estructura de este file.

En time de ejecución si existe un local_settings, sus valores anularán los valores del file de configuration principal.

Por ejemplo en 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'