coredns-ldap/sync.go

95 lines
2.3 KiB
Go
Raw Normal View History

2020-06-08 04:12:18 +00:00
package ldap
import (
"context"
"fmt"
2020-06-09 03:01:53 +00:00
"net"
2020-06-08 04:12:18 +00:00
"time"
"github.com/coredns/coredns/plugin"
"github.com/coredns/coredns/plugin/file"
)
// Run updates the zone from ldap.
func (l *Ldap) Run(ctx context.Context) error {
if err := l.updateZones(ctx); err != nil {
return err
}
go func() {
for {
select {
case <-ctx.Done():
log.Infof("Breaking out of Ldap update loop: %v", ctx.Err())
return
2020-06-09 03:01:53 +00:00
case <-time.After(l.syncInterval):
2020-06-08 04:12:18 +00:00
if err := l.updateZones(ctx); err != nil && ctx.Err() == nil {
log.Errorf("Failed to update zones: %v", err)
}
}
}
}()
return nil
}
func (l *Ldap) updateZones(ctx context.Context) error {
2020-06-09 03:01:53 +00:00
zoneFileMap := make(map[string]*file.Zone, len(l.Zones.Names))
for _, zn := range l.Zones.Names {
zoneFileMap[zn] = nil
2020-06-08 04:12:18 +00:00
}
2020-06-09 03:01:53 +00:00
ldapRecords, err := l.fetchLdapRecords()
2020-06-08 04:12:18 +00:00
if err != nil {
2020-06-09 03:01:53 +00:00
return fmt.Errorf("updating zones: %w", err)
2020-06-08 04:12:18 +00:00
}
2020-06-09 03:01:53 +00:00
for zn, lrpz := range l.mapLdapRecordsToZone(ldapRecords) {
if lrpz == nil {
continue
2020-06-08 04:12:18 +00:00
}
2020-06-09 03:01:53 +00:00
if zoneFileMap[zn] == nil {
zoneFileMap[zn] = file.NewZone(zn, "")
zoneFileMap[zn].Upstream = l.Upstream
2020-06-10 02:54:01 +00:00
zoneFileMap[zn].Insert(SOA(zn))
2020-06-08 04:12:18 +00:00
}
2020-06-09 03:01:53 +00:00
for _, lr := range lrpz {
zoneFileMap[zn].Insert(lr.A())
2020-06-08 04:12:18 +00:00
}
2020-06-09 03:01:53 +00:00
}
l.zMu.Lock()
for zn, zf := range zoneFileMap {
// TODO: assignement copies lock value from file.Zone
(*l.Zones.Z[zn]) = *zf
2020-06-09 03:01:53 +00:00
}
l.zMu.Unlock()
return nil
2020-06-08 04:12:18 +00:00
2020-06-09 03:01:53 +00:00
}
2020-06-08 04:12:18 +00:00
2020-06-09 03:01:53 +00:00
func (l *Ldap) mapLdapRecordsToZone(ldapRecords []ldapRecord) (ldapRecordsPerZone map[string][]ldapRecord) {
lrpz := make(map[string][]ldapRecord, len(l.Zones.Names))
for _, zn := range l.Zones.Names {
lrpz[zn] = nil
}
for _, lr := range ldapRecords {
zone := plugin.Zones(l.Zones.Names).Matches(lr.fqdn)
if zone != "" {
lrpz[zone] = append(lrpz[zone], lr)
2020-06-08 04:12:18 +00:00
}
2020-06-09 03:01:53 +00:00
}
return lrpz
2020-06-08 04:12:18 +00:00
2020-06-09 03:01:53 +00:00
}
2020-06-08 04:12:18 +00:00
2020-06-09 03:01:53 +00:00
func (l *Ldap) fetchLdapRecords() (ldapRecords []ldapRecord, err error) {
searchResult, err := l.Client.SearchWithPaging(l.searchRequest, l.pagingLimit)
if err != nil {
return nil, fmt.Errorf("fetching data from server: %w", err)
}
ldapRecords = make([]ldapRecord, len(searchResult.Entries))
for i := 0; i < len(ldapRecords); i++ {
2020-06-09 03:01:53 +00:00
ldapRecords[i] = ldapRecord{
fqdn: searchResult.Entries[i].GetAttributeValue(l.fqdnAttr),
ip: net.ParseIP(searchResult.Entries[i].GetAttributeValue(l.ip4Attr)),
2020-06-08 04:12:18 +00:00
}
}
2020-06-09 03:01:53 +00:00
return ldapRecords, nil
2020-06-08 04:12:18 +00:00
}