Affichage des articles dont le libellé est ldap. Afficher tous les articles
Affichage des articles dont le libellé est ldap. Afficher tous les articles

samedi 20 décembre 2008

Fedora Directory Server une alternative à openldap

Fedora Directory server est l'évolution de l'ancien server LDAP de Netscape lui même issu de la même souche de l'Université du Michigan (Umich) qu'openldap.

FDS et openldap sont donc des cousins. Une visite sur le site de Fedora Directory server vous démontrera que les gars de Red Hat ont fait fructifier l'héritage de Netscape.

Jugez plutot :

1. Multimaster replication
2. aci
3. directory server gateway : offre un service SOAP d'annuaire et une interface WEB
4. Organigramme : plugin pour fournir un vrai organigramme d'entreprise
5. etc...


Tous les composants de FDS sont open Source.

vendredi 7 novembre 2008

Les APIs LDAP pour Ruby

J'ai recensé 3 APIs LDAP pour Ruby :

Net-ldap c'est l'équivalent au Net::LDAP de Perl .
activeldap: Cette librairie émule activerecord qui au lieu d'utiliser une base de données va se connecter à un annuaire LDAP.
ruby-ldap: Ca ressemble un peu à l'ancinne librairie perl-ldap.

Dans mes recherches , je veux recuperer le schémas de l'annuaire.

Seule ruby-ldap permet de réaliser cette opération facilement.
Le programme suivant est donné en exemple:

require 'ldap'
require 'ldap/schema'

#conn = LDAP::Conn.new( 'localhost', 389 )
#conn.bind( '', '' )
$HOST ='localhost'
$PORT=389


conn = LDAP::Conn.new($HOST, $PORT)
conn.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 )

conn.bind{
schema = conn.schema()
p schema.must("person")
p schema.attr("person", "MUST")
p schema.may("person")
p schema.attr("person", "MAY")
p schema.sup("person")
p schema.attr("person", "SUP")
schema.each{|key,vals|
vals.each{|val|
print("#{key}: #{val}\n")
}
}
}

La construction est particuliaire et je vais chercher à l'améliorer.

Par contre la librairie ruby-ldap n'est pas compatible avec les dernieres versions de ruby , j'ai du appliquer le patch suivant sur le fichier schema.rb



--- schema.rb 2008-11-07 15:30:23.000000000 +0100
+++ /usr/local/lib/site_ruby/1.8/ldap/schema.rb 2008-11-07 14:48:58.000000000 +0100
@@ -35,7 +35,7 @@
self['objectClasses'].each{|s|
if( s =~ /NAME\s+'#{oc}'/ )
case s
- when /#{at}\s+\(([\w\d_-\s\$]+)\)/i
+ when /#{at}\s+\(([\w\s\$-]+)\)/i
return $1.split("$").collect{|attr| attr.strip}
when /#{at}\s+([\w\d_-]+)/i
return $1.split("$").collect{|attr| attr.strip}

jeudi 6 novembre 2008

Récupération du schéma d'un annuaire LDAP

Pour interroger le schéma d'un annuaire ldap il faut lancer la commande suivante:

ldapsearch -h localhost -b "cn=subschema" -s base "objectclass=*" + -x

Qui donnera quelque chose comme ceci :

# LDAPv3
# base with scope baseObject
# filter: objectclass=*
# requesting: +
#

# Subschema
dn: cn=Subschema
structuralObjectClass: subentry
createTimestamp: 20081106155906Z
modifyTimestamp: 20081106155906Z
ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' X-NOT-HUMAN-READABLE
'TRUE' )
ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' X-NOT-HUMAN-READABL
E 'TRUE' )
ldapSyntaxes: ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
...........


Si la commande ne donne rien, cela provient souvent d'un problème d'ACL :
Vérifiez d'avoir ceci dans son fichier de configuration :

access to dn.base="cn=Subschema" by * read

Fichier amorce pour un annuaire LDAP

Pour créer un annuaire ldap voici un fichier amorce.ldif

dn: dc=demo,dc=net
objectclass: top
objectclass: organization
objectclass: dcobject
o: demo
dc: demo
description: Top level LDAP for demo ldap


Il ne reste plus qu'a l'injecter avec la commande :

slapadd -f /usr/local/openldap/etc/openldap/slapd.conf -l amorce.ldif

mardi 17 juin 2008

Comment verifier l'état de replication de syncrepl ?

Pour connaitre le niveau de replication de syncrepl , il faut interroger l'attribut 'contextCSN' du maitre et du replicat

