这篇文章是我的团队成员kiwik的实战记录总结,如需再次转发,请标明文章出处!
写在最前面:
以下内容在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
所以这个环境上的登陆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中的数据结构,如果和下图一致,就没有问题了
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:
-
- 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:
-
- 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:
- 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:
-
- # Modified by Bilel Msekni / Institut Telecom
- #
- # Support: openstack@lists.launchpad.net
- # 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=admin@domain.com)
-
-
- # 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=nova@domain.com)
- 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=glance@domain.com)
- 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=quantum@domain.com)
- 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=cinder@domain.com)
- 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