#!/bin/bash # ldapsync -- Synchronize the flat UNIX directory files with LDAP tables. # Copyright (c) 2010 by The Regents of the University of California # Author: Jim Carter -- 2010-07-21. Contains bash-isms. # -v Verbose output, announces tables being stuffed, and outcomes. # -a Ignores the "last pushed" file and works on every table. # Without -a, only flat files modified after the "last pushed" # file are pushed out. Filename: $opt_m/ldap.push # -B Bail out after the first update failure. # -m "d1 d2" Directory where the flat files are. Can be a space separated # list; the first directory holding the flat file is used. # Default: "/etc/master /etc" # -t "t1 t2" Space separated list of table basenames to work on. See below # for the default value (all of them). # -I file Input file, overrides the auto-selected input file for the # first -t argument only. (For debugging only.) # -p dir Directory where persistent files are kept # (/var/lib/ldap/sync.d). # -D uid=... Distinguished Name of the root user. # Default: uid=ldaproot,dc=math,dc=ucla,dc=edu # -y file File containing the password of the -D user. # Default: /etc/openldap/root.secret # -n LDAP tables are not changed (for debugging). # -d 054 Debug option (in octal) to pass to ldaputil. Default: 0. # Test command line: # ./ldapsync -v -D uid=ldaproot,dc=cft,dc=ca,dc=us # $Header: /src/math/etc/ldap/RCS/ldapsync,v 1.2 2011/03/05 05:49:36 jimc Exp $ # $Log: ldapsync,v $ # Revision 1.2 2011/03/05 05:49:36 jimc # Added -I switch to override input file. # Added -n switch (passed to ldaputil) to not actually update anything. # Added tables udata, hostgroup, netgroup, auto_home. # The realm in root's distinguished name is computed from the host's FQDN, # not inferred through a case statement over predefined realms. # Comments improved. # # Revision 1.1 2010/08/16 18:07:24 jimc # Initial revision # # Directory where the flat files are: opt_m="/etc/master /etc" # List of tables to be synced (flat file basename is same for most of them): opt_t="passwd shadow udata group aliases rpc services protocols networks hosts hostgroup netgroup auto_home" # These tables are not used on typical Linux distros: # netmasks # Location of persistent files (push timestamps) (must already exist) opt_p=/var/lib/ldap/sync.d # File containing root's password opt_y=/etc/openldap/root.secret # Preset additional flags opt_v=0 opt_a=0 # Debug flags in octal, 0 if not debugging. 054 gives a good debug output. opt_d=0 # DEBUG DEBUG DEBUG glonch the path, rape security! # (not debugging) export PATH=.:$PATH # Root's Distinguished Name. /etc/ldap.conf should have a paramater ROOTBINDDN. # Fallback: It's assumed to be ldaproot@REALM converted to # the syntax of a D.N. e.g. uid=ldaproot,dc=math,dc=ucla,dc=edu while [ 0 -eq 0 ] ; do if [ -r /etc/ldap.conf ] ; then opt_D=`awk 'BEGIN {IGNORECASE=1} $1 == "rootbinddn" {print $2}' /etc/ldap.conf` if [ -n "$opt_D" ] ; then break ; fi fi # Fallback if rootbinddn is not configured HOSTNAME=`uname -n` myip=`dig +short +search $HOSTNAME A | head -1` if [ -z "$myip" ] ; then break ; fi fqdn=`dig +short -x $myip` if [ -z "$fqdn" ] ; then break ; fi fqdn=${fqdn%.} uid_realm="uid=ldaproot.${fqdn#*.}" opt_D=`echo $uid_realm | sed -e 's/\./,dc=/g'` break done # Prints its arguments on stderr and exits. function barf () { echo "$*" 1>&2 exit 4 } # Interpret command line args. Very forgiving about switch letters... while [ $# -gt 0 ] ; do case "X$1" in X-- ) break ; ;; X-? ) : ; ;; * ) break ; ;; esac case "X$2" in X- ) eval "opt_${1#-}='$2'" ; shift ; ;; # Single - is a filename # Switch or -- follows X | X-* ) eval "opt_${1#-}=1" ; eval "txt_${1#-}=$1" ; ;; * ) eval "opt_${1#-}='$2'" ; shift ; ;; # Normal argument given esac shift done if [ ! -d $opt_p ] ; then echo "$opt_p does not exist, need to create" 1>&2 exit 4 elif [ ! -w $opt_p ] ; then echo "$opt_p write permission denied" 1>&2 exit 4 fi for table in $opt_t ; do # Locate the input file. tpath='' # -I can override the input filename (first table only). if [ -n "$opt_I" ] ; then tpath=$opt_I opt_I='' else # Special case input files for a few tables. case $table in hostgroup ) tpath1=hostgroup.db ; ;; auto_home ) tpath1=passwd ; ;; * ) tpath1=$table ; ;; esac # Hunt for the file in the -m directories. for t in $opt_m ; do tpath=$t/$tpath1 if [ -r $tpath ] ; then break ; fi done fi if [ ! -r $tpath ] ; then echo "Can't read $tpath, skipped" 1>&2 continue fi # Bypass table if input hasn't changed since the last update. ppath=$opt_p/$table.push if [ -r $ppath -a ! $tpath -nt $ppath -a $opt_a = '0' ] ; then if [ $opt_v != '0' ] ; then echo "Don't need to push $table" ; fi continue fi # Update this table. if [ $opt_v != '0' ] ; then echo "Updating $table" ; fi # Command line args for ldaputil: # -d Debug output desired # -D Distinguished Name of root user # -y Filename containing root's special LDAP password # -Z Use TLS # -k Remove table entries not in the -i file # -a Check for and create realm container objects # -f Type of table # -i Flat file with table content # -v Verbose output (show statistics) # -B Bail after the first error is found # -n LDAP tables are not changed (for debugging) ldaputil $txt_v $txt_B $txt_n -d $opt_d -x -D $opt_D -y $opt_y -Z -k -a -f $table -i $tpath rc=$? if [ $rc != 0 ] ; then echo "ldaputil -f $table returns $rc, stopping here" break else if [ $opt_v != '0' ] ; then echo " $table updated OK" ; fi echo "ldapsync -t $table at `date`" > $ppath fi done exit $rc