jueves, 27 de octubre de 2011

Generar certificados autofirmados con OpenSSL


Software is like sex: It’s better when it’s free.
Linus Torvalds.


Tengo la suerte de trabajar en un lugar rodeado de extraordinarios profesionales como compañeros. El artículo que traigo aquí hoy es un resumen de un correo electrónico de uno de ellos que, con su permiso (y sugerencia) he convertido humildemente en otro post más para este blog. Gracias, Josete. Es un placer y un honor trabajar contigo.



Mini How-To: Generar certificados autofirmados con OpenSSL para Apache HTTP Server

-por José Morales Mora.

PASO 1. Generar Clave RSA

Ejecutar:

openssl genrsa -des3 -out server.key 1024

Genera una clave CA para realizar la firma del certificado. Nos pide la clave privada para este certificado. Podemos especificar el tamaño de la clave ( 1024, 2048)

PASO 2. Generar CSR ( Petición de Firma de Certificado)

Ejecutar:

openssl req -new -key server.key -out server.csr

Realiza una petición para la firma con clave privada especificado. Al realizarlo nos pide datos:

Country Name (2 letter code) []:
State or Province Name (full name) []:
Locality Name (eg, city) []:
Organization Name (eg, company) []:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []: 
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
 

IMPORTANTE: El "Common Name" debe corresponder con la URL que queremos Securizar. Si la URL a poner por SSL es www.paco.es, este campo debe contener exactamente eso.


PASO 3. Eliminar Clave Privada DES3

Ejecutar:

cp server.key server.key.org
openssl rsa -in server.key.org -out server.key

Esto es necesario porque en estos casos que tenemos un certificado firmado con clave primaria, Apache HTTP Server pide en cada arranque esa clave para utilizar el certificado. La solución es eliminar la encriptación DES3 para la clave.


PASO 4 . Generar Certificado Autofirmado.

Ejecutar:

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Con este paso obtenemos el CRT autofirmado preparado para ser utilizado en apache.

PASO 5. Configurar Apache

Para utilizar estos certificados en apache, lo que tenemos que hacer es añadir al Virtual Host que queramos:

SSLEngine on
SSLCertificateFile /usr/local/apache/conf/ssl.crt/server.crt
SSLCertificateKeyFile /usr/local/apache/conf/ssl.key/server.key



Referencias y más información:

domingo, 9 de octubre de 2011

Combinando XPath con JAXB


El primer 90% del código ocupa el 90% del tiempo de desarrollo. El 10% restante del código ocupa el otro 90% de tiempo de desarrollo.


Usar JAXB es tremendamente cómodo si tenemos que procesar datos XML bien definidos y cuya estructura sea bastante estable en el tiempo: nos evitamos toda la fontanería de análisis, verificación y marshalling / unmarshalling. Por otro lado, nos resuelve de un plumazo convertir los datos XML a objetos DTO/VO de datos en nuestra aplicación ya que nos permitirá pasarlos directamente a Servicios de negocio o a vista (si usamos un MVC), en lugar de crearlos y mantenerlos manualmente cada vez que se modifican las especificaciones.

Pero no todo son ventajas. A la hora de acceder a un dato de un elemento, tratar con objetos puede suponer un verdadero engorro de iteraciones anidadas o tener que usar predicados para las colecciones de elementos, cuando con XPath podemos realizar un acceso rápido y directo al elemento a través de sencillas expresiones.

Por ejemplo, supongamos que tenemos el siguiente XML:
  
    
      1
      
        
          ...
          06002
        
      
    
    
      2
      
        
          ...
          28034
        
      
    
    
      3
      
        
          ...
          06002
        
      
    
  
Si necesitamos acceder a todos los elementos/objetos empleado cuyo elemento cp sea 06002, usando objetos generados por JAXB deberíamos iterar por la colección empleados, así:

List<Empleado> empleados06 = new ArrayList<Empleado>();
for ( Empleado empleado : empleados.getEmpleadoList() ) {
  for ( direccion : empleado.getDirecciones().getDireccionList() ) {
    if ( direccion.getCp().equals("06002") ) {
      empleados06.add(empleado);
    }
  }
}

con XPath es mucho más simple: podemos obtener una lista usando la expresión

//empleado[cp='06002']

