informatique:securite:idp_shibboleth

Shibboleth

Cette doc explique la mise en place du service Shibboleth dans le cadre de la fédération d'identité Renater. Ce service permet aux utilisateurs d'un membre de la fédération de se connecter aux ressources (=applications, services, …) offert par les membres de la fédération d'identité Renater à l'aide de leur identifiant de connexion habituels.

Pour authentifié les utilisateurs, le service Shibboleth fait appel traditionnellement au service CAS de l'établissment. Une fois la personne connectée via le CAS, le service Shibboleth se connecte à l'annuaire LDAP de l'établissment pour récupérer les informations de l'utilisateur (appelé attributs). Ces informations sont fournies aux ressources de la fédération les réclamant.

Cette documentation a été rédigé pour la version 2.4.5 de Shibboleth, sur la base de la documentation fournis par Renater : https://services.renater.fr/federation/docs/installation/idp
  • Apache qui servira de service HTTP en frontal
  • Un certificat valide pour le nom de domaine sur lequel le service d'IDP sera accessible
  • Tomcat
  • MySQL
  • Un service NTP fonctionnel synchronisant l'horloge de la machine
  • Un accès HTTPS ouvert sans proxy vers les URLs des services de la fédération Renater :

L'installation se fait à partir des sources du logiciel Shibboleth téléchargeable ici : https://shibboleth.net/downloads/identity-provider/. Une fois le tar.gz récupéré, décompresser dans le dossier de votre choix de la machine, puis :

  • Configuration de l'authentification CAS :
    • éditer le fichier src/main/webapp/WEB-INF/web.xml et ajouter le bloc suivant après le bloc <!-- Spring 2.0 listener used to load up the configuration --> (Documentation) :
       <!-- CAS Filter Configuration -->
          <context-param>
            <param-name>serverName</param-name>
            <param-value>[URL du service Shibboleth]</param-value>
          </context-param>
       
          <!-- CAS Authentication Filter -->
          <filter>
            <filter-name>CAS Authentication Filter</filter-name>
            <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
            <init-param>
              <param-name>casServerLoginUrl</param-name>
              <param-value>[URL du service CAS]/login</param-value>
            </init-param>
          </filter>
       
          <!-- CAS Validation Filter -->
          <filter>
            <filter-name>CAS Validation Filter</filter-name>
            <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
            <init-param>
              <param-name>casServerUrlPrefix</param-name>
              <param-value>[URL du service CAS]/casv3</param-value>
            </init-param>
          </filter>
       
          <!-- CAS HttpServletRequest Wrapper Filter -->
          <filter>
            <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
            <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
          </filter>
       
          <!-- CAS Assertion Thread Local Filter -->
          <filter>
            <filter-name>CAS Assertion Thread Local Filter</filter-name>
            <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
          </filter>
       
          <!-- CAS Filter for Shibb RemoteUser -->
          <filter-mapping>
            <filter-name>CAS Authentication Filter</filter-name>
            <url-pattern>/Authn/RemoteUser</url-pattern>
          </filter-mapping>
       
          <filter-mapping>
            <filter-name>CAS Validation Filter</filter-name>
            <url-pattern>/Authn/RemoteUser</url-pattern>
          </filter-mapping>
       
          <filter-mapping>
            <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
            <url-pattern>/Authn/RemoteUser</url-pattern>
          </filter-mapping>
          <filter-mapping>
            <filter-name>CAS Assertion Thread Local Filter</filter-name>
            <url-pattern>/Authn/RemoteUser</url-pattern>
          </filter-mapping>
    • télécharger le fichier suivant dans le dossier lib à la racine des sources : http://repo2.maven.org/maven2/org/jasig/cas/client/cas-client-core/3.3.3/cas-client-core-3.3.3.jar
  • Télécharger de la librairie client MySQL mysql-connector-java-5.1.40.jar dans le dossier lib à la racine des sources (FIXME : URL de téléchargement ?)
  • Mise en place du logo de l'établissement à la place du dummylogo :
    • déposer le logo de l'établissement (logo.png) dans le dossier src/main/webapp/images
    • remplacer les occurrences de dummylogo.png par logo.png dans les fichiers suivants :
      • src/main/webapp/error-404.jsp
      • src/main/webapp/error.jsp
      • src/main/webapp/login-error.jsp
      • src/main/webapp/login.jsp
      • src/main/webapp/logout.jsp
      • src/main/webapp/nonresp-login.jsp

