Refactor memberOf management logic

This commit is contained in:
Alex 2020-02-13 14:14:27 +01:00
parent 6f893138a3
commit 49be2069f6
3 changed files with 83 additions and 95 deletions

View file

@ -1,5 +1,5 @@
BIN=bottin BIN=bottin
SRC=main.go ssha.go util.go acl.go read.go write.go SRC=main.go ssha.go util.go acl.go read.go write.go memberof.go
DOCKER=lxpz/bottin_amd64 DOCKER=lxpz/bottin_amd64
all: $(BIN) all: $(BIN)

60
memberof.go Normal file
View file

@ -0,0 +1,60 @@
package main
func (server *Server) memberOfAdd(member string, group string) {
// Retreive previous memberOf value
memberGroups, err := server.getAttribute(member, ATTR_MEMBEROF)
if err != nil {
server.logger.Warnf("Could not add %s to memberOf of %s: %s", group, member, err)
return
}
// Return early if group is already in memberOf
for _, mb := range memberGroups {
if mb == group {
server.logger.Warnf("Inconsistency detected, %s was memberOf %s at a time when it didn't exist! (not an issue anymore)",
member, group)
return
}
}
// Add group to memberOf
memberGroups = append(memberGroups, group)
err = server.addElements(member, Entry{
ATTR_MEMBEROF: memberGroups,
})
if err != nil {
server.logger.Warnf("Could not add %s to memberOf of %s: %s", group, member, err)
}
}
func (server *Server) memberOfRemove(member string, group string) {
// Retreive previous memberOf value
memberOf, err := server.getAttribute(member, ATTR_MEMBEROF)
if err != nil || memberOf == nil {
server.logger.Warnf("Could not remove %s from memberOf of %s: %s", group, member, err)
return
}
// Filter out group
newMemberOf := []string{}
for _, mb := range memberOf {
if mb != group {
newMemberOf = append(newMemberOf, group)
}
}
// Return early if group already not in memberOf
if len(newMemberOf) == len(memberOf) {
server.logger.Warnf("Inconsistency detected, %s was not memberOf %s at a time when it should have been! (not an issue anymore)",
member, group)
return
}
// Update value of memberOf
err = server.addElements(member, Entry{
ATTR_MEMBEROF: newMemberOf,
})
if err != nil {
server.logger.Warnf("Could not remove %s from memberOf of %s: %s", group, member, err)
}
}

116
write.go
View file

