ldappool

package module
v1.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 30, 2022 License: MIT Imports: 6 Imported by: 2

README

github.com/randolphcyg/ldappool

Based on ldapV3 ldap connection pool, it is convenient to quickly obtain ldap connection objects.

1. install

go get github.com/randolphcyg/ldappool

2. Usage

This case is to initialize the ldap connection pool, query all users and store the dn attribute in the file.

package main

import (
	"bufio"
	"crypto/tls"
	"flag"
	"fmt"
	"github.com/randolphcyg/ldappool"
	"github.com/go-ldap/ldap/v3"
	"os"
	"time"
)

var (
	LdapConns LdapConn
	LdapPool  ldappool.Pool
	attrs = []string{
		"employeeNumber",     // 工号
		"sAMAccountName",     // SAM账号
		"distinguishedName",  // dn
		"userAccountControl", // 用户账户控制
		"accountExpires",     // 账户过期时间
		"pwdLastSet",         // 用户下次登录必须修改密码
		"whenCreated",        // 创建时间
		"whenChanged",        // 修改时间
		"displayName",        // 显示名
		"sn",                 // 姓
		"name",
		"givenName",  // 名
		"mail",       // 邮箱
		"mobile",     // 手机号
		"company",    // 公司
		"department", // 部门
		"title",      // 职务
	}
)


// LdapConn LDAP服务器连接配置
type LdapConn struct {
	// 连接地址
	ConnUrl string `json:"conn_url" gorm:"type:varchar(255);unique_index;not null;comment:连接地址 逻辑外键"`
	// SSL加密方式
	SslEncryption bool `json:"ssl_encryption" gorm:"type:tinyint;length:1;comment:SSL加密方式"`
	// 超时设置
	Timeout time.Duration `json:"timeout" gorm:"type:int;comment:超时设置"`
	// 根目录
	BaseDn string `json:"base_dn" gorm:"type:varchar(255);not null;comment:根目录"`
	// 用户名
	AdminAccount string `json:"admin_account" gorm:"type:varchar(255);not null;comment:用户名"`
	// 密码
	Password string `json:"password" gorm:"type:varchar(255);not null;comment:密码"`
}

type LdapAttributes struct {
	// ldap字段
	Num         string `json:"employeeNumber" gorm:"type:varchar(100);unique_index"`     // 工号
	Sam         string `json:"sAMAccountName" gorm:"type:varchar(128);unique_index"`     // SAM账号
	Dn          string `json:"distinguishedName" gorm:"type:varchar(100);unique_index"`  // dn
	AccountCtl  string `json:"UserAccountControl" gorm:"type:varchar(100);unique_index"` // 用户账户控制
	Expire      string `json:"accountExpires" gorm:"type:varchar(100);unique_index"`     //  账户过期时间
	PwdLastSet  string `json:"pwdLastSet" gorm:"type:varchar(100);unique_index"`         //  用户下次登录必须修改密码
	WhenCreated string `json:"whenCreated" gorm:"type:varchar(100);unique_index"`        //  创建时间
	WhenChanged string `json:"whenChanged" gorm:"type:varchar(100);unique_index"`        //  修改时间
	DisplayName string `json:"displayName" gorm:"type:varchar(32);unique_index"`         //  真实姓名
	Sn          string `json:"sn" gorm:"type:varchar(100);unique_index"`                 //  姓
	Name        string `json:"name" gorm:"type:varchar(100);unique_index"`               // 姓名
	GivenName   string `json:"givenName" gorm:"type:varchar(100);unique_index"`          // 名
	Email       string `json:"mail" gorm:"type:varchar(128);unique_index"`               // 邮箱
	Phone       string `json:"mobile" gorm:"type:varchar(32);unique_index"`              // 移动电话
	Company     string `json:"company" gorm:"type:varchar(128);unique_index"`            // 公司
	Depart      string `json:"department" gorm:"type:varchar(128);unique_index"`         // 部门
	Title       string `json:"title" gorm:"type:varchar(100);unique_index"`              // 职务
}

