«The human brain starts working the moment you are born
and never stops until you stand up to speak in public. »
Sir George Jessel
Ce que le client a aujourd'hui :
Extensions sauvages du schéma LDAP
diff -ur schema/core.schema ../../../isis/ldap/schema/core.schema --- schema/core.schema 2002-02-08 18:38:54.000000000 +0100 +++ ../../../isis/ldap/schema/core.schema 2007-10-15 10:31:04.000000000 +0200 @@ -1,3 +1,6 @@ +# Objectclass 'person' a ete modifier pour prendre en compte l attribut +# usergroup pour gerer les differents droits d acces a la base ldap sur l 'intra +# # $OpenLDAP: pkg/ldap/servers/slapd/schema/core.schema,v 1.7.2.18 2002/02/08 17:38:54 kurt Exp $ # # OpenLDAP Core schema @@ -369,7 +379,7 @@ objectclass ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn ) - MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) ) + MAY ( userPassword $ telephoneNumber $ seeAlso $ description $ intragroup) ) objectclass ( 2.5.6.7 NAME 'organizationalPerson' SUP person STRUCTURAL MAY ( title $ x121Address $ registeredAddress $ destinationIndicator $
Ce que le client veut :
Solutions possibles :
Solutions possibles :
#:: ::-| ::-| .-. :||-:: 0-| .-| ::||-| .:|-. :||
open(Q,$0);while(<Q>){if(/^#(.*)$/){for(split('-',$1)){$q=0;for(split){s/\|
/:.:/xg;s/:/../g;$Q=$_?length:$_;$q+=$q?$Q:$Q*20;}print chr($q);}}}print"\n";
#.: ::||-| .||-| :|||-| ::||-| ||-:: :|||-| .:|
Solutions possibles :
def getldapinfos(ldappointer, file):
""" get uid and mailhost from ldap then print on stdout uid IN CNAME mailhost """
""" in case of error for an entry stderr will be used """
...
if I_HAS_PYTHON == True:
for entry in resultlist:
for fields in entry:
res = myreg.match(entry[1]["mailHost"][0])
if res != None:
file.write("%s.imap.mail\tIN\tCNAME\t%s.\n" %( entry[1]["uid"][0], res.group(1)))
if entry[1]["name"] = "LOL!!11":
print "All your base are belong to us"
return 0
Solutions possibles :
Dans la migration, il y a plusieurs tâches, séquentielles ou pas, à enchaîner
On veut :
Pourquoi pas Makefile ?
INFILE := customer-orig.ldif
OUTFILE := customer-clean.ldif
CLEANER := ./customer-clean-ldif.rb
ROOTDN := "cn=admin, o=customer, c=fr"
ROOTPW := "XXXXX"
clean_ldif:
ssh old-srv "slapcat" > $(INFILE)
$(CLEANER) $(INFILE) > $(OUTFILE)
test_ldif: clean_ldif
ldapadd -n -x -h localhost -D $(ROOTDN) -w $(ROOTPW) -f $(OUTFILE)
#...etc...
Rake est un logiciel écrit en Ruby, qui permet de décrire et de contrôler des tâches à la Makefile
Dans un fichier Rakefile on n'écrit que du Ruby
TESTDIR = File.join(File.dirname(__FILE__), "test")
INFILE = File.join(TESTDIR, "customer-orig.ldif")
CLEANER = File.join("lib", "customer-clean-ldif.rb")
ROOTDN = "cn=admin, o=custmer, c=fr"
ROOTPW = "XXXXXX"
#...
namespace :ldap do
desc "Récupération de l'annuaire 'isis' et nettoyage"
task :clean_ldif => :config do
puts "Récupération de l'annuaire LDAP d'isis"
puts_and_exec %{ssh old-srv "slapcat" > "#{INFILE}"}
puts "Nettoyage de l'annuaire LDAP"
puts_and_exec %{#{CLEANER} "#{INFILE}" > "#{OUTFILE}"}
end
desc "Test d'insertion des enregistrements LDAP sur #{HOSTNAME}"
task :test_ldif => :clean_ldif do
puts "Simulation d'insertion des enregistrements LDAP"
puts_and_exec %{ldapadd -n -x -h localhost -D "#{ROOTDN}" -w "#{ROOTPW}" -f "#{OUTFILE}"}
end
#...
Première impression :
Quand d'autres pensent à :
Nous faisons appel à :
Super-YAML !
On va utiliser YAML pour le stockage de la configuration :
# Configuration de l'outil de migration LDAP/IMAP # Date : 2009-01-13 # Copyright (C) 2009 Farzad FARIDhostname: new-srv ldap: user: cn=admin, o=customer, c=fr password: XXXXXXXX infile: customer-orig.ldif outfile: customer-clean.ldif imap: user: cyrus password: YYYYY
MyConfig = YAML.load(IO.read(File.join(File.dirname(__FILE__), "config.yml")))
HOSTNAME = MyConfig["hostname"]
ROOTDN = MyConfig["ldap"]["user"]
ROOTPW = MyConfig["ldap"]["password"]
INFILE = File.join(DATADIR, MyConfig["ldap"]["infile"])
#...
namespace :ldap do
desc "Insère les enregistrements LDAP sur #{HOSTNAME} en détruisant le contenu précédent"
task :insert_full => [ :clean_ldif, :empty_directory] do
puts "Insertion complète des enregistrements LDAP"
show_exec %{sleep 2
ldapadd -c -x -h localhost -D "#{ROOTDN}" -w "#{ROOTPW}" -f "#{OUTFILE}"}
end
#...
Comment fonctionne le script principal de nettoyage LDAP ?
Comment fonctionne le script principal de nettoyage LDAP ?
if rdn_name =="pu" && !attrs["objectclass"].include?("projectUnit")
# On enlève les OC erronées, s'il y en a
attrs["objectclass"] -= [ "societyUnit"]
attrs["objectclass"] << "projectUnit"
attrs.delete("su")
end
if (rdn_name == "su" && rdn_value == "glucoz.com") || dn == "su=gensduvoyage.com, o=customer, c=fr"
attrs.delete("ou")
end
# Pour certains RDN "ou=", l'object class organizationalUnit correspondant
# est manquant
if rdn_name == "ou" && !attrs["objectclass"].include?("organizationalUnit")
attrs["objectclass"] << "organizationalUnit"
end
Quelles avantages pour les tâches système et d'intégration ?
Facile de dialoguer avec un serveur IMAP (quand on connaît le RFC..)
IMAP = Net::IMAP.new("localhost")
IMAP.login(MyConfig["imap"]["user"], MyConfig["imap"]["password"])
IMAP.getacl("user.ffarid").each do |right|
puts " #{right.user} : #{right.rights}"
end
IMAP.setacl("user.ffarid", "cyrus", "lrswipcda")
MBOXLIST.each do |folder_dst|
begin
IMAP.create(folder_dst)
rescue Net::IMAP::NoResponseError => e
#...
Il faut utiliser SMTP ? C'est encore plus simple :
begin
Net::SMTP.start('localhost', 25) do |smtpclient|
smtpclient.send_message(the_email, user_from, users_to_list)
end
puts "Mail envoyé"
rescue Exception => e
print "Exception occured: " + e
end
Comment étendre les classes standard avec élégance ?
class << IMAP
def method_missing(method, *arguments)
# Si la fonction appelée est "show_*" alors affiche
# la commande "*" et ensuite exécute la dans le contexte IMAP
if method.to_s =~ /^show_(\w+)$/
imapcmd = $1
puts ">> IMAP #{imapcmd}#{arguments.inspect}"
self.send(imapcmd, *arguments)
else
super
end
end
end
Améliorations possibles :
screen est votre ami !Mission réussie !