Añadimos esta entrada de última hora pensando en añadir dos elementos que pueden ser útiles en cuanto
- el primero para hacer más sencilla la prueba de concepto que alguien quiera realizar, de forma que el repositorio sea local.
- el segundo para mostrar como añadir una segunda capa de protección a datos sensibles.
Repositorio local
En la primera entrada vimos como configurar sel config-server apuntando a un repositorio gitlab. Como dijimos, es lo usual. No obstante para una prueba de concepto, si se se desea, se puede optar por usar un repo local.
Efectivamente, podemos indicar una carpeta local como base de ficheros de configuración de las aplicaciones cliente que vayan a usar este server-config como gestor centralizado de configuraciones.
Lo que deberemos hacer es simplemente modificar el application.yml del server config, dejando, en lo que se refiere
spring:
cloud:
config:
server:
git:
#uri: https://gitlab.com/gincol-blog/config-files.git
uri: file://C:/Desarrollo/workareas/workarea_blog/config-files
searchPaths: '{application}'
#cloneOnStart: true
#force-pull: true
#username: XXXX
#password: XXXX
Dejamos expresamente con comentarios (#) las líneas que ya no son necesarias para que sea más patente los cambios a realizar. La diferencia principal es que ahora usamos una ruta local, en nuestro caso "file://C:/Desarrollo/workareas/workarea_blog/config-files". En dicha ruta tenemos la misma configuración de carpetas y ficheros que teníamos en el gitlab original.
Como se ve, no necesitamos clonar el repositorio, ni usar el force-pull. Evidentemente, también sobran username y password.
Ahora podemos arrancar nuestro config-server, arrancar el cliente y todo seguirá funcionando como antes.
Securización de propiedades (clave simétrica)
Seguramente alguien se habrá cuestionado por la seguridad de acceso y propiedades.
La seguridad de acceso se implementa mediante autienticación básica, los "username" y "password" de acceso al repositorio gitlab.
Pero qué pasa con aquellas propiedades que puedan ser sensibles, como passwords, por ejemplo y vayan en los ficheros de configuración de las aplicaciones cliente. Si las dejamos en claro, cualquiera que disponga de credenciales de acceso al repo podría verlas. Esto no es lo deseable.
Mostramos aquí la forma de evitar esta situación utilizando los endpoints "/encrypt" y "/decript" que expone el config-server. Veamoslo en detalle.
application.yml
Supongamos que en el application.yml de la aplicación cliente, hemos de poner las credenciales de acceso a una bdd:
spring:
datasource:
username: dbuser
password: dbpassword
Claro, esto no es demasiado seguro que digamos. Queda en claro el password de acceso a nuestra bdd. Vamos con la solución.
encript.key
Deberemos encriptar los datos sensibles mediante el mecanismo de clave simétrica (misma clave para encriptación y desencriptación). Para ello debemos añadir a nuestro config-server un nuevo fichero, el "bootstrap.yml", ubicado en el classpath (habitualmente en el resources) de dicho config server.
Este fichero es cargado en primer lugar cuando se levanta el config-server, antes que el application.yml. Dentro del mismo pondremos nuestra clave de encriptación:
encrypt:
key: mysecret
Arrancamos ahora nuestro config-server y lanzamos la siguiente petición
curl -X POST http://localhost:8888/encrypt -d dbpassword
la cual nos devuelve el valor encriptado de "dbpassword" a partir de la clave "mysecret"
60ad32c8284fa7a75bc912cdcaa3d184b85d11b315ed99117cdf1bfa20bfc2c9
Ahora sustituimos este valor en el application-yml de nuestro cliente, y que reside en la ruta local del repositorio que gestiona el config-server. No nos olvidemos de anteponer añadiendo {cipher} delante:
spring:
datasource:
username: dbuser
password: '{cipher}60ad32c8284fa7a75bc912cdcaa3d184b85d11b315ed99117cdf1bfa20bfc2c9'
Si queremos hacer una prueba previa para validar que este valor es correcto podemos invocar
curl -X POST http://localhost:8888/decrypt -d 60ad32c8284fa7a75bc912cdcaa3d184b85d11b315ed99117cdf1bfa20bfc2c9
obtenemos "dbpassword"
java
para probarlo, añadamos un endpoint a nuestro RestController y la captura vía @Value de ambos parámetros:
@Value("${spring.datasource.username}")
String username;
@Value("${spring.datasource.password}")
String password;
@GetMapping(path = "/database")
public String database() {
return String.format("el username es %s, y el password es %s", username, password);
}
Prueba
Lancemos nuestro cliente e invoquemos la url del nuevo endpoint "http://localhost:8181/database"
Como se puede apreciar, el valor del password lo vemos en claro, por lo que podríamos usarlo sin ningún problema en nuestra app cliente para acceder a nuestra bdd.
Securización de propiedades (clave asimétrica)
En lugar del uso de claves simétricas, se puede optar por usar claves asimétricas. El cambio es pequeño, básicamente se trata de cambiar la clave simétrica por un almacén.
Almacén
Para generarlo lanzamos el siguiente comando desde las keytool de java8 (para evitar problemas, ya que el código de ejemplo está preparado para usar java8):
keytool -genkeypair -alias mytestkey -keyalg RSA \
-dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \
-keypass changeme -keystore server.jks -storepass letmein
El almacén generado lo hemos colocado en la carpeta "secure" dentro del classpath del config-server.
bootstrap.yml
Ahora en lugar el "encript.key" usado en la anterior opción, pondremos esta otra configuración en el fichero bootstrap.yml del config-server
key-store:
location: classpath:/secure/server.jks
password: letmein
alias: mytestkey
secret: changeme
Arrancamos y lanzamos la petición siguiente
curl -X POST http://localhost:8888/encrypt -d dbpassword
lo cual nos devuelve
AQCN7lWTrOegj1rMd0QbdtPrRObDFZpgCSB6gjDMH9yM0jQuLh0efCJsBLAFAM1xpZ0n6fbe6x48AwzdDTyPrjtiLihBqVPYqjmxU2w5MTeRL2YVVcaqDSo1K2XEmObqYZYKnT+1+EMuvlh8txbxNcFvs3ZzKb0jWCB7oOa7yzuQl7f94Nkp+yiec2TB35IM1M3TC/ZjFbCsjIrUSBnLoGVnHIeBn+cPxskLcar+EsoEdfmUF/1LmpKE0dAz9z7vG1aOfIFSB6NDYwjYLBAp6WHGux0m4sVrBp/JcO0i132Bghh4U4oc4NzbQ+hh2quo7Rg4kPtvzAJhR33dZuwGDP9xIfWDFa/wa2opm7CE1Q3mUn0Uy8FJKBqoJn9zXtbqfZg=
Podemos validar, como antes, la corrección del valor devuelto
curl -X POST http://localhost:8888/decrypt -d AQCN7lWTrOegj1rMd0QbdtPrRObDFZ......
application.yml
En el fichero application.yml del cliente ahora ponemos el valor obtenido anteriormente tal como sigue:
password: '{cipher}AQCN7lWTrOegj1rMd0...........'
El resto se mantiene igual
Prueba
Como antes, levantamos la aplicación cliente e invovamos la url "http://localhost:8181/database"
El resultado es, como se esperaba, exactamente el mismo que en la prueba con clave simétrica.
Más info
Recordamos los repos de donde descargar los fuentes de lo mostrado en los tres artículos sobre externalización:server-config: https://gitlab.com/gincol-blog/config-server-example.git
client-config: https://gitlab.com/gincol-blog/config-client-example.git
ficheros-config: https://gitlab.com/gincol-blog/config-files.git
Documentación oficial de Spring: https://cloud.spring.io/spring-cloud-config/multi/multi__spring_cloud_config_server.html
No hay comentarios:
Publicar un comentario