// Init 初始化ldap连接池
func Init(c *LdapConn) (err error) {
	LdapConns = LdapConn{
		ConnUrl:       c.ConnUrl,
		SslEncryption: c.SslEncryption,
		Timeout:       c.Timeout,
		BaseDn:        c.BaseDn,
		AdminAccount:  c.AdminAccount,
		Password:      c.Password,
	}
	// 初始化ldap连接池 初始连接数是50
	LdapPool, err = ldappool.NewChannelPool(50, 1000, "originalLdapPool",
		func(s string) (ldap.Client, error) {
			conn, err := ldap.DialURL(LdapConns.ConnUrl)
			if err != nil {
				fmt.Print("Fail to dial ldap url, err: ", err)
			}

			// 重新连接TLS
			if err = conn.StartTLS(&tls.Config{InsecureSkipVerify: true}); err != nil {
				fmt.Print("Fail to start tls, err: ", err)
			}

			// 与只读用户绑定
			if err = conn.Bind(LdapConns.AdminAccount, LdapConns.Password); err != nil {
				fmt.Print("admin user auth failed, err: ", err)
			}
			return conn, nil
		}, []uint16{ldap.LDAPResultTimeLimitExceeded, ldap.ErrorNetwork})
	if err != nil {
		fmt.Print(err)
		return
	}
	return
}

func NewLdapConnContext() *LdapConn {
	return &LdapConn{}
}

func FetchLdapUsers(user *LdapAttributes) (result []*ldap.Entry) {
	// 获取连接
	LdapConn, err := LdapPool.Get()
	if err != nil {
		fmt.Printf(err.Error())
	}

	// 多查询条件
	ldapFilterNum := "(employeeNumber=" + user.Num + ")"
	ldapFilterSam := "(sAMAccountName=" + user.Sam + ")"
	ldapFilterEmail := "(mail=" + user.Email + ")"
	ldapFilterPhone := "(mobile=" + user.Phone + ")"
	ldapFilterName := "(displayName=" + user.DisplayName + ")"
	ldapFilterDepart := "(department=" + user.Depart + ")"
	ldapFilterCompany := "(company=" + user.Company + ")"
	ldapFilterTitle := "(title=" + user.Title + ")"

	searchFilter := "(&(objectClass=user)(mail=*))" // 有邮箱的用户 排除系统级别用户

	if user.Num != "" {
		searchFilter += ldapFilterNum
	}
	if user.Sam != "" {
		searchFilter += ldapFilterSam
	}
	if user.Email != "" {
		searchFilter += ldapFilterEmail
	}
	if user.Phone != "" {
		searchFilter += ldapFilterPhone
	}
	if user.DisplayName != "" {
		searchFilter += ldapFilterName
	}
	if user.Depart != "" {
		searchFilter += ldapFilterDepart
	}
	if user.Company != "" {
		searchFilter += ldapFilterCompany
	}
	if user.Title != "" {
		searchFilter += ldapFilterTitle
	}
	searchFilter = "(&" + searchFilter + ")"

	searchRequest := ldap.NewSearchRequest(
		LdapConns.BaseDn,
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 500, 0, false,
		searchFilter,
		attrs,
		nil,
	)

	sr, err := LdapConn.SearchWithPaging(searchRequest, 100)
	if err != nil {
		fmt.Printf("Fail to search users, err: " + err.Error())
	}
	if len(sr.Entries) > 0 && len(sr.Entries[0].Attributes) > 0 {
		result = sr.Entries
	}
	return
}

