8. Accéder à l'annuaire LDAP depuis un service Web

Du point de vue métier, les manipulations à base de fichiers LDIF sont réservées aux traitements en volume réalisés par les administrateurs système. Les développeurs disposent de bibliothèques fournies avec les langages de programmation. Dans la plupart des cas, les développements ont pour but de fournir une interface web.

Le projet LDAP Tool Box project propose un outil baptisé white pages qui permet de constituer un trombinoscope des utilisateurs enregistrés dans un annuaire LDAP.

8.1. Installer le service White Pages

L'objectif de cette section est d'installer le service web White Pages avant de paramétrer l'accès à l'annuaire LDAP.

Q171.

Quel sont les paquets à installer pour mettre en place le service web White Pages ?

Recherchez sur le site LDAP Tool Box project, le lien de téléchargement direct du paquet Debian pour le service White Pages. Ensuite, identifiez les dépendances du service et installez les paquets supplémentaires

À partir du lien Download du menu de la page principale, on trouve un lien direct vers les paquets proposés par le projet LDAP Tool Box project.

  • Lancez le téléchargement du paquet du projet LDAP Tool Box project.

    wget https://ltb-project.org/archives/white-pages_0.5-1_all.deb
  • Lancez l'installation locale du paquet et de ses dépendances.

    sudo apt install -y ./white-pages_0.5-1_all.deb
  • Complétez les installations avec le service Web de présentation et le module PHP associé.

    sudo apt install -y apache2 libapache2-mod-php

Q172.

Comment activer l'accès au service Web de présentation ?

Consultez les fichiers de documentation et de configuration fournis avec le paquet apache2. Repérez les instructions d'activation et de désactivation d'un site. Localisez les éléments spécifiques à la configuration du service White Pages pour activer le site.

  • Identifiez les outils du paquet apache2 dédiés aux manipulations sur les sites et leur configuration.

    dpkg -L apache2 | grep "bin.*a2"
    /usr/sbin/a2enmod
    /usr/sbin/a2query
    /usr/sbin/a2disconf
    /usr/sbin/a2dismod
    /usr/sbin/a2dissite
    /usr/sbin/a2enconf
    /usr/sbin/a2ensite

    Ce sont les commandes a2dissite et a2ensite qui sont utiles dans le cadre de cette question. Consultez les pages de manuel associées.

    man a2dissite
    man a2ensite
  • Utilisez la commande a2dissite pour désactiver le site par défaut livré avec l'installation du paquet apache2 et la commande a2ensite pour activer les pages blanches.

    Affichez la liste des sites disponibles.

    sudo ls -l /etc/apache2/sites-available/
    total 16
    -rw-r--r-- 1 root root 1286  5 déc.  11:21 000-default.conf
    -rw-r--r-- 1 root root 4573 30 déc.  12:48 default-ssl.conf
    -rw-r--r-- 1 root root  531 25 mars   2018 white-pages.conf

    Affichez la liste des sites actifs.

    sudo ls -l /etc/apache2/sites-enabled/

    Désactivez le site par défaut.

    sudo a2dissite 000-default

    Acitvez le site des pages blanches.

    sudo a2ensite white-pages

    Vérifiez que la configuration est valide.

    sudo apachectl configtest
    Syntax OK

    Rechargez la configuration apache2.

    sudo systemctl reload apache2

    Ouvrez iensuite la page Web du site avec un navigateur. Comme vous l'avez déjà vu lors des précédents travaux pratiques, utilisez la connexion SSH pour établir un tunnel d'accès Web entre votre poste personnel et le système qui héberge le service Web.

  • Consultez les paramètres de configuration du site des pages blanches dans le fichier /etc/apache2/sites-available/white-pages.conf.

    Sélectionnez l'option Répertoire du bandeau en haut de la page Web principale et constatez que l'accès à l'annuaire n'a pas encore été configuré.

8.2. Configurer l'accès à l'annuaire LDAP depuis le service Web

Dans cette section, vous devez ouvrir une connexion à l'annuaire LDAP depuis le service Web de pages blanches tout en respectant le principe de moindre privilège.

Q173.

Comment créer un compte de service dédié aux pages blanches dans l'annuaire LDAP ?

Reprenez la démarche suivie lors dans la Section 6.2, « Configurer l'accès transparent à l'annuaire LDAP sur un système client » avec la création du compte nslcd-proxy.

Codez un script de création du compte de service wp-proxy sur le serveur LDAP.

Voici un exemple de code pour le script create-wp-proxy.sh.

#!/usr/bin/env bash

set -euo pipefail

readonly DOMAIN="lab.local"
readonly BASE_DN="dc=${DOMAIN%%.*},dc=${DOMAIN#*.}"
readonly USERS_OU="ou=users,${BASE_DN}"
readonly WP_UID="wp-proxy"
readonly WP_DN="uid=${WP_UID},${USERS_OU}"

readonly LDIF_FILE="/tmp/create_${WP_UID}.ldif"
readonly WP_PASS_FILE="${HOME}/.ldap_${WP_UID}_pass"

echo "=== 1. Password generation ==="
WP_PASS=$(openssl rand -base64 28 | cut -c -24)

rm -f "${WP_PASS_FILE}"
printf "%s" "${WP_PASS}" >"${WP_PASS_FILE}"
chmod 400 "${WP_PASS_FILE}"

WP_HASH=$(sudo slappasswd -o module-load=argon2.la -h "{ARGON2}" -s "${WP_PASS}")

echo "=== 2. LDIF file creation ==="
rm -f "${LDIF_FILE}"
cat <<EOF >"${LDIF_FILE}"
dn: ${WP_DN}
objectClass: inetOrgPerson
uid: ${WP_UID}
cn: White Pages Proxy Service
sn: Service
description: Read-only service account for LDAP Tool Box White Pages
userPassword: ${WP_HASH}
EOF

echo "=== 3. Insertion into the LDAP directory ==="
sudo ldapdelete -Y EXTERNAL -H ldapi:/// "${WP_DN}" 2>/dev/null || true
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f "${LDIF_FILE}"

rm -f "${LDIF_FILE}"

echo ""
echo "================================================================="
echo " Success: Service account '${WP_UID}' has been created."
echo " Bind DN: ${WP_DN}"
echo " Plaintext password (keep this for White Pages configuration):"
echo " -> ${WP_PASS}"
echo " (This secret is also saved in: ${WP_PASS_FILE})"
echo "================================================================="

Lancez le script de création du compte de service.

bash srv13-create-wp-proxy.sh
=== 1. Password generation ===
=== 2. LDIF file creation ===
=== 3. Insertion into the LDAP directory ===
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "uid=wp-proxy,ou=users,dc=lab,dc=local"


=================================================================
 Success: Service account 'wp-proxy' has been created.
 Bind DN: uid=wp-proxy,ou=users,dc=lab,dc=local
 Plaintext password (keep this for White Pages configuration):
 -> IcH...
 (This secret is also saved in: /home/etu/.ldap_wp-proxy_pass)
=================================================================

Q174.

Comment vérifier les droits d'accès du nouvel utilisateur avec les ACL existantes ?

Affichez la liste des contrôles d'accès (ACL) configurés dans votre annuaire LDAP et évaluez les droits de l'utilisateur wp-proxy.

Affichez les ACLs.

sudo ldapsearch -LLL -Y EXTERNAL -H ldapi:/// \
    -b "olcDatabase={1}mdb,cn=config" \
    olcAccess
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: olcDatabase={1}mdb,cn=config
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external
 ,cn=auth manage by * break
olcAccess: {1}to attrs=userPassword by self write by anonymous auth by * none
olcAccess: {2}to attrs=shadowLastChange by self write by * read
olcAccess: {3}to * by users read by * none

Évaluez les droits d'accès pour uid=wp-proxy,ou=users,dc=lab,dc=local :

  • Le compte est dans l'OU users (utilisateur authentifié), donc la règle {3} lui donne le droit de lecture (read) sur toutes les entrées.

  • Il ne peut pas lire userPassword (règle {1}) et ne voit shadowLastChange qu’en lecture (règle {2}).

  • Il n’a aucun droit d’écriture : parfait pour un compte de service “pages blanches”.

Q175.

Comment tester les accès du compte de service à l'annuaire depuis le système client ?

