Autenticació LDAP

De wikijoan
Salta a la navegació Salta a la cerca

Introducció

Hem vist la teoria de LDAP, i ara ho posarem en pràctica:

  • crearàs un servidor LDAP
  • crearàs 4 usuaris en el directori del LDAP
  • t'autenticaràs al servidor LDAP des de diferents llenguatges de programació.

Pràctica

Seguim aquest tutorial:

Creem una carpeta per al projecte:

$ mkdir DAW_M08_DESPL/UF3/LDAP/
$ cd DAW_M08_DESPL/UF3/LDAP/

Iniciem un docker que crearà un servidor LDAP pel port 389:

$ docker run -p 389:389 --name ldap-service --hostname ldap-service --env LDAP_ORGANISATION="ScytaleLabs" --env LDAP_DOMAIN="scytalelabs.com" \
--env LDAP_ADMIN_PASSWORD="adminPassword" --env LDAP_BASE_DN="dc=scytalelabs,dc=com" --volume /data/slapd/database:/var/lib/ldap \
--volume /data/slapd/config:/etc/ldap/slapd.d --detach osixia/openldap:1.3.0

Fixa't amb el password que necessitaràs (adminPassword), que l'hem entrat com a variable d'entorn.

Ja tenim el servidor docker funcionant. Però per interactuar amb ell necessitem per exemple una interfície web. Tenim el projecte PHPLDAPAdmin, que també el tenim dockeritzat:

$ docker run --name phpldapadmin-service --hostname phpldapadmin-service --link ldap-service:ldap-host --env PHPLDAPADMIN_LDAP_HOSTS=ldap-service --detach osixia/phpldapadmin:0.9.0

A hores d'ara tenim els dos dockers engegats. Ho pots comprovar fent:

$ docker ps
CONTAINER ID        IMAGE                       COMMAND                 CREATED             STATUS              PORTS                           NAMES
e6cf9de7ca04        osixia/phpldapadmin:0.9.0   "/container/tool/run"   5 days ago          Up About an hour    80/tcp, 443/tcp                 phpldapadmin-service
4ff8564a1df8        osixia/openldap:1.3.0       "/container/tool/run"   5 days ago          Up About an hour    0.0.0.0:389->389/tcp, 636/tcp   ldap-service
Phpldapadmin.png

NOTA: hem arrencat dos dockers manualment. Aquest procés es pot automatitzar amb una eina que es diu docker-compose, per gestionar projectes que necessiten varis dockers i tota la seva configuració de com s'han d'arrencar aquests dockers.

Per saber com hem d'accedir a la web del PHPLDAPAdmin necessitem la IP:

$ docker inspect -f "{{ .NetworkSettings.IPAddress }}" phpldapadmin-service
172.17.0.3

I ja podem accedir:

Nota: següent sessió

Quan arrenques la màquina, no cal tornar a crear els dockers, ja estan creats, el que passa és que estan apagats. Per veure tots els dockers que hi ha a la teva màquina:

$ docker ps -a -> tots els dockers
$ docker ps -> tots els dockers que esta engegats

Aquí pots veure els IDs de cada docker. I per arrencar-los has de fer un start:

docker start 4ff8564a1df8
docker start e6cf9de7ca04

Creació d'usuaris

Podem autenticar-nos de manera anònima, però només tindrem permisos de lectura, no podrem crear usuaris. Les credencials per autenticar-nos al LDAP són:

  • login: cn=admin,dc=scytalelabs,dc=com
  • password: adminPassword

Per crear un usuari, no és evident:

Abans de crear un usuari, el primer que hem de fer és crear una ou (Organization Unit), doncs els usuaris han d'estar dins d'una ou. Per exemple, Balmes. (fer commit).

I dins d'aquesta ou has de crear un cn. Ho faràs de la següent manera:

  • Create new entry here > Generic Posix Group > li posaràs el nom de Informàtica

I ara ja podem crear els usuaris. Especificarem com a mínim: En l'arrel: Create new entry here > Generic: user Account

  • First Name
  • Last Name
  • Common Name
  • UserID
  • password
  • GID Number: Informàtica (aquí posaràs el departament a què pertany aquest usuari)

Crees l'usuari fent commit, i més endavant pots afegir nous atributs com ara el EMail, etc.

Progamació. Scripts per autenticar-se

PHP

Primer de tot necessitem instal·lar el mòdul de PHP per a LDAP:

$ sudo apt-cache search php | grep ldap
php-ldap - LDAP module for PHP [default]

$ sudo apt-get install php-ldap

script autenticacio_ldap.php:

<?php

$ldaprdn  = 'cn=admin,dc=scytalelabs,dc=com';
$ldappass = 'adminPassword';

// connexió al servidor LDAP
$ldapconn = ldap_connect("localhost")
    or die("Could not connect to LDAP server.");

if ($ldapconn) {

    //important
    if (ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3)) {
         echo "Using LDAPv3<br />";
    } else {
        echo "Failed to set protocol version to 3";
    }

    // realizar l'autenticació
    $ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);

    // verificació de l'enllaç
    if ($ldapbind) {
        echo "LDAP bind successful...";
    } else {
        echo "LDAP bind failed...";
    }

}
?>

Aquest script també es pot executar a la consola:

$ php autenticacio_ldap.php

Consulta dels usuaris que hem creat: script ldap_search.php:

<?php
// https://www.php.net/manual/en/ldap.examples-basic.php
// basic sequence with LDAP is connect, bind, search, interpret search
// result, close connection
$ldaprdn  = 'cn=admin,dc=scytalelabs,dc=com';
$ldappass = 'adminPassword';

echo "<h3>LDAP query test</h3>";
echo "Connecting ...";
$ds=ldap_connect("localhost");  // must be a valid LDAP server!
echo "connect result is " . $ds . "<br />";

if ($ds) {
    if (ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
         echo "Using LDAPv3<br />";
    } else {
        echo "Failed to set protocol version to 3";
    }

    echo "Binding ...";
    //$r=ldap_bind($ds);     // this is an "anonymous" bind, typically read-only access
    $r=ldap_bind($ds, $ldaprdn, $ldappass);

    echo "Bind result is " . $r . "<br />";

    echo "Searching for (cn=*) ...";
    // Search surname entry
    $sr=ldap_search($ds, "dc=scytalelabs,dc=com", "cn=*");
    echo "Search result is " . $sr . "<br />";


    echo "Number of entries returned is " . ldap_count_entries($ds, $sr) . "<br />";

    echo "Getting entries ...<p>";
    $info = ldap_get_entries($ds, $sr);
    echo "Data for " . $info["count"] . " items returned:<p>";

    for ($i=0; $i<$info["count"]; $i++) {
        echo "dn is: " . $info[$i]["dn"] . "<br />";
        echo "first cn entry is: " . $info[$i]["cn"][0] . "<br />";
        if (isset($info[$i]["givenname"])) echo "givenName entry is: " . $info[$i]["givenname"][0] . "<br />";
        if (isset($info[$i]["mail"])) echo "first email entry is: " . $info[$i]["mail"][0] . "<br />";
        echo "<hr />";
    }

    echo "Closing connection";
    ldap_close($ds);

} else {
    echo "<h4>Unable to connect to LDAP server</h4>";
}
?>

NodeJS

Primer de tot hem d'instal·lar el mòdul ldapjs:

$ npm install ldapjs

script autenticacio_ldap.js:

// npm install ldapjs
const ldap = require("ldapjs")

const username  = 'cn=admin,dc=scytalelabs,dc=com';
const password = 'adminPassword';

function authDN(dn, password, cb) {
  var client = ldap.createClient({url: 'ldap://localhost:389'});

  client.bind(dn, password, function (err) {
    client.unbind();
    cb(err === null, err);
  });
}

function output(res, err) {
  if (res) {
    console.log('success');
  } else {
    console.log('failure');
  }
}

// should print "success"
authDN(username, password, output);
// should print "failure"
authDN(username, 'badpasswd', output);

I ara fem la cerca dels usuaris: script search_ldap.js:

var ldap = require('ldapjs');

const username  = 'cn=admin,dc=scytalelabs,dc=com';
const password = 'adminPassword';

var client = ldap.createClient({
	url: 'ldap://127.0.0.1:389'
});

var opts = {
	filter: '(cn=*)',
	scope: 'sub',
	paged: true,
	password: 'adminPassword',
	sizeLimit: 200,
	attributes: ['dn', 'sn', 'cn', 'userPassword']
};

client.bind(username, password, (err) => {
  console.log('connexió OK')
});

client.search('dc=scytalelabs,dc=com', opts, function(err, res) {
res.on('searchEntry', function(entry) {
console.log('entryJsonFormat: ' + JSON.stringify(entry.object));
});
res.on('searchReference', function(referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function(err) {
console.error('error: ' + err.message);
});
res.on('end', function(result) {
console.log('status: ' + result.status);
});
})

Obtenim un resultat similar a:

connexió OK
entryJsonFormat: {"dn":"cn=admin,dc=scytalelabs,dc=com","controls":[],"cn":"admin","userPassword":"{SSHA}TNzZ00WHBrEsrCPrQ8RzNUT5TIqU6bm6"}
entryJsonFormat: {"dn":"cn=Informàtica,ou=Balmes,dc=scytalelabs,dc=com","controls":[],"cn":"Informàtica"}
entryJsonFormat: {"dn":"cn=Joan Quintana,dc=scytalelabs,dc=com","controls":[],"sn":"Quintana","cn":"Joan Quintana","userPassword":"{MD5}q2uM/Cm7XEjd/rDkeIissA=="}
entryJsonFormat: {"dn":"cn=Roger Viaplana,dc=scytalelabs,dc=com","controls":[],"sn":"Viaplana","cn":"Roger Viaplana","userPassword":"{MD5}q2uM/Cm7XEjd/rDkeIissA=="}
entryJsonFormat: {"dn":"cn=Pere Quintana,dc=scytalelabs,dc=com","controls":[],"sn":"Quintana","cn":"Pere Quintana","userPassword":"{MD5}q2uM/Cm7XEjd/rDkeIissA=="}
entryJsonFormat: {"dn":"cn=Jordi Q,dc=scytalelabs,dc=com","controls":[],"sn":"Q","cn":"Jordi Q","userPassword":"{MD5}X03MO1qnZdYdgyfeuILPmQ=="}
status: 0

Tasques a realitzar

Has de seguir pas a pas el que s'ha fet a classe i que funcioni en la teva màquina. Concretament.

  1. crear el docker del servidor LDAP
  2. crear el docker del PHPLDAPAdmin
  3. Dins del PHPLDAPAdmin, crear la unitat organitzativa d'Informàtica
  4. Dins del PHPLDAPAdmin, crear 4 usuaris (nom, cognom, telèfon, correu electrònic), dins de la unitat organitzativa d'Informàtica
  5. scripts PHP: autenticació i cerca dels usuaris.
  6. scripts NodeJS: autenticació i cerca dels usuaris.

Entrega

Entregaràs al classroom dins del termini previst els exercicis proposats, amb evidències de què ho has fet tu i en la teva màquina. Quan ho tinguis acabat també pots demanar-li al professor que t'ho revisi i validi in-situ.


creat per Joan Quintana Compte, març 2022