Hace dos días se nos planteó un pequeño reto que consistía en lo
siguiente. Desarrollar un sistema de smart-logon, hacer login en un
sistema con una tarjeta inteligente como el dnie, para liferay en una
plazo bastante ajustado con las siguientes características:
- El usuario debía poder acceder al portal tanto
con tarjeta inteligente como con usuario/password. - Se debía poder decidir que usuarios podrían acceder con
tarjeta y cuales con no. - Debido a que algunos usuarios disponían de varias tarjetas,
izenpe, dnie etc.. se debería poder acceder con cada una de
ellas de manera transparente.
Una vez planteado el reto hicimos un pequeño brain storming y
obtuvimos dos propuestas viables para solucionar el problema que son:
- Integrar liferay con un sistema de sigle-sign-on como CAS y usar el conector
para certificados x509 que tiene. - Desarrollar un hook de autologin para liferay.
El primero tenía ciertas ventajas entre ellas:
- Ya lo habíamos usado en algún otro proyecto.
- La integración entre liferay y CAS existe y
está soportada por el core de producto.
Pero tenía un par de desventajas claras:
- El modelo de asignación de usuarios y sus certificados no está
soportado por el Handler de CAS - Liferay no se entera de que hay una conexión basada en X509 ya
que delega en el CAS
El segundo tenía ciertas ventajas entre ellas:
- Hemos desarrollado módulos de autlogin para otro tipo
de casuísticas (facebook, idProvider de SAML etc…) - El desarrollo de las partes nuevas basado en
liferay es bastante sencillo - La integración del desarrollo en el portal se
hace de manera natural
Pero claro tenía ciertas desventajas:
- El módulo de autlogin puede dar problemas al consumir
servicios de liferay creados fuera del core (temas de classloader) - No existe un módulo parecido en liferay
Al final nos decantamos por la segunda opción y aplicamos un modelo
scrum
(en un sprint de una semana lo cual no es que tenga mucho sentido pero
bueo…) con las siguientes historias de usuario.
- El usuario debía poder acceder al portal tanto con
tarjeta inteligente como con usuario/password. - Se debía poder decidir que usuarios podrían
acceder con tarjeta y cuales con no. - Debido a que algunos usuarios disponían de varias tarjetas,
izenpe, dnie etc.. se debería poder acceder con
cada una de ellas de manera transparente.
LLegados a este punto dividimos las historias en las siguientes tareas:
Historia primera
- Configurar el liferay para que permita un acceso basado en
https con certificado de cliente. - Configurar el liferay para que permite un acceso basado en
https sin certificado de cliente. - Configurar el liferay para que trabaje con un servidor
web como capa de front-end, en este caso apache web server. - Configurar el apache web para que permita servir
páginas bajo protocolo seguro (https) con y sin
certificado de cliente - Crear el módulo de autologin con smart-card
(hook de liferay)
Historias segunda y terecera
- Crear un módulo de liferay que permita asignar un o
varios certificados a un usuario concreto y que además
está información sea usada por el hook de autologin - Integrar el módulo de asignación certificados a usuarios en el
control panel de liferay
Como tareas generales habría que:
- Crear el modelo de despliegue de la solución
- Documentar la misma
Un vez planteado el proyecto nos repartimos las tareas entre el
grupo de trabajo (tres personas en
este caso) y nuestro optimismo a la hora de valora el
coste de las tareas nos llevó a concluir que este
proyecto se podía afrontar en menos tiempo del estimado y que nos
sobraría tiempo para tomar unas cervezas, así que nos
pusimos manos a la obra y … un poco optimistas
fuimos pero tenemos el proyecto terminado y nos hemos tomado
las cervecas… Paso a continuación a detallar algunos
aspectos técnicos y a presentar algunos pantallazos del mismo:
Las cosas a tener en cuenta a la hora de conectar el servidor
web y el servidor de aplicaciones y que las credenciales solicitadas
por el servidor web (https client) se pasen entre las capas son:
Configurar el apache en modo https
y añadir las directivas siguiente
SSLVerifyClient optional_no_ca
SSLVerifyDepth 0
SSLOptions +ExportCertData +StdE
n
vVars
Configurar el modulo de comunicaciones entre apache web y
servidor tomcat (mod_jk) para que pase las credenciales a
la capa de aplicaciones
JkExtractSSL On
JkMount /* localhost_worker
Una vez conectadas ambas capas la capa web solicita, si el
usuario dispone de uno, el certificado de cliente y lo pasa a la capa
de aplicaciones. En ese punto entra el hook de
liferay que nos permite añadir una clase de autologin que
recoge esas credenciales las valida contra el servicio que hemos
creado en liferay y crear la sesión si el usuario ha
presentado un certificado de los que tiene asignados.
Para hacer esta segunda parte creamos un servicio con
el serice-builder que a grandes rasgos almacena el
fingerpint
del certificado público que el usuario va a presentar y lo
asocia a un usuario concreto. Es decir una relación 1:n entre el
usuario y los fingerprints de los certificados que tiene asociado ese usuario.
Además hemos creado un portet que permite dar de alta
estos fingerprints desde el control panel de liferay.
Hay bastantes detalles que no hemos contado
relacionados con el classloader y los proxies que se usan
para la invocación remota del servicio o temas relacionados con
el proceso que extrae el certificado de la petición
https, pero el post está quedando ya muy largo….