Implement Modify
This commit is contained in:
parent
f9cb0552be
commit
7e4079b3d8
1 changed files with 190 additions and 1 deletions
191
main.go
191
main.go
|
@ -43,7 +43,7 @@ func consulToDN(pair *consul.KVPair) (string, string, []byte) {
|
||||||
}
|
}
|
||||||
dn = cpath + dn
|
dn = cpath + dn
|
||||||
}
|
}
|
||||||
return dn, "", nil
|
panic("Consul key " + pair.Key + " does not end with attribute=something")
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseValue(value []byte) ([]string, error) {
|
func parseValue(value []byte) ([]string, error) {
|
||||||
|
@ -156,6 +156,7 @@ func main() {
|
||||||
routes.Add(gobottin.handleAdd)
|
routes.Add(gobottin.handleAdd)
|
||||||
routes.Compare(gobottin.handleCompare)
|
routes.Compare(gobottin.handleCompare)
|
||||||
routes.Delete(gobottin.handleDelete)
|
routes.Delete(gobottin.handleDelete)
|
||||||
|
routes.Modify(gobottin.handleModify)
|
||||||
ldapserver.Handle(routes)
|
ldapserver.Handle(routes)
|
||||||
|
|
||||||
// listen on 10389
|
// listen on 10389
|
||||||
|
@ -686,3 +687,191 @@ func (server *Server) handleDeleteInternal(state *State, r *message.DelRequest)
|
||||||
return ldap.LDAPResultSuccess, nil
|
return ldap.LDAPResultSuccess, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (server *Server) handleModify(s ldap.UserState, w ldap.ResponseWriter, m *ldap.Message) {
|
||||||
|
state := s.(*State)
|
||||||
|
r := m.GetModifyRequest()
|
||||||
|
|
||||||
|
code, err := server.handleModifyInternal(state, &r)
|
||||||
|
|
||||||
|
res := ldap.NewResponse(code)
|
||||||
|
if err != nil {
|
||||||
|
res.SetDiagnosticMessage(err.Error())
|
||||||
|
}
|
||||||
|
w.Write(message.ModifyResponse(res))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) handleModifyInternal(state *State, r *message.ModifyRequest) (int, error) {
|
||||||
|
dn := string(r.Object())
|
||||||
|
|
||||||
|
_, err := server.checkSuffix(dn, false)
|
||||||
|
if err != nil {
|
||||||
|
return ldap.LDAPResultInvalidDNSyntax, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO check user for permissions to write dn
|
||||||
|
|
||||||
|
// Retrieve previous values (by the way, check object exists)
|
||||||
|
items, _, err := server.kv.List(dnToConsul(dn) + "/attribute=", nil)
|
||||||
|
if err != nil {
|
||||||
|
return ldap.LDAPResultOperationsError, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(items) == 0 {
|
||||||
|
return ldap.LDAPResultNoSuchObject, fmt.Errorf("Not found: %s", dn)
|
||||||
|
}
|
||||||
|
|
||||||
|
prevEntry := Entry{}
|
||||||
|
for _, item := range items {
|
||||||
|
itemDN, attr, val := consulToDN(item)
|
||||||
|
if itemDN != dn {
|
||||||
|
panic("itemDN != dn in handleModifyInternal")
|
||||||
|
}
|
||||||
|
vals, err := parseValue(val)
|
||||||
|
if err != nil {
|
||||||
|
return ldap.LDAPResultOperationsError, err
|
||||||
|
}
|
||||||
|
prevEntry[attr] = vals
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep track of group members added/deleted
|
||||||
|
addMembers, delMembers := []string{}, []string{}
|
||||||
|
|
||||||
|
// Produce new entry values to be saved
|
||||||
|
newEntry := Entry{}
|
||||||
|
for _, change := range r.Changes() {
|
||||||
|
attr := string(change.Modification().Type_())
|
||||||
|
values := change.Modification().Vals()
|
||||||
|
|
||||||
|
if change.Operation() == ldap.ModifyRequestChangeOperationAdd {
|
||||||
|
newEntry[attr] = prevEntry[attr]
|
||||||
|
for _, val := range values {
|
||||||
|
present := false
|
||||||
|
for _, prevVal := range newEntry[attr] {
|
||||||
|
if prevVal == string(val) {
|
||||||
|
present = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !present {
|
||||||
|
newEntry[attr] = append(newEntry[attr], string(val))
|
||||||
|
if strings.EqualFold(attr, "member") {
|
||||||
|
addMembers = append(addMembers, string(val))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if change.Operation() == ldap.ModifyRequestChangeOperationDelete {
|
||||||
|
if len(values) == 0 {
|
||||||
|
// Delete everything
|
||||||
|
newEntry[attr] = []string{}
|
||||||
|
if strings.EqualFold(attr, "member") {
|
||||||
|
delMembers = append(delMembers, prevEntry[attr]...)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Delete only those specified
|
||||||
|
newEntry[attr] = []string{}
|
||||||
|
for _, prevVal := range prevEntry[attr] {
|
||||||
|
keep := true
|
||||||
|
for _, delVal := range values {
|
||||||
|
if string(delVal) == prevVal {
|
||||||
|
keep = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if keep {
|
||||||
|
newEntry[attr] = append(newEntry[attr], prevVal)
|
||||||
|
} else {
|
||||||
|
if strings.EqualFold(attr, "member") {
|
||||||
|
delMembers = append(delMembers, prevVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if change.Operation() == ldap.ModifyRequestChangeOperationReplace {
|
||||||
|
newEntry[attr] = []string{}
|
||||||
|
for _, newVal := range values {
|
||||||
|
newEntry[attr] = append(newEntry[attr], string(newVal))
|
||||||
|
}
|
||||||
|
if strings.EqualFold(attr, "member") {
|
||||||
|
for _, newMem := range newEntry[attr] {
|
||||||
|
mustAdd := true
|
||||||
|
for _, prevMem := range prevEntry[attr] {
|
||||||
|
if prevMem == newMem {
|
||||||
|
mustAdd = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if mustAdd {
|
||||||
|
addMembers = append(addMembers, newMem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, prevMem := range prevEntry[attr] {
|
||||||
|
mustDel := true
|
||||||
|
for _, newMem := range newEntry[attr] {
|
||||||
|
if newMem == prevMem {
|
||||||
|
mustDel = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if mustDel {
|
||||||
|
delMembers = append(delMembers, prevMem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that added members actually exist
|
||||||
|
for _, addMem := range addMembers {
|
||||||
|
exists, err := server.objectExists(addMem)
|
||||||
|
if err != nil {
|
||||||
|
return ldap.LDAPResultOperationsError, err
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
return ldap.LDAPResultNoSuchObject, fmt.Errorf(
|
||||||
|
"Cannot add member %s, it does not exist", addMem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the edited values
|
||||||
|
server.addElements(dn, newEntry)
|
||||||
|
|
||||||
|
// Update memberOf for added members and deleted members
|
||||||
|
for _, addMem := range addMembers {
|
||||||
|
memberOf, err := server.getAttribute(addMem, "memberOf")
|
||||||
|
if err != nil {
|
||||||
|
return ldap.LDAPResultOperationsError, err
|
||||||
|
}
|
||||||
|
if memberOf == nil {
|
||||||
|
memberOf = []string{}
|
||||||
|
}
|
||||||
|
memberOf = append(memberOf, dn)
|
||||||
|
err = server.addElements(addMem, Entry{"memberOf": memberOf})
|
||||||
|
if err != nil {
|
||||||
|
return ldap.LDAPResultOperationsError, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, delMem := range delMembers {
|
||||||
|
memberOf, err := server.getAttribute(delMem, "memberOf")
|
||||||
|
if err != nil {
|
||||||
|
return ldap.LDAPResultOperationsError, err
|
||||||
|
}
|
||||||
|
if memberOf == nil {
|
||||||
|
memberOf = []string{}
|
||||||
|
}
|
||||||
|
newMemberOf := []string{}
|
||||||
|
for _, g := range memberOf {
|
||||||
|
if g != dn {
|
||||||
|
newMemberOf = append(newMemberOf, g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = server.addElements(delMem, Entry{"memberOf": newMemberOf})
|
||||||
|
if err != nil {
|
||||||
|
return ldap.LDAPResultOperationsError, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ldap.LDAPResultSuccess, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue