Ubuntu下LDAP和OpenStack Keystone安装集成小结
崔炳华
2013年12月16日
1 环境准备
1.1 版本
- Linux系统版本:Ubuntu Server 12.04.1 LTS;
- Python版本:2.7.3(稍后安装);
- Swift版本:1.8.0(稍后安装);
- Python-swiftclient版本:1.8.0(稍后安装);
- Keystone版本:0.4.1(稍后安装);
- Python-keystoneclient版本:0.4.1(稍后安装);
注意,python-keystoneclient与Keystone的版本需要统一,否则可能会出现版本兼容性问题,采用依赖项的方式安装python-keystoneclient,可确保不会出现版本兼容性问题。
1.2 节点IP
- Proxy Node IP/Auth Node IP:172.17.10.14。
1.3 替换镜像(可选步骤)
“网速较慢”或者“安装软件失败”的情况下,可以考虑替换成国内的镜像:
vsroot@proxy:~$ sudo sed -i's#us.archive.ubuntu.com#mirrors.163.com#g' /etc/apt/sources.list
vsroot@proxy:~$ sudo apt-get update
1.4 系统时间
vsroot@proxy:~$ date #查看系统时间是否正确,正确的话则忽略下面两步
vsroot@proxy:~$ sudo date -s"2013-11-04 15:05:57" #设置系统时间
vsroot@proxy:~$ sudo hwclock –w #写入硬件时间
1.5 关闭防火墙
请确保已关闭SELinux。
vsroot@proxy:~$ sudo ufw disable #关闭防火墙
2 安装OpenStack组件
OpenStack的Keystone是必要安装组件,Nova、Glance、Swift等是可选安装组件。
本文假定需要安装的OpenStack组件为:Swift、Keystone和Horizon。其安装集成流程,具体请参考本人写的《Ubuntu下Swift、Keystone和Horizon安装集成小结》,本文不再介绍。
3 安装LDAP
OpenStack在Grizzly版本上对LDAP验证机制已经有非常好的支持,但对LDAP服务有较为严苛的要求。
OpenStack Keystone利用现有的LDAP后端进行账户验证时,LDAP服务需要满足Keystone的一些较为严苛的需求,主要有以下几点:
- 用户和租户分别存储在不同的子树中。
- 角色必须作为用户及租户的一个属性记录在相应的子树中。
- 拥有LDAP服务的写权限,并且提前写入各个服务帐号(Nova、Glance、Cinder、Swift、Neutron、Ceilometer等组件)以及各组件所在的服务租户(即Service租户)。
3.1 安装LDAP库
root@proxy:~# apt-get install ldap-utils
root@proxy:~# apt-get install slapd #这一步执行过程中会要求输入Administrator的密码,不妨设为openstack
另外,附上完全删除LDAP的命令,后续可能用得到:apt-getpurge slapd。
3.2 验证LDAP登录
查看hosts信息:
root@proxy:~# cat /etc/hosts
127.0.0.1 localhost
172.17.10.14 proxy.huacloud.demo proxy
# The following lines are desirable forIPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
根据以上内容可知,这个环境上的登录DN为 cn=admin,dc=huacloud,dc=demo。
使用如下命令可以验证是否配置成功:
root@proxy:~# ldapsearch -x -LLL -H ldap:///-b dc=huacloud,dc=demo dn
dn: dc=huacloud,dc=demo
dn: cn=admin,dc=huacloud,dc=demo
3.3 修改LDAP的默认schema
LDAP的默认schema不能直接和OpenStack配合使用,默认schema中缺少有些OpenStack的用户、角色、租户需要的属性,例如:enable、description等等,需要修改;其次,需要添加存储OpenStack相关模型(user、tenant、group、role、domain)的dn,以便保存数据。
下面新建两个ldif文件,以便分别完成上面的两件事情。
modify.ldif的内容为如下:
root@proxy:~# 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
将以上内容保存到对应的文件之后,执行如下命令:
root@proxy:~# ldapmodify -c -Y EXTERNAL -Hldapi:/// -f modify.ldif
add.ldif的内容为如下:
root@proxy:~# cat >~/add.ldif <<EOF
dn: ou=users,dc=huacloud,dc=demo
objectClass: top
objectClass: organizationalUnit
dn: ou=projects,dc=huacloud,dc=demo
objectClass: top
objectClass: organizationalUnit
dn: ou=roles,dc=huacloud,dc=demo
objectClass: top
objectClass: organizationalUnit
dn: ou=groups,dc=huacloud,dc=demo
objectClass: top
objectClass: organizationalUnit
dn: ou=domains,dc=huacloud,dc=demo
objectClass: top
objectClass: organizationalUnit
EOF
将以上内容保存到对应的文件之后,执行如下命令:
root@proxy:~# ldapadd -x -c -D "cn=admin,dc=huacloud,dc=demo"-w "openstack" -f add.ldif
注意,上面的命令中,openstack是安装LDAP的时候给Administrator设置的密码。
4 修改Keystone等
4.1 修改Keystone配置文件
需要为Keystone配置文件新增如下部分配置:
root@proxy:~# vim /etc/keystone/keystone.conf
[identity]
driver = keystone.identity.backends.ldap.Identity
[ldap]
url = ldap://localhost
user = cn=admin,dc=huacloud,dc=demo
password = openstack
suffix = dc=huacloud,dc=demo
use_dumb_member = True
allow_subtree_delete = False
user_tree_dn = ou=users,dc=huacloud,dc=demo
tenant_tree_dn =ou=projects,dc=huacloud,dc=demo
role_tree_dn = ou=roles,dc=huacloud,dc=demo
group_tree_dn =ou=groups,dc=huacloud,dc=demo
domain_tree_dn =ou=domains,dc=huacloud,dc=demo
配置完成之后,重启keystone服务。
root@proxy:~# cd keystone
root@proxy:~/keystone# sudo keystone-all
4.2 初始化Keystone的基本用户
在~/keystone目录下创建一个脚本,名字为keystone_for_ldap.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: openstack@lists.launchpad.net
# License: Apache Software License (ASL) 2.0
#
#. /root/novarc
#HOST_IP=${MASTER}
ADMIN_PASSWORD=openstack
SERVICE_PASSWORD=openstack
SERVICE_TENANT_NAME=${SERVICE_TENANT_NAME:-service}
get_id () {
echo `$@ | awk '/ id / { print $4 }'`
}
# Tenants
ADMIN_TENANT=$(get_id keystone tenant-create --name=adminTenant)
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)
TEST_USER=$(get_id keystone user-create --name=test --pass="$ADMIN_PASSWORD" --email=test@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 $TEST_USER --role-id $ADMIN_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
SWIFT_USER=$(get_idkeystone user-create --name=swift --pass="$SERVICE_PASSWORD"--email=swift@domain.com)
keystoneuser-role-add --tenant-id $SERVICE_TENANT --user-id $SWIFT_USER --role-id$ADMIN_ROLE
注意到,上面这个脚本,我们为adminTenant这个租户创建了两个用户admin和test。
接着,就可以执行这个脚本:
root@proxy:~# shkeystone/keystone_for_ldap.sh
4.3 更新Service和Endpoint
需要使用keystone命令检查一下Swift和Keystone的Service和Endpoint是否正常。
由于Service没有发生变化,不用重新创建。Keystone的Endpoint也不用重新创建。
由于Tenant发生了变化,我们需要为Swift重新创建Endpoint,会用到Swift这个Service对应的Service id,以及adminTenant这个租户对应的Tenantid:
root@proxy:~# keystoneendpoint-create --region RegionOne \
--service_id b645a621b27b476ea897cc51563ee73e--publicurl \
http://172.17.10.14:8080/v1/AUTH_1ba28c96213b4db48d70a1de287931c4 \
--adminurl http://172.17.10.14:8080 --internalurl \
http://172.17.10.14:8080/v1/AUTH_1ba28c96213b4db48d70a1de287931c4
4.4 修改Swift配置文件
由于Role发生变化,所以要修改Swift配置文件/etc/swift/proxy-server.conf的[filter:keystoneauth]中的operator_roles部分:
root@proxy:~# vim /etc/swift/proxy-server.conf
[filter:keystoneauth]
use = egg:swift#keystoneauth
# operator_roles = adminRole, swiftoperator
operator_roles = admin, swiftoperator
reseller_prefix = AUTH_
set log_level = DEBUG
set log_name = keystoneauth
4.5 重启Swift服务
root@proxy:~# sudo swift-init proxy restart
4.6 测试swift命令
我们用adminTenant这个租户下的admin用户来访问,预期可以成功:
root@proxy:~# swift -V 2 -A http://172.17.10.14:5000/v2.0 -U adminTenant:admin -K openstack stat
我们用adminTenant这个租户下的test用户来访问,预期也可以成功:
root@proxy:~# swift -V 2 -A http://172.17.10.14:5000/v2.0 -U adminTenant:test -K openstack stat
这两个用户各自创建的Container和Object,彼此可以互相共享或者删除。
4.7 测试Horizon
由于Swift服务已经占用了8080端口,所以作为同一个节点上的Horizon服务,就不能再使用8080端口了,这里不妨改成8088端口:
root@proxy:~/horizon# tools/with_venv.sh./manage.py runserver 172.17.10.14:8088
现在可以尝试通过IE浏览器访问:
- 链接:http://172.17.10.14:8088
- 用户名:admin或者test
- 密码:openstack
5 LDAP测试
5.1 下载LDAP软件
Windows下有很多LDAP软件。一款比较小巧的软件:LDAP Browser,主要用于查看LDAP数据;另外,再介绍一款比较强大的软件:JXplorer,可以读写LDAP数据(需要先安装JDK)。
5.2 登录LDAP软件
按照如下配置,就可以在Windows客户端成功登录LDAP Browser并查看LDAP中的数据结构:
- Host:192.168.1.76
- Port:389
- Protocol:3
- Base DN:dc=huacloud,dc=demo(点击"Fetch DNs"可以自动获取DN)
- User:cn=admin,dc=huacloud,dc=demo
- Password:openstack
按照如下配置,就可以在Windows客户端成功登录JXplorer并查看LDAP中的数据结构:
- 主机:192.168.1.76
- 端口:389
- 协定:LDAP v3
- 基底DN:dc=huacloud,dc=demo
- 层级:用户+密码
- 使用者DN:cn=admin,dc=huacloud,dc=demo
- 密码:openstack
在JXplorer中的树形结构中可以看到:
- DC(Domain Component,域名)嵌套了两层,依次是demo和huacloud。
- huacloud这个DC下有若干个OU(Organizational Unit,组织单元),依次是groups、projects、roles、users。
- users这个OU下有若干个CN(Common Name,常用名称),列出了所有的普通用户。
- roles这个OU下有若干个CN,列出了所有的角色。
- projects(相当于Tenant)这个OU下嵌套了有两层CN,第一层CN列出了所有的租户;每个租户下又列出了和该租户相关联的所有角色;在每个角色中的属性类型里,使用roleOccupant记录了和该租户的该角色相关联的所有用户。
如果我们想通过JXplorer来新增一个OpenStack用户,可以按照如下步骤操作:
- 选中users这个OU,单击右键菜单中的“新增”。
- 在弹出的“设定项目对象类别”的对话框中,在“输入RDN”不妨填写cn=testusercn(对应着Keystone中的User ID),然后单击“确定”。
- 在“表格编辑器”中,为sn(对应着Keystone中的User Name)这个属性类型设置一个用户名,例如:testuser;为enabled这个属性类型选择TRUE值;为userpassword这个属性类型设置密码,例如:openstack;然后单击“送出”,testuser这个用户就被创建成功了。
- 选中projects这个OU,再选中期望的租户,再选择期望的角色;在该角色的“表格编辑器”中,选中任一个roleOccupant属性类型,单击右键菜单中的“新增另一个值”,在value栏填写:cn=testusercn,ou=users,dc=huacloud,dc=demo,然后单击“送出”,testuser这个用户就被成功地加入到相应的租户和相应的角色了。
现在,用户testuser就可以正常访问Swift了。
6 调试手段
6.1 日志查询
Swift的相关日志会输出到var/log/syslog中。
6.2 增强日志
var/log/syslog可能日志太少影响定位问题,我们可以增强日志。参考http://docs.openstack.org/developer/swift/deployment_guide.html#account-server-configuration,可以在/etc/swift/proxy-server.conf等配置文件中设定log的输出等级为DEBUG。
例如,/etc/swift/proxy-server.conf文件中,[app:proxy-server]这一部分追加了setlog_level = DEBUG,[filter:tempauth]这一部分追加了set log_level = DEBUG。
6.3 查看端口
使用“telnet IP PORT”或者“lsof -i PORT”命令查看端口。ProxyNode/Auth Node上主要关注端口11211/8080/2021/8088等,Storage Node上主要关注Ring的相关端口,如6000/6001/6002等。
7 小结
OpenStack在Grizzly版本上对LDAP验证机制已经有非常好的支持,Keystone可以通过LDAP服务来进行统一的身份验证。
8 参考资料
1) 《Openstack KeystoneLDAP后端配置》,http://blog.csdn.net/u011196209/article/details/10197725
2) 《Openstack Keystone LDAP Redux》,http://adam.younglogic.com/2012/02/openstack-keystone-ldap-redux/