@ -58,8 +58,10 @@ func (server *Server) handleAddInternal(state *State, r *message.AddRequest) (in
return ldap.LDAPResultEntryAlreadyExists, nil return ldap.LDAPResultEntryAlreadyExists, nil
} }
// TODO: check that parent object exists
// If adding a group, track of who the members will be so that their memberOf field can be updated later // If adding a group, track of who the members will be so that their memberOf field can be updated later
var members []string = nil members := []string{}
// Check attributes // Check attributes
entry := Entry{} entry := Entry{}
@ -77,8 +79,7 @@ func (server *Server) handleAddInternal(state *State, r *message.AddRequest) (in
} }
// If they are writing a member key, we have to check they are adding valid members // If they are writing a member key, we have to check they are adding valid members
if strings.EqualFold(key, ATTR_MEMBER) { if strings.EqualFold(key, ATTR_MEMBER) {
members = vals_str for _, member := range vals_str {
for _, member := range members {
member_canonical, err := server.checkDN(member, false) member_canonical, err := server.checkDN(member, false)
if err != nil { if err != nil {
return ldap.LDAPResultInvalidDNSyntax, err return ldap.LDAPResultInvalidDNSyntax, err
@ -93,8 +94,13 @@ func (server *Server) handleAddInternal(state *State, r *message.AddRequest) (in
member_canonical) member_canonical)
} }
} }
members = append(members, vals_str...)
}
if prev, ok := entry[key]; ok {
entry[key] = append(prev, vals_str...)
} else {
entry[key] = vals_str
} }
entry[key] = vals_str
} }
entry[ATTR_CREATORSNAME] = []string{state.login.user} entry[ATTR_CREATORSNAME] = []string{state.login.user}
@ -111,34 +117,8 @@ func (server *Server) handleAddInternal(state *State, r *message.AddRequest) (in
// ~~ future errors cause inconsistencies in the DB and are logged ~~ // ~~ future errors cause inconsistencies in the DB and are logged ~~
// If our item has a member list, add it to all of its member's memberOf attribute // If our item has a member list, add it to all of its member's memberOf attribute
if members != nil { for _, member := range members {
for _, member := range members { server.memberOfAdd(member, dn)
memberGroups, err := server.getAttribute(member, ATTR_MEMBEROF)
if err != nil {
server.logger.Warnf("Could not add %s to memberOf of %s: %s", dn, member, err)
continue
}
alreadyMember := false
for _, mb := range memberGroups {
if mb == dn {
alreadyMember = true
server.logger.Warnf("Warning: inconsistency detected, %s was memberOf %s at a time when it didn't exist!",
member, dn)
break
}
}
if !alreadyMember {
memberGroups = append(memberGroups, dn)
err = server.addElements(member, Entry{
ATTR_MEMBEROF: memberGroups,
})
if err != nil {
server.logger.Warnf("Could not add %s to memberOf of %s: %s", dn, member, err)
}
}
}
} }
return ldap.LDAPResultSuccess, nil return ldap.LDAPResultSuccess, nil
@ -196,7 +176,7 @@ func (server *Server) handleDeleteInternal(state *State, r *message.DelRequest)
} }
if itemDN != dn { if itemDN != dn {
return ldap.LDAPResultNotAllowedOnNonLeaf, fmt.Errorf( return ldap.LDAPResultNotAllowedOnNonLeaf, fmt.Errorf(
"Cannot delete %d as it has children", dn) "Cannot delete %s as it has children", dn)
} }
} }
@ -244,28 +224,8 @@ func (server *Server) handleDeleteInternal(state *State, r *message.DelRequest)
} }
// Delete it from all of its member's memberOf info // Delete it from all of its member's memberOf info
if memberList != nil { for _, member := range memberList {
for _, member := range memberList { server.memberOfRemove(member, dn)
memberOf, err := server.getAttribute(member, ATTR_MEMBEROF)
if err != nil || memberOf == nil {
server.logger.Warnf("Could not remove %s from memberOf of %s: %s", dn, member, err)
continue
}
newMemberOf := []string{}
for _, group := range memberOf {
if group != dn {
newMemberOf = append(newMemberOf, group)
}
}
err = server.addElements(member, Entry{
ATTR_MEMBEROF: newMemberOf,
})
if err != nil {
server.logger.Warnf("Could not remove %s from memberOf of %s: %s", dn, member, err)
}
}
} }
return ldap.LDAPResultSuccess, nil return ldap.LDAPResultSuccess, nil
@ -455,57 +415,25 @@ func (server *Server) handleModifyInternal(state *State, r *message.ModifyReques
addMembers[i] = addMem addMembers[i] = addMem
} }
// Now, the modification has been processed and accepted and we want to commit it
newEntry[ATTR_MODIFIERSNAME] = []string{state.login.user} newEntry[ATTR_MODIFIERSNAME] = []string{state.login.user}
newEntry[ATTR_MODIFYTIMESTAMP] = []string{genTimestamp()} newEntry[ATTR_MODIFYTIMESTAMP] = []string{genTimestamp()}
// Save the edited values // Save the edited values
server.addElements(dn, newEntry) err = server.addElements(dn, newEntry)
if err != nil {
return ldap.LDAPResultOperationsError, err
}
// ~~ from this point on, our operation succeeded ~~ // ~~ from this point on, our operation succeeded ~~
// ~~ future errors cause inconsistencies in the DB and are logged ~~ // ~~ future errors cause inconsistencies in the DB and are logged ~~
// Update memberOf for added members and deleted members // Update memberOf for added members and deleted members
for _, addMem := range addMembers { for _, addMem := range addMembers {
memberOf, err := server.getAttribute(addMem, ATTR_MEMBEROF) server.memberOfAdd(addMem, dn)
if err != nil {
server.logger.Warnf("Could not add %s to memberOf of %s: %s", dn, addMem, err)
continue
}
alreadyMember := false
for _, mb := range memberOf {
if mb == dn {
alreadyMember = true
break
}
}
if !alreadyMember {
memberOf = append(memberOf, dn)
err = server.addElements(addMem, Entry{
ATTR_MEMBEROF: memberOf,
})
if err != nil {
server.logger.Warnf("Could not add %s to memberOf of %s: %s", dn, addMem, err)
}
}
} }
for _, delMem := range delMembers { for _, delMem := range delMembers {
memberOf, err := server.getAttribute(delMem, ATTR_MEMBEROF) server.memberOfRemove(delMem, dn)
if err != nil {
server.logger.Warnf("Could not remove %s from memberOf of %s: %s", dn, delMem, err)
continue
}
newMemberOf := []string{}
for _, g := range memberOf {
if g != dn {
newMemberOf = append(newMemberOf, g)
}
}
err = server.addElements(delMem, Entry{ATTR_MEMBEROF: newMemberOf})
if err != nil {
server.logger.Warnf("Could not remove %s from memberOf of %s: %s", dn, delMem, err)
}
} }
return ldap.LDAPResultSuccess, nil return ldap.LDAPResultSuccess, nil