Copiez le mot de passe généré plus haut et lancez des requêtes ldapsearch depuis le poste client.

  • Exemple de requête sur les attributs d'un utilisateur de l'annuaire :

    ldapsearch -ZZ -LLL \
        -H ldap://ldap-srvr.lab.local \
        -D "uid=wp-proxy,ou=users,dc=lab,dc=local" \
        -y ~/.ldap_wp-proxy_pass \
        -b "dc=lab,dc=local" \
        "(uid=anakin)" cn mail jpegPhoto
    dn: uid=anakin,ou=users,dc=lab,dc=local
    cn: Anakin Skywalker
    mail: anakin@lab.local

    Les résultats attendus sont bien affichés, à l'exception de la photo qui n'a pas encore été ajoutée.

  • Exemple de requête de lecture de mot de passe :

    ldapsearch -ZZ -LLL \
        -H ldap://ldap-srvr.lab.local \
        -D "uid=wp-proxy,ou=users,dc=lab,dc=local" \
        -y ~/.ldap_wp-proxy_pass \
        -b "dc=lab,dc=local" \
        "(uid=leia)" userPassword

    Aucun résultat. Le compte de service n'a pas accès aux mots de passe des autres utilisateurs.

  • Exemple de tentative d'écriture directe :

    ldapmodify -ZZ \
        -H ldap://ldap-srvr.lab.local \
        -D "uid=wp-proxy,ou=users,dc=lab,dc=local" \
        -y ~/.ldap_wp-proxy_pass <<EOF
    dn: uid=anakin,ou=users,dc=lab,dc=local
    changetype: modify
    replace: description
    description: Test write from wp-proxy
    EOF
    modifying entry "uid=anakin,ou=users,dc=lab,dc=local"
    ldap_modify: Insufficient access (50)

    Le compte de service est limité a un accès en lecture seule.

Q176.

Comment paramétrer le service Web de pages blanches pour utiliser le compte de service ?

Identifiez le fichier de configuration fourni avec le paquet white-pages.

Recherchez dans la documentation du projet LDAP Tool Box project la méthode recommandée pour affecter les valeurs des paramètres LDAP.

Lancez une recherche des fichiers de configuration du paquet white-pages.

dpkg -L white-pages | grep 'etc.*conf'
/etc/apache2/sites-available/white-pages.conf
/etc/white-pages/config.inc.php

C'est le fichier /usr/share/white-pages/conf/config.inc.php qui contient les éléments d'accès à l'annuaire LDAP. Voici un extrait de ce fichier avec les lignes utiles.

grep ^\$ldap /etc/white-pages/config.inc.php
$ldap_url = "ldap://localhost";
$ldap_starttls = false;
$ldap_binddn = "cn=manager,dc=example,dc=com";
$ldap_bindpw = "secret";
$ldap_base = "dc=example,dc=com";
$ldap_user_base = "ou=users,".$ldap_base;
$ldap_user_filter = "(objectClass=inetOrgPerson)";
$ldap_login_attribute = "uid";
$ldap_login_filter = "(&$ldap_user_filter($ldap_login_attribute={login}))";
$ldap_scope = "sub"; # possible values: sub, one, base
$ldap_group_base = "ou=groups,".$ldap_base;
$ldap_group_filter = "(|(objectClass=groupOfNames)(objectClass=groupOfUniqueNames))";
$ldap_size_limit = 100;

La documentation du projet préconise la création d'un fichier de configuration local dédié. Voici un exemple d'application d'un jeu de paramètres LDAP complet avec un script appelé configure-wp.sh.

#!/usr/bin/env bash

set -euo pipefail

readonly WP_PASS_FILE=".ldap_wp-proxy_pass"
readonly WP_CONF_DIR="/etc/white-pages"
readonly WP_LOCAL_CONF_FILE="${WP_CONF_DIR}/config.inc.local.php"
readonly WP_PASS_PATH="${WP_CONF_DIR}/${WP_PASS_FILE}"

echo "=== 1. Copy wp-proxy password ==="
if [[ ! -f "${HOME}/${WP_PASS_FILE}" ]]; then
        echo "Error: Password file '${WP_PASS_FILE}' not found."
        exit 1
fi

sudo install -m 400 "${HOME}/${WP_PASS_FILE}" "${WP_CONF_DIR}/${WP_PASS_FILE}"
sudo chown www-data:www-data "${WP_CONF_DIR}/${WP_PASS_FILE}"

echo "=== 2. Create White Pages local configuration file ==="

# shellcheck disable=SC2250
cat <<'EOF' |
<?php
$ldap_url          = "ldaps://ldap-srvr.lab.local:636";
$ldap_starttls     = false;
$ldap_binddn       = "uid=wp-proxy,ou=users,dc=lab,dc=local";
$ldap_bindpw       = trim(file_get_contents('__WP_PASS_PATH__'));
$ldap_base         = "dc=lab,dc=local";
$ldap_user_base    = "ou=users,".$ldap_base;
$ldap_user_filter  = "(objectClass=inetOrgPerson)";
$ldap_login_attribute = "uid";
$ldap_login_filter = "(&$ldap_user_filter($ldap_login_attribute={login}))";
$ldap_scope        = "sub";
$ldap_group_base   = "ou=groups,".$ldap_base;
$ldap_group_filter = "(|(objectClass=groupOfNames)(objectClass=groupOfUniqueNames)(objectClass=posixGroup))";
$ldap_size_limit   = 100;
EOF
        sed "s|__WP_PASS_PATH__|${WP_PASS_PATH}|g" | sudo tee "${WP_LOCAL_CONF_FILE}" >/dev/null

echo "=== 3. Set permissions for the local configuration file ==="
sudo chown www-data:www-data "${WP_LOCAL_CONF_FILE}"
sudo chmod 600 "${WP_LOCAL_CONF_FILE}"

echo "=== 4. Test Apache configuration ==="
sudo apache2ctl configtest

echo "=== 5. Reload Apache configuration ==="
sudo systemctl reload apache2

echo "================================================================="
echo " Success: White Pages has been configured to use the 'wp-proxy' service account."
echo " Local configuration file: ${WP_LOCAL_CONF_FILE}"
echo "================================================================="

Lancez le script :

bash configure-wp.sh
=== 1. Copy wp-proxy password ===
=== 2. Create White Pages local configuration file ===
=== 3. Set permissions for the local configuration file ===
=== 4. Test Apache configuration ===
Syntax OK
=== 5. Reload Apache configuration ===
=================================================================
 Success: White Pages has been configured to use the 'wp-proxy' service account.
 Local configuration file: /etc/white-pages/config.inc.local.php
=================================================================

Consultez la page du service Web pour afficher les listes des utilisateurs et des groupes.

8.3. Ajouter des photos au trombinoscope

l'objectif de cette section est d'enrichir le service Web à partir de manipulations sur les attributs des utilisateurs de l'annuaire LDAP.

Q177.

Quel est l'attribut de la classe inetOrgPerson qui correspond à une photo d'identité ?

Recherchez la syntaxe de la commande ldapsearch qui permet d'afficher la liste des attributs de la classe inetOrgPerson.

Cette recherche doit se faire dans le schéma de la base de configuration de l'annuaire.

Voici un exemple d'affichage de tous les attributs de la classe inetOrgPerson à partir du serveur LDAP.

