Buscar este blog

sábado, 18 de abril de 2015

JBoss + mod_cluster + SSL + Windows

Hace tiempo había publicado una entrada sobre este mismo tema aquí pero después de haber aplicado esta configuración en varios proyectos he visto que no es del todo correcta e incluso tiene algunos aspectos innecesarios.

Partiendo de la experiencia adquirida en este tiempo he decido rehacerla completamente, si bien mantendré la entrada antigua como marca de vergüenza y de lo que no se debe hacer.

El código fuente del proyecto y los certificados de apache pueden descargarse de GitHub.

Comencemos.

El escenario será el siguiente:
  • Windows 7
  • Apache 2.2.X como front end
  • JBoss  EAP 6.2 como back end
  • La comunicación entre Apache y JBoss se hará empleando mod_cluster
  • Apache se encargará del SSL, solicitando al usuario un certificado válido
  • Habrá una aplicación Spring MVC en JBoss que leerá el certificado y mostrará cierta información al respecto.

Preparación previa

Aunque no sea necesario, vamos a configurar correctamente Apache con un ServerName y un certificado de identidad asociado con él mismo. Por tanto lo más conveniente es asignar un nombre de dominio a la instalación.

Se añade al fichero de hosts (en C:\Windows\System32\drivers\etc) una entrada para referenciar desarr.local contra localhost:
   
    # The proxy server - proxy server:port number
    127.0.0.1 desarr.local

Instalación y configuración de Apache

Instalación

Se descargará la última revisión disponible para la versión 2.2 openssl. El formato del nombre del archivo será el siguiente httpd-2.2.${XX}-win32-x86-openssl-0.9.8y.msi.
La URL de descarga es la siguiente: https://archive.apache.org/dist/httpd/binaries/win32/ 

La instalación se efectuará con todos los parámetros por defecto. Por defecto se instalará en el puerto 80, pero si estuviera ocupado se puede indicar cualquier otro. Además se instalará como un servicio que arranca automáticamente.

Si inicialmente no se instala como servicio se podrá establecer manualmente accediendo a la carpeta bin del directorio de instalación y ejecutando httpd -K install.

Una vez arrancado aparecerá un icono en la barra de tareas desde donde se podrá iniciar y parar.

Para abreviar, de aquí en adelanta se referenciará el directorio de instalación de apache como ${httpd}.

Durante el proceso de configuración, puede ser conveniente iniciar/parar apache directamente desde línea de comandos porque así se mostrarán los posibles mensajes de error por consola, sin necesidad de consultar el log. Para ello bastará con ejecutar los siguientes comandos:
  • Iniciar normalmente: httpd
  • Iniciar servicio: httpd -k start
  • Parar servicio: httpd -k stop
  • Comprobar sintaxis del fichero: httpd -t
También se recomienda ejecutar apache como administrador para que no haya problemas de permisos con Windows 7.

Configuración

Configuración de Virtual Hosts

El primer paso será configurar la conexión HTTP del servidor. Para ello se editará el fichero ${httpd}/conf/httpd.conf y se descomentarán/añadirán las siguientes líneas:
   
#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
ServerName desarr.local:80


# Virtual hosts
Include conf/extra/httpd-vhosts.conf