Cuanto más niveles jerárquicos tenga nuestro árbol de información (más grados de anidación), más compleja se hace la recuperación de datos usando JAXB. Sin embargo, con XPath es tan simple como evaluar una expresión.

Hasta que descubrí JXPath, tenía que elegir entre XPath (y pagar la "penalización" de realizar el marshalling/unmarshalling manualmente) o JAXB (y pagar la penalización de la selección de elementos con código manual).

JXPath

JXPath es otro genial componente de Apache Commons: una librería que evalúa expresiones (basadas en) XPath contra jerarquías de objetos Java, permitiendo hacer complejas consultas e iteraciones sobre estructuras y conjuntos de simples objetos POJO.

Es decir, te permite usar XPath sobre objetos. Y no sólo sobre objetos serializados vía JAXB, sino cualquier POJO o colección de éstos. Si XPath es al XML lo que el SQL a las bases de datos, JXPath es el equivalente a los objetos Java. Es la solución perfecta para simplificar código que debe evaluar y filtrar conjuntos de objetos o, por ejemplo, cuando debemos seleccionar datos en objetos en tiempo de ejecución, en los que es sencillo construir una expresión XPath dinámica. El artículo "Java Object Querying Using JXPath", muestra una serie de ejemplos muy ilustrativos.

Referencias y más información:

martes, 13 de septiembre de 2011

Sincronización de llamadas a Webservices y EJB

A la vista de suficientes ojos, todos los errores resultan evidentes.
Ley de Linus, formulada por Linus Torvalds, (1997).

Los servidores de aplicaciones y la arquitectura J2EE fue diseñada desde el principio con el multithreading en mente. La idea de escalabilidad y procesamiento paralelo de forma segura ha sido en una constante en su desarrollo y evolución para que los desarrolladores pudiéramos construir aplicaciones seguras sin preocuparnos de asuntos como la gestión de memoria o la sincronización de objetos.

Sin embargo, para las aplicaciones "de la vida real" nos encontramos con que algunas veces tenemos que "serializar" (en el sentido de alinear poniendo en serie, encolar manteniendo un orden y como contraposición al procesamiento paralelo) llamadas o procesamientos concretos... Algo para lo que J2EE no fue pensado desde el principio. Así, en el diseño y construcción de aplicaciones empresariales se suelen dar una serie de necesidades relacionadas entre si que, hasta hace poco, no han tenido solución directa manejada en el estándar JEE:
  • Serialización o sincronización de procesamiento de peticiones de un webservice. Es decir, poder hacer un WebService como si fuese un Servlet SingleThreadModel (ya obsoleto, por cierto). En definitiva: garantizar que no se atiende otra petición mientras se está atendiendo ya una, evitando la simultaneidad y por tanto evitando también duplicidad de procesamientos realizada por un cliente demasiado impaciente.
  • Serialización o proceso ordenado de los mensajes de una cola JMS o, lo que es lo mismo, mantenimiento del orden de llegada en el procesamiento de los mensajes. Esto, que podría parecer obvio, no lo es tanto, ya que para un MDB (Message Driven Bean), el contenedor crea un pool de objetos que trabajan en paralelo de forma que si se sacan 2 o 4 mensajes simultáneamente, puede ser que un mensaje más reciente se tarde menos en procesar que un mensaje anterior.
  • Instanciación de un singleton, patrón en principio no permitido por la especificación J2EE (hasta la reciente EJB 3.1, de la que hablaré más adelante). El patrón singleton es tremendamente necesario para asegurar la instanciación única de motores o manejadores de objetos (conexiones, datos, cachés, clientes, etc) que deben estar perfectamente sincronizados.
El que no haya tenido que solucionar este problema podrá pensar que nada más fácil como especificar al servidor que instancie un pool de tamaño 1 para el EJB/MDB que queramos y, voilà, problema solucionado. La idea es buena. Si aseguramos una y sólo una exclusiva y única instancia de nuestro EJB, podemos resolver las tres necesidades de un sólo plumazo: podríamos publicar dicho EJB como un Webservice, tener un sólo MDB o tener nuestro Singleton.... Por ejemplo, en el caso de Glassfish, podríamos indicarlo en el correspondiente fichero sun-ejb-jar.xml, de la siguiente forma:


    
        
            DataProviderService
            
                1
                1
                1
                0
            
        
    



Pero lamentablemente no es así: no funciona. Al menos en Weblogic, Glassfish y JBoss. Dudo que eso sea posible en ninguno. La razón es sencilla: el contenedor no está diseñado para eso, sino justamente para lo contrario, con lo que conseguiremos un nivel altísimo de reciclado de instancias, pero no conseguiremos mantener la misma instancia de forma permanente sin que la recicle el servidor. Tampoco haciendo variaciones con esos parámetros. Tras un número suficiente de pruebas comprobaremos que el servidor recicla y mantiene, aunque sea durante pocos instantes, varias instancias del mismo EJB.

Las soluciones

En principio hay tres soluciones válidas.

Si estás usando JEE 5 o inferior, es decir, un contenedor EJB 3.0 o inferior, tienes dos soluciones a tu alcance que básicamente pasan por mantener la sincronización fuera del servidor de aplicaciones: crear un JMX MBean o sincronizar por tu cuenta. Si estás usando JEE 6, estás de enhorabuena. Aquí están mis propuestas.

Usar un MBean de JMX
Un MBean es, en definitiva, un singleton accesible vía JMX. No es un objeto manejado por el contenedor de EJB ni un estándar JEE, pero es una solución más elegante que realizar un Singleton por código ya que podemos controlar su ciclo de vida e incluso acceder a su estado de manera remota. Eso si, como decía, la sincronización de los objetos que use (colas JMS, etc) corre por nuestra cuenta. El problema del WebService lo podemos reducir a un problema de JMS, ya que podríamos publicar los mensajes en una cola y extraerlos uno a uno haciendo que nuestro MBean sea un cliente JMS.

Usar un recurso sincronizable
Un mismo EJB puede ejecutarse en diferentes JVM's. El ciclo de vida de los objetos y su concurrencia es cosa del contenedor. Por tanto, declarar un método de un EJB como "synchronized" es una violación de la especificación y no debería ser una opción. Por tanto, nuestros EJB's deberán usar un objeto manejado que pueda ser sincronizado: bien un Singleton propio (si nos basta con sincronizar para una única JVM), bien usando la transacciones serializables de base de datos (si necesitamos sincronizar entre varias JVM's o queremos hacerlo más escalable).

Crear un Singleton Session Bean
Si puedes usar un contenedor JEE 6 compatible, puedes implementar un Singleton Session Bean. Ésta es por fin la solución adecuada dentro del estándar JEE: un singleton manejado con atributos para controlar la sincronización. Con este método se solucionan de un plumazo todas las cuestiones de sincronización o singletons de una forma segura y manejada por parte del contenedor EJB.



Referencias y más información:

jueves, 28 de julio de 2011

Cambiar la URL de conexión y establecer timeout a un Web Service JAX-WS

En el artículo anterior explicaba cómo realizar un cliente de Web Service JAX-WS con maven. Las herramientas de JAX-WS generan la url de conexión (endpoint) a partir de la url definida en el WSDL. Sin embargo, desplegar nuestro cliente en un entorno de producción final requerirá que realicemos una programación un poco más afinada y parametrizada permitiendo cambiar la url de conexión (típicamente hacia el servicio de producción final) y establecer timeouts.

Establecer los timeouts es extremadamente recomendable para prevenir que nuestra aplicación se quede "pegada" al servicio y eventualmente pueda bloquearse toda nuestra aplicación al quedarnos sin threads libres, ya que los tiempos máximos de espera suelen estar indefinidos por defecto.

Para especificar todo esto no es necesario regenerar el cliente. La práctica habitual es parametrizar los valores de URL, timeout de conexión y timeout de lectura (request timeout) usando algún fichero de configuración o similar, recuperarlos y especificarlos en nuestro proxy cliente.

A continuación dejo un snippet de código típico de ejemplo:


import javax.xml.ws.BindingProvider;
import com.sun.xml.ws.client.BindingProviderProperties;
...
int requestTimeout = 5000;
int connectTimeout = 500;
String nuevaUrl = "http://www.cestel.es/jdialer/dataProvider";

Jdialer jdialer = new Jdialer();
BindingProvider bp = (BindingProvider) jdialer.getDataproviderPort();
bp.getRequestContext().put(BindingProviderProperties.REQUEST_TIMEOUT,
		requestTimeout);
bp.getRequestContext().put(BindingProviderProperties.CONNECT_TIMEOUT,
		connectTimeout);
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
				nuevaUrl);

