mrc0mmand / rpms / openldap

Forked from rpms/openldap 3 years ago
Clone
adf540
#!/bin/bash
adf540
# This script serves one purpose, to add a possibly missing attribute
adf540
# to a ppolicy schema in a dynamic configuration of OpenLDAP. This
adf540
# attribute was introduced in openldap-2.4.43 and slapd will not 
adf540
# start without it later on.
adf540
#
adf540
# The script tries to update in a directory given as first parameter,
adf540
# or in /etc/openldap/slapd.d implicitly.
adf540
#
adf540
# Author: Matus Honek <mhonek@redhat.com>
adf540
# Bugzilla: #1487857
adf540
adf540
function log {
adf540
    echo "Update dynamic configuration: " $@
adf540
    true
adf540
}
adf540
adf540
function iferr {
adf540
    if [ $? -ne 0 ]; then
adf540
	log "ERROR: " $@
adf540
	true
adf540
    else
adf540
	false
adf540
    fi
adf540
}
adf540
adf540
function update {
adf540
    set -u
adf540
    shopt -s extglob
adf540
adf540
    ORIGINAL="${1:-/etc/openldap/slapd.d}"
adf540
    ORIGINAL="${ORIGINAL%*(/)}"
adf540
adf540
    ### check if necessary
adf540
    grep -r "pwdMaxRecordedFail" "${ORIGINAL}/cn=config/cn=schema" >/dev/null
adf540
    [ $? -eq 0 ] && log "Schemas look up to date. Ok. Quitting." && return 0
adf540
adf540
    ### prep
adf540
    log "Prepare environment."
adf540
    
adf540
    TEMPDIR=$(mktemp -d)
adf540
    iferr "Could not create a temporary directory. Quitting." && return 1
adf540
    DBDIR="${TEMPDIR}/db"
adf540
    SUBDBDIR="${DBDIR}/cn=temporary"
adf540
adf540
    mkdir "${DBDIR}"
adf540
    iferr "Could not create temporary configuration directory. Quitting." && return 1
adf540
    cp -r --no-target-directory "${ORIGINAL}" "${SUBDBDIR}"
adf540
    iferr "Could not copy configuration. Quitting." && return 1
adf540
    
adf540
    pushd "$TEMPDIR" >/dev/null
adf540
adf540
    cat > temp.conf <
adf540
database ldif
adf540
suffix cn=temporary
adf540
directory db
adf540
access to * by * manage
adf540
EOF
adf540
    
adf540
    SOCKET="$(pwd)/socket"
adf540
    LISTENER="ldapi://${SOCKET//\//%2F}"
adf540
    CONN_PARAMS=("-Y" "EXTERNAL" "-H" "${LISTENER}")
adf540
    
adf540
    slapd -f temp.conf -h "$LISTENER" -d 0 >/dev/null 2>&1 &
adf540
    SLAPDPID="$!"
adf540
    sleep 2
adf540
adf540
    ldapadd ${CONN_PARAMS[@]} -d 0 >/dev/null 2>&1 <
adf540
dn: cn=temporary
adf540
objectClass: olcGlobal
adf540
cn: temporary
adf540
EOF
adf540
    iferr "Could not populate the temporary database. Quitting." && return 1
adf540
    
adf540
    ### update
adf540
    log "Update with new pwdMaxRecordedFailure attribute."
adf540
    FILTER="(&"
adf540
    FILTER+="(olcObjectClasses=*'pwdPolicy'*)"
adf540
    FILTER+="(!(olcObjectClasses=*'pwdPolicy'*'pwdMaxRecordedFailure'*))"
adf540
    FILTER+="(!(olcAttributeTypes=*'pwdMaxRecordedFailure'*))"
adf540
    FILTER+=")"
adf540
    RES=$(ldapsearch ${CONN_PARAMS[@]} \
adf540
		     -b cn=schema,cn=config,cn=temporary \
adf540
		     -LLL \
adf540
		     -o ldif-wrap=no \
adf540
		     "$FILTER" \
adf540
		     dn olcObjectClasses \
adf540
		     2>/dev/null \
adf540
	      | sed '/^$/d')
adf540
    DN=$(printf "$RES" | grep '^dn:')
adf540
    OC=$(printf "$RES" | grep "^olcObjectClasses:.*'pwdPolicy'")
adf540
    NEWOC="${OC//$ pwdSafeModify /$ pwdSafeModify $ pwdMaxRecordedFailure }"
adf540
adf540
    test $(echo "$DN" | wc -l) = 1
adf540
    iferr "Received more than one DN. Cannot continue. Quitting." && return 1
adf540
    test "$NEWOC" != "$OC"
adf540
    iferr "Updating pwdPolicy objectClass definition failed. Quitting." && return 1
adf540
adf540
    ldapmodify ${CONN_PARAMS[@]} -d 0 >/dev/null 2>&1 <
adf540
$DN
adf540
changetype: modify
adf540
add: olcAttributeTypes
adf540
olcAttributeTypes: ( 1.3.6.1.4.1.42.2.27.8.1.30 NAME 'pwdMaxRecordedFailur
adf540
 e' EQUALITY integerMatch ORDERING integerOrderingMatch  SYNTAX 1.3.6.1.4.1.
adf540
 1466.115.121.1.27 SINGLE-VALUE )
adf540
-
adf540
delete: olcObjectClasses
adf540
$OC
adf540
-
adf540
add: olcObjectClasses
adf540
$NEWOC
adf540
EOF
adf540
    iferr "Updating with new attribute failed. Quitting." && return 1
adf540
adf540
    popd >/dev/null
adf540
adf540
    ### apply
adf540
    log "Apply changes."
adf540
    cp -r --no-target-directory "$ORIGINAL" "$ORIGINAL~backup"
adf540
    iferr "Backing up old configuration failed. Quitting." && return 1
adf540
    cp -r --no-target-directory "$SUBDBDIR" "$ORIGINAL"
adf540
    iferr "Applying new configuration failed. Quitting." && return 1
adf540
    
adf540
    ### clean up
adf540
    log "Clean up."
adf540
    kill "$SLAPDPID"
adf540
    SLAPDPID=
adf540
    rm -rf "$TEMPDIR"
adf540
    TEMPDIR=
adf540
}
adf540
adf540
SLAPDPID=
adf540
TEMPDIR=
adf540
update "$1"
adf540
if [ $? -ne 0 ]; then
adf540
    log "Clean up."
adf540
    echo "$SLAPDPID"
adf540
    echo "$TEMPDIR"
adf540
    kill "$SLAPDPID"
adf540
    rm -rf "$TEMPDIR"
adf540
fi
adf540
log "Finished."