LDAP 基础知识

LDAP 基础知识

目录
LDAP 基础知识
--简介
--协议概览
--目录结构架构(Schema)
------对象类(objectClass)
------属性(Attribute)
------条目(Entry)
--LDAP 中的数据常用命令
------启动和关闭: start-ds / stop-ds
------检查 LDAP 服务器状态: status
------搜寻条目: ldapsearch
------修改密码: ldappasswordmodify
------列出 backends: list-backends
------导出 LDIF 文件: export-ldif
------导入 LDIF 文件: import-ldif
------管理账户: manage-account
--性能
--LDAP 浏览器
--参考文献

简介

LDAP 是 Lightweight Directory Access Protocol 的缩写,即 轻量目录访问协议。它基于 X.500 标准下更简单的子集标准开发,因此有时 LDAP 也被称之为 X.500-lite,即轻量级 x.500

目录服务在发展内部网络和因特网应用方面扮演着重要角色,它可以通过互联网分享用户、系统、网络、服务以及应用信息。

目录服务可以提供任何系统化的数据集,并以等级结构(hiearchical structure)呈现结果。比如,公司的邮件目录,或者包含地址和电话号码的电话目录。

LDAP 的一个常用功能是提供用户名和密码的集中存储。不同的应用和服务可以用其来认证用户。

协议概览

客户端发起 LDAP 会话连接到 LDAP 服务器。默认连接端口是 389(LDAP),或者 636(LDAPS)。客户端发起操作请求到服务器,服务器返回响应结果。客户端无需等待服务器响应即可发送下一个请求。服务器则会依次返回响应结果。

客户端可以发送如下操作请求:

  • StartTLS - 使用 LDAPv3 TLS 扩展来请求安全连接
  • Bind - 认证并指定 LDAP 协议版本
  • Search - 搜索目录条目
  • Compare - 测试命名条目是否包含指定的属性值
  • Add a new entry - 添加一个条目
  • Delete an entry - 删除一个条目
  • Modify an entry - 修改一个条目
  • Modify DN - 修改唯一识别名
  • Extended Operation - 用于定义其他操作的通用操作
  • Unbind - 关闭连接(注意,并非指 Bind 的逆向操作)

目录结构

在 LDAP 里, 一切都是等级化的,或者称之为层级化(hiearchical)。

一棵树有树干,树枝和树叶;树叶长在树枝上,树枝依附于树干。这就是一个简单的层级结构。LDAP 的结构同一棵树类似。假设 LDAP 里存储的是公司的信息,那么可以把公司(company)本身理解为树干,公司里面的各个部门,比如(group),理解为树干,把用户(user)理解为树叶。这样的结构称之为目录信息树(DIrectory Information Tree,DIT)。

architecture.png

我们在目录信息树里创建一个条目(entry)时,条目的信息存储在属性(attribute)里,属性又被组合成对象类(objectClass),对象类进一步组成了架构(schema)。

下满我们来解释一下这几个重要的概念。

架构(Schema)

  • Schema 就是一个集合。所有的 objectClassattribute 都定义在 Schema 里。

  • 每一个 attributeobjectClass,包括其父级 attributeobjectClass 都必须定义在一个 Schema 里,且该 Schema 必须能够被 LDAP 服务器识别。

  • 定义在一个 Schema 里的 attribute 可以被另一个 Schema 里的 objectClass 使用。

    schema.png

对象类(objectClass)

  • objectClassattribute 的集合。
  • objectClass 定义在 Shema 里。
  • objectClass 可以是下面的类型:
    • STRUCTURAL - 可以用于创建条目,即数据对象
    • AUXILIARY - 可以添加到任何条目
    • ABSTRACT - 不存在,抽象的。最常见的 ABSTRACT objectClasstop,表示每个 objectClass 层级的最高形式,用来结束一个层级。
  • objectClass 可以以层级的形式呈现,这里它可以继承来自父级的属性。也就是说,objectClass 可以是一个层级的一部分,这种情况下,objectClass 必须和它的父级 objectClass 保持同样的类型,即 STRUCTURAL 或者 AUXILIARY 类型。当父级是 top ABSTRACT 时无需遵守此规则,因为 top ABSTRACT 用结束任何层级结构。
  • 一个 objectClass 可以有一个或多个父级的 objectClass
  • objectClass 是用来包含属性的方式。
  • objectClass 定义一个 attribute 是否是必须的(MUST)或者是可选的(MAY)。
  • objectClass 遵守 ASN.1 注释标准。

