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.
Python, Ruby, javascript, node.js, cloud ,NoSQL bref que des bonnes choses
Contacter le robot germanlinux: german.eric AT gmail.com
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
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}
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
ldapsearch -h localhost -b "cn=subschema" -s base "objectclass=*" + -x
Qui donnera quelque chose comme ceci :
# LDAPv3
# base
# 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
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
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";
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";
Inscription à :
Articles (Atom)