domingo, 19 de junio de 2011

JAX-WS Web Services con Maven


Como decía en "Generación de código JAXB con Maven", una de las ventajas que aporta maven es la capacidad de automatizar tareas repetitivas y reproducibles del proyecto de desarrollo en el propio gestor del ciclo de vida del mismo independizándolo de la herramienta de desarrollo.

Por ejemplo, si necesitamos acceder a un Web Service tenemos que generar los artefactos cliente que permitan "consumirlo" (Service Endpoint Interface -SEI-, clases valor de dependencias, etc...) y cada vez que cambie en algo el servicio tendremos que regenerar nuestros artefactos. Si esta tarea se realiza con un IDE, siempre necesitaremos el mismo IDE para actualizarla y (probablemente) pasar por algún tedioso wizard. Con maven, basta tener nuestros fuentes y el fichero pom.xml para que nuestro proyecto se construya en un momento sin instalar ni configurar nada.

El plugin jaxws-maven-plugin provee los adaptadores para las herramientas wsgen y wsimport de JAXWS a través de los goals jaxws:wsgen y jaxws:wsimport para crear web services y clientes de éstos respectivamente.

Para crear un web service, bastará con indicar el SEI en la sección execution del plugin y las opciones que queramos (en este caso, generar el fichero WSDL. Por ejemplo:

    org.codehaus.mojo
    jaxws-maven-plugin
    1.10
        
            
                1
                
                    wsgen
                
                
                     cestel.jdialer.provider.DataProviderService
                     true
                
            
        
    
Si queremos crear un cliente para un determinado servicio especificaremos, como habitualmente, el fichero de definición WSDL, el paquete donde queremos que se generen los artefactos y el directorio donde se generarán los ficheros fuente. Por ejemplo:

    org.codehaus.mojo
    jaxws-maven-plugin
    1.10
        
            
                1
                
                    wsimport
                
                
                    
                        ${project.build.directory}/jaxws/wsgen/wsdl/Jdialer.wsdl
                    
                    gesif.sgi.jdialer.dataprovider
                    ${basedir}/src/main/java
                
            
        
    


Referencias y más información:

jueves, 19 de mayo de 2011

Cerrar una sesión de telnet ordenadamente

telnet towel.blinkenlights.nl
Antes de que el ssh se extendiera como la forma de inicio de sesión remota a servidores UNIX y Linux, era frecuente realizar sesiones de telnet para acceso a una consola del servidor. Actualmente, el uso del telnet se limita prácticamente a realizar sesiones 5250 o 3270 hacia AS/400 o Mainframes o se reduce a realizar meras pruebas de conectividad TCP básicas cuando no tenemos el hping a mano y un tcptraceroute nos resulta teclear demasiado.

Siempre que realizamos un telnet solemos ver un mensaje "Escape character is '^]'." como el siguiente:

zarza@szarza:~$ telnet ftp.es.debian.org 80
Trying 82.194.78.250...
Connected to ftp.es.debian.org.
Escape character is '^]'.
^]
telnet> quit
Connection closed.
szarza@szarza:~$

Hasta ahora, nunca había sabido cancelar las conexiones de telnet que se quedaban pegadas, así que acababa matando la sesión cerrando el proceso padre del telnet (konsole, xterm, cmd.exe, etc) porque no me había preocupado de saber cómo obtener y enviar la famosa secuencia "^]". Sin embargo, es bastante sencillo: se trata de la combinación CTRL+ALT GR+], lo cual es lógico: "^" significa CTRL y el carácter ] se obtiene pulsando la tecla "Alt Gr"+]. Una vez en el prompt del telnet, podemos poner "quit" para salir.

Por otro lado, este artículo me ha servido para comprobar que sigue estando disponible la película Star Wars Episode IV en ASCII vía telnet haciendo "telnet towel.blinkenlights.nl" gracias a Simon Jansen.
Related Posts Plugin for WordPress, Blogger...
cookieassistant.com