Showing posts with label openldap. Show all posts
Showing posts with label openldap. Show all posts

Monday, September 15, 2014

Migrating WebLogic Embedded LDAP to OpenLDAP

Oracle WebLogic memiliki Embedded LDAP yang berfungsi sebagai penyedia otentikasi, otorisasi, credential mapping, dan role mapping. Ketika sebuah WebLogic Domain dibuat, secara default user dan group administratif seperti user weblogic tersimpan di WebLogic Embedded LDAP server. Secara fungsi, Embedded LDAP sudah menyediakan fungsi yang lengkap untuk WebLogic Domain. Namun pada ada kasus di mana menggunakan Embedded LDAP kurang disarankan, terutama pada deployment yang memiliki user lebih dari 10.000 user. Solusinya adalah dengan memindahkan LDAP service keluar dari WebLogic Domain.

Pada artikel kali ini saya ingin berbagi langkah-langkah untuk memigrasikan user yang tersimpan di WebLogic Embedded LDAP ke OpenLDAP. Pada dasarnya aktivitas migrasinya bisa dilihat pada diagram aktivitas berikut ini:
Activity Diagram for Embedded LDAP to OpenLDAP Migration

Penjelasan detilnya adalah:
  1. Shutdown, Backup, and Startup WebLogic Domain
    Langkah wajib setiap kali kita akan melakukan perubahan yang sifatnya domain-wide. Full backup dapat dilakukan dengan membuat tarball dari direktori di mana WebLogic Domain dan Oracle binary berada, diikuti dengan backup skema database-nya. Jika sudah selesai melakukan backup, jalankan kembali cukup AdminServer saja.
  2. Export myrealm
    Login ke Administration Console, pilih $NAMA_DOMAIN -> Security Realms -> myrealm -> Migration -> Export. Tulis nama direktori tempat hasil export akan disimpan, kemudian tekan tombol Save. Aktivitas ini akan menghasilkan beberapa file, namun yang perlu kita proses adalah file DefaultAuthenticator.dat yang sebenarnya merupakan file dengan format LDIF.
    Export DefaultAuthenticator
  3. Parse DefaultAuthenticator.dat and Generate OpenLDAP LDIF
    Pada tahap ini saya akan menggunakan Perl script sederhana yang memanfaatkan kekuatan regex untuk melakukan parsing file DefaultAuthenticator.dat dan mengubah formatnya menjadi OpenLDAP-friendly. Tidak semua field ter-cover pada script ini, namun cukup untuk kasus yang saya temui. Output dari script in akan menghasilkan beberapa file, namun yang penting adalah file people.ldif yang berisi seluruh user dan groups.ldif yang berisi seluruh group serta mapping-nya terhadap user yang ada.
     #!/usr/bin/perl -w  
       
     # Author : Okky Hendriansyah (okky@nostratech.com)  
     # Date   : 2014/07/14  
     # Desc.  : Oracle WebLogic Embedded LDAP LDIF Converter to OpenLDAP LDIF  
     # Input  : DefaultAuthenticator.dat exported from WebLogic Administration Console  
     # Output : processed/excluded.ldif, processed/groups.ldif, processed/people.ldif, and processed/people_rdn.ldif  
     # Run    : ./weblogic_to_openldap.pl  
       
     # Change this constant to resemble the directory root tree  
     use constant ORGANIZATION => "dc=nostra,dc=tech";  
       
     # Open the exported DefaultAuthenticator LDIF file and slurp the whole contents  
     open FILEHANDLE, '<DefaultAuthenticator.dat' or die $!;  
     my $default_authenticator = do { local $/; <FILEHANDLE>; };  
     close FILEHANDLE;  
       
     # Open output files  
     open EXCLUDED_ENTRIES, '>processed/excluded.ldif' or die $!;  
     open GROUP_ENTRIES, '>processed/groups.ldif' or die $!;  
     open GROUP_RDN_ENTRIES, '>processed/groups_rdn.ldif' or die $!;  
     open PERSON_ENTRIES, '>processed/people.ldif' or die $!;  
     open PERSON_RDN_ENTRIES, '>processed/people_rdn.ldif' or die $!;  
       
     # Split LDAP entries to array elements  
     @ldap_entries = split /\n\n/, $default_authenticator;  
     $total_ldap_entries = scalar @ldap_entries;  
       
     # Variables initialization  
     $total_groups = 0;  
     $total_people = 0;  
     $total_excluded = 0;  
     my %groups;  
       
     # Traverse all the LDAP entries  
     foreach $ldap_entry (@ldap_entries) {  
         # Initial parse group entries  
         if ($ldap_entry =~ m/objectclass: groupOfUniqueNames/i) {  
             # RDN  
             if ($ldap_entry =~ m/dn: cn=([^,]+),ou=groups,ou=\@realm\@,dc=\@domain\@/i) {  
                 # Register the group  
                 $groups{$1} = qw();  
             }  
         }  
         # Parse person entries  
         elsif ($ldap_entry =~ m/objectclass: inetOrgPerson/i) {  
             # Person total  
             $total_people++;  
             # RDN  
             if ($ldap_entry =~ m/dn: uid=([^,]+),ou=people,ou=\@realm\@/) {  
                 $person_uid_value = $1;  
                 $person_rdn = "dn: uid=$person_uid_value,ou=people," . ORGANIZATION . "\n";  
                 $output = $person_rdn;   
                 # objectclass  
                 $person_objectclass = "objectClass: inetOrgPerson\n";  
                 $person_objectclass .= "objectClass: organizationalPerson\n";  
                 $person_objectclass .= "objectClass: person\n";  
                 $person_objectclass .= "objectClass: top\n";  
                 $output .= $person_objectclass;  
                 # Group  
                 while ($ldap_entry =~ m/wlsMemberOf: cn=([^,]+),ou=groups,ou=\@realm\@/gi) {  
                     push @{$groups{$1}}, $person_uid_value;  
                 }  
                 # description  
                 if ($ldap_entry =~ m/description: ([^\n]+)/i) {  
                     $person_description = "description: $1\n";  
                     $output .= $person_description;  
                 }  
                 # cn  
                 if ($ldap_entry =~ m/cn: ([^\n]+)/i) {  
                     $person_cn = "cn: $1\n";  
                     $output .= $person_cn;  
                 }  
                 # sn  
                 if ($ldap_entry =~ m/sn: ([^\n]+)/i) {  
                     $person_sn = "sn: $1\n";  
                     $output .= $person_sn;  
                 }  
                 # uid  
                 if ($ldap_entry =~ m/uid: ([^\n]+)/i) {  
                     $person_uid = "uid: $1\n";  
                     $output .= $person_uid;  
                 }  
                 # userpassword  
                 if ($ldap_entry =~ m/userpassword:: ([^\n]+)/i) {  
                     $person_userpassword = "userPassword:: $1\n";  
                     $output .= $person_userpassword;  
                 }  
                 # mail  
                 if ($ldap_entry =~ m/mail: ([^\n]+)/i) {  
                     $person_mail = "mail: $1\n";  
                     $output .= $person_mail;  
                 }  
                 # displayname  
                 if ($ldap_entry =~ m/displayname: ([^\n]+)/i) {  
                     $person_displayname = "displayName: $1\n";  
                     $output .= $person_displayname;  
                 }  
                 # givenname  
                 if ($ldap_entry =~ m/givenname: ([^\n]+)/i) {  
                     $person_givenname = "givenName: $1\n";  
                     $output .= $person_givenname;  
                 }  
                 # title  
                 if ($ldap_entry =~ m/title: ([^\n]+)/i) {  
                     $person_title = "title: $1\n";  
                     $output .= $person_title;  
                 }  
                 # departmentnumber  
                 if ($ldap_entry =~ m/departmentnumber: ([^\n]+)/i) {  
                     $person_departmentnumber = "departmentNumber: $1\n";  
                     $output .= $person_departmentnumber;  
                 }  
                 # employeenumber  
                 if ($ldap_entry =~ m/employeenumber: ([^\n]+)/i) {  
                     $person_employeenumber = "employeeNumber: $1\n";  
                     $output .= $person_employeenumber;  
                 }  
                 # employeetype  
                 if ($ldap_entry =~ m/employeetype: ([^\n]+)/i) {  
                     $person_employeetype = "employeeType: $1\n";  
                     $output .= $person_employeetype;  
                 }  
                 # o  
                 if ($ldap_entry =~ m/o: ([^\n]+)/i) {  
                     $person_o = "o: $1\n";  
                     $output .= $person_o;  
                 }  
                 # preferredlanguage  
                 if ($ldap_entry =~ m/preferredlanguage: ([^\n]+)/i) {  
                     $person_preferredlanguage = "preferredLanguage: $1\n";  
                     $output .= $person_preferredlanguage;  
                 }  
                 # telephonenumber  
                 if ($ldap_entry =~ m/telephonenumber: ([^\n]+)/i) {  
                     $person_telephonenumber = "telephoneNumber: $1\n";  
                     $output .= $person_telephonenumber;  
                 }  
                 # jpegphoto  
                 if ($ldap_entry =~ m/jpegphoto:: ([^\n]+)/i) {  
                     $person_jpegphoto = "jpegPhoto:: $1\n";  
                     $output .= $person_jpegphoto;  
                 }  
                 # Print to file  
                 print PERSON_ENTRIES "$output\n";  
                 print PERSON_RDN_ENTRIES "uid=$person_uid_value,ou=people," . ORGANIZATION . "\n";  
             }  
         }  
         # No need to parse these entries   
         else {  
             $total_excluded++;  
             print EXCLUDED_ENTRIES "$ldap_entry\n\n";  
         }  
     }  
       
     # Repeat traversing the LDAP entries but only group entries are processed  
     foreach $ldap_entry (@ldap_entries) {  
         # Compose group entries  
         if ($ldap_entry =~ m/objectclass: groupOfUniqueNames/i) {  
             # Group total  
             $total_groups++;  
             # RDN  
             if ($ldap_entry =~ m/dn: cn=([^,]+),ou=groups,ou=\@realm\@,dc=\@domain\@/i) {  
                 $group_cn_value = $1;  
                 $group_rdn = "dn: cn=$group_cn_value,ou=groups," . ORGANIZATION . "\n";  
                 $output = $group_rdn;  
                 # objectclass  
                 $group_objectclass = "objectClass: groupOfUniqueNames\n";  
                 $group_objectclass .= "objectClass: top\n";  
                 $output .= $group_objectclass;  
                 # cn  
                 if ($ldap_entry =~ m/cn: ([^\n]+)/i) {  
                     $group_cn = "cn: $1\n";  
                     $output .= $group_cn;  
                 }  
                 # description  
                 if ($ldap_entry =~ m/description: ([^\n]+)/i) {  
                     $group_description = "description: $1\n";  
                     $output .= $group_description;  
                 }  
                 # uniqueMember  
                 $group_uniquemember = "";  
                 foreach $member_uid (@{$groups{$group_cn_value}}) {  
                     $group_uniquemember .= "uniqueMember: uid=$member_uid,ou=people," . ORGANIZATION . "\n";  
                 }  
                 # handles groups without any member defined  
                 if ($group_uniquemember eq "") {  
                     $group_uniquemember .= "uniqueMember: \n";  
                 }  
                 $output .= $group_uniquemember;  
                 # Print to file  
                 print GROUP_ENTRIES "$output\n";  
                 print GROUP_RDN_ENTRIES "cn=$group_cn_value,ou=groups," . ORGANIZATION . "\n";  
             }  
         }  
         # Ignore if encounter the first entry of a person  
         elsif ($ldap_entry =~ m/objectclass: inetOrgPerson/i) {  
             # Skip all person entries  
             last;  
         }  
     }  
       
     # Close output files  
     close EXCLUDED_ENTRIES;  
     close GROUP_ENTRIES;  
     close GROUP_RDN_ENTRIES;  
     close PERSON_ENTRIES;  
     close PERSON_RDN_ENTRIES;  
       
     # Print summary  
     print "Total Groups\t: $total_groups\n";  
     print "Total People\t: $total_people\n";  
     print "Total Excluded\t: $total_excluded\n";  
     print "Total Entries\t: $total_ldap_entries\n";  
    
  4. Import People and Groups
    Jalankan LDAP browser seperti Apache Directory Studio, koneksikan dengan OpenLDAP server yang sudah running. Import terlebih dahulu file people.ldif dilanjutkan oleh groups.ldif
  5. Recreate Admin Users in OpenLDAP
    Langkah ini opsional, kita juga dapat menggunakan user weblogic yang ter-import melalui langkah sebelumnya.
  6. Reassociate Authentication Provider
    Login kembali ke Administration Console. Pilih $NAMA_DOMAIN -> Security Realms -> myrealm -> Providers. Buat authentication provider baru dengan cara tekan tombol New dan masukkan tipe OpenLDAPAuthenticator. Pilih OpenLDAPAuthenticator tersebut dan ubah Control Flag menjadi SUFFICIENT. Setelah save, pilih tab Provider Specific dan masukkan detil informasi ke OpenLDAP server. Save setelah selesai memasukkan semua informasi tersebut. Kembali ke halaman Providers, masuk ke DefaultAuthenticator dan ganti Control Flag menjadi SUFFICIENT dan ubah urutan provider menjadi OpenLDAPAuthenticator, DefaultAuthenticator, dan DefaultIdentityAsserter.
  7. Restart WebLogic Domain
    Activate changes dan restart WebLogic Domain agar perubahan tersebut dapat diaplikasikan.
  8. Remap Global Roles, especially Admin
    Langkah ini tidak diperlukan jika kita tidak melakukan langkah ke-5.
  9. Enable Identity Virtualization
    Login ke WebLogic Enterprise Manager Fusion Middleware Control. Pilih $NAMA_DOMAIN -> WebLogic Domain -> Security -> Security Provider Configuration. Buka bagian Identity Store Provider kemudian pilih Configure. Tambahkan custom property virtualize dengan nilai true kemudian Save.
    Enable Identity Virtualization
  10. Restart WebLogic Domain
    Activate changes dan restart WebLogic Domain agar perubahan tersebut dapat diaplikasikan.
  11. Reassociate Application-specific Roles/Group
    Remap role dan grup pada masing-masing aplikasi, agar tidak lagi menggunakan grup yang ada di Embedded LDAP.
  12. Test and Validate
    Ganti password user yang tersimpan pada OpenLDAP dan lakukan aktivitas login dan logout baik ke Administration Console maupun ke aplikasi yang menggunakan WebLogic Authentication Provider. Seharusnya sekarang sudah bisa login menggunakan user dan password yang sesuai dengan OpenLDAP.
Selamat mencoba! :D


Setting Up OpenLDAP Mirror-Mode

OpenLDAP merupakan implementasi Lightweight Directory Access Protocol server yang bersifat open source. OpenLDAP dapat menjadi alternatif solusi LDAP service selain solusi lain seperti Microsoft Active Directory dan Oracle Internet Directory. Saya mulai mempelajari OpenLDAP ketika ada kebutuhan untuk memindahkan user aplikasi dari WebLogic Embedded LDAP ke OpenLDAP. Pada kesempatan kali ini saya ingin mencoba melakukan instalasi OpenLDAP server, serta melakukan konfigurasi replikasi mirror-mode dengan 2 node.

Instalasi dilakukan pada mesin Red Hat Enterprise Linux 5.5 (64-bit). Environment yang ada tidak terhubung dengan Internet dan versi OpenLDAP pada official package belum mendukung fitur replikasi mirror-mode yang diperlukan, sehingga saya download RPM yang tersedia di LTB Project.

OpenLDAP Initialization

Berikut adalah langkah-langkah instalasinya:
  1. Download GPG Key dari LTB Project
     root@ldap1.nostra.tech ~# wget http://ltb-project.org/wiki/lib/RPM-GPG-KEY-LTB-project  
    
  2. Upload GPG Key tersebut ke server kemudian import
     root@ldap1.nostra.tech ~# rpm --import RPM-GPG-KEY-LTB-project  
    
  3. Download RPM BerkleyDB dan OpenLDAP dari LTB Project kemudian upload ke server
  4. Instalasi BerkeleyDB dan OpenLDAP
     root@ldap1.nostra.tech ~# yum localinstall berkeleydb-ltb* openldap-ltb*  
    
  5. Jika ada dependency yang tidak terpenuhi, download dan instalasi RPM dependency lainnya menggunakan perintah yum downloadonly (lihat detilnya blog ini) pada mesin dengan akses Internet
  6. Sukses, instalasi BerkeleyDB dan OpenLDAP akan ada di path /usr/local/ 
  7. Lakukan langkah serupa pada node ke-2

    OpenLDAP Initialization

    Sebelum OpenLDAP dapat dijalankan untuk pertama kalinya, OpenLDAP harus diinisialisasi terlebih dahulu. Proses inisialisasi OpenLDAP dapat dijabarkan sebagai berikut:
    1. Mendefinisikan root, ubah file /usr/local/openldap/etc/openldap/ldap.conf menjadi seperti ini:
       #  
       # LDAP Defaults  
       #  
       # See ldap.conf(5) for details  
       # This file should be world readable but not world writable.  
       BASE   dc=nostra,dc=tech  
       URI    ldap://ldap1.nostra.tech ldap://ldap2.nostra.tech  
       #SIZELIMIT    12  
       #TIMELIMIT    15  
       #DEREF        never  
      
    2. Membuat password untuk rootdn
       root@ldap1.nostratech.com ~# slappasswd  
       New password:   
       Re-enter new password:   
       {SSHA}lHpQpKI0+rQgZ+4cpQpa0dy/Q+gkcQnN  
      
    3. Mendaftarkan password tersebut ke OpenLDAP, dengan cara mengubah bagian BDB pada file /usr/local/openldap/etc/openldap/slapd.conf
      ...
       #######################################################################  
       # BDB database definitions  
       #######################################################################  
       database    bdb  
       suffix      "dc=nostra,dc=tech"  
       rootdn      "cn=ldapadmin,dc=nostra,dc=tech"  
       # Cleartext passwords, especially for the rootdn, should  
       # be avoid. See slappasswd(8) and slapd.conf(5) for details.  
       # Use of strong authentication encouraged.  
       rootpw      {SSHA}YiQMY8N84rgoZOol8Y2vB1+lkBc3KT9n  
      ...
      
    4. Ubah default startup configuration di /etc/default/slapd, pastikan untuk mengganti SLAPD_USER dan SLAPD_GROUP menjadi root jika ingin menjalankan OpenLDAP pada port < 1024
       #====================================================================  
       # Configuration example of OpenLDAP's init script  
       #====================================================================  
       # IP and port to listen  
       IP="192.168.10.100"  
       SSLIP="192.168.10.100"  
       PORT="389"  
       SSLPORT="636"  
      
       # OpenLDAP directory and files  
       SLAPD_PATH="/usr/local/openldap"  
       SLAPD_PID_FILE="$SLAPD_PATH/var/run/slapd.pid"  
       SLAPD_CONF="$SLAPD_PATH/etc/openldap/slapd.conf"  
       SLAPD_CONF_DIR=""  
       SLAPD_SERVICES="ldap://$IP:$PORT ldaps://$SSLIP:$SSLPORT"  
       SLAPD_PARAMS=""  
       SLAPD_BIN="$SLAPD_PATH/libexec/slapd"  
       SLAPD_USER="root"  
       SLAPD_GROUP="root"  
       SLAPD_SYSLOG_LOCAL_USER="local4"  
       ... 
      
    5. Startup OpenLDAP
       root@ldap1.nostra.tech ~# service slapd start  
       slapd: [INFO] Using /etc/default/slapd for configuration  
       slapd: [INFO] Launching OpenLDAP configuration test...  
       slapd: [OK] OpenLDAP configuration test successful  
       slapd: [INFO] No db_recover done  
       slapd: [INFO] Launching OpenLDAP...  
       slapd: [OK] File descriptor limit set to 1024  
       slapd: [OK] OpenLDAP started    
      
    6. Cek status dari OpenLDAP server, pastikan statusnya sudah running
       root@ldap1.nostra.tech ~# service slapd status   
        slapd: [INFO] Using /etc/default/slapd for configuration   
        slapd: [INFO] LDAP Tool Box OpenLDAP init script version 1.9   
        slapd: [INFO] Process OpenLDAP is running (PID 1200)   
        slapd: [INFO] Listening to services ldap://192.168.10.100:389 ldaps://192.168.10.100:636   
        slapd: [INFO] Process usage: 4.2% CPU / 0.1% MEM   
        slapd: [INFO] Detected suffix: dc=nostra,dc=tech  
      
    7. Buat file ldap-init.ldif untuk membuat struktur LDAP tree awal dan rootdn
       dn: dc=nostra,dc=tech  
       objectclass: dcObject  
       objectclass: organization  
       o: LDAP Tree of Nostra Technology  
       dc: nostra  
       
       dn: cn=ldapadmin,dc=nostra,dc=tech  
       objectclass: organizationalRole  
       cn: ldapadmin  
      
    8. Import file tersebut ke OpenLDAP server
       root@ldap1.nostra.tech ~# ldapadd -a -x -D 'cn=ldapadmin,dc=nostra,dc=tech' -W -f ldap-init.ldif  
      
    9. OpenLDAP selesai di-inisialisasi
    10. Lakukan langkah serupa pada node ke-2

    OpenLDAP Mirror-Mode Configuration

    Update /usr/local/openldap/etc/openldap/slapd.conf pada kedua node menjadi seperti berikut ini:
     #  
     # See slapd.conf(5) for details on configuration options.  
     # This file should NOT be world readable.  
     #  
     include     /usr/local/openldap/etc/openldap/schema/core.schema  
     include     /usr/local/openldap/etc/openldap/schema/cosine.schema  
     include     /usr/local/openldap/etc/openldap/schema/inetorgperson.schema  
     include     /usr/local/openldap/etc/openldap/schema/nis.schema  
     include     /usr/local/openldap/etc/openldap/schema/dyngroup.schema  
    
     # Define global ACLs to disable default read access.  
     # Do not enable referrals until AFTER you have a working directory  
     # service AND an understanding of referrals.  
     #referral    ldap://root.openldap.org  
     pidfile     /usr/local/openldap/var/run/slapd.pid  
     argsfile    /usr/local/openldap/var/run/slapd.args  
    
     # Load dynamic backend modules:  
     # modulepath    /usr/local/openldap/libexec/openldap  
     # moduleload    back_bdb.la  
     # moduleload    back_hdb.la  
     # moduleload    back_ldap.la  
     moduleload dyngroup.la  
     moduleload dynlist.la  
     moduleload syncprov.la  
     moduleload accesslog.la  
     moduleload back_bdb.la  
    
     # Sample security restrictions  
     #    Require integrity protection (prevent hijacking)  
     #    Require 112-bit (3DES or better) encryption for updates  
     #    Require 63-bit encryption for simple bind  
     # security ssf=1 update_ssf=112 simple_bind=64  
     # Sample access control policy:  
     #    Root DSE: allow anyone to read it  
     #    Subschema (sub)entry DSE: allow anyone to read it  
     #    Other DSEs:  
     #        Allow self write access  
     #        Allow authenticated users read access  
     #        Allow anonymous users to authenticate  
     #    Directives needed to implement policy:  
     # access to dn.base="" by * read  
     # access to dn.base="cn=Subschema" by * read  
     # access to *  
     #    by self write  
     #    by users read  
     #    by anonymous auth  
     #  
     # if no access controls are present, the default policy  
     # allows anyone and everyone to read anything but restricts  
     # updates to rootdn. (e.g., "access to * by * read")  
     #  
     # rootdn can always read and write EVERYTHING!  
    
     # OpenLDAP Server Idenfitier
     serverID 1  
    
     #######################################################################  
     # BDB database definitions  
     #######################################################################  
     database     bdb  
     suffix       "dc=nostra,dc=tech"  
     rootdn       "cn=ldapadmin,dc=nostra,dc=tech"  
     # Cleartext passwords, especially for the rootdn, should  
     # be avoid. See slappasswd(8) and slapd.conf(5) for details.  
     # Use of strong authentication encouraged.  
     rootpw       {SSHA}YiQMY8N84rgoZOol8Y2vB1+lkBc3KT9n  
     # The database directory MUST exist prior to running slapd AND   
     # should only be accessible by the slapd and slap tools.  
     # Mode 700 recommended.  
     directory    /usr/local/openldap/var/openldap-data  
     checkpoint   10240 720  
     cachesize    50000  
    
     # Indices to maintain  
     index  objectClass,entryCSN,entryUUID  eq,pres  
     index  ou,cn,mail,surname,givenname    eq,pres,sub  
     index  uidNumber,gidNumber,loginShell  eq,pres  
     index  uid,memberUid                   eq,pres,sub  
     index  nisMapName,nisMapEntry          eq,pres,sub  
     
     # DBConfig
     dbconfig set_cachesize 0 268435456 1  
     dbconfig set_lk_max_locks 3000  
     dbconfig set_lk_max_objects 1500  
     dbconfig set_lk_max_lockers 1500  
     dbconfig set_lg_regionmax 262144  
     dbconfig set_lg_bsize 2097152  
     
     # Replication  
     syncrepl    rid=001  
                 provider=ldap://ldap2.nostra.tech:389  
                 binddn="cn=ldapadmin,dc=nostra,dc=tech"  
                 bindmethod=simple  
                 credentials=secret
                 searchbase="dc=nostra,dc=tech"
                 type=refreshAndPersist  
                 interval=00:00:00:10  
                 retry="60 10 300 +"  
                 timeout=1  
                 mirrormode TRUE  
    
     overlay syncprov  
     syncprov-nopresent TRUE  
     syncprov-reloadhint TRUE  
     syncprov-checkpoint 1000 60  
     syncprov-sessionlog 100  
    
     overlay dynlist  
     dynlist-attrset groupOfURLs memberURL  
    


    Perbedaan dari kedua node ada pada baris-baris berikut:
    ...
     # OpenLDAP Server Idenfitier
     serverID 2  
    ...  
     # Replication  
     syncrepl    rid=002
                 provider=ldap://ldap1.nostra.tech:389  
                 binddn="cn=ldapadmin,dc=nostra,dc=tech"  
                 bindmethod=simple  
                 credentials=secret
                 searchbase="dc=nostra,dc=tech"
                 type=refreshAndPersist  
                 interval=00:00:00:10  
                 retry="60 10 300 +"  
                 timeout=1  
                 mirrormode TRUE  
    ...
    


    Restart OpenLDAP server pada kedua node, dan coba untuk melakukan perubahan data dari salah satu node. Seharusnya node yang lainnya akan mereplikasi perubahan tersebut seketika.

    Frontend with HAProxy-Keepalived Combo

    OpenLDAP mirror-mode akan lebih optimal jika di-frontend-kan oleh HAProxy, karena HAProxy yang akan bertugas untuk me-load-balance kedua node OpenLDAP secara active passive. Sehingga
    default akses ke OpenLDAP ke-1, dan hanya akan failover ke node ke-2 jika node ke-1 gagal. Saya sempat membahas bagaimana konfigurasi HAProxy dengan keepalived secara active passive pada blog sebelumnya. Sehingga pada langkah ini cukup mengubah/menambahkan rule active passive pada backend server-nya.

    Ubah konfigurasi HAProxy pada /etc/haproxy/haproxy.cfg di mana ldap.dppb.go.id adalah frontend server-nya dengan IP 192.168.10.99.
    ...
    listen ldap.dppb.go.id 192.168.10.99:389      
         mode tcp  
         option tcplog  
         server ldap1 ldap1.dppb.go.id:389 check inter 5000 downinter 500  
         server ldap2 ldap2.dppb.go.id:389 check inter 5000 backup  
    ...
    

    Restart proses HAProxy setelah mengubah file konfigurasi tersebut. Selamat mencoba! :)