#!/bin/bash
#
# lib/ldap
# Functions to control the installation and configuration of **ldap**

# ``lib/keystone`` calls the entry points in this order:
#
# - install_ldap()

# Save trace setting
_XTRACE_LDAP=$(set +o | grep xtrace)
set +o xtrace


LDAP_DOMAIN=${LDAP_DOMAIN:-openstack.org}
# Make an array of domain components
DC=(${LDAP_DOMAIN/./ })

# Leftmost domain component used in top-level entry
LDAP_BASE_DC=${DC[0]}

# Build the base DN
dn=""
for dc in ${DC[*]}; do
    dn="$dn,dc=$dc"
done
LDAP_BASE_DN=${dn#,}

LDAP_MANAGER_DN="${LDAP_MANAGER_DN:-cn=Manager,${LDAP_BASE_DN}}"
LDAP_URL=${LDAP_URL:-ldap://localhost}

LDAP_SERVICE_NAME=slapd

if is_ubuntu; then
    LDAP_OLCDB_NUMBER=1
    LDAP_ROOTPW_COMMAND=replace
elif is_fedora; then
    LDAP_OLCDB_NUMBER=2
    LDAP_ROOTPW_COMMAND=add
elif is_suse; then
    # SUSE has slappasswd in /usr/sbin/
    PATH=$PATH:/usr/sbin/
    LDAP_OLCDB_NUMBER=1
    LDAP_ROOTPW_COMMAND=add
    LDAP_SERVICE_NAME=ldap
fi


# Functions
# ---------

# Perform common variable substitutions on the data files
# _ldap_varsubst file
function _ldap_varsubst {
    local infile=$1
    local slappass=$2
    sed -e "
        s|\${LDAP_OLCDB_NUMBER}|$LDAP_OLCDB_NUMBER|
        s|\${SLAPPASS}|$slappass|
        s|\${LDAP_ROOTPW_COMMAND}|$LDAP_ROOTPW_COMMAND|
        s|\${BASE_DC}|$LDAP_BASE_DC|
        s|\${BASE_DN}|$LDAP_BASE_DN|
        s|\${MANAGER_DN}|$LDAP_MANAGER_DN|
    " $infile
}

# clean_ldap() - Remove ldap server
function cleanup_ldap {
    uninstall_package $(get_packages ldap)
    if is_ubuntu; then
        uninstall_package slapd ldap-utils libslp1
        sudo rm -rf /etc/ldap/ldap.conf /var/lib/ldap
    elif is_fedora; then
        sudo rm -rf /etc/openldap /var/lib/ldap
    elif is_suse; then
        sudo rm -rf /var/lib/ldap
    fi
}

# init_ldap
# init_ldap() - Initialize databases, etc.
function init_ldap {
    local keystone_ldif

    local tmp_ldap_dir
    tmp_ldap_dir=$(mktemp -d -t ldap.$$.XXXXXXXXXX)

    # Remove data but not schemas
    clear_ldap_state

    # Add our top level ldap nodes
    if ldapsearch -x -w $LDAP_PASSWORD -D "$LDAP_MANAGER_DN" -H $LDAP_URL -b "$LDAP_BASE_DN" | grep -q "Success"; then
        printf "LDAP already configured for $LDAP_BASE_DC\n"
    else
        printf "Configuring LDAP for $LDAP_BASE_DC\n"
        # If BASE_DN is changed, the user may override the default file
        if [[ -r $FILES/ldap/${LDAP_BASE_DC}.ldif.in ]]; then
            local keystone_ldif=${LDAP_BASE_DC}.ldif
        else
            local keystone_ldif=keystone.ldif
        fi
        _ldap_varsubst $FILES/ldap/${keystone_ldif}.in >$tmp_ldap_dir/${keystone_ldif}
        if [[ -r $tmp_ldap_dir/${keystone_ldif} ]]; then
            ldapadd -x -w $LDAP_PASSWORD -D "$LDAP_MANAGER_DN" -H $LDAP_URL -c -f $tmp_ldap_dir/${keystone_ldif}
        fi
    fi

    rm -rf $tmp_ldap_dir
}

# install_ldap
# install_ldap() - Collect source and prepare
function install_ldap {
    echo "Installing LDAP inside function"
    echo "os_VENDOR is $os_VENDOR"

    local tmp_ldap_dir
    tmp_ldap_dir=$(mktemp -d -t ldap.$$.XXXXXXXXXX)

    printf "installing OpenLDAP"
    if is_ubuntu; then
        # Ubuntu automatically starts LDAP so no need to call start_ldap()
        :
    elif is_fedora; then
        start_ldap
    elif is_suse; then
        _ldap_varsubst $FILES/ldap/suse-base-config.ldif.in >$tmp_ldap_dir/suse-base-config.ldif
        sudo slapadd -F /etc/openldap/slapd.d/ -bcn=config -l $tmp_ldap_dir/suse-base-config.ldif
        sudo sed -i '/^OPENLDAP_START_LDAPI=/s/"no"/"yes"/g' /etc/sysconfig/openldap
        start_ldap
    fi

    echo "LDAP_PASSWORD is $LDAP_PASSWORD"
    local slappass
    slappass=$(slappasswd -s $LDAP_PASSWORD)
    printf "LDAP secret is $slappass\n"

    # Create manager.ldif and add to olcdb
    _ldap_varsubst $FILES/ldap/manager.ldif.in $slappass >$tmp_ldap_dir/manager.ldif
    sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f $tmp_ldap_dir/manager.ldif

    # On fedora we need to manually add cosine and inetorgperson schemas
    if is_fedora; then
        sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
        sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
    fi

    rm -rf $tmp_ldap_dir
}

# start_ldap() - Start LDAP
function start_ldap {
    sudo service $LDAP_SERVICE_NAME restart
}

# stop_ldap() - Stop LDAP
function stop_ldap {
    sudo service $LDAP_SERVICE_NAME stop
}

# clear_ldap_state() - Clear LDAP State
function clear_ldap_state {
    ldapdelete -x -w $LDAP_PASSWORD -D "$LDAP_MANAGER_DN" -H $LDAP_URL -r "$LDAP_BASE_DN" || :
}

# Restore xtrace
$_XTRACE_LDAP

# Tell emacs to use shell-script-mode
## Local variables:
## mode: shell-script
## End:
