Documentation :
Le fichier de configuration attribute-resolver.xml
définit les sources de données pour les attributs utilisateurs ainsi que les attributs qui vont en être extraits. Chaque attribut fait référence à une (ou plusieurs) source de données dont il dépend ; plusieurs types de sources de données sont disponibles.
Les sources de données :
Static
) : permet de définir un ensemble d'attributs ayant une valeur fixe. Ce type de source est utile lorsque tous les utilisateurs d'un organisme ont la même valeur pour un attribut. Exemple d'usage : identifiant de l'organisme, entitlement pour l'accès à une ressource.RelationalDatabase
)
: permet d'interroger une base de données SQL.LDAPDirectory
) : interrogation d'un annuaire LDAPScript
) : construction d'attributs à partir de scripts JavaScript ;ComputedId
ou StoredId
) : permet de calculer/charger un identifiant opaque. Exemple d'utilisation : calcul de l'attribut targetedId/persistentId.Par ailleurs, il existe différents types d'attributs qui permettent de calculer un attribut à partir de plusieurs sources ou de transformer un attribut avant de le transmettre en SAML.
Des exemples de types d'attributs :
Simple
) : le type standard d'attribut issu d'une source ou d'un autre attribut, sans transformation de la valeur de l'attribut.Scoped
) : permet de définir un attribut + domaine. Exemple : eduPersonScopedAffiliation
(student@univ-test.fr).RegexSplit
) : permet d'extraire une partie de la valeur d'un attribut, à partir d'une expression régulière.Mapped
) : on transforme les valeurs issues d'un ou plusieurs sources.Template
) : Velocity est un moteur de template ; vous pouvez utiliser ce format de template pour construire un nouvel attribut (http://velocity.apache.org/).Script
) : permet de construire à partir d'un script ECMAScript.
Nous vous invitons à expérimenter ces possibilités de configuration en adaptant votre fichier attribute-resolver.xml
.
Documentation :
persistentID
à la fois comme format de NameID (alternatif au transcientID
) et de générer un attribut eduPersonTargetedID
via le connecteur StoreIdConnector
. Voir cette documentation
Le persistentID
est un format particulier d'identifiant de session. Il est composé d'un triplet concaténé (Identifiant du SP + identifiant de l'IdP + identifiant de l'utilisateur en hash). C'est donc un identifiant opaque et persistant dans le temps. Il est unique par utilisateur et par ressource. Cet attribut est également appelé le persistentID en SAML2.
L'IdP Shibboleth vous propose deux alternatives pour gérer les persistentID
:
persistentID
: cette approche est simple à mettre en oeuvre. Elle présente cependant des limitations : il n'est pas possible de retrouver un utilisateur connaissant son persistentID, il n'est pas possible de révoquer ou modifier la valeur du persistentID
d'un utilisateur ;Dans le chapitre suivant nous allons mettre en oeuvre des persistentID stockés en base de données.
Nous installons le serveur MariaDB (version open source de MySQL distribué avec CentOS 7) et créons dans la foulée la base de données :
$> sudo yum install mariadb-server
Une fois le serveur installé, on le démarre et on le configure :
$> sudo systemctl start mariadb $> mysql -u root mysql> SET NAMES 'utf8'; SET CHARACTER SET utf8; CHARSET utf8; CREATE DATABASE IF NOT EXISTS shibboleth CHARACTER SET=utf8; USE shibboleth; mysql> connect shibboleth mysql> CREATE TABLE IF NOT EXISTS shibpid ( localEntity VARCHAR(255) NOT NULL, peerEntity VARCHAR(255) NOT NULL, persistentId VARCHAR(255) NOT NULL, principalName VARCHAR(255) NOT NULL, localId VARCHAR(255) NOT NULL, peerProvidedId VARCHAR(255) NULL, creationDate TIMESTAMP NOT NULL, deactivationDate TIMESTAMP NULL, PRIMARY KEY (localEntity, peerEntity, persistentId) ) DEFAULT CHARSET=utf8;
On vérifie que la base est bien constituée :
mysql> DESCRIBE shibpid; +------------------+--------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +------------------+--------------+------+-----+-------------------+-----------------------------+ | localEntity | varchar(255) | NO | PRI | NULL | | | peerEntity | varchar(255) | NO | PRI | NULL | | | persistentId | varchar(255) | NO | PRI | NULL | | | principalName | varchar(255) | NO | | NULL | | | localId | varchar(255) | NO | | NULL | | | peerProvidedId | varchar(255) | YES | | NULL | | | creationDate | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | | deactivationDate | timestamp | YES | | NULL | | +------------------+--------------+------+-----+-------------------+-----------------------------++ 8 rows in set (0.00 sec)
Nous allons à présent créer l'utilisateur privilégié pour la connexion à cette table :
mysql> USE mysql; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> INSERT INTO user (Host,User,Password,Select_priv, Insert_priv,Update_priv,Delete_priv,Create_tmp_table_priv, Lock_tables_priv,Execute_priv) VALUES ('localhost','shibboleth',PASSWORD('demo'), 'Y','Y','Y','Y','Y','Y','Y'); Query OK, 1 row affected, 3 warnings (0.00 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec) mysql> GRANT ALL ON shibboleth.* TO 'shibboleth'@'localhost'IDENTIFIED BY 'demo'; Query OK, 0 rows affected (0.00 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec) mysql> exit
Vérifiez que l'utilisateur « shibboleth » a bien été créé en tentant une connexion (mot de passe 'demo') :
$> mysql -u shibboleth -p Enter password: **demo** Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 4 Server version: 5.5.65-MariaDB MariaDB Server Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]>
Le fichier saml-nameid.properties
contrôle le format des NameID ; vous devez l'éditer :
... # For computed IDs, set a source attribute and a secret salt: **idp.persistentId.sourceAttribute = eduPersonPrincipalName** #idp.persistentId.useUnfilteredAttributes = true # Do *NOT* share the salt with other people, it's like divulging your private key. #idp.persistentId.algorithm = SHA **idp.persistentId.salt = XXXXXXXXXX** # BASE64 will match V2 values, we recommend BASE32 encoding for new installs. idp.persistentId.encoding = BASE32 # To use a database, use shibboleth.StoredPersistentIdGenerator **idp.persistentId.generator = shibboleth.StoredPersistentIdGenerator** # For basic use, set this to a JDBC DataSource bean name: **idp.persistentId.dataSource = MyDataSource** # For advanced use, set to a bean inherited from shibboleth.JDBCPersistentIdStore #idp.persistentId.store = MyPersistentIdStore # Set to an empty property to skip hash-based generation of first stored ID **idp.persistentId.computed = shibboleth.ComputedPersistentIdGenerator** ...
Vous devez également ajouter un certain nombre d'objets pour produire cet attribut:
Nous allons définir la source de données au sein du fichier /opt/shibboleth-idp/conf/global.xml
:
<!-- source de données MariaDB: accès bas niveau à la base --> <bean id="myDataSource" class="org.apache.tomcat.dbcp.dbcp2.BasicDataSource" p:driverClassName="org.mariadb.jdbc.Driver" p:url="jdbc:mariadb://localhost:3306/shibboleth" p:username="shibboleth" p:password="demo" p:validationQuery="select 1" p:validationQueryTimeout="0" />
Et les autres objets au sein du fichier /opt/shibboleth-idp/conf/attribute-resolver-ldap.xml
:
<DataConnector id="myStoredId" xsi:type="StoredId" generatedAttributeID="persistentID" salt="%{idp.persistentId.salt}" queryTimeout="0"> <InputAttributeDefinition ref="%{idp.persistentId.sourceAttribute}" /> <BeanManagedConnection>myDataSource</BeanManagedConnection> </DataConnector> <!-- définition de l'attribut eduPersonTargetedID --> <AttributeDefinition id="eduPersonTargetedID" xsi:type="SAML2NameID" nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"> <InputDataConnector ref="myStoredId" attributeNames="persistentID"/> <DisplayName xml:lang="en">Targeted ID</DisplayName> <DisplayDescription xml:lang="en">Targeted ID: A unique identifier for a person, different for each service provider.</DisplayDescription> <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" /> <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" friendlyName="eduPersonTargetedID" /> </AttributeDefinition>
Adaptez également votre filtre d'attributs pour autoriser la diffusion de l'attribut eduPersonTargetedID
aux SPs (à tous les SPs dans l'exemple ci-dessous) :
<AttributeFilterPolicyGroup id="ShibbolethFilterPolicy" xmlns="urn:mace:shibboleth:2.0:afp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mace:shibboleth:2.0:afp http://shibboleth.net/schema/idp/shibboleth-afp.xsd"> <!-- Release an additional attribute to an SP. --> <AttributeFilterPolicy id="example1"> <PolicyRequirementRule xsi:type="ANY" /> <AttributeRule attributeID="uid" permitAny="true" /> <AttributeRule attributeID="mail" permitAny="true" /> <AttributeRule attributeID="eduPersonPrincipalName" permitAny="true" /> ** <AttributeRule attributeID="eduPersonTargetedID" permitAny="true" />** </AttributeFilterPolicy> </AttributeFilterPolicyGroup>
Vous devez installer le pilote JDBC pour la connexion à une base MySQL (pour d'autre type de bases SQL, se référer à la documentation Internet2 ci-dessus). Aller sur le site de téléchargement http://www.mysql.com/downloads/connector/j/.
$> cd $> wget https://downloads.mariadb.com/Connectors/java/connector-java-2.6.2/mariadb-java-client-2.6.2.jar $> sudo cp mariadb-java-client-2.6.2.jar /opt/shibboleth-idp/edit-webapp/WEB-INF/lib/
Il est nécessaire de reconstruire le fichier idp.war
pour prendre en compte l'ajout de la bibliothèque mysql :
$> cd /opt/shibboleth-idp $> sudo -E ./bin/build.sh Installation Directory: [/opt/shibboleth-idp/] Rebuilding /opt/shibboleth-idp/war/idp.war ... ...done BUILD SUCCESSFUL Total time: 24 seconds
Pour vérifier la génération de ce nouvel attribut, vous devez :
conf/intercept/consent-intercept-config.xml
.
L'attribut eduPersonEntitlement est défini dans les recommandations eduPerson ; il n'est pas repris dans SupAnn car cet attribut est a priori spécifique à l'environnement Shibboleth et la valeur de l'attribut peut être calculée dynamiquement par une brique Shibboleth fournisseur d'identités. Cet attribut sera généré à l'aide d'un Attribut de type Script dans le resolver.
Cet attribut permet à un fournisseur d'identités de transmettre des privilèges spécifiques à l'utilisateur courant, en fonction du fournisseur de services courant. Sa valeur est donc positionnée selon le fournisseur de services et l'utilisateur au moment de la connexion.
Dans le cas d'un accès à de la documentation électronique, la valeur attendue est souvent urn:mace:dir:entitlement:common-lib-terms, la sémantique associée est « cet utilisateur est duement autorisé à accéder à la ressource, selon les termes du contrat entre l'éditeur et l'université. » Cette valeur est à positionner pour toute personne étant référencée member par exemple dans l'annuaire de l'établissement.
Commentez l' eduPersonEntitlement
qui serait déjà présent dans le fichier attribute-resolver-ldap.xml
et ajoutez cette nouvelle déclaration comme suit :
<AttributeDefinition id="eduPersonEntitlement" xsi:type="ScriptedAttribute"> <InputAttributeDefinition ref="eduPersonAffiliation" /> <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonEntitlement" /> <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7" friendlyName="eduPersonEntitlement" /> <Script> <![CDATA[ if (eduPersonAffiliation.getValues().contains("member")) { eduPersonEntitlement.getValues().add("urn:mace:dir:entitlement:common-lib-terms"); } ]]> </Script> </AttributeDefinition>
Une fois la modification effectuée, rechargez la configuration de résolution d'attribut et vérifiez le résultat sur le SP de test.
Dans quels cas utiliser cet attribut ?
Cet attribut est adapté lorsque la décision d'autorisation d'accès à une ressource ne peut pas être réalisée du côté du fournisseur de services (car les attributs ne sont pas standards ou pas divulguables). Dans ce cas, le fournisseur d'identités prépare l'attribut eduPersonEntitlement pour exprimer les droits de l'utilisateur vis à vis de ce fournisseur de services, en fonction des autres attributs de l'utilisateur.
Cet exemple ne montre pas comment générer un entitlement en fonction du fournisseur de services. Voici une fiche technique que vous pouvez consulter pour plus d'options : voir la documentation