2 comandos para proteger tu contraseña

En este artículo te explico cómo evitar que tu contraseña quede expuesta en la terminal a través del historial del shell, en Mac. Pero el concepto para otros sistemas operativos es el mismo.

Como desarrolladores estamos ejecutando comandos en el shell de nuestro equipo gran parte del tiempo. Algunas de las aplicaciones que ejecutamos pueden requerir que pasemos nuestra contraseña como argumento para validar el acceso a un servicio. Y si ese comando queda en el historial del shell, nuestra contraseña quedará expuesta.

Si bien muchas aplicaciones de línea de comando evitan recibir un password como argumento con el fin de evitar el problema mencionado anteriormente. Puede que necesitemos escribir un shell script para ejecutar muchos comandos y algunos requieran la contraseña por entrada estándar. Pero al mismo tiempo, esta no se encuentre disponible cuando ejecutamos el script. En este caso la técnica que describo a continuación también puede ser útil.

Tal cómo lo menciona el título esta técnica consta de dos comandos:

  • Guardar nuestra contraseña en el Llaveros (Keychain, repositorio de claves)
  • Recuperarla cuando la necesitamos

La aplicación a utilizar en ambos casos se llama security y está disponible en nuestra Mac sin necesidad de hacer instalaciones o configuraciones adicionales. Para guardar una contraseña deberemos proporcionar además del password en sí, un nombre de usuario y un dominio o contexto. Este último nos permitirá saber en qué lugar tiene sentido utilizar esa contraseñas y también servirá para agrupar las que pertenezcan al mismo servicio.

$ security add-generic-password -a <USUARIO> -s <CONTEXTO> -w

Reemplazando <USUARIO> con nuestro nombre de usuario (o el usuario al que corresponde el password) y <CONTEXTO> con una palabra que identifique el servicio al que pertenece la contraseña este comando nos pedirá que ingresemos la clave y al almacenará en la Llaveros de MacOS.

El segundo paso consiste en recuperar una contraseña almacenada previamente. Tal como hicimos con el comando anterior.

Este comando deberíamos correrlo al menos una vez luego de agregar una contraseña para verificar que el alta fue correcta.

$ security find-generic-password -a <USUARIO> -s <CONTEXTO> -w

Reemplazando <USUARIO> y <CONTEXTO> al igual que en la ejecución del primer comando, este nos mostrará en pantalla el texto de la contraseña recuperada. Para ello nos pedirá que ingresemos nuestra contraseña de usuario de Mac. Si lo ejecutamos para validar el alta y el texto es correcto estamos en condiciones de utilizar el password.

Ejemplo de uso

Como situación hipotética digamos que hay un servidor de Artifactory donde tenemos que subir artifacts de un proyecto manejado con Maven. No vamos a entrar en los detalles de configuración del proyecto. Sólo vamos a mencionar que en nuestro archivo ~/.m2/settings.xml tenemos una sección como la siguiente para configurar el servidor al cual subiremos los artifacts:

<servers>
      <server>
        <id>${server.id}</id>
        <username>${server.username}</username>
        <password>${server.password}</password>
      </server>
  </servers>

Y que normalmente deberíamos ejecutar la siguiente línea de comandos para hacer un deploy a ese servidor:

$ mvn deploy -Dserver.id=miArtifactory -Dserver.username=miUsuario -Dserver.password=miPassword

Y desde luego miArtifactory, miUsuario y miPassword son valores imaginarios donde escribimos, en la vida real, valores reales. Entonces en nuestro historial de shell quedaría expuesta la clave:

$ history
...
...
236 cd proyecto
237 mvn deploy -Dserver.id=miArtifactory -Dserver.username=miUsuario -Dserver.password=miPassword
238 ls target
...
...

Para evitar este problema cambiaremos el comando que ejecutamos normalmente de esta forma:

$ mvn deploy -Dserver.id=miArtifactory -Dserver.username=miUsuario -Dserver.password=$(security find-generic-password -a miUsuario -s artifactory -w)

Desde luego, para que esto funcione debimos haber agregado una contraseña al Keychain (Llaveros) previamente para el usuario miUsuario y contexto artifactory. Al ejecutar esto, primero se ejecutará el reemplazo de shell, es decir, todo lo encerrado en $(...). Y luego se ejecutará el comando con el resultado de la llamada a security como reemplazo justo después del igual. Con lo que el comando es idéntico al anterior a los fines prácticos para Maven.

Una alternativa no muy efectiva

Si nuestro problema se limitara exclusivamente a no dejar rastros de la contraseña en el historial, siempre podemos evitar que un comando se guarde si le agregamos un espacio adelante. Si vamos a ejecutar el comando ls, por ejemplo, en realidad ponemos un espacio, luego la l y la s. Y con eso el shell evitará guardarlo en el historial.

El problema con esto es que requiere que nos acordemos siempre antes de escribir cualquier comando donde se expondría la clave, que debemos precederlo con un espacio. Ciertamente algunas personas puede adquirir esta costumbre pero no es mi caso. Y lo que en el pasado me ocurría era que terminaba siempre teniendo que eliminar el comando el historial a mano.

Por este motivo creo que vale la pena el esfuerzo extra de la solución propuesta en este artículo. Espero que les sea útil. ¡Hasta la próxima!