示例:下面是一个简单的 objectClass 定义

objectclass ( 2.5.6.2 NAME 'country' DESC 'RFC2256: a country'
  SUP top STRUCTURAL
  MUST c
  MAY ( searchGuide $ description ) )

解释:

  • objectClass 是关键字,指明这是一个 objectClass 的定义
  • 2.5.6.2 NAME 'country' 定义 objectClass 的全局唯一识别名。它由两部分组成:
    • NAME 'country' 为 objectClass 定义一个好理解的名字 country
    • 2.5.6.2 定义全局唯一识别名,这种形式称之为 OID(ObjectIdentifier)。由哪个组织分配这个号码并不重要,但是必须是全局唯一的。通常推荐向 IANA申请一个 PEN (Private Enterprise Number)作为 OID 使用。
  • SUP 'top' 表示该 objectClass 有一个父级的 objectClass,也就是说它是一个层级的一部分。一个 objectClass 可以有一个或多个父级的 objectClass
  • STRUCTURAL 表示该 objectClass 包含属性且可以形成目录信息树(DIT)里的条目(entry)。一个条目里只能包含一个 STRUCTURAL objectClass。objectClass 也可以是 AUXILIARY,这说明它包含 attributes,可以和任何 STRUCTURAL objectClass一起使用构成一个条目,但是不可以单独构成一个条目
  • DESC 'a country' 为可选值,用来描述 objectClass
  • MUST c 表示 c 属性是必须的。这里的属性 c (c 或者 countryName)必须存在,否则 objectClass 实例无法创建成功。如果要指明多个属性是必须的,写法是 ( attr1 $ attr2 $ attrn)
  • MAY ( searchGuide $ description ) 表示 searchGuidedescription 是可选的,即创建 objectClass 时这两个属性不需要一定存在。

属性(Attribute)

  • attribute 定义在 Schema里。
  • 一个 attribute 可以包含在一个或多个 objectClass 里。
  • 一个 attribute 可以在包含它的 objectClass 里出现一次(SINGLE-VALUE)或多次(MULTI-VALUE)。默认为多次。
  • 一个 attribute 可以是一个层级的一部分,此时它继承所有来自父级的属性。比如,commonName(cn),givenName(gn) 和 surname(sn)都是 name 属性的子类。
  • attribute 的定义包含它的类型(SYNTAX),比如,通过 matchingRules 定义字符串(string)或者数字(number)比较时是否大小写敏感。
  • attribute 定义遵守 ASN.1 注释标准

示例 1:下面是一个简单的 attribute 定义

attributetype ( 2.5.4.3 NAME ( 'cn' 'commonName' ) SUP name )

解释:

  • attributetype 说明这是一个关于 attribute 的定义
  • 2.5.4.3 NAME ('cn' 'commonName') 定义一个全局唯一识别名。该识别名由两部分组成:
    • NAME ('cn' 'commonName') 定义一个可理解的名字 commonName 或者短别名 cn。原则上,短别名的个数没有限制。cn 排在第一位,它被称为主要名称(primary name)。这在为搜索优化做条目索引时非常重要。
    • 2.5.4.3 定义全局唯一的 OID (ObjectIdentifier)。由哪个组织分配这个号码并不重要,但是必须是全局唯一的。通常推荐向 IANA申请一个 PEN (Private Enterprise Number)作为 OID 使用。

示例 2:

attributetype ( 2.5.4.41 NAME 'name'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )

解释:

  • attributetype 同上。
  • 2.5.4.41 NAME 'name' 同上。
  • EQUALITY caseIgnoreMatch 定义了该属性在搜索过滤(serach filter)中的行为。比如,(name=andy)。这里指定该属性在搜索中大小写不敏感。这里的 caseIgnoreSubstringMatch 就是一个 matchingRule
  • SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} 是一个 OID,定义数据类型(data type)和要应用到数据的规则(data validation)。完整的定义可参考 RFC 2252 section 4.3.2。在本例中,OID 定义该属性为目录字符串(Directory String)类型(参考 RFC 2252 section 6.10)。 {32768} 定义字符串的最大长度,这是可选的。

条目(Entry)

  • 目录信息树objectClass 的集合
  • entry 有且只能有一个 STRUCTURAL objectClass。一个 STRUCTURAL objectClass 可能有一个同为 STRUCTURAL 类型的父级。
  • entry 可以包含任意数目的 AUXILIARY objectClass
  • entry 可以有子 entry(child entry),父 entry(parent entry),同级 entry(sibling entry)
  • entry 有三种类型:
    • object entry - 最常见的一种,包含位于 objectClass 属性(attributes)里的用户数据
    • alias entry - 带有单一属性 aliasedObjectNameobjectClass 别名
    • subentry - 用于存储与父 entry 相关的管理或者操作数据

