OpenLDAP的官网上,并没有使用方面专题介绍,所以这部分的学习也只能一半参考一半摸索的进行。OpenLDAP的使用与管理,可以通过内置工具、第三方工具以及其他具体场景来进行,这里仅介绍系统内置工具的日常使用。
工具概述在前一篇安装篇中所说,默认情况下LDAP的客户端管理工具被安装在: /usr/local/bin/ 目录中。我们可以通过 man 命令,或者 –help 参数来查看工具的具体使用方法。不过前者的返回实在是太多了,用后者即可。
查询操作 ldapsearch回忆一下上一节中的两个查询命令,同时对照帮助文档:
# 刚启动后 ldapsearch -x -LLL -b '' -s base '(objectclass=*)' namingContexts # 添加了根条目后 ldapsearch -x -LLL -b 'dc=example,dc=com' '(objectclass=*)' # 帮助文档 ldapsearch --help # 返回模板 usage: ldapsearch [options] [filter [attributes...]]
可以看到参数主要包含选项、过滤方式及显示属性。其中,过滤方式遵循 RFC 4515 规范,我也没再深入研究,以后再说吧。
其中属性是由空格分隔的多个名称列表,或者使用 * 显示所有用户属性,用 + 显示所有可选属性,例如:
ldapsearch -x -LLL -b 'dc=example,dc=com' '(objectclass=*)' +
对于简单的查询来说,以下几个选项基本就够用了:
- -x : 简单身份验证
- -LLL : 简化输出,不输出注释
- -b : 表示搜索的起始节点
- -s : 搜索范围,base, one, sub or children的一个
- -H : 用于指定链接的服务器,如果不指定默认为本机地址及ldap协议
我是谁?这个命令用于请求用户身份验证。
# 简单身份验证 ldapwhoami -x # 返回表示为匿名用户 anonymous # 简单身份验证,指定绑定DN ldapwhoami -x -w 123456 -D cn=Manager,dc=example,dc=com # 返回绑定的DN身份信息 dn:cn=Manager,dc=example,dc=com # 密码错误或者DN错误,则返回下面的错误信息 ldap_bind: Invalid credentials (49)
查询选项中的 -w 是指明文提供相应的密码明文;-W 为交互式密码输入方式。
编辑操作 添加操作回想一下上一节的最后,通常在 LDAP 中添加条目,分为两步:1.编辑LDIF文件;2.添加文件到LDAP节点中。
再次编辑一个文件,名为 add_group.ldif,添加如下内容:
dn: ou=group,dc=example,dc=com objectclass: organizationalUnit ou: group
然后添加到上一节创建的根节点中:
ldapadd -x -W -D "cn=Manager,dc=example,dc=com" -f add_group.ldif # 返回下面的结果表示添加成功 adding new entry "ou=group,dc=example,dc=com" # 查询 ldapsearch -x -LLL -b 'dc=example,dc=com' '(objectclass=*)'
复盘一下前面的文件,这是一个最简单的LDAP管理文件,其中至少包括:
- dn: 为条目的名字,必须全局唯一,对于添加操作来说,会根据路径进行搜索,如果上级不存在,会返回No Object错误;
- objectclass : 必须包含的内容,表示该条目是什么类型,一个文件中可以包含多个指令;
- ou : ou 是 organizationalUnit 对象的必要属性,如果不填写必要属性,会返回错误。
phpLDAPadmin提供了一个工具,可以查看到所有的 objectclass , 以及所有属性。打开文末的参考资料,选择左侧的 C6:OpenLDAP 2.4.40: config 下拉后,点击 schema 图标。
修改操作修改操作略微复杂一些,又可以进一步区分为添加修改(为条目添加属性)、更新修改(为条目更新属性)、删除修改(删除属性)。但是要注意的是,这些操作应该只能针对于可选属性。想要修改类似于: ou 属性,会直接返回错误。
添加修改我们继续编辑一个文件,名为: edit_group.ldif ,添加下面的内容:
dn: ou=group,dc=example,dc=com changetype: modify add: description description: I'm first description!
然后执行 ldapmodify 命令:
ldapmodify -x -W -D "cn=Manager,dc=example,dc=com" -f edit_group.ldif # 返回下面的结果表示修改成功 modifying entry "ou=group,dc=example,dc=com" # 查询,此处已经可以看到修改添加的结果 ldapsearch -x -LLL -b 'ou=group,dc=example,dc=com'更新修改
再次编辑前面的 edit_group.ldif 文件,修改下面的内容:
dn: ou=group,dc=example,dc=com changetype: modify replace: description description: I'm second description!
再次执行 ldapmodify 命令:
ldapmodify -x -W -D "cn=Manager,dc=example,dc=com" -f edit_group.ldif # 返回下面的结果表示修改成功 modifying entry "ou=group,dc=example,dc=com" # 查询,此处已经可以看到修改添加的结果 ldapsearch -x -LLL -b 'ou=group,dc=example,dc=com'删除修改
再次编辑前面的 edit_group.ldif 文件,修改下面的内容:
dn: ou=group,dc=example,dc=com changetype: modify delete: description
再次执行 ldapmodify 命令:
ldapmodify -x -W -D "cn=Manager,dc=example,dc=com" -f edit_group.ldif # 返回下面的结果表示修改成功 modifying entry "ou=group,dc=example,dc=com" # 查询,此处可以看到 description 属性已经被删除 ldapsearch -x -LLL -b 'ou=group,dc=example,dc=com'总结
总结下来,修改操作需要通过 DN 来指定一个待修改的条目对象,changetype 的值固定为 modify 。通过动作指令来声明需要进行的操作,例如:add、replace和delete,同时指定要执行该动作的属性。最后指定该属性的值(对于删除动作来说并不需要)。
删除操作上面的删除修改,实际上只是删除某个条目的具体值,那么如何彻底删除一个条目呢?这里需要用到 ldapdelete 命令,在此之前,我们创建一个新的条目用于测试删除。
# add_sub_group.ldif dn: ou=tsd,ou=group,dc=example,dc=com objectclass: organizationalUnit ou: tsd
执行操作命令:
ldapadd -x -W -D "cn=Manager,dc=example,dc=com" -f add_sub_group.ldif # 返回下面的操作 adding new entry "ou=tsd,ou=group,dc=example,dc=com" # 查询,此处可以看到子级分组已经添加 ldapsearch -x -LLL -b 'ou=group,dc=example,dc=com'
最后,我们执行删除操作:
ldapdelete -x -W -D "cn=Manager,dc=example,dc=com" -r ou=tsd,ou=group,dc=example,dc=com # 查询,此处可以看到子级分组已经添加 ldapsearch -x -LLL -b 'ou=group,dc=example,dc=com'
从上面的操作可以看到,节点删除并不会返回明确的结果。如果不指定具体的DN,则在输入密码后已交互式方式,要求用户输入DN来进行删除操作。其中的 -r 选项,用于指定递归删除。
多协议支持可以说经过上面的实操,已经算是掌握了LDAP的操作。但是可能心细的人会注意到一个差异,我所有的命令操作,使用的身份验证都是: -x -W 或者 -x -w 123456 这种形式,而网上绝大多数的教程都是: -Q -Y EXTERNAL -H ldapi:// ,这是为什么呢?
首先我们尝试一下依样画瓢是否可行,简单改写下上面的命令,结果…………。Oops,返回错误:
ldapsearch -LLL -Q -Y EXTERNAL -H ldapi:// -b 'ou=group,dc=example,dc=com' ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)
考虑到再做一下简化,看看可能的问题在哪里:
ldapsearch -x -LLL -H ldapi:// -b 'ou=group,dc=example,dc=com' ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)
WTF!!!
遇到这个问题,很多人去搜帖子,不外乎解决方案不外乎:添加 sudo 执行、不该用 ldapi:/// 要用 ldapi:// 、不该用 ldapi:// 要用 ldapi:/// 等等……
然而正如前面所讲的那样,这全部都是 设定先行 的想当然。 这里的本质原因在于2点:
- 不给定参数的前提下,slapd只启动ldap的监听!
- 下回再说!
第一点原因的解决方法也很简单,kill 掉之前的启动命令,添加参数后再次启动 slapd:
/usr/local/libexec/slapd -F /usr/local/etc/slapd.d -h "ldap:/// ldapi:///" # 简单授权方式 ldapsearch -x -LLL -H ldapi:// -b 'ou=group,dc=example,dc=com' # SASL 机制 ldapsearch -Q -Y EXTERNAL -LLL -H ldapi:// -b 'ou=group,dc=example,dc=com'总结
以为这样就完了么?当根据网上的资料,尝试使用 SASL 机制添加前面创建的条目时:
ldapadd -Q -Y EXTERNAL -H ldapi:// -f add_sub_group.ldif
WTF!!!这又是为什么???
# 返回结果 adding new entry "ou=tsd,ou=group,dc=example,dc=com" ldap_add: Insufficient access (50) additional info: no write access to parent
这依旧是一个 设定先行 的问题,带着这个问题进入下一章内容!
文中所涉及的相关配置文件,请点击链接下载。
参考资料- 运行slapd
- 如何使用openldap工具管理和使用ldap
- objectclass查询



