Recherche

Sommaire

Pages enfant
  • Configuration de shibboleth

Vous regardez une version antérieure (v. /wiki/display/PROJESUPECM/Configuration+de+shibboleth) de cette page.

afficher les différences afficher l'historique de la page

« Afficher la version précédente Vous regardez la version actuelle de cette page. (v. 11) afficher la version suivante »

Le consortium ESUP-Portail a financé un développement auprès de la société Nuxeo pour permettre l'utilisation de l'authentification shibboleth dans Nuxeo.

Vous pouvez vous référer à cette page pour plus d'informations sur le cahier des charges et la recette.

Pré-requis

Installation d'un SP provider : vous pouvez vous référer à la documentation disponible sur le site de la Fédération Education-Recherche

Avoir procédé à l'installation minimale de Nuxeo

Configuration de l'authentification Shibboleth

Opérations préliminaires

Récupérez dans un premier temps les deux jars nécessaires : nuxeo-platform-login-shibboleth-5.4.1.jar et nuxeo-platform-shibboleth-groups-web-5.4.1.jar.

Quelques modifications ont été apportées par rapport aux plugins disponibles sur le site de Nuxeo. A terme, nous espérons pouvoir utiliser les mêmes.

Déposez les dans le répertoire templates/custom/bundles (voir cette page pour plus d'informations sur l'utilisation des templates).

Configuration du fichier esup-login-config.xml

Éditez le fichier templates/custom/config/esup-login-config.xml comme suit et modifier le avec vos propres paramètres :

 <component name="ecm.shibboleth.config">
<!-- certains composants doivent être chargés avant lecture de ce fichier pour éviter que la configuration ici présente soit surchargée -->
<require>org.nuxeo.ecm.platform.ui.web.auth.defaultConfig</require>
<require>org.nuxeo.opensocial.OAuthFilter</require>
<require>org.nuxeo.ecm.platform.ui.web.auth.WebEngineConfig</require>
<require>org.nuxeo.ecm.platform.usermanager.UserManagerImpl</require>

<!-- chainage d'authentification, on garde l'authentification BASIC pour les flux RSS/REST/cmis ...) -->
  <extension target="org.nuxeo.ecm.platform.ui.web.auth.service.PluggableAuthenticationService" point="chain">
    <authenticationChain>
      <plugins>
        <plugin>BASIC_AUTH</plugin>
       <plugin>SHIB_AUTH</plugin>
        <plugin>ANONYMOUS_AUTH</plugin>
      </plugins>
    </authenticationChain>
  </extension>
<!-- configuration de l'authentification shibboleth -->
<extension target="org.nuxeo.ecm.platform.shibboleth.service.ShibbolethAuthenticationService"  point="config">
    <config>
      <uidHeaders>
        <!-- possibilité de préciser quel attribut servira d'identifiant suivant l'idp, ici on prend l'uid pour notre idp local -->
        <uidHeader idpUrl="https://idp.my-univ.fr/idp/shibboleth">uid</uidHeader>        
        <!-- pour tous les autres idp, on utilise l'eppn -->
        <default>eppn</default>
      </uidHeaders>
      <!--  URL de login du SP -->
      <loginURL>https://nuxeo.my-univ.fr/Shibboleth.sso/DS</loginURL>
      <!-- URL de logout du SP -->
      <logoutURL>https://nuxeo.my-univ.fr/Shibboleth.sso/Logout</logoutURL>
      <!-- URL vers laquellle on est redirigé une fois la déconnexion effectuée -->
     <logoutReturnURL>https//www.my-univ.fr/</logoutReturnURL>
      <!-- Mapping entre les attributs remontés via Shib et les attributs utilisateurs du schema user de nuxeo -->    
      <fieldMapping header="mail">email</fieldMapping>
      <fieldMapping header="givenName">firstName</fieldMapping>
      <fieldMapping header="sn">lastName</fieldMapping>
      <fieldMapping header="supannEtablissement">company</fieldMapping>
    </config>
  </extension>

  <!-- Gestion des utilisateurs admin/guest et des groupes virtuels -->
  <extension target="org.nuxeo.ecm.platform.usermanager.UserService"
    point="userManager">
   <userManager>
      <users>
        <anonymousUser id="Guest">
          <property name="firstName">Anonyme</property>
          <property name="lastName">Utilisateur</property>
           <property name="email">foo@bar.org</property>
       </anonymousUser>
      </users>
    <defaultAdministratorId>joe</defaultAdministratorId>
    <!-- en cas d'utilisation avec un annuaire, possibilite de choisir un groupe d'admins -->
    <administratorsGroup>myAdmingroup</administratorsGroup>
      <defaultGroup>members</defaultGroup>
    </userManager>
  </extension>