func main() {
	ldapConnContext := NewLdapConnContext()
	flag.StringVar(&ldapConnContext.ConnUrl, "connUrl", "ldap://192.168.x.x:389", "ad域连接地址")
	flag.StringVar(&ldapConnContext.BaseDn, "baseDn", "OU=组织名称,DC=XXX,DC=com", "基础dn")
	flag.StringVar(&ldapConnContext.AdminAccount, "adminAccount", "CN=Admin用户名,CN=Users,DC=XXX,DC=com", "管理员用户")
	flag.StringVar(&ldapConnContext.Password, "password", "Admin用户密码", "管理员用户密码")
	flag.BoolVar(&ldapConnContext.SslEncryption, "sslEncryption", false, "是否ssl")
	flag.CommandLine.SetOutput(os.Stdout)
	flag.Parse()

	err := Init(ldapConnContext)
	if err != nil {
		fmt.Printf(err.Error())
	}

	filePath := "./allUserDns.txt"
	file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println("文件打开失败", err)
	}
	// 及时关闭file句柄
	defer file.Close()
	// 写入文件时,使用带缓存的 *Writer
	write := bufio.NewWriter(file)

	users := FetchLdapUsers(&LdapAttributes{})
	for idx, user := range users {
		fmt.Println(idx+1, user.DN)
		//break
		write.WriteString(user.DN + "\n")
		break
	}

	//Flush将缓存的文件真正写入到文件中
	write.Flush()

}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrClosed is the error resulting if the pool is closed via pool.Close().
	ErrClosed = errors.New("pool is closed")
)

Functions

This section is empty.

Types

type Pool

type Pool interface {
	// Get returns a new connection from the pool. Closing the connections puts
	// it back to the Pool. Closing it when the pool is destroyed or full will
	// be counted as an error.
	Get() (*PoolConn, error)

	// Close closes the pool and all its connections. After Close() the pool is
	// no longer usable.
	Close()

	// Len returns the current number of connections of the pool.
	Len() int
}

Pool interface describes a pool implementation. A pool should have maximum capacity. An ideal pool is threadsafe and easy to use.

func NewChannelPool

func NewChannelPool(initialCap, maxCap int, name string, factory PoolFactory, closeAt []uint16) (Pool, error)

NewChannelPool returns a new pool based on buffered channels with an initial capacity and maximum capacity. Factory is used when initial capacity is greater than zero to fill the pool. A zero initialCap doesn't fill the Pool until a new Get() is called. During a Get(), If there is no new connection available in the pool, a new connection will be created via the Factory() method.

closeAt will automagically mark the connection as unusable if the return code of the call is one of those passed, most likely you want to set this to something like []uint16{ldap.LDAPResultTimeLimitExceeded, ldap.ErrorNetwork}

type PoolConn

type PoolConn struct {
	Conn ldap.Client
	// contains filtered or unexported fields
}

PoolConn implements Client to override the Close() method

func (*PoolConn) Add

func (p *PoolConn) Add(addRequest *ldap.AddRequest) error

func (*PoolConn) Bind

func (p *PoolConn) Bind(username, password string) error

func (*PoolConn) Close

func (p *PoolConn) Close()

Close() puts the given connects back to the pool instead of closing it.

func (*PoolConn) Compare

func (p *PoolConn) Compare(dn, attribute, value string) (bool, error)

func (*PoolConn) Del

func (p *PoolConn) Del(delRequest *ldap.DelRequest) error

func (*PoolConn) MarkUnusable

func (p *PoolConn) MarkUnusable()

MarkUnusable() marks the connection not usable any more, to let the pool close it instead of returning it to pool.

func (*PoolConn) Modify

func (p *PoolConn) Modify(modifyRequest *ldap.ModifyRequest) error

func (*PoolConn) PasswordModify

func (p *PoolConn) PasswordModify(passwordModifyRequest *ldap.PasswordModifyRequest) (*ldap.PasswordModifyResult, error)

func (*PoolConn) Search

func (p *PoolConn) Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error)

func (*PoolConn) SearchWithPaging

func (p *PoolConn) SearchWithPaging(searchRequest *ldap.SearchRequest, pagingSize uint32) (*ldap.SearchResult, error)

func (*PoolConn) SetTimeout

func (p *PoolConn) SetTimeout(t time.Duration)

func (*PoolConn) SimpleBind

func (p *PoolConn) SimpleBind(simpleBindRequest *ldap.SimpleBindRequest) (*ldap.SimpleBindResult, error)

func (*PoolConn) Start

func (p *PoolConn) Start()

func (*PoolConn) StartTLS

func (p *PoolConn) StartTLS(config *tls.Config) error

type PoolFactory

type PoolFactory func(string) (ldap.Client, error)

PoolFactory is a function to create new connections.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL