¿Estrategia para mantener la información secreta, como las claves API fuera del control de origen?

209

Estoy trabajando en un sitio web que permitirá a los usuarios iniciar sesión con las credenciales de OAuth de usuarios como Twitter, Google, etc. Para hacer esto, debo registrarme con estos proveedores y obtener una clave API súper secreta que tengo que proteger con prendas contra varias partes del cuerpo. Si mi llave se anula, la pieza se jala.

La clave API debe viajar con mi fuente, ya que se usa en tiempo de ejecución para realizar solicitudes de autenticación. En mi caso, la clave debe existir dentro de la aplicación en un archivo de configuración o dentro del propio código. Eso no es un problema cuando compilo y publico desde una sola máquina. Sin embargo, cuando lanzamos el control de la fuente en la mezcla, las cosas se complican.

Como soy un bastardo barato, prefiero usar servicios de control de código fuente gratuitos como TFS en la nube o GitHub. Esto me deja con un ligero enigma:

¿Cómo puedo mantener mi cuerpo intacto cuando mis claves de API están en mi código, y mi código está disponible en un repositorio público?

Puedo pensar en varias maneras de manejar esto, pero ninguna de ellas es tan satisfactoria.

  • Podría eliminar toda la información privada del código y editarla nuevamente después de la implementación. Esto sería un dolor severo de implementar (no detallaré las muchas maneras) y no es una opción.
  • podría cifrarlo. Pero como tengo que descifrarlo, cualquiera con la fuente podría descubrir cómo hacerlo. Sin sentido.
  • Podría pagar el control de la fuente privada. LOL j / k gastar dinero? Por favor.
  • Podría usar funciones de lenguaje para separar la información confidencial del resto de mi fuente y, por lo tanto, mantenerla fuera del control de la fuente. Esto es lo que estoy haciendo ahora, pero se podría arruinar fácilmente al verificar el archivo secreto.

Realmente estoy buscando una forma garantizada para garantizar que no comparto mis secretos con el mundo (excepto en Snapchat) que funcionará sin problemas a través del desarrollo, la depuración y la implementación, y también seré infalible. Esto es completamente irrealista. Entonces, ¿qué puedo hacer de manera realista?

Detalles técnicos: VS2012, C # 4.5, el control de la fuente será el servicio de TF o GitHub. Actualmente, se usa una clase parcial para dividir las claves confidenciales en un archivo .cs separado que no se agregará al control de origen. Creo que GitHub puede tener la ventaja, ya que .gitignore podría usarse para asegurarse de que el archivo de clase parcial no se haya registrado, pero lo he arruinado antes. Espero un "oh, problema común, así es como lo haces", pero es posible que tenga que conformarme con "eso no apesta tanto como podría",: /

    
pregunta Will 21.07.2013 - 22:18

12 respuestas

124

No pongas tu información secreta en tu código. Póngalo en un archivo de configuración que lea su código al inicio. Los archivos de configuración no deben colocarse en el control de versiones, a menos que sean los "valores predeterminados de fábrica", y luego no deben tener ninguna información privada.

Consulte también la pregunta Control de versiones y archivo de configuración personal para cómo hacerlo bien.

    
respondido por el Philipp 21.07.2013 - 22:43
28

Podría poner todas las claves privadas / protegidas como variables de entorno del sistema. Su archivo de configuración se verá así:

private.key=#{systemEnvironment['PRIVATE_KEY']}

Así es como manejamos esos casos y nada entra en el código. Funciona muy bien combinado con diferentes archivos de propiedades y perfiles. Utilizamos diferentes archivos de propiedades para diferentes entornos. En nuestro entorno de desarrollo local, colocamos las claves de desarrollo en los archivos de propiedades para simplificar la configuración local:

private.key=A_DEVELOPMENT_LONG_KEY
    
respondido por el Ioannis Tzikas 22.07.2013 - 13:40
27

Pure Git way

  • .gitignore incluye archivo con datos privados
  • Use una rama local, en la que reemplaza TEMPLATE con DATA
  • Use filtros de borrado / limpieza, en los que el script del filtro (local) realice el reemplazo bidireccional TEMPLATE < - > %código%

Camino mercurial

  • MQ-patch (es) encima del código de relleno, que reemplaza DATA con TEMPLATE (los conjuntos de cambios son públicos, el parche es privado)
  • Extensión de palabra clave con palabras clave especialmente diseñadas (expandidas solo en su directorio de trabajo )

SCM-agnostic way

  • Reemplazo de palabras clave como parte del proceso de compilación / implementación
respondido por el Lazy Badger 21.07.2013 - 23:29
14

Esto es muy específico para Android / Gradle pero puede definir las claves en su archivo global gradle.properties ubicado en user home/.gradle/ . Esto también es útil, ya que puede usar diferentes propiedades dependiendo del tipo de compilación o el sabor, es decir, la API para dev y una diferente para la versión.

gradle.properties

MY_PRIVATE_API_KEY=12356abcefg

build.gradle

buildTypes {
        debug{
            buildConfigField("String", "GOOGLE_VERIFICATION_API_KEY", "\"" + MY_PRIVATE_API_KEY +"\"")
            minifyEnabled false
            applicationIdSuffix ".debug"
            }
        }

En el código al que harías referencia de esta manera

String myAPI = BuildConfig.GOOGLE_VERIFICATION_API_KEY;
    
respondido por el scottyab 29.05.2015 - 20:40
13

Puse secretos en archivos cifrados que luego confirmo. La frase de contraseña se proporciona cuando se inicia el sistema, o se almacena en un archivo pequeño que no confirmo. Es bueno que Emacs administre alegremente estos archivos encriptados. Por ejemplo, el archivo de inicio de Emacs incluye: (cargar "secrets.el.gpg"), que simplemente funciona y me solicita la contraseña en esas raras ocasiones cuando inicio el editor. No me preocupa que alguien rompa el cifrado.

    
respondido por el Ben Hyde 09.12.2013 - 06:16
11

Se supone que no debe distribuir esa clave con su aplicación o almacenarla en el repositorio de código fuente. Esta pregunta es cómo hacerlo, y eso no es lo que se hace normalmente.

Aplicación web móvil

Para Android / iPhone, el dispositivo debe solicitar la LLAVE a su propio servicio web cuando se ejecute la aplicación por primera vez. La clave se almacena en un lugar seguro. En caso de que la clave sea cambiada o revocada por el editor. Su servicio web puede publicar una nueva clave.

Aplicación web alojada

Los clientes que utilicen una licencia de su software deberán ingresar manualmente la clave cuando configuren el software por primera vez. Puede darles a todos la misma clave, diferentes claves o ellos obtendrán la suya.

Código fuente publicado

Almacena su código fuente en un repositorio público pero no en la CLAVE. En la configuración del archivo, agregue las líneas * colocar clave aquí * . Cuando un desarrollador utiliza su código fuente, realiza una copia del archivo sample.cfg y agrega su propia clave.

No mantienes tu archivo config.cfg utilizado para el desarrollo o la producción en el repositorio.

    
respondido por el cgTag 23.07.2013 - 21:28
5

Use variables de entorno para cosas secretas que cambian para cada servidor.

enlace

El uso de ellos depende del idioma.

    
respondido por el Filipe Giusti 23.07.2013 - 20:39
4

Creo que este es un problema con el que todos hemos tenido algún problema en algún momento.

Aquí hay un flujo de trabajo que he usado, que podría funcionar para usted. Utiliza .gitignore con un toque:

  1. Todos los archivos de configuración van en una carpeta especial (con archivos de configuración de muestra - opcional)
  2. Todos los archivos de configuración están incluidos en .gitignore, para que no se hagan públicos
  3. Configure un servidor gitolite (o su servidor git favorito) en una caja privada
  4. Agregue un repositorio con todos los archivos de configuración en el servidor privado
  5. Agregue un script para copiar los archivos de configuración a la carpeta especial en el repositorio principal (opcional)

Ahora, puede clonar el repositorio de configuración en cualquier sistema de desarrollo e implementación. Simplemente ejecute el script para copiar los archivos a la carpeta correcta y listo.

