www.zeroshell.org Forum Index www.zeroshell.org
Linux Distribution for server and embedded devices
 SearchSearch  RegisterRegister  UsergroupsUsergroups 
 ProfileProfile  Log inLog in  Log in to check your private messagesPrivate Message 

[Janus / twin Alix2] #5 Partial LDAP backup & restore

Post new topic   Reply to topic    www.zeroshell.org Forum Index -> ZeroShell
View previous topic :: View next topic  
Author Message

Joined: 03 Nov 2012
Posts: 50

PostPosted: Sun Jul 12, 2015 9:52 am    Post subject: [Janus / twin Alix2] #5 Partial LDAP backup & restore Reply with quote


Today I give you my solution to backup and reload specific parts of the LDAP database of ZS.
Notably I proceed this way to keep my backup DNS server an exact replica of the prime.
I explain in post #4 of the series why I prefer to have 2 clone DNS servers rather than a master and slave pair.

The commands ldapsearch, ldapadd, ldapdelete and ldapmodify are available. They enable to extract parts of the data and to update the database with no need to stop anything (unlike slapcat).
The partial LDIF files can be moved to/from a backup server using RSync (installed in my post #2).

Then I wrote a generic pair of scripts to automate and secure the operations for a given LDAP section. The sections I identified are:

ou: Aliases
ou: Computers
ou: DNS
ou: Group
ou: Hosts
ou: Mounts
ou: NAS
ou: Netgroup
ou: Networks
ou: People
ou: Protocols
ou: Radius
ou: Rpc
ou: Services

I will mainly talk about DNS: definition of the DNS zone.

In order to get a human manageable LDIF file, for each 'ou' key must be chosen an attribute to sort by. For 'DNS', the most pertinent is 'relativeDomainName':

# janus1, mydomain, lan, DNS, mydomain.lan
dn: relativeDomainName=janus1,dc=mydomain,dc=lan,ou=DNS,dc=mydomain,dc=lan
objectClass: top
objectClass: dNSZone
relativeDomainName: janus1
zoneName: mydomain.lan
aRecord: 192.168.xxx.11
pTRRecord: janus1.mydomain.lan.
tXTRecord: "MyDomain's LAN Master (prime)"
hInfoRecord: "Alix 2D13" "Zeroshell"

Extraction from LDAP

At least when run as root, it requires no authentication:

ldapsearch -x -b "ou=DNS,dc=mydomain,dc=lan" -S relativeDomainName > $ExportFile

Notice that I don't use the traditional option -u because it generates 'ufn' items that would fail the reloading with ldapmodify:

ufn: janus1, mydomain, lan, DNS, mydomain.lan

For the same reason the extraction must be added a filter to comment (or remove) 2 status lines that ldapsearch generates at the end:

# search result
search: 2
result: 0 Success

# numResponses: 38
# numEntries: 37

They cause ldapmodify to say "ldapmodify: no DN specified" and I found that messy, so my solution is:

ldapsearch -x -b "ou=DNS,dc=mydomain,dc=lan" -S relativeDomainName > $TempExportFile
cat $TempExportFile | sed -e 's/^\(\(search\|result\): *[0-9]*\)\( *Success\)* *$/# \1\3/g' > $TrueExportFile

Then my script pushes the file to the backup server using RSync and even sends an email, using the nail installed too in post #2. But this is out of topic...

Injection into LDAP

In this part I assume that a valid LDIF file was retrieved from the backup server, using RSync again. The goal is to replace completely the corresponding section in the LDAP.

Since I am very prudent, in case the file could be damaged, obsolete (or what else ?), at first my script performs a new extraction of the LDAP section, same ldapsearch as previously. This local backup could then be used to manually repair the mess.

Unlike ldapsearch, the other commands require authentication. From a local script the simple authentication (option -x) suffices:
- the correct admin_name is "cn=Manager",
- the password can be read from "/Database/var/register/system/ldap/rootpw".

NB: The option -y password_file has a problem, then I rather use -w $(cat password_file).

The option -D is used to introduce the admin_name:

ldapmodify -v -x -D "cn=Manager,dc=mydomain,dc=lan" -w $(cat password_file) -a -f $NewDataFile

But doing so ldapmodify will not do a subtree replacement, not even a merge, and it will complain about keys already existing. So the result could be messy.

The simplest solution I found is to first delete (recursive mode: option -r) the whole subtree, then inject the replacement subtree.

ldapdelete -v -r -x -D "cn=Manager,dc=mydomain,dc=lan" -w $(cat password_file) "ou=DNS,dc=mydomain,dc=lan"

ldap_initialize( <DEFAULT> )
deleting entry "ou=DNS,dc=mydomain,dc=lan"
deleting children of: ou=DNS,dc=mydomain,dc=lan
deleting children of: dc=lan,ou=DNS,dc=mydomain,dc=lan
deleting children of: dc=mydomain,dc=lan,ou=DNS,dc=mydomain,dc=lan
deleting children of: relativeDomainName=websvn,dc=mydomain,dc=lan,ou=DNS,dc=mydomain,dc=lan
        removing relativeDomainName=websvn,dc=mydomain,dc=lan,ou=DNS,dc=mydomain,dc=lan
        relativeDomainName=websvn,dc=mydomain,dc=lan,ou=DNS,dc=mydomain,dc=lan removed
        removing dc=mydomain,dc=lan,ou=DNS,dc=mydomain,dc=lan
        dc=mydomain,dc=lan,ou=DNS,dc=mydomain,dc=lan removed
        removing dc=lan,ou=DNS,dc=mydomain,dc=lan
        dc=lan,ou=DNS,dc=mydomain,dc=lan removed
Delete Result: Success (0)


ldapmodify -v -x -D "cn=Manager,dc=mydomain,dc=lan" -w $(cat password_file) -a -f $NewDataFile

adding new entry "relativeDomainName=*,dc=mydomain,dc=lan,ou=DNS,dc=mydomain,dc=lan"
adding new entry "relativeDomainName=@,dc=mydomain,dc=lan,ou=DNS,dc=mydomain,dc=lan"
adding new entry "relativeDomainName=_kerberos,dc=mydomain,dc=lan,ou=DNS,dc=mydomain,dc=lan"

Then my script sends a report email too, but this is out of topic again...


These 2 scripts are both driven by a unique parameter 'task name' and are generic thanks to a small shared attribute map:

# TaskName   LdapQueryKey   LdapSortingAttributeName
# ------------------------------------------------------
DNS          ou=DNS         relativeDomainName

Of course the sequence of operations is secured with many checks, the preliminary backup file etc.

This way I can easily replicate any change done to my prime server to the backup one, and also keep specific backups on my dedicated backup server Very Happy
=> This second aspect may interest more people here.

In my next post I will explain how I can (not so) easily run these scripts from the GUI of Zeroshell...

Hope it can help someone.

Ideas for improvements are welcome.

Best regards.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    www.zeroshell.org Forum Index -> ZeroShell All times are GMT
Page 1 of 1

Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Powered by phpBB © 2001, 2005 phpBB Group