forked from Deuxfleurs/bottin
282 lines
6.6 KiB
Go
282 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
|
||
|
}
|