package main import ( "fmt" "strings" "sync" "github.com/go-ldap/ldap/v3" "github.com/sirupsen/logrus" ) //Mux value, this value permits do not have two identicals values in the parallel instances type StoreAllCN struct { mu sync.Mutex cn map[string]struct{} } var allNames = StoreAllCN{cn: make(map[string]struct{})} //Type used for the tests type attributes struct { Name string Data []string } type data_DN struct { DN string Attributes []attributes } type instance struct { numberUsers, numberGroups int dataGroups, dataUsers []data_DN logging *ldap.Conn } //Create a new object instance //With this instance, we can obtain an isolated container where //we have our users and groups. It allows to run tests in parallel. func NewInstance(numberUsers, numberGroups int) (*instance, error) { l, err := Connect() if err != nil { return nil, err } logging.Level = logrus.InfoLevel inst := instance{ numberUsers: numberUsers, numberGroups: numberGroups, dataGroups: []data_DN{}, dataUsers: []data_DN{}, logging: l, } err = inst.createOrganizationnalUnit() if ldap.IsErrorWithCode(err, uint16(68)) { logging.Warn("OrganizationnalUnit already created") err = nil } if err != nil { return nil, err } err = inst.CreateGroups() if err != nil { return nil, err } err = inst.CreateUsers() if err != nil { return nil, err } return &inst, nil } //Part: Created users or groups or OU func (inst *instance) createOrganizationnalUnit() error { dn := []string{"ou=groups,dc=deuxfleurs,dc=fr", "ou=users,dc=deuxfleurs,dc=fr"} attributes := []map[string][]string{{ "description": []string{"OrganizationalUnit qui regroupe tous les groupes"}, "objectclass": []string{"organizationalUnit", "top"}, "ou": []string{"groups"}, "structuralobjectclass": []string{"organizationalUnit"}, }, { "description": []string{"OrganizationalUnit qui regroupe tous les users"}, "objectclass": []string{"organizationalUnit", "top"}, "ou": []string{"users"}, "structuralobjectclass": []string{"organizationalUnit"}, }, } for index := range dn { err := inst.Add_Request(dn[index], attributes[index]) if err != nil { return err } } return nil } //Part: Create User or group func (inst *instance) CreateUsers() (err error) { dn := "cn=%s,ou=users,dc=deuxfleurs,dc=fr" attributes := map[string][]string{ "displayname": {}, "objectclass": {"inetOrgPerson", "organizationalPerson", "person", "top"}, "structuralobjectclass": {"inetOrgPerson"}, } du, err := inst.create(dn, []string{"displayname"}, inst.numberUsers, attributes, inst.dataUsers) if err == nil { inst.dataUsers = du } return err } func (inst *instance) CreateGroups() error { dn := "cn=%s,ou=groups,dc=deuxfleurs,dc=fr" attributes := map[string][]string{ "description": {}, "objectclass": {"groupOfNames", "top"}, "structuralobjectclass": {"groupOfNames"}, } dg, err := inst.create(dn, []string{"description"}, inst.numberGroups, attributes, inst.dataGroups) if err == nil { inst.dataGroups = dg } return err } //Hard Function: She does: //- generate an unique name //- store the Data of each AddRequest in instance struct //- send AddRequest to Bottin func (inst *instance) create(dn string, unique_attr []string, number int, attributes map[string][]string, data []data_DN) ([]data_DN, error) { for i := 0; i < number; i++ { name := inst.GenerateName() datDn := data_DN{DN: fmt.Sprintf(dn, name)} for _, value := range unique_attr { attributes[value] = []string{name} } datDn.Attributes = MapAttToStruct(attributes) data = append(data, datDn) err := inst.Add_Request(fmt.Sprintf(dn, name), attributes) if err != nil { return nil, err } } return data, nil } //Part: clean func (inst *instance) Clean() error { err := inst.CleanGroups() if err != nil { return err } err = inst.CleanUsers() return err } func (inst *instance) CleanUsers() error { err := inst.clean(inst.dataUsers) if err != nil { return err } inst.dataUsers = []data_DN{} return err } func (inst *instance) CleanGroups() error { err := inst.clean(inst.dataGroups) if err != nil { return err } inst.dataGroups = []data_DN{} return err } func (inst *instance) clean(stock []data_DN) error { logging.Debugf("Delete %d elements.", len(stock)) for _, value := range stock { err := inst.Delete_Request(value.DN) if err != nil { return err } } return nil } //Part: Verify if a data_Dn is a group or an user func (inst *instance) VerifyUser(user data_DN) (bool, error) { dn := "ou=users,dc=deuxfleurs,dc=fr" cn := strings.Split(user.DN, ",")[0] filter := fmt.Sprintf("(%s)", cn) res, err := inst.Search_Request(dn, filter, []string{"cn"}) return len(res.Entries) == 1, err } func (inst *instance) VerifyGroup(group data_DN) (bool, error) { dn := "ou=groups,dc=deuxfleurs,dc=fr" cn := strings.Split(group.DN, ",")[0] filter := fmt.Sprintf("(%s)", cn) res, err := inst.Search_Request(dn, filter, []string{"cn"}) return len(res.Entries) == 1, err } //Part: Add user in a group func (inst *instance) AddUserInGroup(user, group data_DN) error { err := inst.Modify_Request(group.DN, nil, nil, map[string][]string{ "member": {user.DN}, }) return err } func (inst *instance) AddUserSliceInGroup(users_cn []string, group_dn string) error { err := inst.Modify_Request(group_dn, nil, nil, map[string][]string{ "member": users_cn, }) return err } //Part: modify, add, delete data_DN struct func AddAtt(name string, data []string, dat data_DN) data_DN { dat.Attributes = append(dat.Attributes, attributes{ Name: name, Data: data, }) logging.Debug(fmt.Sprintf("Attributes %s add from %s.", name, dat.DN)) return dat } func DelAtt(name string, dat data_DN) data_DN { for index, value := range dat.Attributes { if value.Name == name { dat.Attributes[index] = dat.Attributes[len(dat.Attributes)-1] //tmp := dat.Attributes[:len(dat.Attributes)-1] dat.Attributes = []attributes{} logging.Debugf("Attributes %s delete from %s.", name, dat.DN) return dat } } logging.Debugf("Can't delete attribute %s from %s.", name, dat.DN) return dat } func ReplaceAtt(name string, data []string, dat data_DN) data_DN { for index, value := range dat.Attributes { if value.Name == name { dat.Attributes[index] = attributes{ Name: name, Data: data, } logging.Debugf("Replace attributes %s from %s succesful..", name, dat.DN) return dat } } logging.Debugf("Can't replace attributes %s from %s.", name, dat.DN) return dat }