Create and delete groups

merge-requests/6/head
meskio 5 years ago
parent 6ce99fa65e
commit dec4f29f41
Signed by: meskio
GPG Key ID: 52B8F5AC97A2DA86
  1. 19
      examples/data.ldif
  2. 2
      examples/lowry.conf
  3. 61
      ldap/group.go
  4. 24
      ldap/group_test.go
  5. 2
      ldap/ldap.go
  6. 4
      main.go

@ -1,16 +1,6 @@
dn: cn=nss,dc=nodomain
objectClass: organizationalRole
objectClass: simpleSecurityObject
cn: nss
description: The `nss' user is used for user lookups avoiding anonymous binds
userPassword: {SSHA}FHqod3gytvH9MDGhpMV1DKjyU7eO1EDG
structuralObjectClass: organizationalRole
dn: ou=People,dc=nodomain
objectClass: organizationalUnit
ou: People
structuralObjectClass: organizationalUnit
entryUUID: 769a5134-d439-1029-9cfe-a18622f82764
dn: uid=user,ou=People,dc=nodomain
uid: user
@ -21,8 +11,7 @@ userPassword: {SSHA}FHqod3gytvH9MDGhpMV1DKjyU7eO1EDG
loginShell: /bin/bash
uidNumber: 1000
gidNumber: 1000
homeDirectory: /home/sindominio/user
gecos: User,,,,Madrid
homeDirectory: /home/user
dn: uid=superuser,ou=People,dc=nodomain
uid: superuser
@ -33,21 +22,18 @@ userPassword: {SSHA}FHqod3gytvH9MDGhpMV1DKjyU7eO1EDG
loginShell: /bin/bash
uidNumber: 1001
gidNumber: 1001
homeDirectory: /home/sindominio/superuser
gecos: SuperUser,,,,Calanda
homeDirectory: /home/superuser
dn: ou=Group,dc=nodomain
objectClass: top
objectClass: organizationalUnit
ou: Group
structuralObjectClass: organizationalUnit
dn: cn=adm,ou=Group,dc=nodomain
objectClass: top
objectClass: posixGroup
cn: adm
gidNumber: 1
structuralObjectClass: posixGroup
memberUid: superuser
dn: cn=user,ou=Group,dc=nodomain
@ -55,4 +41,3 @@ objectClass: top
objectClass: posixGroup
cn: user
gidNumber: 1000
structuralObjectClass: posixGroup

@ -1,4 +1,4 @@
ldapaddr=localhost:389
ldapdc=dc=nodomain
nsspass=foobar
ldappass=foobar
httpaddr=:8080

@ -3,6 +3,7 @@ package ldap
import (
"errors"
"fmt"
"strconv"
"github.com/go-ldap/ldap"
)
@ -10,6 +11,7 @@ import (
// Group has the ldap data of the group
type Group struct {
Name string
GID int
Members []string
}
@ -58,6 +60,61 @@ func (l Ldap) UserGroups(user string) ([]Group, error) {
return l.searchGroup(filter)
}
// CreateGroup adds the group to ldap
func (l Ldap) CreateGroup(name string) error {
if _, err := l.GetGroup(name); err == nil {
return errors.New("Group '" + name + "' already exist, can't create it")
}
gid, err := l.getLastGid()
if err != nil {
return err
}
gid++
conn, err := l.connect()
if err != nil {
return err
}
defer conn.Close()
groupStr := ldap.EscapeFilter(name)
dn := fmt.Sprintf("cn=%s,ou=group,%s", groupStr, l.DC)
addRequest := ldap.NewAddRequest(dn)
addRequest.Attribute("cn", []string{groupStr})
addRequest.Attribute("objectClass", []string{"top", "posixGroup"})
addRequest.Attribute("gidNumber", []string{strconv.Itoa(gid)})
return conn.Add(addRequest)
}
// DeleteGroup removes the group in ldap
func (l Ldap) DeleteGroup(name string) error {
conn, err := l.connect()
if err != nil {
return err
}
defer conn.Close()
dn := fmt.Sprintf("cn=%s,ou=group,%s", ldap.EscapeFilter(name), l.DC)
delRequest := ldap.NewDelRequest(dn, nil)
return conn.Del(delRequest)
}
func (l Ldap) getLastGid() (int, error) {
filter := "(&(objectClass=posixGroup))"
groups, err := l.searchGroup(filter)
if err != nil {
return 0, err
}
gid := 1000
for _, group := range groups {
if group.GID > gid {
gid = group.GID
}
}
return gid, err
}
func (l Ldap) searchGroup(filter string) ([]Group, error) {
conn, err := l.connect()
if err != nil {
@ -69,7 +126,7 @@ func (l Ldap) searchGroup(filter string) ([]Group, error) {
"ou=group,"+l.DC,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
filter,
[]string{"cn", "memberUid"},
[]string{"cn", "memberUid", "gid"},
nil,
)
sr, err := conn.Search(searchRequest)
@ -84,8 +141,10 @@ func (l Ldap) searchGroup(filter string) ([]Group, error) {
}
func newGroup(entry *ldap.Entry) Group {
gid, _ := strconv.Atoi(entry.GetAttributeValue("gidNumber"))
return Group{
Name: entry.GetAttributeValue("cn"),
Members: entry.GetAttributeValues("memberUid"),
GID: gid,
}
}

@ -74,3 +74,27 @@ func TestUserGroups(t *testing.T) {
t.Errorf("superuser not in adm: %v", groups)
}
}
func TestCreateDeleteGroups(t *testing.T) {
const name = "test"
l := testLdap()
_, err := l.GetGroup(name)
if err == nil {
t.Errorf("group %s allready exist", name)
}
err = l.CreateGroup(name)
if err != nil {
t.Fatalf("CreateGroup(\"%s\") failed: %v", name, err)
}
_, err = l.GetGroup(name)
if err != nil {
t.Errorf("GetGroup(\"%s\") failed: %v", name, err)
}
err = l.DeleteGroup(name)
if err != nil {
t.Errorf("DeleteGroup(\"%s\") failed: %v", name, err)
}
}

@ -27,6 +27,6 @@ func (l Ldap) connect() (*ldap.Conn, error) {
if err != nil {
return nil, err
}
err = conn.Bind("cn=nss,"+l.DC, l.Pass)
err = conn.Bind("cn=admin,"+l.DC, l.Pass)
return conn, err
}

@ -12,7 +12,7 @@ func main() {
var (
ldapaddr = flag.String("ldapaddr", "localhost:389", "LDAP server address and port")
ldapdc = flag.String("ldapdc", "", "LDAP domain components")
nsspass = flag.String("nsspass", "", "Password of the LDAP `nss' user")
ldappass = flag.String("ldappass", "", "Password of the LDAP `admin' user")
httpaddr = flag.String("httpaddr", ":8080", "Web server address and port")
ro = flag.Bool("ro", false, "Read-Only mode")
)
@ -22,7 +22,7 @@ func main() {
l := ldap.Ldap{
Addr: *ldapaddr,
DC: *ldapdc,
Pass: *nsspass,
Pass: *ldappass,
RO: *ro,
}
err := l.Test()

Loading…
Cancel
Save