====== Schéma d'annuaire LDAP ======
Le schéma d'un annuaire LDAP permet de spécifier le type d'objet que pourra stocker l'annuaire.
===== Les classes d'objet =====
Un objet de l'annuaire est typé en lui attribuant une ou plusieurs classes d'objets. Il existe trois types de classes d'objet : //structurelle//, //auxiliaire// et //abstraite//. Un objet doit obligatoirement avoir une et une seule classe d'objet structurelle et il peut avoir une ou plusieurs classes auxiliaires. Une classe d'objet abstraite ne peut être affectée à un utilisateur directement : celle-ci sert uniquement à être dérivée (via le système d'héritage entre classes d'objets). Les classes d'un objet permet de déterminer quels sont les attributs que peux/doit porter l'objet.
==== L'héritage entre les classes d'objet ====
Une classe d'objet héritera toujours une autre classe d'objet (par défaut ''top''). En héritant d'une classe parente, la classe déclarée hérite automatiquement des tous les attributs facultatifs et/ou obligatoires de la classe parente (tout comme ceux que celle-ci a elle-même hérité). Il est possible dans une classe fille d'ajouter de nouveaux attributs ou encore de transformer un attribut obligatoire en attribut facultatif (ou inversement).
Il n'est en outre pas possible de changer le type de classe lors d'un héritage, à l'exception de l'héritage d'une classe abstraite. Ainsi, par exemple, une classe auxiliaire ne pourra hérité que d'une autre classe auxiliaire ou abstraite, mais pas d'une classe structurelle.
Lors de la recherche en filtrant sur la classe d'objet, les objets ayant une classe d'objet héritée de la classe recherchée seront également pris en compte. Ainsi, en imaginant un annuaire avec une classe d'objet ''specificPerson'' héritant de la classe ''person'', lors d'une recherche avec le filtre ''(objectClass=person)'', les objets ''specificPerson'' seront également retournés.
===== Les attributs des objets =====
L'attribut d'un objet permet de stocker une information sur un objet. Les attributs sont également déclarés dans le schéma de l'annuaire. Cette déclaration permet :
* de les nommer
* de leur associé une description (documentation)
* de déterminer s'ils sont mono-valués ou multi-valués (par défaut)
* de spécifier la syntaxe de l'information stockée (via des types prédéfinis) et éventuellement la longueur maximale
* de spécifier des règles de comparaison et d'ordonnancement des valeurs
==== L'héritage entre attribut ====
Un attribut pourra hériter d'un autre attribut. En héritant d'un autre attribut, l'attribut déclaré hérite automatiquement de la syntaxe, des règles de comparaison et d’ordonnancement ainsi de la propriété mono/multi-valué de l'attribut parent. Il est possible de modifier la syntaxe d'un attribut hérité, mais il n'est en outre pas possible de modifier ses règles de comparaison et d'ordonnancement ou encore de sa propriété mono/multi-valué.
Lors de la recherche en filtrant sur un attribut, les objets portant un attribut hérité de l'attribut recherché seront également pris en compte. Ainsi, en imaginant un annuaire avec un attribut ''alternativeMail'' héritant de l'attribut ''mail'', lors d'une recherche avec le filtre ''(mail=test@example.com)'', les objets dont l'attribut ''alternativeMail'' correspondrait seront également retournés.
===== Les OID des objets d'un schéma =====
Chaque classes d'objet et attributs du schéma sont identifiés de manière unique à l'aide d'un //OID//. Un //OID// est une suite de nombres séparés par des points (exemple: ''1.3.4.54.76''). Pour garantir une unicité parmi les //OID//, il est important de respecter les affectations gérées par l'[[https://www.iana.org/assignments/ldap-parameters/ldap-parameters.xhtml#ldap-parameters-3|IANA]].
Il est également possible de déclarer des alias d'OID (via l'attribut //olcObjectIdentifier//) qui permettront de faciliter la déclaration des classes et attributs en évitant de répéter systématiquement les racines d'//OID//. Ainsi, par exemple, avec un alias d'//OID// ''test'' valant ''1.2.3'', on pourra par exemple déclarer un objet avec l'OID ''1.2.3.4'' en utilisant l'abréviation ''test:4''.
===== Configuration du schéma d'un annuaire OpenLDAP =====
Les schémas sont configurer dans la branche //cn=schema,cn=config// de l'annuaire OpenLDAP. Cette branche contient des objets //olcSchemaConfig// qui permettent de déclarer les objets du schéma :
* les alias d'//OID// via les valeurs de l'attribut //olcObjectIdentifier//
* les attributs via les valeurs de l'attribut //olcAttributeTypes//
* les classes d'objets via les valeurs de l'attribut //olcObjectClasses//
Les valeurs de ces attributs sont numérotés via un préfixe, par exemple ''{10}''. Cela permet de définir l'ordre d'interprétation des valeurs par OpenLDAP lors du chargement du schéma. L'ordre d'interprétation a notamment son importance avec des classes d'objet (ou des attributs) héritant d'une autre classe : il est important que la classe parente soit chargée **avant** la classe fille.
==== Configuration d'un attribut ====
Pour configurer un attribut, il faudra affecter une valeur à un attribut //olcAttributeTypes// d'un objet //olcSchemaConfig// en respectant le format suivant :
(
[OID]
NAME [nom de l'attribut]
DESC '[description de l'attribut]'
SUP [nom de l'attribut parent]
EQUALITY [règle de comparaison d'égalité]
SUBSTR [règle de comparaison de sous-chaîne]
ORDERING [règle de comparaison pour l’ordonnancement]
SYNTAX [OID de la syntaxe]{[limite]}
SINGLE-VALUE
)
**Remarques :**
* l'//OID// doit être globalement unique
* le nom de l'attribut doit être unique parmi les autres attributs déjà déclarés dans l'ensemble des schémas chargés par l'annuaire
* l'attribut parent, dans le cas d'un attribut hérité, doit être chargé avant l'attribut fils
* les règles de comparaison doivent être compatibles avec la syntaxe de l'attribut (voir section ci-dessous). Elles pourront être omises, mais cela affectera les recherches sur l'attribut : si une recherche porte sur un attribut non-déclaré dans le schéma, la recherche ne retournera aucun résultat.
* l'OID de la syntaxe pourra être suffixé par la taille maximale autorisée par l'attribut entouré par des accolades (exemple: ''1.3.6.1.4.1.1466.115.121.1.26{256}''). À défaut, aucune limite ne sera prévu en dehors d'une éventuelle limite technique.
* les retours à la ligne sont possibles et considérés au même titre que les espaces
* le mot clé ''SINGLE-VALUE'' pourra être ajouté pour spécifié que l'attribut est mono-valué et il sera considéré comme multi-valué à défaut
**Exemple de déclaration :**
(
testLDAPAttribute:0
NAME 'testIdentifier'
DESC 'Object identifiers'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
)
**Explications :** Cet attribut s'appelle ''testIdentifier'' et porte l'//OID// ''0'' préfixé de la valeur de l'alias ''testLDAPAttribute''. Il est décrit comme stockant //l'identifiant des objets//. Sa syntaxe est //IA5 String// (OID 1.3.6.1.4.1.1466.115.121.1.26) avec une longueur maximale de 256 caractères. Les régles de comparaisons d'égalité et de sous-chaine sont respectivement //caseIgnoreIA5Match// et //caseIgnoreIA5SubstringsMatch//. Cet attribut est multi-valué et n'hérite d'aucun autre attribut. Cet attribut ne dispose pas de règle de comparaison pour l'ordonnancement et il ne sera donc pas possible de demander un tri sur cet attribut.
**Exemple de déclaration d'un attribut hérité :**
(
testLDAPAttribute:1
NAME 'alternativeMail'
DESC 'Alternative e-mail address'
SUP mail
)
**Explications :** Cet attribut s'appelle ''alternativeMail'' et il porte l'//OID// ''1'' préfixé de la valeur de l'alias ''testLDAPAttribute''. Il est décrit comme stockant //une adresse e-mail alternative// et il hérite de l'attribut ''mail'' sans modification de sa syntaxe.
=== Types syntaxiques et règles de comparaison associées ===
* IA5 String : Chaîne de caractères ASCII
* OID : 1.3.6.1.4.1.1466.115.121.1.26
* Règles de comparaison :
* caseExactIA5Match
* caseExactIA5SubstringsMatch
* caseIgnoreIA5Match
* caseIgnoreIA5SubstringsMatch
* Directory String : Chaîne de caractères autorisant les caractères accentués (encodé en UTF8)
* OID : 1.3.6.1.4.1.1466.115.121.1.15
* Règles de comparaison :
* caseExactMatch
* caseExactOrderingMatch
* caseExactSubstringsMatch
* caseIgnoreMatch
* caseIgnoreOrderingMatch
* caseIgnoreSubstringsMatch
* Octet String : Chaîne de caractères traité traité d'un point de vue stockage comme des octets et sans interprétation de l'encoding
* OID : 1.3.6.1.4.1.1466.115.121.1.40
* Règles de comparaison :
* octetStringMatch
* octetStringOrderingMatch
* octetStringSubstringsMatch
* Telephone Number : Chaîne de caractères ASCII interprété par OpenLDAP comme un numéro de téléphone
* OID : 1.3.6.1.4.1.1466.115.121.1.50
* Règles de comparaison :
* telephoneNumberMatch
* telephoneNumberSubstringsMatch
* Boolean : TRUE ou FALSE (case sensitive)
* OID : 1.3.6.1.4.1.1466.115.121.1.7
* Règles de comparaison :
* booleanMatch
* JPEG : Binaire en base64
* OID : 1.3.6.1.4.1.1466.115.121.1.28
* Règles de comparaison : aucune
* NumericString : Chaine de caractère numérique incluant uniquement des chiffres et des espaces
* OID : 1.3.6.1.4.1.1466.115.121.1.36
* Règles de comparaison :
* numericStringMatch
* numericStringSubstringsMatch
* numericStringOrderingMatch
* PostalAdress : Chaîne de caractères autorisant les caractères accentués (encodé en UTF8) et dont les retours à la ligne sont remplacé par des « $ »
* OID : 1.3.6.1.4.1.1466.115.121.1.41
* Règles de comparaison : celles du type //Directory String//
* Name And Optional UID : DN d'un objet
* OID : 1.3.6.1.4.1.1466.115.121.1.34
* Règles de comparaison :
* uniqueMemberMatch
==== Configuration d'une classe d'objet ====
Pour configurer une classe d'objet, il faudra affecter une valeur à un attribut //olcAttributeTypes// d'un objet //olcObjectClasses// en respectant le format suivant :
(
[OID]
NAME [nom de la classe]
DESC '[description de la classe]'
SUP [nom de la classe parente]
[type de la classe parmi ABSTRACT, STRUCTURAL ou AUXILIARY]
MUST ( [attr1] $ [attr2] $ ... )
MAY ( [attr3] $ [attr4] $ ... )
)
**Remarques :**
* l'//OID// doit être globalement unique
* le nom de la classe doit être unique parmi les autres classes déjà déclarées dans l'ensemble des schémas chargés par l'annuaire
* la classe parente doit être chargée avant la classe fille
* la classe parente peut-être omise et sera par défaut la classe ''top''
* le type de la classe doit être spécifiée en utilisant une des valeurs prévues : ''ABSTRACT'', ''STRUCTURAL'' ou ''AUXILIARY''
* les attributs obligatoires et facultatifs des objets //peuvent// être déclarés respectivement derrière les mots clés ''MUST'' et ''MAY''. Si plusieurs attributs doivent être listé derrière ces mots clés, ils devront être entourés par des parenthèses et séparé par le caractère ''$''
**Exemple de déclaration :**
(
testLDAPObjectClass:0
NAME 'testPeople'
DESC 'Test people objects'
SUP person
STRUCTURAL
MUST uid
MAY ( givenName $ personalTitle $ mail )
)
**Explications :** Cette classe d'objet s'appelle ''testPeople'' et porte l'//OID// ''0'' préfixé de la valeur de l'alias ''testLDAPObjectClass''. Elle est décris comme correspondant //aux objets personnes de test//. Elle hérité de la classe //person// et est structurelle. Elle impose la présence de l'attribut ''uid'' et autorise la présence des attributs ''givenName'', ''personalTitle'' et ''mail''.