En Mi Local Funciona

Technical thoughts, stories and ideas

Acceso federado mediante SAML 2.0 en Atlassian

Publicado por Alejandro López Rubio el

AtlassianSSOConfluencemod_auth_mellon

¿Alguna vez has tenido la necesidad de implantar un SSO basado en SAML 2.0 para tus herramientas Atlassian?

Hasta ahora, era posible llevar a cabo esta tarea mediante el uso de add-ons de terceros, pero en este artículo vamos a configurarlo mediante herramientas Open Source.

Pare ello utilizaremos el módulo de Apache Mod_Auth_Mellon, junto con un add-on Open Source (lo instalaremos sobre Confluence en este ejemplo) y algunas modificaciones en el sistema.

Requisitos previos necesarios:

Antes de comenzar, debemos asegurarnos de cumplir estos requisitos:

  • Un servidor web Apache donde tengamos configurado correctamente un sitio web HTTPS ( https://atsistemas/confluence.com ).
  • Un proveedor de identidad SAML (IdP).
  • Una cuenta en ese IdP.
  • Un atributo que se puede usar como nombre de usuario en Confluence (por ejemplo, eduPersonPrincipalName). Los atributos para el nombre completo y el correo electrónico son opcionales, pero se recomiendan. En este caso, asumimos que se pueden usar "mail" y "displayName".
  • El nombre de usuario de la cuenta de administrador. Por lo tanto, si elige eduPersonPrincipalName como atributo para el nombre de usuario, debe conocer su propio valor (por ejemplo, "confluence@atsistemas.com").
  • Disponer de una instancia de Confluence en funcionamiento para realizar las configuraciones.

Una vez que disponemos de todos estos requisitos anteriores, vamos a proceder a comenzar la implantación del sistema de SAML 2.0 para el acceso federado en nuestra instancia de Confluence.

Mod auth mellon

¿Qué es mod auth mellon?

Mod auth mellon es un módulo de autenticación para Apache. Autentica al usuario contra un IdP SAML 2.0 (Permite versiones anteriores) y otorga acceso a los directorios en función de los atributos recibidos del IdP.

Proceso de instalación de Mod auth mellon

En nuestro caso, hemos realizado las pruebas sobre una máquina Ubuntu 16.04, pero esta disponible para la gran mayoría de versiones de Linux, plataformas Windows y Mac.

1º Procedemos a instalar los módulos de Apache necesarios:

apt-get install libapache2-mod-auth-mellon apache2

2º Una vez instalado el modulo, accedemos a la ruta /etc/httpd/ y creamos la carpeta mellon, en esta ruta almacenaremos los metadatos del proveedor de identidad en formato XML en un archivo llamado provedorIdp.xml .

cd /etc/httpd/

mkdir mellon

cd mellon/

3º Accedemos a la ruta /etc/httpd/mellon y creamos los certificados basados en el xml de nuestro Idp

openssl req -new-newkey rsa:4096 -days 3650 -nodes -x509 -keyout sp.key -out sp.crt

Con este paso obtendremos en la ruta dos ficheros adicionales, que serán .key y .cert con el nombre del xml de nuestro Idp.

4º Procedemos a la configuración del vhost (Esta configuración es una muestra orientativa, en nuestro caso en /etc/httpd/conf.d y se debe adaptar a los parámetros de nuestra configuración existente):

ServerName atsistemas.com
 
ProxyRequestsOff
<Proxy http://ip6-localhost:8090>
RequireAllGranted
</Proxy>
 
#Podemos configurar los datos con ipv4 e Ipv6 y el número de puerto que escucha las peticiones.
 
ProxyPass/mellon/ !
ProxyPass/http://ip6-localhost:8090/
ProxyPassReverse/http://ip6-localhost:8090/
 
 
#Mobiletheme doesnothonour new seraph values for loginURL, so we have to redirect that
RewriteEngineon
RewriteCond    %{QUERY_STRING} ^originalUrl=(.*)$      [NC]
Rewriterule    ^/plugins/servlet/mobile/login          /mellon/login?ReturnTo=%1 [R,NE]
 
#Afterupgrading to 5.6 the mobile login links were changed. 
#Newredirects needed:
RewriteCond    %{QUERY_STRING} ^os_destination=%2Fplugins%2Fservlet%2Fmobile%3F%23content%2Fview%2F(.*)$ [NC]
RewriteRule    ^/login.action  /mellon/login?ReturnTo=/pages/viewpage.action?pageId=%1 [R,NE]
 
 
#Removethe jsessionid from theURL, to prevent 404 errorswhen
# unauthenticated visitorstryto access a protected resource.
ReWriteRule    ^(.*);jsessionid=[A-Za-z0-9]+(.*)$ $1$2 [R,NE]
 
 
<Location>
MellonEnable"info"
MellonSecureCookieOn
MellonSessionDumpOff
#Asociamos el atributo que más nos convenga.
MellonUser"eduPersonPrincipalName"
MellonSamlResponseDumpOff
MellonEndpointPath"/mellon"
#Modificamos por la ruta de nuestros ficheros generados en paso anterior.
MellonSPPrivateKeyFile/etc/apache2/mellon/sp.key
MellonSPCertFile/etc/apache2/mellon/sp.crt
MellonIdPMetadataFile/etc/apache2/mellon/idp.xml
 
RequestHeaderunsetCONF_FULL_NAME
RequestHeadersetCONF_FULL_NAME"%{MELLON_displayName}e"env=MELLON_displayName
 
RequestHeaderunsetCONF_EMAIL
RequestHeadersetCONF_EMAIL"%{MELLON_mail}e"env=MELLON_mail
</Location>

Después de este proceso, deberías poder descargar los metadatos del proveedor de servicios desde https://tuDominioConfigurado/mellon/metadata y usarlos para agregarlos a su IdP, creando así una relación de confianza.

Y una vez hecho esto, deberías poder usar la autenticación federada accediendo a https://tuDominioConfigurado/mellon/login?ReturnTo=%2F (Llegarás a tu web de login federado).

Implantación de las configuraciones dentro de la instancia de Confluence

1º Lo primero es parar la instancia de Confluence, para poder modificarlos ficheros de configuración.

sudo bash /opt/atlassian/confluence/bin/shutdown.sh

En este caso, nuestra ruta de instalación es la anterior. Es conveniente mediante un ps -e comprobar que han parado correctamente los servicios del sistema.

2º Debemos descargar el add-on Open source remoteUserAuth.jar desde https://github.com/chauth/confluence_http_authenticator/tree/master/releases, en nuestro caso la última versión existente fue la 2.7.3, pero suelen ir sacando nuevas revisiones.

3º El remoteUserAuth.jar debemos ubicarlo en la ruta de nuestra instancia (nuestro caso es /opt/atlassian/confluence/ ) y dentro de esta ruta en las subcarpetas confluence /WEB-INF/lib (en esta ruta encontraremos más .jar de la instancia).

4º Necesitaremos el archivo de configuración del remoteUserAuth.jar, lo podemos obtener desde este enlace https://github.com/chauth/confluence_http_authenticator/blob/master/conf/remoteUserAuthenticator.properties y debemos ubicarlo dentro de la ruta de Confluence, en confluence/WEB-INF/classes, donde por defecto viene bien configurado. Solo es recomendable cambiar la línea convert.to .utf8 = verdadero (por defecto está en false).

5º Debemos cambiar el fichero confluence/WEB-INF/classes/seraph-config.xml y cambiar los siguientes valores:

<init-param>
     <param-name>login.url</param-name>
     <param-value>/login.action?os_destination=${originalurl}</param-value>
 </init-param>
 <init-param>
     <param-name>link.login.url</param-name>
     <param-value>/login.action</param-value>
 </init-param>

A estos otros:

<init-param>
    <param-name>login.url</param-name>
    <param-value>/mellon/login?ReturnTo=${originalurl}</param-value>
</init-param>
<init-param>
    <param-name>link.login.url</param-name>
    <param-value>/mellon/login?ReturnTo=${originalurl}</param-value>
</init-param>

Además, cambiar el autenticador:

<authenticator class="com.atlassian.confluence.user.ConfluenceAuthenticator"/>

con estos datos:

<authenticator class="shibauth.confluence.authentication.shibboleth.RemoteUserAuthenticator"/>

Ahora debemos de poder utilizar inicios de sesión federados.

Configurar Cierre de sesión en Confluence

El enlace del botón de cierre de sesión se puede configurar en Confluence, pero el archivo de configuración se encuentra dentro de un archivo JAR llamado confluence-x.x.x.jar, donde las x es la versión de Confluence. Debe extraer el archivo JAR y editar el archivo xwork.xml en WEB-INF/classes.

Puedes consultar como editar un jar aquí: https://confluence.atlassian.com/confkb/how-to-edit-files-in-confluence-jar-files-103711179.html

1º Descomprimimos el jar con Winrar u otro descompresor:

mkdir /tmp/jar unzip /opt/atlassian/confluence/confluence/WEB-INF/lib/confluence-x.x.x.jar -d /tmp/jar

Ahora /tmp/jar debe contener el contenido del jar. Copia el archivo xwork.xml a /rutaInstancia/confluence/WEB-INF/classes y cambiamos esta parte:

<actionname="logout"class="com.atlassian.confluence.user.actions.LogoutAction">
<interceptor-refname="defaultStack"/><resultname="error"type="velocity">/logout.vm</result>
<resultname="success"type="redirect">/login.action?logout=true</result>
</action>

a esta otra:

<actionname="logout"class="com.atlassian.confluence.user.actions.LogoutAction">
<interceptor-refname="defaultStack"/>
<resultname="error"type="velocity">/logout.vm</result>
<resultname="success"type="redirect">/mellon/logout?ReturnTo=%2Fdashboard.action</result>
</action>

Siguiendo estos pasos, ya debemos de poder acceder con nuestro acceso Federado por SAML 2.0 y poder cerrar sesión correctamente.

Configuraciones avanzadas para la utilización de grupos de forma dinámica

Para ello debemos editar el fichero remoteUserAuthenticator.properties donde vamos a configurar los siguientes aspectos:

  • Asignación de rol por defecto para acceso a Confluence.
  • Asignación dinámica de roles basada en los atributos recibidos.
  • Purga de Roles.

Este fichero es el encargado de indicar al programa Java que hemos incluido en las librerías de Confluence, las configuraciones y parámetros que debe leer de las cabeceras de ModAuthMellon.

Asignación de rol de acceso

En este apartado podemos configurar roles predeterminados para los accesos válidos en el IdP.

Estos roles son útiles para proporcionar acceso a Confluence y páginas abiertas a cualquier usuario con licencia. Podemos índicar varios grupos sí es necesario, utilizando el separador ",".

default.roles=federated-users
Asignación dinámica de roles

Esta opción nos permite capturar atributos pasados dentro de las cabeceras, y con ellos, asignar dinámicamente grupos durante el inicio del usuario.
En este caso vamos primero a capturar de las cabeceras que proporciona AuthMellon:

header.remote_user=REMOTE_USER
header.email=CONF_EMAIL
header.fullname=CONF_FULLNAME
#CONF_GROUPS es la cabecera que capturamos con los datos necesarios en formato "some:urn:group1:group2" con los atributos que utilizaremos para generar los roles y los almacenamos en atSistemas.
dynamicroles.header.CONF_GROUPS = atSistemas

Una vez realizado esto, vamos a transformar los datos, para poder utilizarlos.

Nota: En caso de configurar los atributos, podemos simplificar los datos recibidos y evitar esta transformación o utilizar "alias".

En este caso vamos a configurar la cadena para coger solo una parte y mediante "$1", vamos a concatenar con la nomenclatura de los grupos que queremos asignar.

dynamicroles.mapper.atSistemas.match=some\:urn\:(\\w+):(.*)
dynamicroles.mapper.atSistemas.casesensitive = false
dynamicroles.mapper.atSistemas.transform=$1-users, $1-admins

Nota: Es importante habilitar la función de debug, para poder localizar los fallos de asignación o transformación de variables en este proceso. Para ello incluimos shibauth.confluence.authentication en "inicio y perfiles" de la administración de Confluence, en modo DEBUG, y mediante la consola consultamos atlassian/confluencedata/logs/atlassian-confluence.log (logs en la carpeta Data).

Purga de roles

Finalmente, podemos configurar la opción de comprobar si los roles del usuario coinciden con los que tenía previamente asignados. En caso de no ser así, podemos eliminarlos con este sistema.

Solo funciona en la fase de inicio en Confluence, si se hacen cambios y está conectado, no surtirán efecto hasta el próximo inicio:

#purge.roles = alum.* , cs101
purge.roles = confluence-administrators , federated-users

¡Y aquí termina este post!. Si te ha gustado, ¡no dudes en seguirnos en Twitter!.