Voici un exemple de programme qui réalise cette opération :
#! /usr/bin/perl
### by germanlinux
use strict;
use Date::Calc qw(Delta_DHMS);
use Net::LDAP ();
## mes fonctions
sub lookup_csn {
my ($ldap, $server_name) = @_;

my $search = $ldap->search(
scope => 'base',
base => $server_name->{base},
filter => "(objectclass=*)",
attrs => [ 'contextCSN' ]
);

$search->code() and do {
print STDERR "Error: failed to execute search on
$server_name->{host}: "
. $search->error() . " (" . $search->code() .
")\n";
exit(1);
};

my $entry = $search->shift_entry() or do {
print STDERR "Error: search on $server_name->{host} failed to find
entry\n";
exit(1);
};
my $csn = $entry->get_value('contextCSN');
if (!defined($csn)) {
print STDERR "Error: no contextCSN attribute found in
$server_name->{host} entry\n";
exit(1);
}
return $csn;
}

my $ldap_master = Net::LDAP->new($master->{host}, ) or do {
print STDERR "Error: failed to connect to LDAP master: $@";
exit(1);
};

my $ldap_replicat = Net::LDAP->new($replicat->{host},port => $replicat->{port},) or do {
print STDERR "Error: failed to connect to LDAP replicat: $@";
exit(1);
};

my $msg1 =$ldap_master->bind(dn =>$master->{dn} ,
password => $master->{password} ) ;

my $msg2 =$ldap_replicat->bind(dn =>$replicat->{dn} ,
password =>$replicat->{password} ) ;

my $master_csn = lookup_csn($ldap_master,$master);
my $replicat_csn = lookup_csn($ldap_replicat, $replicat);

if ($master_csn eq $replicat_csn )
{ print "0 - 0\n";

}
else {

my $master_csn_date=$master_csn;
my $replicat_csn_date =$replicat_csn;
$master_csn_date=~ s/Z.*//;
$replicat_csn_date =~s/Z.*//;
(my $y1,my $m1,my $d1,my $h1,my $mm1,my $s1) = $master_csn_date=~/(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/;
(my $y2,my $m2,my $d2,my $h2,my $mm2,my $s2) = $replicat_csn_date=~/(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/;
(my $dt,my $ht,my $mmt,my $st) = Delta_DHMS (
$y2,$m2,$d2, $h2, $mm2,$s2,
$y1,$m1,$d1, $h1, $mm1,$s1,
);

print "$master_csn_date - $replicat_csn_date\n";
my $deltamin = ($ht * 60) + $mmt ;
print "$dt - $ht - $mmt - $st\n";
print "$deltamin minutes\n";
}



Le résultat du programme est de la forme :

20080617144859 - 20080617140355
0 - 0 - 45 - 4
45 minutes

Comment mesurer la vitesse de propagation de l'information ?

Je suis souvent amené à mesurer la vitesse de propagation de l'information au travers des annuaires.
Pour cela j'ai un programme qui réalise les opérations suivantes:

a) Modifier une entrée de l'annuaire maitre LDAP
b) Armer un timer
c) Interroger à intervalle régulier l'annuaire replicat jusqu'a obtenir l'information à jour.

Voici le programme :
#!/usr/bin/perl -w

### by germanlinux

use Net::LDAP;
use Time::HiResi qw( usleep ualarm gettimeofday tv_interval) ;
my $master= { 'host' => 'ip.ip.ip.ip' ,
'dn' =>'dn bnd' ,
'password' => 'password' ,
'base' => 'base',
'filter' =>'filtre'
};
my $replicat= { 'host' => 'ip.ip.ip.ip' ,
'dn' =>'dn bnd' ,
'password' => 'password' ,
};
#### first bind to master ########
my $master_ldap_connection = Net::LDAP->new($master->{host});
my $msg =$master_ldap_connection->bind($master->{dn} ,
$master->{password} ) ;
my $rech = $master_ldap_connection->search (
base =>$master->{base},
filter =>$master->{filter} ,
);
my $retour= $rech->entry(0) ;
exit if !$retour;
my $dn= $retour->dn;
#### armement du chronometre
my $change=time();
my $t0= [gettimeofday];
#### modification ###########
my $modif = $master_ldap_connection->modify($dn,
replace => { 'unelettre' => $change} );
$master_ldap_connection->unbind;
############# boucle de calcul de temps de propagation ##############
my $not_found=1;
while ($not_found) {
my $replicat_ldap_connection = Net::LDAP->new($replicat->{host});
my $msg =$replicat_ldap_connection->bind($replicat->{dn} ,
$replicat->{password} ) ;
my $compare = $replicat_ldap_connection->compare ($dn,
attr => 'unelettre' ,
value => $change,
);
$not_found =0 if ($compare->code == 6 ) ;
$replicat_ldap_connection->unbind;
sleep(5);
}
## calcul t1-t0;
my $delta = tv_interval ($t0);
print "Vitesse :$delta\n";