From b9e25135c51ee29edbdf48d41e1cb637188cc358 Mon Sep 17 00:00:00 2001 From: Dean Troyer Date: Tue, 1 Oct 2013 14:45:04 -0500 Subject: [PATCH] freshen the LDAP support * Build the base DN from a given domain name * Remove all hard-coded names to allow configuration of base DN * Fix manager DN (cn=Manager,dc=...) * Add ldap init_ldap() * Add support for clean.sh Change-Id: Ieb69be9740653645b8e000574ad3fe59a0f97540 --- clean.sh | 6 + files/apts/ldap | 2 +- .../ldap/{openstack.ldif => keystone.ldif.in} | 16 +- files/ldap/manager.ldif.in | 9 +- ...e-config.ldif => suse-base-config.ldif.in} | 4 +- lib/keystone | 14 +- lib/ldap | 146 +++++++++++++----- 7 files changed, 141 insertions(+), 56 deletions(-) rename files/ldap/{openstack.ldif => keystone.ldif.in} (54%) rename files/ldap/{base-config.ldif => suse-base-config.ldif.in} (77%) diff --git a/clean.sh b/clean.sh index 395941ae21..480a81214f 100755 --- a/clean.sh +++ b/clean.sh @@ -15,6 +15,8 @@ TOP_DIR=$(cd $(dirname "$0") && pwd) # Import common functions source $TOP_DIR/functions +FILES=$TOP_DIR/files + # Load local configuration source $TOP_DIR/stackrc @@ -84,6 +86,10 @@ cleanup_nova cleanup_neutron cleanup_swift +if is_service_enabled ldap; then + cleanup_ldap +fi + # Do the hypervisor cleanup until this can be moved back into lib/nova if [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then cleanup_nova_hypervisor diff --git a/files/apts/ldap b/files/apts/ldap index 81a00f27bf..26f7aeffe3 100644 --- a/files/apts/ldap +++ b/files/apts/ldap @@ -1,3 +1,3 @@ ldap-utils -slapd # NOPRIME +slapd python-ldap diff --git a/files/ldap/openstack.ldif b/files/ldap/keystone.ldif.in similarity index 54% rename from files/ldap/openstack.ldif rename to files/ldap/keystone.ldif.in index 02caf3f368..cf51907cf6 100644 --- a/files/ldap/openstack.ldif +++ b/files/ldap/keystone.ldif.in @@ -1,26 +1,26 @@ -dn: dc=openstack,dc=org -dc: openstack +dn: ${BASE_DN} objectClass: dcObject objectClass: organizationalUnit -ou: openstack +dc: ${BASE_DC} +ou: ${BASE_DC} -dn: ou=UserGroups,dc=openstack,dc=org +dn: ou=UserGroups,${BASE_DN} objectClass: organizationalUnit ou: UserGroups -dn: ou=Users,dc=openstack,dc=org +dn: ou=Users,${BASE_DN} objectClass: organizationalUnit ou: Users -dn: ou=Roles,dc=openstack,dc=org +dn: ou=Roles,${BASE_DN} objectClass: organizationalUnit ou: Roles -dn: ou=Projects,dc=openstack,dc=org +dn: ou=Projects,${BASE_DN} objectClass: organizationalUnit ou: Projects -dn: cn=9fe2ff9ee4384b1894a90878d3e92bab,ou=Roles,dc=openstack,dc=org +dn: cn=9fe2ff9ee4384b1894a90878d3e92bab,ou=Roles,${BASE_DN} objectClass: organizationalRole ou: _member_ cn: 9fe2ff9ee4384b1894a90878d3e92bab diff --git a/files/ldap/manager.ldif.in b/files/ldap/manager.ldif.in index e522150f2e..de3b69de7c 100644 --- a/files/ldap/manager.ldif.in +++ b/files/ldap/manager.ldif.in @@ -1,10 +1,15 @@ dn: olcDatabase={${LDAP_OLCDB_NUMBER}}hdb,cn=config changetype: modify replace: olcSuffix -olcSuffix: dc=openstack,dc=org +olcSuffix: ${BASE_DN} - replace: olcRootDN -olcRootDN: dc=Manager,dc=openstack,dc=org +olcRootDN: ${MANAGER_DN} - ${LDAP_ROOTPW_COMMAND}: olcRootPW olcRootPW: ${SLAPPASS} +- +replace: olcDbIndex +olcDbIndex: objectClass eq +olcDbIndex: default pres,eq +olcDbIndex: cn,sn,givenName,co diff --git a/files/ldap/base-config.ldif b/files/ldap/suse-base-config.ldif.in similarity index 77% rename from files/ldap/base-config.ldif rename to files/ldap/suse-base-config.ldif.in index 026d8bc0fc..00256ee9d8 100644 --- a/files/ldap/base-config.ldif +++ b/files/ldap/suse-base-config.ldif.in @@ -12,8 +12,10 @@ objectClass: olcSchemaConfig cn: schema include: file:///etc/openldap/schema/core.ldif +include: file:///etc/openldap/schema/cosine.ldif +include: file:///etc/openldap/schema/inetorgperson.ldif dn: olcDatabase={1}hdb,cn=config objectClass: olcHdbConfig olcDbDirectory: /var/lib/ldap -olcSuffix: dc=openstack,dc=org +olcSuffix: ${BASE_DN} diff --git a/lib/keystone b/lib/keystone index c1fa0af8af..76eff54e35 100644 --- a/lib/keystone +++ b/lib/keystone @@ -143,17 +143,17 @@ function configure_keystone() { if is_service_enabled ldap; then #Set all needed ldap values - iniset $KEYSTONE_CONF ldap password $LDAP_PASSWORD - iniset $KEYSTONE_CONF ldap user "dc=Manager,dc=openstack,dc=org" - iniset $KEYSTONE_CONF ldap suffix "dc=openstack,dc=org" + iniset $KEYSTONE_CONF ldap password $LDAP_PASSWORD + iniset $KEYSTONE_CONF ldap user $LDAP_MANAGER_DN + iniset $KEYSTONE_CONF ldap suffix $LDAP_BASE_DN iniset $KEYSTONE_CONF ldap use_dumb_member "True" iniset $KEYSTONE_CONF ldap user_attribute_ignore "enabled,email,tenants,default_project_id" iniset $KEYSTONE_CONF ldap tenant_attribute_ignore "enabled" iniset $KEYSTONE_CONF ldap tenant_domain_id_attribute "businessCategory" iniset $KEYSTONE_CONF ldap tenant_desc_attribute "description" - iniset $KEYSTONE_CONF ldap tenant_tree_dn "ou=Projects,dc=openstack,dc=org" + iniset $KEYSTONE_CONF ldap tenant_tree_dn "ou=Projects,$LDAP_BASE_DN" iniset $KEYSTONE_CONF ldap user_domain_id_attribute "businessCategory" - iniset $KEYSTONE_CONF ldap user_tree_dn "ou=Users,dc=openstack,dc=org" + iniset $KEYSTONE_CONF ldap user_tree_dn "ou=Users,$LDAP_BASE_DN" iniset $KEYSTONE_CONF DEFAULT member_role_id "9fe2ff9ee4384b1894a90878d3e92bab" iniset $KEYSTONE_CONF DEFAULT member_role_name "_member_" fi @@ -320,6 +320,10 @@ create_keystone_accounts() { # init_keystone() - Initialize databases, etc. function init_keystone() { + if is_service_enabled ldap; then + init_ldap + fi + # (Re)create keystone database recreate_database keystone utf8 diff --git a/lib/ldap b/lib/ldap index 80992a7a09..e4bd41624d 100644 --- a/lib/ldap +++ b/lib/ldap @@ -9,68 +9,137 @@ XTRACE=$(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 + 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 + + 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 + keystone_ldif=${LDAP_BASE_DC}.ldif + else + 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 "LDAP_PASSWORD is $LDAP_PASSWORD" echo "os_VENDOR is $os_VENDOR" - printf "installing" + + TMP_LDAP_DIR=$(mktemp -d -t ldap.$$.XXXXXXXXXX) + + printf "installing OpenLDAP" if is_ubuntu; then - LDAP_OLCDB_NUMBER=1 - LDAP_ROOTPW_COMMAND=replace - sudo DEBIAN_FRONTEND=noninteractive apt-get install slapd ldap-utils - #automatically starts LDAP on ubuntu so no need to call start_ldap + # Ubuntu automatically starts LDAP so no need to call start_ldap() + : elif is_fedora; then - LDAP_OLCDB_NUMBER=2 - LDAP_ROOTPW_COMMAND=add start_ldap elif is_suse; then - LDAP_OLCDB_NUMBER=1 - LDAP_ROOTPW_COMMAND=add - LDAP_SERVICE_NAME=ldap - # SUSE has slappasswd in /usr/sbin/ - PATH=$PATH:/usr/sbin/ - sudo slapadd -F /etc/openldap/slapd.d/ -bcn=config -l $FILES/ldap/base-config.ldif + _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 - printf "generate password file" - SLAPPASS=`slappasswd -s $LDAP_PASSWORD` + echo "LDAP_PASSWORD is $LDAP_PASSWORD" + SLAPPASS=$(slappasswd -s $LDAP_PASSWORD) + printf "LDAP secret is $SLAPPASS\n" - printf "secret is $SLAPPASS\n" - #create manager.ldif - TMP_MGR_DIFF_FILE=`mktemp -t manager_ldiff.$$.XXXXXXXXXX.ldif` - sed -e "s|\${LDAP_OLCDB_NUMBER}|$LDAP_OLCDB_NUMBER|" -e "s|\${SLAPPASS}|$SLAPPASS|" -e "s|\${LDAP_ROOTPW_COMMAND}|$LDAP_ROOTPW_COMMAND|" $FILES/ldap/manager.ldif.in >> $TMP_MGR_DIFF_FILE - - #update ldap olcdb - sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f $TMP_MGR_DIFF_FILE + # Create manager.ldif and add to olcdb + _ldap_varsubst $FILES/ldap/manager.ldif.in >$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 || is_suse; then + 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 - # add our top level ldap nodes - if ldapsearch -x -w $LDAP_PASSWORD -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -x -b dc=openstack,dc=org | grep -q "Success"; then - printf "LDAP already configured for OpenStack\n" - if [[ "$KEYSTONE_CLEAR_LDAP" == "yes" ]]; then - # clear LDAP state - clear_ldap_state - # reconfigure LDAP for OpenStack - ldapadd -c -x -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -w $LDAP_PASSWORD -f $FILES/ldap/openstack.ldif - fi - else - printf "Configuring LDAP for OpenStack\n" - ldapadd -c -x -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -w $LDAP_PASSWORD -f $FILES/ldap/openstack.ldif - fi + rm -rf TMP_LDAP_DIR } # start_ldap() - Start LDAP @@ -78,7 +147,6 @@ function start_ldap() { sudo service $LDAP_SERVICE_NAME restart } - # stop_ldap() - Stop LDAP function stop_ldap() { sudo service $LDAP_SERVICE_NAME stop @@ -86,7 +154,7 @@ function stop_ldap() { # clear_ldap_state() - Clear LDAP State function clear_ldap_state() { - ldapdelete -x -w $LDAP_PASSWORD -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -x -r "dc=openstack,dc=org" + ldapdelete -x -w $LDAP_PASSWORD -D "$LDAP_MANAGER_DN" -H $LDAP_URL -r "$LDAP_BASE_DN" } # Restore xtrace