coredns-ldap/ldap.go

132 lines
3.2 KiB
Go
Raw Permalink Normal View History

2020-06-01 07:59:41 +00:00
// Package ldap is a CoreDNS plugin that resolves A, AAAA y PTR RR from a ldap backend.
//
2020-06-01 07:59:41 +00:00
// It serves as a backend connector for autoritative zone data.
// Ldap is often used for bare metal inventories. This use is the main use case
// for this plugin. Other use cases might eventually be supported.
2020-06-10 07:16:34 +00:00
// fqdn and ip4 / ip6 information is mapped from it's respective ldap schema and
2020-06-01 07:59:41 +00:00
// served as DNS records over coredns. Mapping is configurable. To reduce load
// on the backend, a configurable cache is bundled.
2020-06-01 07:48:07 +00:00
package ldap
import (
2020-06-09 19:07:31 +00:00
"net"
2020-06-08 04:12:18 +00:00
"sync"
"time"
2017-09-15 20:29:47 +00:00
"github.com/coredns/coredns/plugin"
2020-06-09 03:01:53 +00:00
"github.com/coredns/coredns/plugin/file"
"github.com/coredns/coredns/plugin/pkg/fall"
2020-06-08 04:12:18 +00:00
"github.com/coredns/coredns/plugin/pkg/upstream"
2018-02-27 11:39:01 +00:00
"github.com/miekg/dns"
"github.com/go-ldap/ldap/v3"
)
2020-06-09 03:01:53 +00:00
type ldapRecord struct {
fqdn string
2021-05-28 23:47:39 +00:00
ip4 net.IP
ip6 net.IP
2020-06-09 03:01:53 +00:00
}
2020-06-10 08:03:59 +00:00
func (r *ldapRecord) A() (a *dns.A) {
2021-05-28 23:47:39 +00:00
return &dns.A{Hdr: dns.RR_Header{Name: r.fqdn, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}, A: r.ip4}
2020-06-09 03:01:53 +00:00
}
2021-05-28 23:47:39 +00:00
func (r *ldapRecord) AAAA() (a *dns.AAAA) {
return &dns.AAAA{Hdr: dns.RR_Header{Name: r.fqdn, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 86400}, AAAA: r.ip6}
}
2020-06-01 07:59:41 +00:00
// Ldap is an ldap plugin to serve zone entries from a ldap backend.
2020-06-01 07:48:07 +00:00
type Ldap struct {
2020-06-09 03:01:53 +00:00
Next plugin.Handler
Fall fall.F
Upstream *upstream.Upstream
Client ldap.Client
Zones file.Zones
2020-06-08 04:12:18 +00:00
// Exported for mocking in test
SearchRequest *ldap.SearchRequest
FqdnAttr string
Ip4Attr string
2021-05-28 23:47:39 +00:00
Ip6Attr string
ldapURL string
pagingLimit uint32
syncInterval time.Duration
username string
password string
sasl bool
zMu sync.RWMutex
ttl time.Duration
}
2018-04-19 06:25:30 +00:00
2020-06-03 17:47:21 +00:00
// New returns an initialized Ldap with defaults.
2020-06-09 03:01:53 +00:00
func New(zoneNames []string) *Ldap {
l := new(Ldap)
l.Zones.Names = zoneNames
l.pagingLimit = 0
l.syncInterval = 60 * time.Second
2020-06-08 04:12:18 +00:00
// SearchRequest defaults
l.SearchRequest = new(ldap.SearchRequest)
l.SearchRequest.DerefAliases = ldap.NeverDerefAliases // TODO: Reason
l.SearchRequest.Scope = ldap.ScopeWholeSubtree // search whole subtree
l.SearchRequest.SizeLimit = 500 // TODO: Reason
l.SearchRequest.TimeLimit = 500 // TODO: Reason
l.SearchRequest.TypesOnly = false // TODO: Reason
l.Zones.Z = make(map[string]*file.Zone, len(zoneNames))
for _, zn := range zoneNames {
l.Zones.Z[zn] = nil
}
2020-06-10 07:41:44 +00:00
2020-06-09 03:01:53 +00:00
return l
2020-06-03 17:47:21 +00:00
}
2020-06-04 17:41:04 +00:00
// InitClient initializes a Ldap client.
2020-06-03 17:47:21 +00:00
func (l *Ldap) InitClient() (err error) {
2020-06-08 04:12:18 +00:00
l.Client, err = ldap.DialURL(l.ldapURL)
2020-06-03 17:47:21 +00:00
if err != nil {
log.Fatal(err)
2020-06-08 04:12:18 +00:00
return err
2020-06-03 17:47:21 +00:00
}
2021-05-29 00:13:50 +00:00
err = l.Client.Bind(l.username, l.password)
if err != nil {
log.Fatal(err)
}
if err := l.UpdateZones(); err != nil {
return err
}
2020-06-04 17:41:04 +00:00
defer l.Client.Close()
2020-06-10 07:41:44 +00:00
2020-06-08 04:12:18 +00:00
return nil
2020-06-03 17:47:21 +00:00
}
2020-06-10 02:54:01 +00:00
// SOA returns a syntetic SOA record for a zone.
2020-06-10 07:16:34 +00:00
func SOA(zone string) dns.RR {
2020-06-10 02:54:01 +00:00
ttl := uint32(300)
header := dns.RR_Header{Name: zone, Rrtype: dns.TypeSOA, Ttl: ttl, Class: dns.ClassINET}
Mbox := hostmaster + "."
Ns := "ns.dns."
2020-06-10 07:41:44 +00:00
2020-06-10 02:54:01 +00:00
if zone[0] != '.' {
Mbox += zone
Ns += zone
}
return &dns.SOA{Hdr: header,
Mbox: Mbox,
Ns: Ns,
Serial: 12345,
Refresh: 7200,
Retry: 1800,
Expire: 86400,
Minttl: ttl,
}
}
2020-06-10 07:16:34 +00:00
2020-06-10 02:54:01 +00:00
const hostmaster = "hostmaster"