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

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:

You probably just want to create an end user account by selecting the 'Default' option and selecting the inetOrgPerson object class and click the "Proceed" button. On the next screen, you can complete the attribute template to create your entry.

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>";
}
?>
*http://localhost/M08/UF3/LDAP/ldap_search.php (l'alumne posa la seva ruta)

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

creat per Joan Quintana Compte, març 2022