下图是关于 objectClass, attribute 以及 entry 的示意图:

dit2.png

LDAP 中的数据

LDAP 中的数据以条目(entry)的形式呈现,就像英文字典里单词的条目。比如下面这个条目。它有很多属性,例如:uid:bjensen,mail:bjensen@example.com。查找条目时,只需要指定一个或者多个属性即可。

同时,该条目有一个唯一识别名称:dn: uid=bjensen,ou=People,dc=example,dc=com。DN 是 Distinguished Name 的缩合。在目录里没有两条相同的唯一识别名称。

dn: uid=bjensen,ou=People,dc=example,dc=com
uid: bjensen
cn: Babs Jensen
cn: Barbara Jensen
facsimileTelephoneNumber: +1 408 555 1992
gidNumber: 1000
givenName: Barbara
homeDirectory: /home/bjensen
l: San Francisco
mail: bjensen@example.com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: posixAccount
objectClass: top
ou: People
ou: Product Development
roomNumber: 0209
sn: Jensen
telephoneNumber: +1 408 555 1862
uidNumber: 1076

常用命令

鉴于大多数的 LDAP 软件大同小异,这里的内容就以OpenDS/OpenDJ 为例。

启动和关闭: start-ds / stop-ds

  • 语法: start-ds / stop-ds
  • Windows:
    • 打开命令窗口
    • 浏览到到 <INSTALL-DIR>\bat
    • 运行:
      • 启动: start-ds
      • 关闭: stop-ds
  • *nix:
    • 打开命令窗口
    • 浏览到到 <INSTALL-DIR>/bin
    • 运行:
      • 启动: ./start-ds
    • 关闭: ./stop-ds

检查 LDAP 服务器状态: status

  • 语法: status
  • Windows:
    • 打开命令窗口
    • 浏览到到 <INSTALL-DIR>\bat
    • 运行: status
  • *nix:
    • 打开命令窗口
    • 浏览到到 <INSTALL-DIR>/bin
  • 运行: ./status

搜寻条目: ldapsearch

  • 语法: ldapsearch <options> <filter> <attributes>,其中:<options> 为选项,<filter> 为过滤条件,<attributes> 为显示的属性

  • 示例: ldapsearch -p 389 -h 192.168.93.128 -D cn=Manager -w ts -b o=ptc uid=demo ,其中:

    • <options>:-p 389 -h 192.168.93.128 -D cn=Manager -w ts -b o=ptc
    • <filter>: uid=demo
    dn: uid=demo,ou=people,cn=AdministrativeLdap,cn=Windchill_11.2,o=ptc
    objectClass: organizationalPerson
    objectClass: top
    objectClass: person
    objectClass: inetOrgPerson
    uid: demo
    mail: demouser
    preferredLanguage: en-US
    description: demo
    sn: Demo
    cn: Demo, User
      o: Demo Organization
      userPassword: {SSHA}IDSc3KN4Q1b2YSGfCBQiU4CXgBySg+AQsWkpEA==
      
    
  • 我们可以使用更复杂的条件,比如 "(|(uid=demo)(mail=demouser))"ldapsearch -p 389 -h 192.168.93.128 -D cn=Manager -w ts -b o=ptc "(|(uid=demo)(mail=demouser))"

修改密码: ldappasswordmodify

  • 语法: ldappasswordmodify <options>
  • 示例: ldappasswordmodify -p 389 -h 192.168.93.128 -D cn=Manager -w ts -a uid=demo,ou=people,cn=AdministrativeLdap,cn=Windchill_11.2,o=ptc -n tsts ,其中:
    • <options>: -p 389 -h 192.168.93.128 -D cn=Manager -w ts -a uid=demo,ou=people,cn=AdministrativeLdap,cn=Windchill_11.2,o=ptc -n tsts
  • 如果修改成功,则会输出: The LDAP password modify operation was successful

列出 backends: list-backends

  • 语法: list-backends <options>,其中:

    • -b, --baseDN {baseDN}
    • -n, --backendID {backendName}
  • 示例:list-backends

    Backend ID     : Base DN
    ---------------:------------------
    adminRoot      : cn=admin data
    ads-truststore : cn=ads-truststore
    backup         : cn=backups
    config         : cn=config
    monitor        : cn=monitor
    schema         : cn=schema
    tasks          : cn=tasks
    userRoot       : o=ptc
    