Todavía recibes todos los dulces de GitHub, compartes tu código con el mundo y los datos confidenciales nunca están en el repositorio principal, por lo que no se hacen públicos. Todavía están a solo un tirón y una copia de cualquier sistema de implementación.

Utilizo una caja de 15 $ / año para el servidor git privado, pero también puedes configurar uno en casa, según el requisito de cheapskate ;-)

PS: También puedes usar un submódulo git ( enlace ), pero siempre me olvido de los comandos, así que rápido & reglas sucias!

    
respondido por el Kostas 08.12.2013 - 22:24
2

Use el cifrado, pero proporcione una clave maestra al inicio, como una contraseña en la consola, en un archivo que solo el usuario del proceso puede leer, o en un almacén de claves proporcionado por el sistema como el llavero de Mac OS o el almacén de claves de Windows.

Para la entrega continua, querrás varias teclas grabadas en algún lugar. La configuración debe estar delimitada del código, pero tiene mucho sentido mantenerla bajo control de revisión.

    
respondido por el erickson 23.07.2013 - 12:15
1

3 estrategias, aún no mencionadas (?)

En el check in o en un VCS pre-check in hook

  • busque cadenas con alta entropía, por ejemplo, detect-secrets
  • búsqueda de expresiones regulares para patrones de clave API conocidos. Las claves AKIA * de AWS son un ejemplo, git-secrets es una herramienta basada en eso. Además, nombres de variables como 'contraseña' con asignación constante.
  • buscar secretos conocidos: conoce sus secretos, busque el texto en busca de ellos. O use una herramienta, escribí esta prueba de concepto .

Estrategias ya mencionadas

  • almacenar en un archivo fuera del árbol de origen
  • tenlo en el árbol de origen, pero dile a VCS que lo ignore
  • las variables de entorno son una variación en el almacenamiento de datos fuera del árbol de origen
  • simplemente no le des los secretos valiosos a los desarrolladores
respondido por el MatthewMartin 24.07.2018 - 05:02
0

Mantenga la información privada fuera de su control de código fuente. Cree un valor predeterminado no cargado para la distribución y haga que su VCS ignore el real. Su proceso de instalación (ya sea manual, configurar / compilar o asistente) debe manejar la creación y el llenado del nuevo archivo. Opcionalmente, modifique los permisos en el archivo para asegurarse de que solo el usuario requerido (¿servidor web?) Pueda leerlo.

Beneficios:

  • No asume entidad de desarrollo == entidad de producción
  • No asume que todos los colaboradores / revisores de código son confiables
  • Evite errores fáciles manteniéndolo fuera del control de versiones
  • Fácil de automatizar instalaciones con configuración personalizada para QA / builds

Si ya está haciendo esto y lo está registrando accidentalmente, agréguelo a .gitignore de su proyecto. Esto hará que sea imposible hacerlo de nuevo.

Hay hay muchos hosts de Git gratuitos que proporcionan repositorios privados. Si bien nunca debes versionar tus credenciales, puedes ser barato y tener repositorios privados también. ^ _ ^

    
respondido por el Adrian Schneider 27.07.2013 - 06:40
-2

En lugar de tener la clave OAuth almacenada como datos sin procesar en cualquier lugar, ¿por qué no ejecutar la cadena a través de algún algoritmo de cifrado y almacenarla como un hash con sal? Luego use un archivo de configuración para restaurarlo en tiempo de ejecución. De esa manera, la clave no se almacena en ningún lugar, ya sea que se almacene en una caja de desarrollo o en el propio servidor.

Incluso podría crear una API tal que su servidor genere automáticamente una nueva clave de API con sal y hash por solicitud, de esa forma ni siquiera su equipo podrá ver la fuente de OAuth.

Editar: Tal vez intente la Biblioteca de criptografía de Javascript de Stanford , esto permite un cifrado / descifrado simétrico bastante seguro.

    
respondido por el David Freitag 23.07.2013 - 22:19

Lea otras preguntas en las etiquetas