ldap-upstream/internal/ldap/option.go
2026-11-01 22:17:59 -06:00

79 lines
2.7 KiB
Go

package ldap
import (
"fmt"
"os"
"sync/atomic"
"github.com/hashicorp/go-hclog"
ldap "github.com/vjeantet/ldapserver"
)
// Option handle configuration of the underlying ldap.server type.
type Option func(*server)
// protocolSink receives the protocol level output of the underlying
// LDAP server. The underlying server logs through a single process
// wide variable, so the destination is swapped atomically: replacing
// it while connections from an earlier server instance are still
// logging would otherwise be a data race.
var protocolSink atomic.Value // hclog.Logger
func init() {
// Route the underlying server's output through the sink rather
// than letting it write directly to stdout.
ldap.Logger = &protocolLogger{}
}
// WithLogger sets the loggers for the server. Protocol chatter from
// the underlying LDAP server is funneled into the provided hclog and
// downgraded to trace level, which is the only level at which that
// output is interesting.
func WithLogger(l hclog.Logger) Option {
return func(s *server) {
s.l = l.Named("ldap")
protocolSink.Store(l.Named("ldap.protocol"))
}
}
// protocolLogger adapts hclog to the small logging interface the
// underlying LDAP server uses. Everything it emits is protocol level
// noise, so it arrives as trace; fatal keeps its exit semantics.
type protocolLogger struct{}
func (p *protocolLogger) sink() hclog.Logger {
if l, ok := protocolSink.Load().(hclog.Logger); ok {
return l
}
return hclog.NewNullLogger()
}
func (p *protocolLogger) Print(v ...interface{}) { p.sink().Trace(fmt.Sprint(v...)) }
func (p *protocolLogger) Printf(f string, v ...interface{}) { p.sink().Trace(fmt.Sprintf(f, v...)) }
func (p *protocolLogger) Println(v ...interface{}) { p.sink().Trace(fmt.Sprintln(v...)) }
func (p *protocolLogger) Fatal(v ...interface{}) {
p.sink().Error(fmt.Sprint(v...))
os.Exit(1)
}
func (p *protocolLogger) Fatalf(f string, v ...interface{}) {
p.sink().Error(fmt.Sprintf(f, v...))
os.Exit(1)
}
func (p *protocolLogger) Fatalln(v ...interface{}) {
p.sink().Error(fmt.Sprintln(v...))
os.Exit(1)
}
func (p *protocolLogger) Panic(v ...interface{}) { panic(fmt.Sprint(v...)) }
func (p *protocolLogger) Panicf(f string, v ...interface{}) { panic(fmt.Sprintf(f, v...)) }
func (p *protocolLogger) Panicln(v ...interface{}) { panic(fmt.Sprint(v...)) }
// WithNetAuth sets the NetAuth client for the server.
func WithNetAuth(n naClient) Option { return func(s *server) { s.c = n } }
// WithAnonBind enables anonymous bind support which is necessary in
// some cases that the client wishes to do an initial anonymous bind,
// followed by an immediate rebind as a real entity.
func WithAnonBind(a bool) Option { return func(s *server) { s.allowAnon = a } }