Mostrando entradas con la etiqueta seguridad. Mostrar todas las entradas
Mostrando entradas con la etiqueta seguridad. Mostrar todas las entradas

viernes, 25 de diciembre de 2020

Axis2 Client: Como indicar un certificado de confianza

Me ha pasado recientemente que tenía que hacer llamadas SOAP a través de un cliente basado en Axis2 y utilizar un certificado de confianza concreto. El problema venía por la manera de indicar el certificado de confianza y como estábamos invocando a nuestro programa. 

La primera solución ha sido la ampliamente conocida de setear dicho certificado en el sistema. De la siguiente forma:

System.setProperty("javax.net.ssl.trustStore", trustStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", trstStorePass);
System.setProperty("javax.net.ssl.trustStoreType", trustStoreType);

Esta solución funciona correctamente por sí sola. El problema en nuestro caso lo teníamos al lanzar la ejecución a través de Maven. Y esto es debido a que Maven hace sus propias llamadas a determinados repositorios para comprobar el estado de las librerías del proyecto. Y al hacer esto Axis2 cachea el certificado utilizado previamente por Maven, es decir el certificado de la máquina virtual Java. Por tanto el seteo posterior de nuestro certificado no sirve para nada. 

¿Como he llegado a esta conclusión? Si ejecutaba el programa con el comando offline de Maven, funcionaba correctamente. Y si lo ejecutaba sin dicho comando, al intentar realizar la llamada, indicaba que no encontraba un certificado válido. 

unable to find valid certification path to requested target

La solución puede ser simplemente descargarnos el certificado del host al que vayamos a llamar y añadirlo al certificado de confianza de la máquina virtual. 

sudo keytool -import -trustcacerts -file /path/to/ca/ca.pem \
-alias mydomain -keystore $JAVA_HOME/jre/lib/security/cacerts

Pero como estamos en una Web sobre Java nosotros vamos a ver como hacerlo con Java. Y para ellos vamos ha hacer uso de la librería commons-io y su clase Protocol. Esta nos permitirá indicar nuestra propia autorización a utilizar en las llamadas con el protocolo indicado, en nuestro caso SSL.

En nuestro caso lo realizaremos a través de la clase AuthSSLProtocolSocketFactory la cual nos permite validar la identidad de servidores HTTPS dentro de una lista de certificados de confianza. El servidor será el endpoint al cual llamaremos y el certificado de confianza será el de dicho servidor que se encuentra almacenado en el keystore que le pasaremos. 

URL url = new File(trustStorePath).toURI().toURL();
ProtocolSocketFactory factory = new AuthSSLProtocolSocketFactory(url, trstStorePass, url, trstStorePass);
Protocol httpsProtocol = new Protocol("https", factory, 443);
Protocol.registerProtocol("https", httpsProtocol);

miércoles, 15 de enero de 2020

Maven: Encriptar contraseñas

Una práctica habitual es crear perfiles para la configuración de distintos entornos en una aplicación maven. Y como es normal dentro de esta configuración es posible que vayan contraseñas. Hoy mostraremos como encriptar contraseñas en Maven y un par de consejos para el correcto manejo de las mismas.

Para empezar debemos generar una clave maestra. Esta la crearemos a través del siguiente comando:

mvn --encrypt-master-password

Al introducirlo nos pedirá que introduzcamos nuestra clave maestra. Y nos la devolverá códificada.

{Q0eIoh2W24Hovj4oE0pXgObO3zHOXn/gvQC1gMFoI=}

Esta clave maestra, con el siguiente formato, la incluiremos en el fichero .m2/settings-security.xml, (que como sabéis se encuentra dentro de la carpeta home del usuario).

<settingsSecurity>
  <master>{Q0eIoh2W24Hovj4oE0pXgObO3zHOXn/gvQC1gMFoI=}</master>
</settingsSecurity>

Ahora ya podremos encriptar contraseñas a través del comando --encrypt-password o -ep

mvn -ep root
{d/vIFp4AAAH2yHgBmc4A5NHaUdhOQWon9htDpHZBY=}

Pero aquí viene un pequeño pero. Estas contraseñas generadas las podremos incluir solamente en el fichero settings.xml (ubicado también en la carpeta m2). ¿Por qué en el settings.xml y no directamente en el pom.xml?. Pues porque es una best practices, y la sección server del settings.xml se creó para eso mismo: gestionar información sensible sobre servidores, la cual no debería esta navegando libremente. Por tanto nuestra configuración quedaría así:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0                         https://maven.apache.org/xsd/settings-1.0.0.xsd">
  <localRepository />
  <interactiveMode />
  <offline />
  <pluginGroups />
  <servers>
    <server>
      <id>mysql-local</id>
      <username>root</username>
      <password>{d/vIFp4AAAH2yHgBmc4A5NHaUdhOQWon9htDpHZBY=}</password>
    </server>
  </servers>
  <mirrors />
  <proxies />
  <profiles /> 
  <activeProfiles />
</settings>

Y con esto ya tendríamos nuestras contraseñas relativas a los servidores codificadas y listas para usar con maven... ¿Pero como lo uso dentro del pom.xml? Esto parece una verdad a medias...

Buena pregunta. podemos hacerlo de dos formas:
  • Si vamos a utilizar un plugin, podemos cambiar la configuración username/password por server. Siempre que ese plugin lo permita, por ejemplo tomcat7-maven-plugin lo permite.  
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <url>http:// localhost:8080/manager</url>
        <server>TomcatServerConfiguredInSettingsXml</server>
    </configuration>
</plugin>
<build>
    <extensions>
        <extension>
            <groupId>com.github.shyiko.servers-maven-extension</groupId>
            <artifactId>servers-maven-extension</artifactId>
            <version>1.3.1</version>
        </extension>
    </extensions>
</build>
<profiles>
    <profile>
        <id>local</id>
        <properties>
            <mysql.userName>${settings.servers.mysql-local.username}</mysql.userName>
            <mysql.password>${settings.servers.mysql-local.password}</mysql.password>
        </properties>
    </profile>
</profiles>