ldap操作AD-OU,Group,User CRUD

DarinHan · · 1661 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

``` // FileName: ldap.go // Author : Darin Han // Copyright 2020 Darin. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ad // package for ad operation by ldap import ( "errors" "fmt" "gopkg.in/ldap.v2" "log" ) type UserClaims struct { UserName string PassWord string } type LDAPClient struct { Host string Port int BaseDN string UserClaims Connection *ldap.Conn } //Const Name for LDAP Elements const ObjectCategory_OU string = "organizationalUnit" const ObjectCategory_Group string = "group" const ObjectCategory_Person string = "user" // open connection for ldap, Close() should be called intermediatly with defer func (client *LDAPClient) Open() (*ldap.Conn, error) { if client.UserName == "" || client.PassWord == "" { return nil, errors.New("no user account and password !") } con, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", client.Host, client.Port)) if err != nil { return nil, err } err = con.Bind(client.UserName, client.PassWord) if err != nil { return nil, err } client.Connection = con return con, nil } // close connection for ldap func (client *LDAPClient) Close() { client.Connection.Close() client.Connection = nil } // try to connect ldap server, return error for fail. func (client *LDAPClient) Connect() (bool, error) { l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", client.Host, client.Port)) if err != nil { return false, err } defer l.Close() err = l.Bind(client.UserName, client.PassWord) if err != nil { log.Fatal(err) } return true, nil } /* OU attributes: description:描述 c:国家简称 co:国家 l:市县 st:省 street:街道 postalCode:邮编 */ //search ou in the whole tree by dn,return ldap.SearchResult which contains entries , controls func (client *LDAPClient) SearchOU(search string) (*ldap.SearchResult, error) { conn, err := client.Open() if err != nil { return nil, err } defer client.Close() return conn.Search(ldap.NewSearchRequest(client.BaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, fmt.Sprintf("(&(objectCategory=%s)(%s))", ObjectCategory_OU, search), // The filter to apply []string{}, // A list attributes to retrieve nil)) } // get ou by specified ouname in specified path func (client *LDAPClient) GetOU(parents []string, subname string) (entry *ldap.Entry, err error) { conn, err := client.Open() if err != nil { return nil, err } defer client.Close() basedn := client.getdn(parents, "") search := fmt.Sprintf("OU=%s", subname) result, err := conn.Search(ldap.NewSearchRequest(basedn, ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false, fmt.Sprintf("(&(objectCategory=%s)(%s))", ObjectCategory_OU, search), // The filter to apply []string{}, // A list attributes to retrieve nil, )) if err != nil { return nil, err } if result.Entries != nil && len(result.Entries) > 0 { return result.Entries[0], nil } return nil, nil } // create ou in specified path with specified attributes func (client *LDAPClient) CreateOU(parents []string, ou string, attributes map[string][]string) (err error) { conn, err := client.Open() if err != nil { return err } defer client.Close() dn := client.getdn(parents, fmt.Sprintf("OU=%s", ou)) request := ldap.NewAddRequest(dn) request.Attribute("ou", []string{ou}) request.Attribute("objectClass", []string{"top", ObjectCategory_OU}) if attributes != nil { for key, val := range attributes { request.Attribute(key, val) } } if attributes != nil { for key, val := range attributes { request.Attribute(key, val) } } return conn.Add(request) } // construct dn func (client *LDAPClient) getdn(parents []string, cn string) string { dn := client.BaseDN if len(parents) > 0 { for _, pou := range parents { dn = fmt.Sprintf("OU=%s,%s", pou, dn) } } if cn != "" { dn = fmt.Sprintf("%s,%s", cn, dn) } return dn } func (client *LDAPClient) UpdateOU(parents []string, ou string, attributes map[string][]string) (err error) { entry, err := client.GetOU(parents, ou) if err != nil { return err } if entry == nil { return errors.New(fmt.Sprintf("no entry find for %s shall not be empty!", client.getdn(parents, ou))) } conn, err := client.Open() if err != nil { return err } defer client.Close() dn := client.getdn(parents, fmt.Sprintf("OU=%s", ou)) mq := ldap.NewModifyRequest(dn) if attributes != nil { for key, val := range attributes { exists := false for _, att := range mq.AddAttributes { if att.Type == key { mq.Replace(att.Type, val) exists = true break } } if !exists { mq.Add(key, val) } } } return conn.Modify(mq) } func (client *LDAPClient) DelOU(parents []string, ou string) (err error) { entry, err := client.GetOU(parents, ou) if err != nil { return err } if entry == nil { return errors.New(fmt.Sprintf("no entry find for %s shall not be empty!", client.getdn(parents, fmt.Sprintf("OU=%s", ou)))) } conn, err := client.Open() if err != nil { return err } defer client.Close() request := ldap.NewDelRequest(client.getdn(parents, fmt.Sprintf("OU=%s", ou)), nil) return conn.Del(request) } func (client *LDAPClient) SearchGroup(search string) (*ldap.SearchResult, error) { conn, err := client.Open() if err != nil { return nil, err } defer client.Close() return conn.Search(ldap.NewSearchRequest(client.BaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, fmt.Sprintf("(&(objectCategory=%s)(%s))", ObjectCategory_Group, search), // The filter to apply []string{}, // A list attributes to retrieve nil)) } func (client *LDAPClient) GetGroup(parents []string, group string) (entry *ldap.Entry, err error) { conn, err := client.Open() if err != nil { return nil, err } defer client.Close() basedn := client.getdn(parents, "") search := fmt.Sprintf("CN=%s", group) result, err := conn.Search(ldap.NewSearchRequest(basedn, ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false, fmt.Sprintf("(&(objectCategory=%s)(%s))", ObjectCategory_Group, search), // The filter to apply []string{}, // A list attributes to retrieve nil, )) if err != nil { return nil, err } if result.Entries != nil && len(result.Entries) > 0 { return result.Entries[0], nil } return nil, nil } func (client *LDAPClient) CreateGroup(parents []string, group string, attributes map[string][]string) error { conn, err := client.Open() if err != nil { return err } defer client.Close() dn := client.getdn(parents, "") dn = fmt.Sprintf("cn=%s,%s", group, dn) request := ldap.NewAddRequest(dn) request.Attribute("CN", []string{group}) request.Attribute("objectClass", []string{"top", ObjectCategory_Group}) if attributes != nil { for key, val := range attributes { request.Attribute(key, val) } } if attributes != nil { for key, val := range attributes { request.Attribute(key, val) } } return conn.Add(request) } func (client *LDAPClient) UpdateGroup(parents []string, group string, attributes map[string][]string) (err error) { entry, err := client.GetGroup(parents, group) if err != nil { return err } if entry == nil { return errors.New(fmt.Sprintf("no entry find for %s shall not be empty!", client.getdn(parents, fmt.Sprintf("cn=%s", group)))) } conn, err := client.Open() if err != nil { return err } defer client.Close() dn := client.getdn(parents, "") dn = fmt.Sprintf("cn=%s,%s", group, dn) mq := ldap.NewModifyRequest(dn) if attributes != nil { for key, val := range attributes { exists := false for _, att := range mq.AddAttributes { if att.Type == key { mq.Replace(att.Type, val) exists = true break } } if !exists { mq.Add(key, val) } } } return conn.Modify(mq) } func (client *LDAPClient) DelGroup(parents []string, group string) error { entry, err := client.GetGroup(parents, group) if err != nil { return err } if entry == nil { return errors.New(fmt.Sprintf("no entry find for %s !", client.getdn(parents, fmt.Sprintf("CN=%s", group)))) } conn, err := client.Open() if err != nil { return err } defer client.Close() request := ldap.NewDelRequest(client.getdn(parents, fmt.Sprintf("cn=%s", group)), nil) return conn.Del(request) } /* User Attributes: sn: givenname: Mail: userPrincipalName: SAMAccountName: displayname: */ func (client *LDAPClient) SearchUser(search string) (*ldap.SearchResult, error) { conn, err := client.Open() if err != nil { return nil, err } defer client.Close() return conn.Search(ldap.NewSearchRequest(client.BaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, fmt.Sprintf("(&(objectCategory=%s)(%s))", ObjectCategory_Person, search), // The filter to apply []string{}, // A list attributes to retrieve nil)) } func (client *LDAPClient) GetUser(parents []string, user string) (entry *ldap.Entry, err error) { conn, err := client.Open() if err != nil { return nil, err } defer client.Close() basedn := client.getdn(parents, "") search := fmt.Sprintf("CN=%s", user) result, err := conn.Search(ldap.NewSearchRequest(basedn, ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false, fmt.Sprintf("(&(objectCategory=%s)(%s))", ObjectCategory_Person, search), // The filter to apply []string{}, // A list attributes to retrieve nil, )) if err != nil { return nil, err } if result.Entries != nil && len(result.Entries) > 0 { return result.Entries[0], nil } return nil, nil } func (client *LDAPClient) CreateUser(parents []string, user string, attributes map[string][]string) error { conn, err := client.Open() if err != nil { return err } defer client.Close() dn := client.getdn(parents, "") dn = fmt.Sprintf("cn=%s,%s", user, dn) log.Println(dn) request := ldap.NewAddRequest(dn) request.Attribute("CN", []string{user}) request.Attribute("objectClass", []string{"top", "person", ObjectCategory_Person, "organizationalPerson"}) if attributes != nil { for key, val := range attributes { request.Attribute(key, val) } } if attributes != nil { for key, val := range attributes { request.Attribute(key, val) } } return conn.Add(request) } ``` ``` // FileName: ldap_test.go // Author : Darin Han // Copyright 2020 Darin. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ad import "testing" func getldapclient() LDAPClient { return LDAPClient{ Host: "adhostnamel", Port: 389, BaseDN: "DC=*,DC=*", UserClaims: UserClaims{ UserName: "domain\\admin", PassWord: "password", }, } } func TestLDAPClient_GetOU(t *testing.T) { tests := []struct { parents []string input string result bool }{ {[]string{}, "集团", false}, } client := getldapclient() for index, test := range tests { entry, err := client.GetOU(test.parents, test.input) if err != nil { t.Fatal(err, index, test.parents, test.input) } t.Log(entry.DN) for _, att := range entry.Attributes { t.Log(att.Name, att.Values) } } } func TestLDAPClient_CreateOU(t *testing.T) { tests := []struct { parents []string input string result bool }{ {[]string{}, "集团2", false}, } client := getldapclient() for _, test := range tests { err := client.CreateOU(test.parents, test.input, nil) if err != nil { t.Fatal(err) } } } func TestLDAPClient_UpdateOU(t *testing.T) { tests := []struct { parents []string input string attributes map[string][]string result bool }{ {[]string{}, "集团2", make(map[string][]string), false}, } client := getldapclient() atts := make(map[string][]string) atts["description"] = []string{"testdesc"} for _, test := range tests { err := client.UpdateOU(test.parents, test.input, atts) if err != nil { t.Fatal(err) } } } func TestLDAPClient_DelOU(t *testing.T) { tests := []struct { parents []string input string result bool }{ {[]string{}, "集团2", false}, } client := getldapclient() for _, test := range tests { err := client.DelOU(test.parents, test.input) if err != nil { t.Fatal(err) } } } func TestLDAPClient_SearchGroup(t *testing.T) { tests := []struct { input string result bool }{ {"cn=testgroup", false}, } client := getldapclient() for index, test := range tests { searchresult, err := client.SearchGroup(test.input) if err != nil { t.Fatal(err, index, test.input) } t.Log(index, searchresult.Entries[0]) } } func TestLDAPClient_CreateGroup(t *testing.T) { tests := []struct { parents []string input string result bool }{ {[]string{}, "testgroup", false}, {[]string{"集团"}, "testgroup", false}, } client := getldapclient() for _, test := range tests { err := client.CreateGroup(test.parents, test.input, nil) if err != nil { t.Fatal(err) } } } func TestLDAPClient_GetGroup(t *testing.T) { tests := []struct { parents []string input string result bool }{ {[]string{}, "testgroup", false}, } client := getldapclient() for _, test := range tests { err := client.DelGroup(test.parents, test.input) if err != nil { t.Fatal(err) } } } func TestLDAPClient_DelGroup(t *testing.T) { tests := []struct { parents []string input string result bool }{ {[]string{}, "testgroup", false}, {[]string{}, "testgroup2", false}, {[]string{"集团"}, "testgroup", false}, } client := getldapclient() for _, test := range tests { err := client.DelGroup(test.parents, test.input) if err != nil { t.Fatal(err) } } } func TestLDAPClient_SearchUser(t *testing.T) { tests := []struct { input string result bool }{ {"cn=userid", false}, } client := getldapclient() for index, test := range tests { searchresult, err := client.SearchUser(test.input) if err != nil { t.Fatal(err, index, test.input) } for ii, entry := range searchresult.Entries { t.Log(ii, "dn:", entry.DN) for _, att := range entry.Attributes { t.Log(att.Name, att.Values) } } } } func TestLDAPClient_CreateUser(t *testing.T) { tests := []struct { parents []string input string atts map[string][]string result bool }{ {[]string{"集团"}, "testuser", nil, false}, } client := getldapclient() for _, test := range tests { err := client.CreateUser(test.parents, test.input, test.atts) if err != nil { panic(err) } } } ```

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1661 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传