<!-- extension pour l'interface de gestion des groupes
     définit un séparateur et un répertoire de base, utilisé pour contruire l'arborescence des groupes (utile avec grouper) -->
<extension target="org.nuxeo.ecm.platform.shibboleth.web.service.ShibbolethGroupsService" point="config">
    <config>
      <parseString>:</parseString>
      <basePath>groupes:GroupesExternes</basePath>
    </config>
</extension>
</component>

Configuration du frontal apache

Il faut également configurer le frontal apache comme dans l'exemple donné ci-dessous (+ mod_jk ou mod_ajp):

ProxyPass /nuxeo ajp://localhost:8009/nuxeo
<Location "/nuxeo">
        AuthType shibboleth
        ShibRequestSetting requireSession 0
        ShibUseHeaders On
        Require shibboleth
</Location>

Les groupes "Shib"

Il est possible de définir des groupes en utilisant les attributs utilisateurs. Par exemple on peut construire un groupe de tous les utilisateurs d'un même établissement avec la définition suivante :

 currentUser.user.company =='{UAI}03314764N'

PB : Pour pouvoir utiliser les expressions régulières et tester les attributs SHIB multivalués correctement, il est nécessaire d'utiliser une bibliothèque juel plus récente que celle livrée par défaut dans nuxeo.

Il faut donc :

Récupérez la dernière version de juel sur http://juel.sourceforge.net/, supprimez nuxeo-dm-5.4.1-tomcat/lib/el-api.jar et nuxeo-dm-5.4.1-tomcat/nxserver/lib/juel-impl-2.1.2.jar et placez la version récupérée de juel (juel-2.2.3.jar) dans nuxeo-dm-5.4.1-tomcat/lib

A partir de là, il est maintenant possible d'utiliser des expressions plus complexes comme celle-ci :

(currentUser.user.affiliation=='student' andcurrentUser.user.username.matches('^g')) or
(currentUser.user.username.contains('jaune')) and (not
(currentUser.user.email.matches('.*@etu.u-bordeaux1.fr') or
currentUser.user.company==('CNRS')))

Attention cependant, pour rendre cela fonctionnel, il nous a été nécessaire de désactiver les vérifications de cohérences des expressions utilisées. Si jamais vous saisissez une définition de groupe inexacte, tout l'affichage des groupes ne fonctionnera plus comme attendu. A manier donc avec une grande précaution tant que l'implémentation n'est pas plus avancée.

Avec le plugin Shib, les groupes sont affichés de manière arborescente (le champ de saisie ne sert que pour  retrouver les utilisateurs). Ceci est particulièrement intéressant pour les établissements qui utilisent grouper car cela permet de retrouver la même arborescence dans nuxeo.

Pour l'instant, la présentation des groupes de façon arborescente n'est possible qu'avec le plugin shib.
Nous allons rapidement essayer de porter cet affichage pour les établissements qui utiliseraient CAS/LDAP et grouper.

Utilisation du multi-Directory

