* outposts/ldap: add tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix missing posixAccount Signed-off-by: Jens Langhammer <jens@goauthentik.io> * attempt to expand attributes Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix routing without base DN Signed-off-by: Jens Langhammer <jens@goauthentik.io> * more logging Signed-off-by: Jens Langhammer <jens@goauthentik.io> * remove our custom attribute filtering since this is done by the ldap library Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add test for schema Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
		
			
				
	
	
		
			56 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			56 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package ldap
 | 
						|
 | 
						|
import (
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"beryju.io/ldap"
 | 
						|
	goldap "github.com/go-ldap/ldap/v3"
 | 
						|
	"goauthentik.io/internal/outpost/ldap/constants"
 | 
						|
	"goauthentik.io/internal/outpost/ldap/search"
 | 
						|
)
 | 
						|
 | 
						|
func (ls *LDAPServer) providerForRequest(req *search.Request) *ProviderInstance {
 | 
						|
	parsedBaseDN, err := goldap.ParseDN(strings.ToLower(req.BaseDN))
 | 
						|
	if err != nil {
 | 
						|
		req.Log().WithError(err).Info("failed to parse base DN")
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	parsedBindDN, err := goldap.ParseDN(strings.ToLower(req.BindDN))
 | 
						|
	if err != nil {
 | 
						|
		req.Log().WithError(err).Info("failed to parse bind DN")
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	var selectedProvider *ProviderInstance
 | 
						|
	longestMatch := 0
 | 
						|
	for _, provider := range ls.providers {
 | 
						|
		providerBase, _ := goldap.ParseDN(strings.ToLower(provider.BaseDN))
 | 
						|
		// Try to match the provider primarily based on the search request's base DN
 | 
						|
		baseDNMatches := providerBase.AncestorOf(parsedBaseDN) || providerBase.Equal(parsedBaseDN)
 | 
						|
		// But also try to match the provider based on the bind DN
 | 
						|
		bindDNMatches := providerBase.AncestorOf(parsedBindDN) || providerBase.Equal(parsedBindDN)
 | 
						|
		if baseDNMatches || bindDNMatches {
 | 
						|
			// Only select the provider if it's a more precise match than previously
 | 
						|
			if len(provider.BaseDN) > longestMatch {
 | 
						|
				req.Log().WithField("provider", provider.BaseDN).Trace("selecting provider for search request")
 | 
						|
				selectedProvider = provider
 | 
						|
				longestMatch = len(provider.BaseDN)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return selectedProvider
 | 
						|
}
 | 
						|
 | 
						|
func (ls *LDAPServer) searchRoute(req *search.Request, pi *ProviderInstance) (ldap.ServerSearchResult, error) {
 | 
						|
	// Route based on the base DN
 | 
						|
	if len(req.BaseDN) == 0 {
 | 
						|
		req.Log().Trace("routing to base")
 | 
						|
		return pi.searcher.SearchBase(req)
 | 
						|
	}
 | 
						|
	if strings.EqualFold(req.BaseDN, "cn=subschema") || req.FilterObjectClass == constants.OCSubSchema {
 | 
						|
		req.Log().Trace("routing to subschema")
 | 
						|
		return pi.searcher.SearchSubschema(req)
 | 
						|
	}
 | 
						|
	req.Log().Trace("routing to default")
 | 
						|
	return pi.searcher.Search(req)
 | 
						|
}
 |