forked from Deuxfleurs/bottin
9a8c19ec0f
V2 the test end-to-end, Tests made similar to V1.0, Add the possibility to pararellize the tests, Create an environnement for easy integration of news test,
281 lines
6.6 KiB
Go
281 lines
6.6 KiB
Go
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
|
|
}
|