package main import ( "sort" ) 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 _, g := range memberGroups { if g == 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.putAttributes(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 _, g := range memberOf { if g != group { newMemberOf = append(newMemberOf, g) } } // 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.putAttributes(member, Entry{ ATTR_MEMBEROF: newMemberOf, }) if err != nil { server.logger.Warnf("Could not remove %s from memberOf of %s: %s", group, member, err) } } func (server *Server) memberOfResync() error { server.logger.Warnf("Starting resync of member/memberOf values") // Load the whole LDAP database basePath, err := dnToConsul(server.config.Suffix) if err != nil { return err } data, _, err := server.kv.List(basePath, &server.readOpts) if err != nil { return err } entries, err := parseConsulResult(data) if err != nil { return err } // Check member values for all objects, and remove deleted objects // Calculate new memberOf sets for all objects newMemberOf := make(map[string][]string) for dn := range entries { newMemberOf[dn] = []string{} } for dn, entry := range entries { member, ok := entry[ATTR_MEMBER] if !ok { continue } keepMember := []string{} for _, mem := range member { if _, exists := entries[mem]; exists { keepMember = append(keepMember, mem) newMemberOf[mem] = append(newMemberOf[mem], dn) } else { server.logger.Warnf("Fixing: %s had as member %s which doesn't exist", dn, mem) } } if len(keepMember) != len(member) { server.logger.Warnf("Writing new member list for %s", dn) err = server.putAttributes(dn, Entry{ ATTR_MEMBER: keepMember, }) if err != nil { return err } } } // Write updated memberOf values for dn, newMemberOfV := range newMemberOf { prevMemberOf := []string{} if v, ok := entries[dn][ATTR_MEMBEROF]; ok { prevMemberOf = v } different := (len(prevMemberOf) != len(newMemberOfV)) if !different { sort.Strings(newMemberOfV) sort.Strings(prevMemberOf) for i := range newMemberOfV { if newMemberOfV[i] != prevMemberOf[i] { different = true break } } } if different { server.logger.Warnf("Fixing memberOf for %s (%d -> %d)", dn, len(prevMemberOf), len(newMemberOfV)) err = server.putAttributes(dn, Entry{ ATTR_MEMBEROF: newMemberOfV, }) if err != nil { return err } } } server.logger.Warnf("Done resyncing member/memberOf values") return nil }