Il peut s'avérer utile pour un établissement de proposer une authentification shibboleth d'une part mais également de pouvoir s'appuyer sur son annuaire local pour récupérer des informations concernant ces utilisateurs (et ces groupes) d'autre part. Pour cela il faut définir deux sources de données pour les utilisateurs et les groupes : une source locale à nuxeo (dans laquelle seront stockés tous les groupes locaux et les utilisateurs authentifiés via shib mais non présent dans l'annuaire) et une source correspondant à l'annuaire de l'établissement.

Configuration du fichier multi-directory-config.xml

Editez le fichier templates/custom/config/multi-directory-config.xml comme suit avec vos propres paramètres :

 <component name="ecm.ldap.config">
  <require>org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory</require>
  <require>org.nuxeo.ecm.directory.sql.storage</require>

  <extension target="org.nuxeo.ecm.directory.multi.MultiDirectoryFactory"
    point="directories">
    <directory name="userDirectory">
      <!-- definition des sources de données pour les utilisateurs -->
      <!-- schema utilise -->
      <schema>user</schema>
      <!-- attributs correspondant (dans le schema nuxeo) à l'identifiant et au mot de passe -->
      <idField>username</idField>
      <readOnly>false</readOnly>
      <passwordField>password</passwordField>
      <!-- déclaration de la source ldap, definie plus bas -->
      <source name="ldapUserDirectory">
        <subDirectory name="ldapUserDirectory"/>
      </source>
      <!-- declaration de la source locale que noux allons definir dans un auter point d'extension -->
      <source name="sqlUserDirectory" creation="true">
        <subDirectory name="sqlUserDirectory"/>
      </source>
    </directory>
  </extension>

  <extension target="org.nuxeo.ecm.directory.multi.MultiDirectoryFactory"
    point="directories">
    <directory name="groupDirectory">
      <!-- définition des sources de données pour les groupes -->

      <!-- schema utilise -->
      <schema>group</schema>
       <!-- attribut correspondant à l'identifiant du groupe (dans schema nuxeo) -->
      <idField>groupname</idField>
      <readOnly>false</readOnly>
      <!-- déclaration de la source ldap pour les groupes, definie plus bas -->
      <source name="ldapGroupDirectory">
        <subDirectory name="ldapGroupDirectory"/>
      </source>
      <!-- déclaration de la source locale défini dans un autre fichier -->
      <source name="sqlGroupDirectory" creation="true">
        <subDirectory name="sqlGroupDirectory"/>
      </source>
    </directory>
  </extension>

  <extension target="org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory"
    point="servers">
     <!-- definition de la connexion ldap au serveur ldap-->
    <server name="default">
      <ldapUrl>ldap://ldap.univ-fr:389</ldapUrl>
      <bindDn>cn=applis,ou=admin,dc=my-univ,dc=fr</bindDn>
      <bindPassword>verySecret</bindPassword>
    </server>
  </extension>

  <extension target="org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory"
    point="directories">
    <!--défintion de l'annuaire comme source de données utilisateur -->
    <directory name="ldapUserDirectory">
      <!-- utilise la connexion qu'on vient de définir juste avant -->
      <server>default</server>
      <schema>user</schema>
      <idField>username</idField>
      <passwordField>password</passwordField>
      <searchBaseDn>ou=people,dc=my-univ,dc=fr</searchBaseDn>
      <searchClass>person</searchClass>
       <searchFilter>(&amp;(!(eduPersonAffiliation=affiliate))(status=valide))</searchFilter>
      <searchScope>onelevel</searchScope>
      <readOnly>true</readOnly>
      <cacheTimeout>3600</cacheTimeout>
      <cacheMaxSize>1000</cacheMaxSize>
      <querySizeLimit>0</querySizeLimit>
      <creationBaseDn>ou=people,dc=u-bordeaux1,dc=fr</creationBaseDn>
      <creationClass>top</creationClass>
      <creationClass>person</creationClass>
      <creationClass>organizationalPerson</creationClass>
      <creationClass>inetOrgPerson</creationClass>
      <rdnAttribute>uid</rdnAttribute>

      <!-- mapping d'attributs, doit être en cohérence avec ce qui est stipulé dans le fichier esup-login-config.xml
           Dans notre exemple, on utilisait l'uid pour notre idp local, on fait donc un mapping avec l'uid) -->
      <fieldMapping name="username">uid</fieldMapping>
      <fieldMapping name="firstName">givenName</fieldMapping>
      <fieldMapping name="lastName">sn</fieldMapping>
      <fieldMapping name="company">supannEtablissement</fieldMapping>
      <fieldMapping name="email">mail</fieldMapping>
      <references>
        <inverseReference field="groups" directory="groupDirectory"
          dualReferenceField="members" />
      </references>
    </directory>
  </extension>

  <extension target="org.nuxeo.ecm.directory.ldap.LDAPDirectoryFactory"
    point="directories">
     <!-- on définit maintenant l'annuaire comme source de données -->
    <directory name="ldapGroupDirectory">
      <!-- connexion utilisee -->
      <server>default</server>
      <!-- schema utilise -->
      <schema>group</schema>
      <!--attribut correspondant à l'identifiant (dans schema nuxeo) -->
      <idField>groupname</idField>
      <searchBaseDn>ou=groups,dc=my-univ,dc=fr</searchBaseDn>
      <searchFilter>(&amp;(objectClass=groupOfNames)(cn=groupes:my-univ:Personnels:*))</searchFilter>
      <searchScope>subtree</searchScope>
      <cacheTimeout>3600</cacheTimeout>
      <cacheMaxSize>1000</cacheMaxSize>
      <querySizeLimit>10000</querySizeLimit>
      <creationBaseDn>ou=grouper,dc=u-bordeaux1,dc=fr</creationBaseDn>
      <creationClass>top</creationClass>
      <creationClass>groupOfUniqueNames</creationClass>
      <rdnAttribute>cn</rdnAttribute>
      <!-- Mapping entre attributs du schema nuxeo et attributs de l'annuaire -->
      <fieldMapping name="groupname">cn</fieldMapping>
      <references>
        <ldapReference field="members" directory="ldapUserDirectory"
          forceDnConsistencyCheck="false"
          staticAttributeId="member"
          dynamicAttributeId="memberURL" />
        <ldapReference field="subGroups" directory="ldapGroupDirectory"
          forceDnConsistencyCheck="false"
          staticAttributeId="uniqueMember"
          dynamicAttributeId="memberURL" />
        <inverseReference field="parentGroups"
          directory="groupDirectory" dualReferenceField="subGroups" />
      </references>
    </directory>
  </extension>

