====== OpenLdap aka slapd ====== **Cleaning this up, it was an email . . .** This is going to contain some notes, scripts, and howto's on installing and administering openldap. I have copious notes and information on this, I will be filling it in as time permits. The problem with openldap is the examples tend not to use cn=admin,cn=config as the base, and it's confusing ===== The ACL Nightmare ===== * The second problem is usually the permission madness. If you want to use -Y EXTERNAL you better have it in there on every rule with "write. * See the script below for some examples  ===== Syntax Madness ===== * If you resort to manually hacking an ldif in .../slapd/ make sure slapd is not running, and remove the CRC check "comments" at the top * Finally dumping entries has the most insane format on the planet. The rule is if the first character of the line is a space it is concatenated to the previous line with the space removed. So it breaks at column 72 or 80 or something no matter what.... ...... something something-else foo="Someth  ing Else", wow wassup Which is fine but you also get weird unseen whitespace that bites you in the a**: ...... word1 word2 word3  word4 word5 it just so happens there is a SPACE after word3 and it works, if you remove the space you get: ...... word1 word2 word3word4 word5, bitch blows up with a cryptic error When I manually create I never leave spaces at the end, and double them at the beginning of the continuation line word word word word word = "word word word word word word" Lastly queries can return things you do not put in a modify/add like "StructuralObjectClass: ..." i.e. Any items that are implied from the DN or system generated like modify timestamps can get returned but not added/updated with a tool. Basically there are two kinds of objects... Objects that identify something, and objects that can contain other objects. That would be a 'StructuralObject', dc=, o=, ou=, or even cn= but not uid= and it's all downhill from there... Most tools will help you. //**All the syntax is just abjectly arcane.**// ===== Installation and Setup ===== I have a huge update for this thing. Will update this page as time permits. What follows is my "replicate" script. Mis-named really, but it sets up openldap for a server pair, primary then secondary. It has an example of pretty much everything, but basically lets you install or reinstall slapd with sane defaults for permissions. Durring install just hit enter on the defaults, it will wipe it out with the info from the definitions at the top of the file. You can use it to create a single instance. I generally use o=Master as a base, and for a level2 item I will add a password which grants permission to the rest of the tree above... So for example: dc=ksmith.com,o=Master dc=cfns.net,o=Master dc=casafiesta.org,o=Master Represent the bases for a few of the domains in my tree. Each of these dn's has a password that allows blanket r/w access up the tree for that domain. Then I like to create a read-only dn: cn=lookup,dc=ksmith.com,o=Master goes up the tree (it can't read passwords, except it's own). "Standards" would have one creating (3) Three databases with bases dc=com dc=net and dc=org, and build up from there. Or you could use a bottom: o=bottom (master) and build them up: dc=ksmith,dc=com,o=Master uid=keith,ou=People,dc=ksmith,dc=com,o=Master As long as you are only 2 dc's deep it's not too bad. but now I have to deal with dc=iwojimashipmates,dc=cfns,dc=net,o=Master which is a seperate entity along with dc=admin,dc=cfns,dc=net,o=Master Now just type along with me, and untangle your fingers. And the rules start getting wierd to propogate up the tree so for me it's: dc=admin.cfns.net,o=Master dc=iwojimashipmates.cfns.net,o=Master It's just a hack, but the defaults build these crazy ldap trees, which are a bitch to type, when it's all arbitrary anyway. I mean a tree with a "base" like dc=mymachine,dc=mydomain,dc=com Is fine. But I'm not ever going to expand my directory from dc=com out, or even dc=mydomain.. And the content is arbitrary, so you could set your base to: dc=mymachine.mydomain.com So my base dn now doesn't have a bunch of "dc="'s and commas to trip up my fingers, or use o= or, . . . I don't run ".com" so I don't need a huge tree above Have FUN! ===== The Script ===== There are a zillion artifacts in this stupid thing... I have a cleaned up update I will get in place here as time permits but the reference material is sound. ./replicate --master -p MYLLDAPPASSWORD #!/bin/sh # # Script: replicate # Title: Create replicated LDAP servers # # Last Modified: 2020-04-02 10:08:34 # dbtype=mdb rootpass=MYLDAPPASSWORD #mirror1=prd-auth-1a #mirror2=prd-auth-1b #mirror1=qa-auth-01 #mirror2=qa-auth-02 mirror1=dev-auth-01 mirror2=dev-auth-02 BASE_DN="o=Master" ROOT_DN="cn=Admin,$BASE_DN" MANAGE_DN="cn=admin,cn=config" #os=centos7 #os=debian9 os=ubuntu18 case "$os" in centos*) ldap_user=ldap ldap_group=ldap etcdir=/etc/openldap libdir=/usr/lib64/openldap vardir=/var/lib/ldap slapd_default=/etc/default/slapd dbnum=2 ;; debian*|ubuntu*) ldap_user=openldap ldap_group=openldap etcdir=/etc/ldap libdir=/usr/lib/ldap vardir=/var/lib/ldap slapd_default=/etc/default/slapd dbnum=1 ;; esac slapdir=$etcdir/slapd.d cfgdir="$slapdir/cn=config" #---------------------------------------------------------------------- # ADD_CONFIG_MIRROR # Add Mirroring to Config #---------------------------------------------------------------------- add_config_mirror() { pause "--- Remove syncprov, Ignore Errors" # Kill it if it's there. $ldmod < /dev/null <\c" read line else echo "$*" fi } #---------------------------------------------------------------------- # CREATE_DIR # Create/Re-Create LDAP Directory Tree #---------------------------------------------------------------------- create_dir() { pause "--- Re-create $vardir" if [ "$vardir" = "" ] then echo "*** No VARDIR!, Aborting" exit 0 fi rm -rf ${vardir} mkdir ${vardir} chmod 0700 ${vardir} chown ${ldap_user}:${ldap_group} ${vardir} } #---------------------------------------------------------------------- # INSTALL_SLAPD # Purge SLAPD if installed # Install a fresh SLAPD #---------------------------------------------------------------------- install_slapd() { systemctl stop slapd case "$os" in debian*|ubuntu*) # Make sure ldap-utils is installed dpkg -l | grep ldap-utils > /dev/null 2>&1 || \ apt-get -y install ldap-utils # Purge slapd if already installed dpkg -l | grep slapd > /dev/null 2>&1 && \ apt-get -y purge slapd && rm -r ${vardir} # Install slapd & remove some stuff DEBIAN_FRONTEND=noninteractive apt-get install slapd #rm -v "${cfgdir}/cn=module{0}.ldif" #rm -v "${cfgdir}/cn=schema/cn={1}cosine.ldif" #rm -v "${cfgdir}/cn=schema/cn={2}nis.ldif" #rm -v "${cfgdir}/cn=schema/cn={3}inetorgperson.ldif" ;; centos*) pause "remove openldap-servers" yum -y remove openldap-servers [ "$slapdir" != "" ] && rm -rf $slapdir/ pause "installing openldap-servers" yum -y install openldap-servers openldap-clients ;; esac # Stop the server, clear out to only cn=config pause "--- Stopping slapd" systemctl stop slapd rm -v "${cfgdir}/olcDatabase={${dbnum}}"* create_dir # Update the default startup to fix -h ... issues # Restart the server. Should be a blank cn=config # And add a password and permissions echo "--- Starting slapd" update_host # Update host file systemctl start slapd add_config_password add_config_sync_module add_config_mirror } #---------------------------------------------------------------------- # UPDATE_HOST # In order for syncrepl to work . . . # Our hostname used in the syncrepl parms, must either reside in # /etc/hosts as the first item after our IP address or ... # Invoking slapd -h '...' one of the arguments must match the syncrepl # provider URL *EXACTLY*, or and it barfs. #---------------------------------------------------------------------- update_host() { host=`hostname -s` ip=`ip address | awk '/inet / && ! /127.0.0.1/ { print $2 ; exit }'` if grep " $host " /etc/hosts > /dev/null 2>&1 then return fi echo "$ip $host" >> /etc/hosts } #---------------------------------------------------------------------- # UPDATE_SLAPD_DEFAULT # Not used . . . See UPDATE_HOST #---------------------------------------------------------------------- update_slapd_default() { pause "--- Updating $slapd_default" cat $slapd_default | awk -v host=`hostname -s` ' /^SLAPD_SERVICES=/ { printf "SLAPD_SERVICES=\"ldapi:/// ldap://%s\"\n",host next } { print $0 } ' > $slapd_default.new if diff $slapd_default $slapd_default.new then rm $slapd_default.new else mv $slapd_default $slapd_default.old mv $slapd_default.new $slapd_default fi } #---------------------------------------------------------------------- # UPDATE_SLAVE_FOLDERS #---------------------------------------------------------------------- update_slave_folders() { pause "--- update_slave_folders" dbnum=1 while [ -f "$slapdir/cn=config/olcDatabase={$dbnum}${dbtype}.ldif" ] do eval `cat "$slapdir/cn=config/olcDatabase={$dbnum}${dbtype}.ldif" | awk ' # /olcDbDirectory:/ { printf "db_folder=\"%s\"\n",$2 } '` # `' mkdir $db_folder chown 0700 $db_folder chown ${ldap_user}:${ldap_group} $db_folder dbnum=`expr $dbnum + 1` done } #---------------------------------------------------------------------- # MAIN #---------------------------------------------------------------------- echo "LDAP Replication Script" debug=n while [ "x$1" != "x" ] do case "x$1" in x--debug) debug=y ;; x--master) function=master ;; x--slave) function=slave ;; x--password|x-p) shift rootpass="$1" ;; esac shift done if [ "$rootpass" = "" ] then echo "Root Password Not Defined" exit 1 fi # This is the LDAP Version of the password root_pw=`slappasswd -s $rootpass` # ldadd="ldapadd -v -h localhost -x -D cn=admin,cn=config -w $rootpass" ldmod="ldapmodify -v -Y EXTERNAL -H ldapi:///" case "$function" in master) install_slapd add_schemas add_database add_database_basedn add_database_mirror ;; slave) install_slapd ;; esac