导出 LDIF 文件: export-ldif

  • 语法: export-ldif <options>
  • 示例:
    • 即刻导出文件: export-ldif --ldifFile /root/config.ldif --backendID config --hostName localhost --port 4444 --bindDN cn=Manager --bindPassword ts --trustAll
    • 定时导出文件,比如,在 2017/03/09 11:25:00 导出文件: export-ldif --ldifFile "/root/20170309112500.ldif" --backendID userRoot --hostName "en2k8-wnc-x24.ptcts.com" --port 4444 --bindDN "cn=Manager" --bindPassword ts --trustAll --start "20170309112500"
    • 定期导出文件,比如,每月的第一天,12:50 分导出文件: *export-ldif --ldifFile "/root/50121.ldif" --backendID userRoot --hostName "en2k8-wnc-x24.ptcts.com" --port 4444 --bindDN "cn=Manager" --bindPassword ts --trustAll --recurringTask "50 12 1 * "

导入 LDIF 文件: import-ldif

  • 语法: import-ldif <options>
  • 示例: import-ldif --ldifFile "/root/export.ldif" --backendID "userRoot" --overwrite --hostName "en2k8-wnc-x24.ptcts.com" --port "4444" --bindDN "cn=Manager" "--bindPassword" ts --trustAll

管理账户: manage-account

  • 显示账户的信息: manage-account -D "cn=manager" -w ts get-all --targetDN "uid=wcadmin,ou=people,cn=AdministrativeLdap,cn=Windchill_11.2,o=ptc"

    Password Policy DN:  cn=Default Password Policy,cn=Password Policies,cn=config
    Account Is Disabled:  false
    Account Expiration Time:
    Seconds Until Account Expiration:
    Password Changed Time:  20190607070745.945Z
    Password Expiration Warned Time:
    Seconds Until Password Expiration:
    Seconds Until Password Expiration Warning:
    Authentication Failure Times:
    Seconds Until Authentication Failure Unlock:
    Remaining Authentication Failure Count:  5
    Last Login Time:
    Seconds Until Idle Account Lockout:
    Password Is Reset:  false
    Seconds Until Password Reset Lockout:
    Grace Login Use Times:
    Remaining Grace Login Count:  0
    Password Changed by Required Time:
    Seconds Until Required Change Time:
    Password History:
    
  • 显示用户状态信息: manage-account -D "cn=manager" -w ts get-account-is-disabled --targetDN "uid=wcadmin,ou=people,cn=AdministrativeLdap,cn=Windchill_11.2,o=ptc"

    Account Is Disabled:  false
    
  • 禁用/启用账户

    • 禁用账户:manage-account -h localhost -p 4444 -D "cn=Manager" -w ts -X set-account-is-disabled --operationValue true --targetDN "uid=kongwusun,ou=people,cn=AdministrativeLdap,cn=Windchill_11.2,o=ptc"
    • 启用账户:manage-account -h localhost -p 4444 -D "cn=Manager" -w ts clear-account-is-disabled --targetDN "uid=kongwushun,ou=people,cn=AdministrativeLdap,cn=Windchill_10.0,o=ptc"

性能

可以快速查看 <install-dir>/logs:

BIND RES conn=5 op=2 msgID=23 result=0 authDN="uid=wcadmin,ou=people,cn=AdministrativeLdap,cn=Windchill_11.2,o=ptc" etime=0

其中,etime 的值默认以毫秒(milliseconds)为单位,表示服务器处理请求的时间。过大的 etime 通常暗示服务器存在性能问题。

如果需要调整 LDAP 的 JVM运行参数,可以编辑 <install-dir>/config/java.properties, 然后使用 dsjavaproperties 命令使设置生效。具体示例可参考这里

其他需要考虑的性能调优因素可以参考官方文档

LDAP 浏览器

LDAP 浏览器可以连接到 LDAP 服务器,让我们可以方便的查看、搜索、编辑 LDAP 内容。JXplorer 就是这样一款免费的开源浏览器。当然,有很多其他的 LDAP 浏览器,大家可以自行下载尝试。

参考文献

  1. https://baike.baidu.com/item/LDAP/2875565?fr=aladdin
  2. https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol
  3. http://www.zytrax.com/books/ldap/
  4. https://backstage.forgerock.com/docs/opendj/3.5/admin-guide/#d67718e231
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容