概述
LDAP是轻量目录访问协议,英文全称是Lightweight Directory Access Protocol.
其分为客户端和服务端.
在服务端, 对外是一棵树, 每个节点可以附加一些属性, 这些属性有内置的, 也有自定义的.
用LDAP Admin Tool可以连接上(类似于navicat一样可以连接mysql-server) ldap服务端, 树结构及属性一目了然:
(图)
概念
ldap中有一些基本概念需要说一下:
- dc: 域名部分, 折开书写, 以example.com为例子, 书写形式为:
dc=example,dc=com
- ou: 个人理解为分组(树的分支), 可以为多个(树枝上还有小树枝), 如:
ou=Department,ou=RD,ou=devops
表示部门下的研发组下的devops组. - cn: Common Name公共名称
- sn: Surname, 姓
- dn: Distinguished Name, 如
uid=tom,ou=oa,dc=example,dc=com
,一条记录的位置(唯一), 是一棵树中节点的访问路径. - rdn: Relative dn.相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如
uid=tom
- Entry: 实体, 其实就是节点, Entry上可以有多个属性, 属性有内置的, 也可再自定义.
说明
实体(Entry)可以分多级(类似于公司下有部门, 部门下有小组这样的关系)
golang操作ldap示例
package main
import (
"fmt"
"os"
"strings"
"gitlab.example.com/example/common/log"
"github.com/go-ldap/ldap/v3"
)
func ldapConn() (l *ldap.Conn, err error) {
l, err = ldap.Dial("tcp", "192.168.1.2:389")
if err != nil {
panic(err)
}
err = l.Bind("cn=admin,dc=example,dc=com", "example@1234")
if err != nil {
panic(err)
}
return
}
func LdapSearch(searchRequest *ldap.SearchRequest) (sr *ldap.SearchResult, err error) {
l, err := ldapConn()
if err != nil {
log.Error("failed to connect openldap,err:", err)
return
}
defer l.Close()
sr, err = l.Search(searchRequest)
if err != nil && !strings.Contains(err.Error(), ldap.LDAPResultCodeMap[ldap.LDAPResultNoSuchObject]) {
log.Error("failed to search openldap,err:", err)
return
}
return
}
var (
BaseDnGroupCustomer = "cn=Customer,ou=Account,dc=example,dc=com"
)
func searchByUUID(uuid string) (err error) {
searceRequest := &ldap.SearchRequest{
BaseDN: BaseDnGroupCustomer,
Scope: ldap.ScopeWholeSubtree,
DerefAliases: ldap.NeverDerefAliases,
SizeLimit: 0,
TimeLimit: 0,
Attributes: []string{"entryUUID"},
TypesOnly: false,
Filter: fmt.Sprintf(`(entryUUID=%s)`, uuid),
}
r, err := LdapSearch(searceRequest)
if err != nil {
return
}
if len(r.Entries) == 0 {
err = fmt.Errorf("no such user: %s", uuid)
return
}
dn := r.Entries[0].DN
fmt.Println("attrs:")
for _, v := range r.Entries[0].Attributes {
fmt.Println(v.Name, v.Values)
}
fmt.Println("attrs end")
// 只留下"uid=abao-c2,uid=abao"
uidsStr := strings.TrimSuffix(dn, BaseDnGroupCustomer)
if len(uidsStr) == 0 {
err = fmt.Errorf("empty uid got")
return
}
return
}
func main() {
err := searchByUUID("some-uuid")
if err != nil {
panic(err)
}
}
客户端
除了用编程语言操作ldap, 还有一些实用的客户端, 比如我用过的
- LDAP Admin Tool, 这个是收费的, 可以免费试用30天.
参考
(未完待续)