sudo ldapsearch -LLL -Y EXTERNAL -H ldapi:/// \
    -b "cn=schema,cn=config" \
    "(olcObjectClasses=*inetOrgPerson*)" \
    olcAttributeTypes olcObjectClasses
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: cn={3}inetorgperson,cn=schema,cn=config
olcAttributeTypes: {0}( 2.16.840.1.113730.3.1.1 NAME 'carLicense' DESC 'RFC279
 8: vehicle license or registration plate' EQUALITY caseIgnoreMatch SUBSTR cas
 eIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
olcAttributeTypes: {1}( 2.16.840.1.113730.3.1.2 NAME 'departmentNumber' DESC '
 RFC2798: identifies a department within an organization' EQUALITY caseIgnoreM
 atch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
olcAttributeTypes: {2}( 2.16.840.1.113730.3.1.241 NAME 'displayName' DESC 'RFC
 2798: preferred name to be used when displaying entries' EQUALITY caseIgnoreM
 atch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SI
 NGLE-VALUE )
olcAttributeTypes: {3}( 2.16.840.1.113730.3.1.3 NAME 'employeeNumber' DESC 'RF
 C2798: numerically identifies an employee within an organization' EQUALITY ca
 seIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.12
 1.1.15 SINGLE-VALUE )
olcAttributeTypes: {4}( 2.16.840.1.113730.3.1.4 NAME 'employeeType' DESC 'RFC2
 798: type of employment for a person' EQUALITY caseIgnoreMatch SUBSTR caseIgn
 oreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
olcAttributeTypes: {5}( 0.9.2342.19200300.100.1.60 NAME 'jpegPhoto' DESC 'RFC2
 798: a JPEG image' SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 )
olcAttributeTypes: {6}( 2.16.840.1.113730.3.1.39 NAME 'preferredLanguage' DESC
  'RFC2798: preferred written or spoken language for a person' EQUALITY caseIg
 noreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.
 15 SINGLE-VALUE )
olcAttributeTypes: {7}( 2.16.840.1.113730.3.1.40 NAME 'userSMIMECertificate' D
 ESC 'RFC2798: PKCS#7 SignedData used to support S/MIME' SYNTAX 1.3.6.1.4.1.14
 66.115.121.1.5 )
olcAttributeTypes: {8}( 2.16.840.1.113730.3.1.216 NAME 'userPKCS12' DESC 'RFC2
 798: personal identity information, a PKCS #12 PFX' SYNTAX 1.3.6.1.4.1.1466.1
 15.121.1.5 )
olcObjectClasses: {0}( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' DESC 'RFC2
 798: Internet Organizational Person' SUP organizationalPerson STRUCTURAL MAY
 ( audio $ businessCategory $ carLicense $ departmentNumber $ displayName $ em
 ployeeNumber $ employeeType $ givenName $ homePhone $ homePostalAddress $ ini
 tials $ jpegPhoto $ labeledURI $ mail $ manager $ mobile $ o $ pager $ photo
 $ roomNumber $ secretary $ uid $ userCertificate $ x500uniqueIdentifier $ pre
ferredLanguage $ userSMIMECertificate $ userPKCS12 ) )

Le nom de l'attribut à utiliser pour manipuler la photo d'identité d'un utilisateur de l'annuaire LDAP est : jpegPhoto.

Q178.

Comment garantir l'intégrité du fichier JPEG à insérer dans l'annuaire LDAP ?

Recherchez dans la liste des outils fournis avec le paquet imagemagick celui qui permet de convertir toute image en un fichier JPEG correctement formaté.

Commencez par installer le paquet imagemagick.

sudo apt install -y imagemagick

Utilisez ensuite la commande magick pour produire un fichier JPEG conforme.

magick leia-organa.jpg \
    -resize 300x300^ \
    -gravity center -extent 300x300 -strip \
    -interlace Plane -quality 90 \
    leia-organa.jpeg

Pour obtenir un carré parfait sans déformation, la commande redimensionne l'image pour qu'elle couvre la zone cible avec -resize 300x300^ avant de la recadrer au centre aux dimensions exactes via -gravity center -extent 300x300.

Enfin, vérifiez que le fichier converti est correctement identifié avec la commande identify.

identify leia-organa.jpeg
leia-organa.jpeg JPEG 443x544 443x544+0+0 8-bit sRGB 54923B 0.000u 0:00.000

La présence de la clé JPEG confirme que le fichier est au bon format et peut être utilisé pour le trombinoscope.

Q179.

Comment ajouter ou supprimer la photo d'un utilisateur de l'annuaire LDAP ?

Créez un script manage-jpegphoto.sh qui débute par les traitements communs suivants :

  1. Définir le jeu des variables communes à partir du code des scripts précédents de ce document

  2. Analysez les options de la ligne de commande avec getopt pour choisir une action :

    • --add USER JPEG_FILE

    • --delete USER

  3. Valider les arguments obligatoires (action, utilisateur, et image pour l’ajout).

  4. Vérifier que l’utilisateur LDAP cible existe (ldapsearch sur uid).

Pour l'ajout d'une photo :

  1. Vérifier que le fichier image existe et n’est pas vide.

  2. Vérifier que le contenu est bien au format JPEG.

  3. Résoudre le chemin absolu de l’image (realpath).

  4. Générer un fichier LDIF de modification avec replace: jpegPhoto et inclure le contenu de l'image jpegPhoto:<....

Pour la suppression d'une photo :

  1. Générer un fichier LDIF avec delete: jpegPhoto.

Pour terminer, appliquer la modification LDAP via ldapmodify.

Voici un exemple de code pour le script manage-jpegphoto.sh.

#!/usr/bin/env bash

set -euo pipefail

readonly DOMAIN="lab.local"
readonly BASE_DN="dc=${DOMAIN%%.*},dc=${DOMAIN#*.}"
readonly USERS_OU="ou=users,${BASE_DN}"
readonly LDAP_URI="ldap://ldap-srvr.lab.local"
readonly ADMIN_DN="cn=admin,${BASE_DN}"
readonly ADMIN_PASS_FILE="${HOME}/.ldap_admin_pass"

# LDAP common options
readonly LDAP_OPTS=(-ZZ -H "${LDAP_URI}" -D "${ADMIN_DN}" -y "${ADMIN_PASS_FILE}")

# --- Functions ---
die() {
        echo "Error: $*" >&2
        exit 1
}

usage() {
        cat <<EOF
Usage: $(basename "$0") -a|--add USER JPEG_FILE | -d|--delete USER
EOF
}

check_user_exists() {
        ldapsearch "${LDAP_OPTS[@]}" -LLL -b "${USERS_OU}" "(uid=$1)" dn | grep -q '^dn:' || die "User $1 not found."
}

validate_jpeg() {
        [[ -f $1 && -s $1 ]] || die "Image missing or empty: $1"
        identify -format '%m' "$1" 2>/dev/null | grep -qi '^JPEG$' || die "$1 is not a valid JPEG."
}

# --- Main ---
main() {
        local action="" user="" jpeg_file=""
        local opts
        opts=$(getopt -o ad -l add,delete -- "$@") || {
                usage
                exit 1
        }
        eval set -- "${opts}"

        while true; do
                case "$1" in
                -a | --add)     action="add";    shift  ;;
                -d | --delete)  action="delete"; shift  ;;
                --)             shift;           break  ;;
                *)              usage;           exit 1 ;;
                esac
        done

        user="${1-}"
        jpeg_file="${2-}"

        [[ -n ${action} && -n ${user} ]] || {
                usage
                exit 1
        }
        [[ ${action} == "add" && -z ${jpeg_file} ]] && die "Add requires a JPEG file."

        check_user_exists "${user}"

        # LDIF file creation
        local ldif
        ldif=$(mktemp)
        trap 'rm -f "${ldif:-}"' EXIT

        echo "dn: uid=${user},${USERS_OU}" >"${ldif}"
        echo "changetype: modify" >>"${ldif}"

        if [[ ${action} == "add" ]]; then
                local jpeg_path
                validate_jpeg "${jpeg_file}"
                jpeg_path=$(realpath -- "${jpeg_file}") || die "Unable to resolve image path: ${jpeg_file}"
                echo "replace: jpegPhoto" >>"${ldif}"
                echo "jpegPhoto:< file://${jpeg_path}" >>"${ldif}"
        else
                echo "delete: jpegPhoto" >>"${ldif}"
        fi

        echo "=== Applying LDAP modification ==="
        ldapmodify "${LDAP_OPTS[@]}" -f "${ldif}"
        echo "Success: Photo ${action}ed for ${user}."
}