</component>

Modification de la source de donnée locale

Il nous reste maintenant à définir la source de données locales :

Éditez le fichier templates/custom/config/default-sql-directories-bundle.xml comme suit avec vos propres paramètres :

 <?xml version="1.0"?>
<component name="org.nuxeo.ecm.directory.sql.storage">
  <implementation />
  <require>org.nuxeo.ecm.directory.sql.SQLDirectoryFactory</require>
  <extension target="org.nuxeo.ecm.directory.sql.SQLDirectoryFactory"
    point="directories">
   <!-- definition de la source de données locale pour les utilisateurs déclarée dans le fichier précédent -->
    <directory name="sqlUserDirectory">
       <!-- schema utilise -->
      <schema>user</schema>
       <!-- data source -->
      <dataSource>jdbc/nxsqldirectory</dataSource>

      <table>users</table>
      <idField>username</idField>
      <passwordField>password</passwordField>
      <passwordHashAlgorithm>SSHA</passwordHashAlgorithm>
      <autoincrementIdField>false</autoincrementIdField>
      <dataFile>users.csv</dataFile>
      <createTablePolicy>on_missing_columns</createTablePolicy>
      <querySizeLimit>15</querySizeLimit>

      <references>
        <inverseReference field="groups" directory="sqlGroupDirectory"
          dualReferenceField="members" />
      </references>

    </directory>

    <directory name="sqlGroupDirectory">
<!-- definition de la source de données locale pour les groupes déclarée dans le fichier précédent --> 
    <schema>group</schema>
      <dataSource>jdbc/nxsqldirectory</dataSource>
      <table>groups</table>
      <idField>groupname</idField>
      <dataFile>groups.csv</dataFile>
      <createTablePolicy>on_missing_columns</createTablePolicy>
      <autoincrementIdField>false</autoincrementIdField>

      <!-- Add 10 min cache to avoid refetching the groups during login -->
      <cacheTimeout>360</cacheTimeout>
      <cacheMaxSize>1000</cacheMaxSize>

      <references>
        <tableReference field="members" directory="userDirectory"
          table="user2group" sourceColumn="groupId" targetColumn="userId" schema="user2group"
          dataFile="user2group.csv" />
        <tableReference field="subGroups" directory="sqlGroupDirectory"
          table="group2group" sourceColumn="parentGroupId"
          targetColumn="childGroupId" schema="group2group" />
        <inverseReference field="parentGroups" directory="sqlGroupDirectory"
          dualReferenceField="subGroups" />
      </references>

    </directory>

  </extension>
</component>
  • Aucune étiquette