Autenticació LDAP
Contingut
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...";
}
}
?>
- http://localhost/M08/UF3/LDAP/autenticacio_ldap.php (l'alumne posa la seva ruta)
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
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.
- crear el docker del servidor LDAP
- crear el docker del PHPLDAPAdmin
- Dins del PHPLDAPAdmin, crear la unitat organitzativa d'Informàtica
- Dins del PHPLDAPAdmin, crear 4 usuaris (nom, cognom, telèfon, correu electrònic), dins de la unitat organitzativa d'Informàtica
- scripts PHP: autenticació i cerca dels usuaris.
- 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