main "$@"

Voici un exemple d'utilisation du script :

bash manage-jpegphoto.sh --add luke luke-skywalker.jpeg
=== Applying LDAP modification ===
modifying entry "uid=luke,ou=users,dc=lab,dc=local"

Success: Photo added for luke.

Affichez le résultat du traitement sur un navigateur.

Affichez le résultat brut de l'ajout d'une photo.

ldapsearch -LLL -H ldaps://ldap-srvr.lab.local \
    -D "cn=admin,dc=lab,dc=local" \
    -y .ldap_admin_pass \
    uid=luke
dn: uid=luke,ou=users,dc=lab,dc=local
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: luke
cn: Luke Skywalker
givenName: Luke
sn: Skywalker
mail: luke@lab.local
shadowLastChange: 20597
loginShell: /bin/bash
uidNumber: 10003
gidNumber: 10003
homeDirectory: /ahome/luke
gecos: Luke Skywalker
userPassword:: e0FSR09OMn0kYXJnb24yaWQkdj0xOSRtPTcxNjgsdD01LHA9MSRuNDc5UGZhTVZ
 NY1FWU05iTVE3eHR3JE9HMURFYTJUTU9Ta25CK2ZLVU5ZamFtVFd5dmhNS05aZWdJdUo2b1JiNjAA
jpegPhoto:: /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBw
 YIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQs
 ...

Dans cette partie, vous avez montré que l'annuaire LDAP ne se limite pas à un référentiel d'identités pour les systèmes Unix. En déployant le service White Pages du projet LDAP Tool Box, en le configurant pour qu'il interroge l'annuaire exclusivement via ldaps://, et en automatisant la gestion de l'attribut jpegPhoto à l'aide d'un script Bash paramétré, vous avez exposé les comptes publiés dans un trombinoscope accessible depuis n'importe quel navigateur, tout en conservant la chaîne de confiance TLS établie dans la partie précédente.