92 lines
2.5 KiB
Go
92 lines
2.5 KiB
Go
// Package ldap is a CoreDNS plugin that resolves A, AAAA y PTR RR from a ldap backend.
|
|
//
|
|
// 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.
|
|
// fqdn and ip4 / ip6 information is mapped from it's repsective ldap schema and
|
|
// served as DNS records over coredns. Mapping is configurable. To reduce load
|
|
// on the backend, a configurable cache is bundled.
|
|
package ldap
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
"net"
|
|
|
|
"github.com/coredns/coredns/plugin"
|
|
"github.com/coredns/coredns/plugin/etcd/msg"
|
|
"github.com/coredns/coredns/plugin/file"
|
|
"github.com/coredns/coredns/plugin/pkg/fall"
|
|
"github.com/coredns/coredns/plugin/pkg/upstream"
|
|
"github.com/coredns/coredns/request"
|
|
|
|
"github.com/miekg/dns"
|
|
"gopkg.in/ldap.v3"
|
|
)
|
|
|
|
type ldapRecord struct {
|
|
fqdn string
|
|
ip net.IP
|
|
}
|
|
|
|
func (r *ldapRecord) A() (A *dns.A) {
|
|
return &dns.A{Hdr: dns.RR_Header{Name: r.fqdn, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}, A: r.ip}
|
|
}
|
|
|
|
// Ldap is an ldap plugin to serve zone entries from a ldap backend.
|
|
type Ldap struct {
|
|
Next plugin.Handler
|
|
Fall fall.F
|
|
Upstream *upstream.Upstream
|
|
Client ldap.Client
|
|
Zones file.Zones
|
|
|
|
searchRequest *ldap.SearchRequest
|
|
ldapURL string
|
|
pagingLimit uint32
|
|
syncInterval time.Duration
|
|
username string
|
|
password string
|
|
sasl bool
|
|
fqdnAttr string
|
|
ip4Attr string
|
|
zMu sync.RWMutex
|
|
ttl time.Duration
|
|
}
|
|
|
|
// New returns an initialized Ldap with defaults.
|
|
func New(zoneNames []string) *Ldap {
|
|
l := new(Ldap)
|
|
l.Zones.Names = zoneNames
|
|
l.pagingLimit = 0
|
|
// 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
|
|
return l
|
|
}
|
|
|
|
var (
|
|
errNoItems = errors.New("no items found")
|
|
errNsNotExposed = errors.New("namespace is not exposed")
|
|
errInvalidRequest = errors.New("invalid query name")
|
|
)
|
|
|
|
// InitClient initializes a Ldap client.
|
|
func (l *Ldap) InitClient() (err error) {
|
|
l.Client, err = ldap.DialURL(l.ldapURL)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
return err
|
|
}
|
|
defer l.Client.Close()
|
|
return nil
|
|
}
|
|
|