Pour finir, lancer le script install.sh à la racine des sources et répondre au question qu'il pose :

  • fournir le chemin d'installation : /opt/shibboleth245
  • le nom de domaine sur lequel le service de l'IDP sera accessible
  • le mot de passe du fichier keystore propre au service (différent du fichier keystore de Tomcat) : par défaut, mettre changeit
  • FIXME : autre ?

Le script va s'occuper de générer le fichier idp.war ainsi que la configuration initiale de l'application et déployer le tout dans le dossier choisi. Corriger ensuite les droits du dossiers logs dans le répertoire de déployer pour faire en sorte que l'utilisateur du service Tomcat est les droits d'écriture dedans.

Le service devant interagir avec le serveur CAS de l'établissement, le certificat SSL utilisé par celui-ci doit être reconnu comme valide par le keystore utilisé par le service Tomcat. Pour cela, il peut être nécessaire d'ajouter le certificat SSL de l'autorité de certification utilisé par l'établissement au keystore.</code>

==== Configuration ====

=== Metadata de la fédération ===

La fédération fournis un fichier de metadata contenant l'ensemble des informations techniques des acteurs de la fédération d'identité. Ce fichier de metadata est téléchargé régulièrement par le service, validé à l'aide du certificat de signature de la fédération et chargé par le service.

Pour configurer les metadata de la fédération, il faut :

  • éditer le fichier conf/relying-party.xml :
    • Mettre l'attribut includeAttributeStatement de <rp:ProfileConfiguration xsi:type="saml:ShibbolethSSOProfile" ~~> à true
    • Dé-commenter le bloque <metadata:MetadataProvider id="URLMD" ~~> et l'adapter comme suit :
              <metadata:MetadataProvider id="URLMD" xsi:type="metadata:FileBackedHTTPMetadataProvider"
                                metadataURL="https://metadata.federation.renater.fr/renater/main/main-all-renater-metadata.xml"
                                backingFile="/opt/shibboleth-idp245/metadata/main-all-renater-metadata.xml">
                  <metadata:MetadataFilter xsi:type="metadata:ChainingFilter">
                      <metadata:MetadataFilter xsi:type="metadata:RequiredValidUntil" 
                                      maxValidityInterval="P0Y0M0DT0H0M0.000S" />
                      <metadata:MetadataFilter xsi:type="metadata:SignatureValidation"
                                      trustEngineRef="shibboleth.MetadataTrustEngine"
                                      requireSignedMetadata="true" />
                          <metadata:MetadataFilter xsi:type="metadata:EntityRoleWhiteList">
                          <metadata:RetainedRole>samlmd:SPSSODescriptor</metadata:RetainedRole>
                      </metadata:MetadataFilter>
                  </metadata:MetadataFilter>
              </metadata:MetadataProvider>
      • Dans le bloque précédent, faite tout particulièrement attention :
        • à la valeur de l'attribut metadataURL qui correspond à l'URL de téléchargement du fichier des metadata de la fédération
        • à la valeur de l'attribut backingFile qui correspond au chemin local sur le serveur de stockage du fichier des metadata de la fédération
        • à la valeur de l'attribut maxValidityInterval qui correspond à la durée maximale de validité des metadata : dans le cadre de la fédération Renater, cet attribut doit valoir P0Y0M0DT0H0M0.000S (=n'expire jamais).
    • Dé-commenter le bloque <security:TrustEngine id="shibboleth.MetadataTrustEngine" ~~> et l'adapter comme suit :
          <security:TrustEngine id="shibboleth.MetadataTrustEngine" xsi:type="security:StaticExplicitKeySignature">
              <security:Credential id="MyFederation1Credentials" xsi:type="security:X509Filesystem">
                  <security:Certificate>/opt/shibboleth-idp245/credentials/renater-metadata-signing-cert-2016.pem</security:Certificate>
              </security:Credential>
          </security:TrustEngine>
      • Dans le bloque précédent, faite tout particulièrement attention au contenu de la balise <security:Certificate> qui correspond au chemin local de stockage du fichier contenant le certificat utilisé pour validé la signature des metadata de la fédération
  • Télécharger le fichier https://metadata.federation.renater.fr/renater/main/main-all-renater-metadata.xml dans le dossier metadata et faite le appartenir à l'utilisateur du service Tomcat
Le service devant télécharger régulièrement les metadatas de la fédération sur les serveurs de Renater, le certificat SSL utilisé par ceux-ci doivent être reconnu comme valide par le keystore utilisé par le service Tomcat. Pour cela, il peut être nécessaire d'ajouter le certificat SSL de l'autorité de certification utilisé par Renater au keystore.

=== Attributs ===

== Récupération des attributs ==

La configuration de la récupération des attributs est défini dans le fichier conf/attribute-resolver.xml. Éditer ce fichier pour :

  • Dé-commenter les bloques de définitions des attributs standards :
    • <!-- Schema: Core schema attributes-->
    • <!-- Schema: inetOrgPerson attributes-->
    • <!-- Schema: eduPerson attributes -->
  • Ajouter la définition de l'attribut eduPersonTargetedID :
            <resolver:AttributeDefinition id="eduPersonTargetedID"
                    xsi:type="ad:SAML2NameID" nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
                    sourceAttributeID="persistentID">
                    <resolver:Dependency ref="storedId" />
                    <resolver:AttributeEncoder xsi:type="enc:SAML1XMLObject"
                            name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" />
                    <resolver:AttributeEncoder xsi:type="enc:SAML2XMLObject"
                            name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" friendlyName="eduPersonTargetedID" />
            </resolver:AttributeDefinition>
  • Dé-commenter le bloque de définition du connecteur à l'annuaire LDAP <resolver:DataConnector id="myLDAP" ~~> et modifier le comme suit :
        <resolver:DataConnector id="myLDAP" xsi:type="dc:LDAPDirectory"
            ldapURL="ldap://ldap.univ.fr" 
            baseDN="ou=people,dc=univ,dc=fr" 
            principal="uid=shibboleth,ou=sysaccounts,dc=univ,dc=fr"
            principalCredential="xxxxxx">
            <dc:FilterTemplate>
                <![CDATA[
                    (uid=$requestContext.principalName)
                ]]>
            </dc:FilterTemplate>
        </resolver:DataConnector>
    • Dans ce bloque, faite tout particulièrement attention :
      • à l'attribut ldapURL qui doit contenir l'URL de connexion à l'annuaire LDAP
      • à l'attribut baseDN qui doit contenir le baseDN de recherche des utilisateurs dans l'annuaire
      • à l'attribut principal qui doit contenir le DN de l'utilisateur de connexion à l'annuaire LDAP
      • à l'attribut principalCredential qui doit contenir le mot de passe de l'utilisateur de connexion à l'annuaire LDAP
      • au contenu de la balise <dc:FilterTemplate> qui doit contenir le filtre de recherche de l'utilisateur dans l'annuaire LDAP. Dans ce filtre, le mot clé $requestContext.principalName sera remplacé par le login utilisé par l'utilisateur pour se connecter au service CAS de l'établissement
  • Ajouter le bloque suivant de connexion à la base de données MySQL de stockage de l'identifiant persistant des connexions utilisateurs <resolver:DataConnector id="storedId" ~~> :
        <resolver:DataConnector id="storedId" xsi:type="dc:StoredId"
                            xmlns="urn:mace:shibboleth:2.0:resolver:dc" generatedAttributeID="persistentID"
                            sourceAttributeID="uid" salt="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
          <resolver:Dependency ref="myLDAP" />
          <dc:ApplicationManagedConnection jdbcDriver="com.mysql.jdbc.Driver" jdbcURL="jdbc:mysql://localhost/shibboleth"
                                       jdbcUserName="shibboleth" jdbcPassword="xxxxxxx" />
        </resolver:DataConnector>
    • Dans ce bloque, faite tout particulièrement attention :
      • à l'attribut salt qui doit contenir une chaîne alfa-numérique généré aléatoirement
      • à l'attribut jdbcURL qui doit contenir l'URI JDBC de connexion à la base MySQL au format jdbc:mysql://[hostname]/[db name]
      • à l'attribut jdbcUserName qui doit contenir le nom d'utilisateur de connexion à la base de données MySQL
      • à l'attribut jdbcPassword qui doit contenir le mot de passe de connexion à la base de données MySQL

Créer ensuite la base de données MySQL comme configurée et créer à l'intérieur la table shibpid avec la requête suivante :

CREATE TABLE `shibpid` (
  `localEntity` text NOT NULL,
  `peerEntity` text NOT NULL,
  `principalName` VARCHAR(255) NOT NULL DEFAULT '',
  `localId` VARCHAR(255) NOT NULL,
  `persistentId` VARCHAR(36) NOT NULL,
  `peerProvidedId` VARCHAR(255) DEFAULT NULL,
  `creationDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `deactivationDate` TIMESTAMP NULL DEFAULT NULL,
  KEY `persistentId` (`persistentId`),
  KEY `persistentId_2` (`persistentId`,`deactivationDate`),
  KEY `localEntity` (`localEntity`(16),`peerEntity`(16),`localId`),
  KEY `localEntity_2` (`localEntity`(16),`peerEntity`(16),`localId`,`deactivationDate`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

== Filtrage des accès aux attributs par les ressources de la fédération ==

Le filtrage d'accès aux attributs par les ressources de la fédération est configuré :

  • d'une part dans le fichier conf/attribute-filter.xml : ce fichier dois contenir les <AttributeFilterPolicy> suivant :
      <!-- Règle permissive renvoyant l'attribut transientID à n'importe quel SP -->
      <AttributeFilterPolicy id="releaseTransientIdToAnyone">
        <PolicyRequirementRule xsi:type="basic:ANY" />
     
        <!-- identifiant utilisateur de session, opaque, généré automatiquement par l'IdP Shibboleth (anciennement appelé nameId dans la fédération du CRU) -->
        <AttributeRule attributeID="transientId">
          <PermitValueRule xsi:type="basic:ANY" />
        </AttributeRule>
     
      </AttributeFilterPolicy>
     
     
      <!-- Règle d'envoi d'un attribut de type targetedID à tout SP de la fédération Education-Recherche-->
      <AttributeFilterPolicy id="releaseTargetedID">
     
        <PolicyRequirementRule xsi:type="saml:AttributeRequesterInEntityGroup" groupID="https://federation.renater.fr/" />
     
        <!-- identifiant utilisateur opaque, persistent et spécifique à un couple SP/IdP -->
        <AttributeRule attributeID="eduPersonTargetedID">
          <PermitValueRule xsi:type="basic:ANY" />
        </AttributeRule>
  • d'autre part par un ensemble de fichiers de configuration fournis par la fédération et mis à jours régulièrement. Ces fichiers de configuration sont définis dans le fichier conf/service.xml dans lequel il faut :
    • Modifier le bloque <srv:Service id="shibboleth.AttributeFilterEngine" ~~> comme suit :
          <srv:Service id="shibboleth.AttributeFilterEngine" xsi:type="attribute-afp:ShibbolethAttributeFilteringEngine"
      configurationResourcePollingFrequency="PT1H0M0.000S"
      configurationResourcePollingRetryAttempts="3"
      >
              <srv:ConfigurationResource url="https://federation.renater.fr/renater/filtres/renater-attribute-filters-all.xml" xsi:type="resource:FileBackedHttpResource" file="/opt/shibboleth-idp245/conf/renater-attribute-filters-all.xml"/>
       
              <srv:ConfigurationResource url="https://federation.renater.fr/renater/filtres/renater-attribute-filters-community.xml" xsi:type="resource:FileBackedHttpResource" file="/opt/shibboleth-idp245/conf/renater-attribute-filters-community.xml"/>
       
              <srv:ConfigurationResource url="https://federation.renater.fr/edugain/filtres/edugain-attribute-filters-all.xml" xsi:type="resource:FileBackedHttpResource" file="/opt/shibboleth-idp245/conf/edugain-attribute-filters-all.xml"/>
       
       
              <srv:ConfigurationResource file="/opt/shibboleth-idp245/conf/attribute-filter.xml" xsi:type="resource:FilesystemResource"/>
          </srv:Service>
      • Dans ce bloque, faite tout particulièrement attention :
        • à l'attribut configurationResourcePollingFrequency qui doit contenir la fréquence de rafraîchissement des fichiers de configuration
        • à l'attribut configurationResourcePollingRetryAttempts qui doit contenir le nombre de tentative de rafraîchissement des fichiers de configuration
        • aux balises <srv:ConfigurationResource url="~~" xsi:type="resource:FileBackedHttpResource" file="~~"/> qui déclare les fichiers de configurations récupérés auprès de la fédération par le service. L'attribut url contient l'URL de téléchargement du fichier et l'attribut file le chemin de stockage du fichier

Il est nécessaire ensuite de télécharger une première fois manuellement les fichiers de configuration fournis par la fédération et de les faire appartenir à l'utilisateur du service Tomcat :

wget -O /opt/shibboleth-idp245/conf/renater-attribute-filters-all.xml https://federation.renater.fr/renater/filtres/renater-attribute-filters-all.xml
wget -O /opt/shibboleth-idp245/conf/renater-attribute-filters-community.xml https://federation.renater.fr/renater/filtres/renater-attribute-filters-community.xml
wget -O /opt/shibboleth-idp245/conf/edugain-attribute-filters-all.xml https://federation.renater.fr/edugain/filtres/edugain-attribute-filters-all.xml
chown tomcat: /opt/shibboleth-idp245/conf/renater-attribute-filters-all.xml /opt/shibboleth-idp245/conf/renater-attribute-filters-community.xml /opt/shibboleth-idp245/conf/edugain-attribute-filters-all.xml
Le service devant télécharger régulièrement les fichiers de configuration auprès de la fédération sur les serveurs de Renater, le certificat SSL utilisé par ceux-ci doivent être reconnu comme valide par le keystore utilisé par le service Tomcat. Pour cela, il peut être nécessaire d'ajouter le certificat SSL de l'autorité de certification utilisé par Renater au keystore.

===== Procédures =====

==== Remettre en place le couple clé privée/certificat d'une ancienne installation ====

Suite à une réinstallation, il peut être nécessaire de remettre en place un ancien couple clé privée/certificat d'une ancienne installation pour conserver celui décléré auprès de la fédération. Pour cela, il faut, alors que Tomcat est éteint :

  • Récupérer les fichiers suivant dans le dossier credentials de l'ancienne installation et les mettre dans le même dossier de la nouvelle :
    • idp.crt
    • idp.key
    • idp.jks
  • Éditer le fichier metadata/idp-metadata.xml et remplacer le contenu des deux balises <ds:X509Certificate> par le contenu du fichier idp.crt en ne prenant que ce qu'il y a entre les lignes -----BEGIN CERTIFICATE----- et -----END CERTIFICATE-----
  • informatique/securite/idp_shibboleth.txt
  • Dernière modification : 2016/12/01 18:59
  • de bn8