Openstack Keystone LDAP后端配置

Openstack Keystone LDAP后端配置

写在最前面:

以下内容在openstack G版2013.1代码和ubuntu 12.04 LTS环境验证

LDAP版本为openldap-2.4.28


1、安装LDAP

apt-get install ldap-utils

apt-get install slapd


2、验证LDAP登录

ldap安装默认根据当前主机的域名,生成登陆的DN

查看 /etc/hosts

Openstack Keystone LDAP后端配置_第1张图片

所以这个环境上的登陆DN为 cn=admin,dc=openstack,dc=org

使用此命令验证是否配置成功

ldapsearch -x -LLL -Hldap:/// -b dc=openstack,dc=org dn



3、修改LDAP的默认schema

LDAP的默认schema不能直接和openstack配合使用,有些openstack的用户、角色、租户需要的属性默认schema中没有,例如:enable,description等等,需要修改;其次,需要添加存储openstack相关模型(user,tenant,group,role,domain)的dn,以便保存数据。

我自己写了两个ldif文件,以便完成上面两件事,内容如下:

modify.ldif

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: {52}( 2.5.4.66 NAME 'enabled' DESC 'RFC2256: enabled of a group' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
delete: olcObjectClasses
olcObjectClasses: {7}( 2.5.6.9 NAME 'groupOfNames' DESC 'RFC2256: a group of names (DNs)' SUP top STRUCTURAL MUST ( member $ cn ) MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
-
add: olcObjectClasses
olcObjectClasses: {7}( 2.5.6.9 NAME 'groupOfNames' DESC 'RFC2256: a group of names (DNs)' SUP top STRUCTURAL MUST ( member $ cn ) MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description $ enabled) )

dn: cn={3}inetorgperson,cn=schema,cn=config
changetype: modify
delete: olcObjectClasses
olcObjectClasses: {0}( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' DESC 'RFC2798: Internet Organizational Person' SUP organizationalPerson STRUCTURAL MAY ( audio $ businessCategory $ carLicense $ departmentNumber $ displayName $ employeeNumber $ employeeType $ givenName $ homePhone $ homePostalAddress $ initials $ jpegPhoto $ labeledURI $ mail $ manager $ mobile $ o $ pager $ photo $ roomNumber $ secretary $ uid $ userCertificate $ x500uniqueIdentifier $ preferredLanguage $ userSMIMECertificate $ userPKCS12 ) )
-
add: olcObjectClasses
olcObjectClasses: {0}( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' DESC 'RFC2798: Internet Organizational Person' SUP organizationalPerson STRUCTURAL MAY ( audio $ businessCategory $ carLicense $ departmentNumber $ displayName $ employeeNumber $ employeeType $ givenName $ homePhone $ homePostalAddress $ initials $ jpegPhoto $ labeledURI $ mail $ manager $ mobile $ o $ pager $ photo $ roomNumber $ secretary $ uid $ userCertificate $ x500uniqueIdentifier $ preferredLanguage $ userSMIMECertificate $ userPKCS12 $ description $ enabled $ email ) )

将以上内容保存到对应的文件之后,执行如下命令:

ldapmodify -c -Y EXTERNAL -H ldapi:/// -f modify.ldif


add.ldif

dn: ou=users,dc=openstack,dc=org
objectClass: top
objectClass: organizationalUnit

dn: ou=projects,dc=openstack,dc=org
objectClass: top
objectClass: organizationalUnit

dn: ou=roles,dc=openstack,dc=org
objectClass: top
objectClass: organizationalUnit

dn: ou=groups,dc=openstack,dc=org
objectClass: top
objectClass: organizationalUnit

dn: ou=domains,dc=openstack,dc=org
objectClass: top
objectClass: organizationalUnit

将以上内容保存到对应的文件之后,执行如下命令:

ldapadd -x -c -D"cn=admin,dc=openstack,dc=org" -w "Galax8800" -f add.ldif

注意Galax8800是安装LDAP的时候,输入的root密码


4、修改keystone的配置文件

/etc/keystone/keystone.conf

将Identity的后端配置为ldap

[identity]
driver = keystone.identity.backends.ldap.Identity

增加ldap段的配置,只需如下配置,其他可以使用默认值
[ldap]
url = ldap://localhost
user = cn=admin,dc=openstack,dc=org
password = Galax8800
suffix = dc=openstack,dc=org
use_dumb_member = True
allow_subtree_delete = False

user_tree_dn = ou=users,dc=openstack,dc=org
tenant_tree_dn = ou=projects,dc=openstack,dc=org
role_tree_dn = ou=roles,dc=openstack,dc=org
group_tree_dn = ou=groups,dc=openstack,dc=org
domain_tree_dn = ou=domains,dc=openstack,dc=org

注意:password = Galax8800 此密码为当时安装LDAP时,输入的root密码

配置完成之后,重启keystone


5、初始化keystone的基本用户

这个步骤网上的一些外国大牛已经提供了一些脚本,这里为了流程完整,就提供一个参考版本

keystone_basic.sh

#!/bin/sh
#
# Keystone basic configuration 

# Mainly inspired by https://github.com/openstack/keystone/blob/master/tools/sample_data.sh

# Modified by Bilel Msekni / Institut Telecom
#
# Support: [email protected]
# License: Apache Software License (ASL) 2.0
#
#. /root/novarc
#HOST_IP=${MASTER}
ADMIN_PASSWORD=Galax8800
SERVICE_PASSWORD=Galax8800
SERVICE_TENANT_NAME=${SERVICE_TENANT_NAME:-service}

get_id () {
    echo `$@ | awk '/ id / { print $4 }'`
}

# Tenants
ADMIN_TENANT=$(get_id keystone tenant-create --name=admin)
SERVICE_TENANT=$(get_id keystone tenant-create --name=$SERVICE_TENANT_NAME)


# Users
ADMIN_USER=$(get_id keystone user-create --name=admin --pass="$ADMIN_PASSWORD" [email protected])


# Roles
ADMIN_ROLE=$(get_id keystone role-create --name=admin)
KEYSTONEADMIN_ROLE=$(get_id keystone role-create --name=KeystoneAdmin)
KEYSTONESERVICE_ROLE=$(get_id keystone role-create --name=KeystoneServiceAdmin)

# Add Roles to Users in Tenants
keystone user-role-add --user-id $ADMIN_USER --role-id $ADMIN_ROLE --tenant-id $ADMIN_TENANT
keystone user-role-add --user-id $ADMIN_USER --role-id $KEYSTONEADMIN_ROLE --tenant-id $ADMIN_TENANT
keystone user-role-add --user-id $ADMIN_USER --role-id $KEYSTONESERVICE_ROLE --tenant-id $ADMIN_TENANT

# The Member role is used by Horizon and Swift
MEMBER_ROLE=$(get_id keystone role-create --name=Member)

# Configure service users/roles
NOVA_USER=$(get_id keystone user-create --name=nova --pass="$SERVICE_PASSWORD" [email protected])
keystone user-role-add --tenant-id $SERVICE_TENANT --user-id $NOVA_USER --role-id $ADMIN_ROLE

GLANCE_USER=$(get_id keystone user-create --name=glance --pass="$SERVICE_PASSWORD" [email protected])
keystone user-role-add --tenant-id $SERVICE_TENANT --user-id $GLANCE_USER --role-id $ADMIN_ROLE

QUANTUM_USER=$(get_id keystone user-create --name=quantum --pass="$SERVICE_PASSWORD" [email protected])
keystone user-role-add --tenant-id $SERVICE_TENANT --user-id $QUANTUM_USER --role-id $ADMIN_ROLE

CINDER_USER=$(get_id keystone user-create --name=cinder --pass="$SERVICE_PASSWORD" [email protected])
keystone user-role-add --tenant-id $SERVICE_TENANT --user-id $CINDER_USER --role-id $ADMIN_ROLE

将以上内容保存到对应的文件之后,执行如下命令:

sh keystone_basic.sh


6、验证keystone

如果上述流程都已经执行成功了,需要验证一下keystone中的数据,执行

keystone user-list


keystone role-list


keystone tenant-list


keystone user-role-list

注意:keystone user-role-list如果执行失败,没有关系,这不是LDAP配置的问题,是一个keystone-client的bug,通过Rest Client重新验证一下就可以了

https://bugs.launchpad.net/python-keystoneclient/+bug/1058750


7、查看LDAP中的数据结构

我们再来看一下LDAP中的数据结构,如果和下图一致,就没有问题了

Openstack Keystone LDAP后端配置_第2张图片


8、重启openstack的所有进程

配置keystone LDAP成功之后,需要重启openstack的所有进程,以nova为例,nova会缓存api-paste.ini中配置的admin_user的token,如果配置LDAP之前是使用的sql Identity后端,那么nova会使用这个缓存的admin_token去验证消息携带的token,keystone在判断admin_token是否可用时,会报错,造成认证失败,这个问题当时困扰了我很久,所以一定要重启openstack的所有进程,然后需要验证一下nova list,cinder list,glane image-list,quantum net-list是否可用。


9、将以上步骤浓缩为一个脚本

写了一个脚本将以上步骤全部实现

#!/bin/bash

# ubunut 12.04 LTS keystone G 2013.1 openldap 2.4.28

LDAP_PASS='Galax8800'

KEYSTONE_CONF='/etc/keystone/keystone.conf'

#step0 install ldap and set password
function install_ldap()
{
    cat <<LDAP_PRESEED | debconf-set-selections 
slapd slapd/password1 password ${LDAP_PASS}
slapd slapd/password2 password ${LDAP_PASS}
LDAP_PRESEED

    apt-get -y --force-yes install slapd
    apt-get -y --force-yes install ldap-utils

}

#step1 check ldap login
function check_ldap_login()
{
    local first_line=$(ldapsearch -x -LLL -H ldap:/// -b dc=openstack,dc=org dn | sed -n 1p)
    
    if [ "${first_line}" == "dn: dc=openstack,dc=org" ]
    then
        echo "login success"
    else
        echo "login failed"
        exit
    fi
}

#step2 modify ldap schema
function modify_ldap_schema()
{
    cat > ./modify.ldif <<EOF
dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: {52}( 2.5.4.66 NAME 'enabled' DESC 'RFC2256: enabled of a group' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
delete: olcObjectClasses
olcObjectClasses: {7}( 2.5.6.9 NAME 'groupOfNames' DESC 'RFC2256: a group of names (DNs)' SUP top STRUCTURAL MUST ( member $ cn ) MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
-
add: olcObjectClasses
olcObjectClasses: {7}( 2.5.6.9 NAME 'groupOfNames' DESC 'RFC2256: a group of names (DNs)' SUP top STRUCTURAL MUST ( member $ cn ) MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description $ enabled) )

dn: cn={3}inetorgperson,cn=schema,cn=config
changetype: modify
delete: olcObjectClasses
olcObjectClasses: {0}( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' DESC 'RFC2798: Internet Organizational Person' SUP organizationalPerson STRUCTURAL MAY ( audio $ businessCategory $ carLicense $ departmentNumber $ displayName $ employeeNumber $ employeeType $ givenName $ homePhone $ homePostalAddress $ initials $ jpegPhoto $ labeledURI $ mail $ manager $ mobile $ o $ pager $ photo $ roomNumber $ secretary $ uid $ userCertificate $ x500uniqueIdentifier $ preferredLanguage $ userSMIMECertificate $ userPKCS12 ) )
-
add: olcObjectClasses
olcObjectClasses: {0}( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' DESC 'RFC2798: Internet Organizational Person' SUP organizationalPerson STRUCTURAL MAY ( audio $ businessCategory $ carLicense $ departmentNumber $ displayName $ employeeNumber $ employeeType $ givenName $ homePhone $ homePostalAddress $ initials $ jpegPhoto $ labeledURI $ mail $ manager $ mobile $ o $ pager $ photo $ roomNumber $ secretary $ uid $ userCertificate $ x500uniqueIdentifier $ preferredLanguage $ userSMIMECertificate $ userPKCS12 $ description $ enabled $ email ) )
EOF

    ldapmodify -c -Y EXTERNAL -H ldapi:/// -f modify.ldif > /dev/null 2>&1 

    if [ $? -eq 0 ]
    then
        echo "modify.ldif success"
    else
        echo "modify.ldif failed"
        exit
    fi
    
    cat > ./add.ldif <<EOF
dn: ou=users,dc=openstack,dc=org
objectClass: top
objectClass: organizationalUnit

dn: ou=projects,dc=openstack,dc=org
objectClass: top
objectClass: organizationalUnit

dn: ou=roles,dc=openstack,dc=org
objectClass: top
objectClass: organizationalUnit

dn: ou=groups,dc=openstack,dc=org
objectClass: top
objectClass: organizationalUnit

dn: ou=domains,dc=openstack,dc=org
objectClass: top
objectClass: organizationalUnit
EOF

    ldapadd -x -c -D "cn=admin,dc=openstack,dc=org" -w "${LDAP_PASS}" -f add.ldif > /dev/null 2>&1 
    
    if [ $? -eq 0 ]
    then
        echo "add.ldif success"
    else
        echo "add.ldif failed"
        exit
    fi
    
    rm -rf ./modify.ldif
    rm -rf ./add.ldif

}

#step3 modify keystone.conf
function modify_keystone_conf()
{
    cat > ./keystone_ldap.conf <<EOF
url = ldap://localhost
user = cn=admin,dc=openstack,dc=org
password = ${LDAP_PASS}
suffix = dc=openstack,dc=org
use_dumb_member = True
allow_subtree_delete = False

user_tree_dn = ou=users,dc=openstack,dc=org
tenant_tree_dn = ou=projects,dc=openstack,dc=org
role_tree_dn = ou=roles,dc=openstack,dc=org
group_tree_dn = ou=groups,dc=openstack,dc=org
domain_tree_dn = ou=domains,dc=openstack,dc=org
EOF

    if [ -w "${KEYSTONE_CONF}" ]
    then
        sed "s/^\(driver = keystone.identity.backends.\).*\(.Identity\)/\1ldap\2/" -i ${KEYSTONE_CONF}
        sed "/^\[ldap\]$/r ./keystone_ldap.conf" -i ${KEYSTONE_CONF}
    else
        echo "modify keystone.conf failed"
        exit
    fi
    
    rm -rf ./keystone_ldap.conf
    
    stop keystone && start keystone > /dev/null 2>&1
    if [ $? -eq 0 ]
    then
        echo "restart keystone success"
    else
        echo "restart keystone failed"
        exit
    fi
    sleep 2
}

#step4 init keystone
function init_keystone()
{
        cat > ./keystone_basic.sh <<EOF
#!/bin/sh
#
# Keystone basic configuration 

# Mainly inspired by https://github.com/openstack/keystone/blob/master/tools/sample_data.sh

# Modified by Bilel Msekni / Institut Telecom
#
# Support: [email protected]
# License: Apache Software License (ASL) 2.0
#
#. /root/novarc
#HOST_IP=\${MASTER}
ADMIN_PASSWORD=Galax8800
SERVICE_PASSWORD=Galax8800
SERVICE_TENANT_NAME=\${SERVICE_TENANT_NAME:-service}

get_id () {
    echo \`\$@ | awk '/ id / { print \$4 }'\`
}

# Tenants
ADMIN_TENANT=\$(get_id keystone tenant-create --name=admin)
SERVICE_TENANT=\$(get_id keystone tenant-create --name=\$SERVICE_TENANT_NAME)


# Users
ADMIN_USER=\$(get_id keystone user-create --name=admin --pass="\$ADMIN_PASSWORD" [email protected])


# Roles
ADMIN_ROLE=\$(get_id keystone role-create --name=admin)
KEYSTONEADMIN_ROLE=\$(get_id keystone role-create --name=KeystoneAdmin)
KEYSTONESERVICE_ROLE=\$(get_id keystone role-create --name=KeystoneServiceAdmin)

# Add Roles to Users in Tenants
keystone user-role-add --user-id \$ADMIN_USER --role-id \$ADMIN_ROLE --tenant-id \$ADMIN_TENANT
keystone user-role-add --user-id \$ADMIN_USER --role-id \$KEYSTONEADMIN_ROLE --tenant-id \$ADMIN_TENANT
keystone user-role-add --user-id \$ADMIN_USER --role-id \$KEYSTONESERVICE_ROLE --tenant-id \$ADMIN_TENANT

# The Member role is used by Horizon and Swift
MEMBER_ROLE=\$(get_id keystone role-create --name=Member)

# Configure service users/roles
NOVA_USER=\$(get_id keystone user-create --name=nova --pass="\$SERVICE_PASSWORD" [email protected])
keystone user-role-add --tenant-id \$SERVICE_TENANT --user-id \$NOVA_USER --role-id \$ADMIN_ROLE

GLANCE_USER=\$(get_id keystone user-create --name=glance --pass="\$SERVICE_PASSWORD" [email protected])
keystone user-role-add --tenant-id \$SERVICE_TENANT --user-id \$GLANCE_USER --role-id \$ADMIN_ROLE

QUANTUM_USER=\$(get_id keystone user-create --name=quantum --pass="\$SERVICE_PASSWORD" [email protected])
keystone user-role-add --tenant-id \$SERVICE_TENANT --user-id \$QUANTUM_USER --role-id \$ADMIN_ROLE

CINDER_USER=\$(get_id keystone user-create --name=cinder --pass="\$SERVICE_PASSWORD" [email protected])
keystone user-role-add --tenant-id \$SERVICE_TENANT --user-id \$CINDER_USER --role-id \$ADMIN_ROLE
EOF
    
    bash keystone_basic.sh > /dev/null 2>&1
    if [ $? -eq 0 ]
    then
        echo "init keystone success"
    else
        echo "init keystone failed"
        exit
    fi
    
    rm -rf ./keystone_basic.sh

}

#step5 check keystone
function check_keystone()
{
    keystone user-list
    keystone role-list
    keystone tenant-list
}


#step6 restart openstack all service
function restart_openstack_all_service()
{
    cd /etc/init.d/; for i in $( ls quantum-* ); do sudo service $i restart; done; cd -;
    cd /etc/init.d/; for i in $( ls nova-* ); do sudo service $i restart; done; cd -;
    cd /etc/init.d/; for i in $( ls cinder-* ); do sudo service $i restart; done; cd -;
    cd /etc/init.d/; for i in $( ls glance-* ); do sudo service $i restart; done; cd -;
    cd /etc/init.d/; for i in $( ls keystone ); do sudo service $i restart; done; cd -;
}


###################### main #######################
install_ldap
check_ldap_login
modify_ldap_schema
modify_keystone_conf
init_keystone
check_keystone
restart_openstack_all_service


脚本中包括:

 #step0 install ldap and setpassword

 #step1 check ldap login

 #step2 modify ldap schema

 #step3 modify keystone.conf

 #step4 init keystone

 #step5 check keystone

 #step6 restartopenstack all service

最后一步重启所有openstack服务的步骤,会重启本节点的所有openstack进程,如果有其他节点需要手动重启

运行自动化脚本

bash config_keystone_ldap.sh

默认LDAP密码为Galax8800


最后附送ubuntu环境下完全删除LDAP的命令

apt-get purge slapd


你可能感兴趣的:(ubuntu,openstack,自动化,LDAP,keystone)