# Añadir esta línea. Incluir todos los ficheros del directorio conf.d
Include conf/conf.d/*.conf

También habrá que crear el directorio ${httpd}/conf/conf.d/, que inicialmente estará vacío.

Luego se editará el fichero ${httpd}/conf/extra/httpd-vhosts.conf y se sustituirá todo su contenido por el siguiente:
 
NameVirtualHost *:80

<virtualhost>
    ServerAdmin webmaster@dummy-host.EMILIO-PC.home
    DocumentRoot "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/htdocs"
    ServerName desarr.local
    ServerAlias www.desarr.local
    ErrorLog "logs/desarr.local-error.log"
    CustomLog "logs/desarr.local-access.log" common

    <directory>
        Options FollowSymLinks
        AllowOverride None
        Order deny,allow
        Allow from all
    </directory>
</virtualhost>

Simplemente habrá que sustituir el DocumentRoot por el directorio de instalación de apache que corresponda en cada caso.

En este punto, arrancando apache y accediendo a la página http://desarr.local/ se debería mostrar la pantalla de bienvenida.

Certificados

Apache necesita tres ficheros de configuración de SSL:
  • SSLCertificateFile. Es un fichero que contiene el certificado y la clave pública del servidor.
  • SSLCertificateKeyFile. Es un fichero que contiene la clave privada del servidor.
  • SSLCACertificateFile. Es un fichero que contiene la concatenación de todos los certificados de las CAs de confianza. Para que apache solicite un certificado de usuario/aplicación, la CA con la que se firme éste deberá estar incluida dentro de este fichero.
Se creará el directorio de ${httpd}/conf/keystores y en él se guardará los ficheros de certificados contenidos dentro del instalables que tiene ese mismo nombre.

Nota. En el proyecto Git ya se incluyen estos ficheros.

Configuración de SSL

Esta versión de apache ya tiene los módulos necesarios para SSL, con lo que simplemente habrá que crear los certificados correspondientes e importar un fichero de configuración preestablecido.
El siguiente paso es configurar el SSL empleando los certificados que se incluyeron en el punto anterior.
Se editará el fichero ${httpd}/conf/httpd.conf y se descomentarán las siguientes líneas:
  • LoadModule ssl_module modules/mod_ssl.so
  • Include conf/extra/httpd-ssl.conf
Luego se editará el fichero ${httpd}/conf/extra/httpd-ssl.conf y se modificarán las siguientes líneas (modificando y/o descomentando):
   
SSLCertificateFile conf/keystores/desarr.local.cer

SSLCertificateKeyFile "conf/keystores/desarr.local.key

SSLCACertificateFile conf/keystores/desarr.local-cas.pem


ServerName desarr.local:443

Además, en sistemas operativos de 64 bits es necesario hacer otro cambio adicional para evitar los problemas descritos en la siguiente página: https://wiki.apache.org/httpd/SSLSessionCache 

Se creará un acceso directo al directorio ${httpd}/logs y se colocará en una ruta fuera de "Programa Files (x86)". Por ejemplo, se puede crear el directorio "C:\Program Files\Apache" y colocar ahí ese acceso directo nombrado como ApacheLogs.
Por último se editará la siguiente línea del fichero httpd-ssl.conf para que apunte a ese directorio.

   
SSLSessionCache        "shmcb:C:/Program Files/Apache/ ApacheLogs/ssl_scache(512000)"

Configuración de mod_cluster

Los módulos de mod_cluster se pueden descargar de la siguiente dirección http://mod-cluster.jboss.org/downloads/1-2-6-Final-bin. No obstante, ya se proporcionan en el paquete de instalación, así que no es necesario bajarlos.

Se copiarán los módulos proporcionados (mod_slotmem.so, mod_manager.so, mod_proxy_cluster.so y mod_advertise.so) en el directorio ${httpd}/modules.

Se editará el fichero ${httpd}/conf/httpd.conf y se incluirán las siguientes directivas de carga de módulos:
   
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_http_module modules/mod_proxy_http.so

LoadModule slotmem_module modules/mod_slotmem.so
LoadModule manager_module modules/mod_manager.so
LoadModule proxy_cluster_module modules/mod_proxy_cluster.so
LoadModule advertise_module modules/mod_advertise.so

Nota. Es posible que algunos de estos módulos ya se estén cargando por defecto, así que hay que asegurarse de que no se incluyan dos veces, porque entonces se producirá un error al iniciar apache.

Se editará el fichero ${httpd}/conf/extra/httpd-vhosts.conf y se añadirán las líneas indicadas.
   
<virtualhost>
   (..)
 
    #Configuración para descubir y establecer el cluster
    KeepAliveTimeout 60
    MaxKeepAliveRequests 0
    ManagerBalancerName mycluster
    AdvertiseFrequency 5
    EnableMCPMReceive
</virtualhost>

Por último se creará el fichero ${httpd}/conf/conf.d/mod_cluster.conf con el siguiente contenido.
   
#Consulta de información del cluster yendo a URL /mod_cluster-manager
<location /mod_cluster-manager>
 #Mostrar información extra en la página del manager
 AllowDisplay on
 SetHandler mod_cluster-manager
</location>

En este punto, arrancando apache y accediendo a la página http://desarr.local/mod_cluster-manager se debería mostrar la pantalla de información de cluster.


Configuración de JBoss

Se empleará el perfil HA del modo standalone.
Para iniciar JBoss en esta configuración se empleará el siguiente comando:
  • standalone.bat -c standalone-ha.xml

El perfil HA de JBoss ya tiene configurado el mod_cluster con sus valores por defecto. Dado que también se dejaron estos mismos valores al configurar apache, no hace falta especificar ninguna configuración adicional.

JBoss debería ser capaz de enviar las tramas de autodiscover a Apache, pero para estar seguros se indicará la URL de éste.
Se entrará en la consola de administración de JBoss, yendo a la opción Profile > Web > mod_cluster > Proxies.



Se editará el campo Proxy List estableciendo el valor desarr.local:80 (el puerto sobraría), que es donde está escuchando el mod_cluster de apache.
Tras esto se reinicia el servidor.

Una vez arrancado de nuevo, al entrar en la URL http://desarr.local/mod_cluster-manager se debería mostrar información sobre el nodo de JBoss.

Pruebas

Para probar la arquitectura, se empleará una aplicación de pruebas que buscará el certificado de usuario como un atributo de la request.

El código del controller es el siguiente:

import java.security.cert.X509Certificate;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/infoCertificado")
public class CetrificadoController {
 private String X509CERT_ATTRIBUTE = "javax.servlet.request.X509Certificate";

 @RequestMapping(method = RequestMethod.GET)
 public ModelAndView prueba(HttpServletRequest request) {  
  X509Certificate[] certs = (X509Certificate[]) request.getAttribute(X509CERT_ATTRIBUTE);

  if (certs == null || certs.length == 0) {
   return crearVistaError("No existe certificado en la request");
  }

  return crearVistaCertificado(certs[0]);
 }

 private ModelAndView crearVistaCertificado(X509Certificate certificado) {
  ModelAndView mav = new ModelAndView("infoCertificado");
  mav.addObject("certificadoRaw",  certificado.toString());
  return mav;
 }

 private ModelAndView crearVistaError(String mensaje) {
  ModelAndView mav = new ModelAndView("infoCertificadoError");
  mav.addObject("mensaje", mensaje);
  return mav;
 }
}

Adicionalmente, es necesario añadir un fichero de configuración para que apache solicte el certificado cuando se encuentra con el contexto de la aplicación. Basta con crear el archivo ${httpd}/conf/conf.d/pruebaCertificado.conf con el siguiente contenido:

<location /certificadoApp>
 SSLVerifyClient optional
 SSLVerifyDepth  2
 SSLOptions +StdEnvVars +ExportCertData +StrictRequire +OptRenegotiate
</location>
Lo que se le indica a apache es que solicite el certificado de usuario de forma opcional, es decer, si lo tiene se lo manda a al aplicación, pero si no redirige igualmente.

El resultado es el siguiente:



1 comentario: