A cloud-native LDAP server backed by a Consul datastore
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
3.7 KiB

  1. package main
  2. import (
  3. "sort"
  4. )
  5. func (server *Server) memberOfAdd(member string, group string) {
  6. // Retreive previous memberOf value
  7. memberGroups, err := server.getAttribute(member, ATTR_MEMBEROF)
  8. if err != nil {
  9. server.logger.Warnf("Could not add %s to memberOf of %s: %s", group, member, err)
  10. return
  11. }
  12. // Return early if group is already in memberOf
  13. for _, mb := range memberGroups {
  14. if mb == group {
  15. server.logger.Warnf("Inconsistency detected, %s was memberOf %s at a time when it didn't exist! (not an issue anymore)",
  16. member, group)
  17. return
  18. }
  19. }
  20. // Add group to memberOf
  21. memberGroups = append(memberGroups, group)
  22. err = server.addElements(member, Entry{
  23. ATTR_MEMBEROF: memberGroups,
  24. })
  25. if err != nil {
  26. server.logger.Warnf("Could not add %s to memberOf of %s: %s", group, member, err)
  27. }
  28. }
  29. func (server *Server) memberOfRemove(member string, group string) {
  30. // Retreive previous memberOf value
  31. memberOf, err := server.getAttribute(member, ATTR_MEMBEROF)
  32. if err != nil || memberOf == nil {
  33. server.logger.Warnf("Could not remove %s from memberOf of %s: %s", group, member, err)
  34. return
  35. }
  36. // Filter out group
  37. newMemberOf := []string{}
  38. for _, mb := range memberOf {
  39. if mb != group {
  40. newMemberOf = append(newMemberOf, group)
  41. }
  42. }
  43. // Return early if group already not in memberOf
  44. if len(newMemberOf) == len(memberOf) {
  45. server.logger.Warnf("Inconsistency detected, %s was not memberOf %s at a time when it should have been! (not an issue anymore)",
  46. member, group)
  47. return
  48. }
  49. // Update value of memberOf
  50. err = server.addElements(member, Entry{
  51. ATTR_MEMBEROF: newMemberOf,
  52. })
  53. if err != nil {
  54. server.logger.Warnf("Could not remove %s from memberOf of %s: %s", group, member, err)
  55. }
  56. }
  57. func (server *Server) memberOfResync() error {
  58. server.logger.Warnf("Starting resync of member/memberOf values")
  59. // Load the whole LDAP database
  60. basePath, err := dnToConsul(server.config.Suffix)
  61. if err != nil {
  62. return err
  63. }
  64. data, _, err := server.kv.List(basePath, nil)
  65. if err != nil {
  66. return err
  67. }
  68. entries, err := parseConsulResult(data)
  69. if err != nil {
  70. return err
  71. }
  72. // Check member values for all objects, and remove deleted objects
  73. // Calculate new memberOf sets for all objects
  74. newMemberOf := make(map[string][]string)
  75. for dn := range entries {
  76. newMemberOf[dn] = []string{}
  77. }
  78. for dn, entry := range entries {
  79. member, ok := entry[ATTR_MEMBER]
  80. if !ok {
  81. continue
  82. }
  83. keepMember := []string{}
  84. for _, mem := range member {
  85. if _, exists := entries[mem]; exists {
  86. keepMember = append(keepMember, mem)
  87. newMemberOf[mem] = append(newMemberOf[mem], dn)
  88. } else {
  89. server.logger.Warnf("Fixing: %s had as member %s which doesn't exist", dn, mem)
  90. }
  91. }
  92. if len(keepMember) != len(member) {
  93. server.logger.Warnf("Writing new member list for %s", dn)
  94. err = server.addElements(dn, Entry{
  95. ATTR_MEMBER: keepMember,
  96. })
  97. if err != nil {
  98. return err
  99. }
  100. }
  101. }
  102. // Write updated memberOf values
  103. for dn, newMemberOfV := range newMemberOf {
  104. prevMemberOf := []string{}
  105. if v, ok := entries[dn][ATTR_MEMBEROF]; ok {
  106. prevMemberOf = v
  107. }
  108. different := (len(prevMemberOf) != len(newMemberOfV))
  109. if !different {
  110. sort.Strings(newMemberOfV)
  111. sort.Strings(prevMemberOf)
  112. for i := range newMemberOfV {
  113. if newMemberOfV[i] != prevMemberOf[i] {
  114. different = true
  115. break
  116. }
  117. }
  118. }
  119. if different {
  120. server.logger.Warnf("Fixing memberOf for %s (%d -> %d)",
  121. dn, len(prevMemberOf), len(newMemberOfV))
  122. err = server.addElements(dn, Entry{
  123. ATTR_MEMBEROF: newMemberOfV,
  124. })
  125. if err != nil {
  126. return err
  127. }
  128. }
  129. }
  130. server.logger.Warnf("Done resyncing member/memberOf values")
  131. return nil
  132. }