outposts/ldap: optimise backend Search API requests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
8cd1223081
commit
0d0dcf8de0
|
@ -99,7 +99,7 @@ func (fe *FlowExecutor) DelegateClientIP(a net.Addr) {
|
|||
func (fe *FlowExecutor) CheckApplicationAccess(appSlug string) (bool, error) {
|
||||
acsp := sentry.StartSpan(fe.Context, "authentik.outposts.flow_executor.check_access")
|
||||
defer acsp.Finish()
|
||||
p, _, err := fe.api.CoreApi.CoreApplicationsCheckAccessRetrieve(context.Background(), appSlug).Execute()
|
||||
p, _, err := fe.api.CoreApi.CoreApplicationsCheckAccessRetrieve(acsp.Context(), appSlug).Execute()
|
||||
if !p.Passing {
|
||||
fe.log.Info("Access denied for user")
|
||||
return false, nil
|
||||
|
@ -125,8 +125,9 @@ func (fe *FlowExecutor) Execute() (bool, error) {
|
|||
func (fe *FlowExecutor) solveFlowChallenge(depth int) (bool, error) {
|
||||
defer fe.sp.Finish()
|
||||
|
||||
// Get challenge
|
||||
gcsp := sentry.StartSpan(fe.Context, "authentik.outposts.flow_executor.get_challenge")
|
||||
req := fe.api.FlowsApi.FlowsExecutorGet(context.Background(), fe.flowSlug).Query(fe.Params.Encode())
|
||||
req := fe.api.FlowsApi.FlowsExecutorGet(gcsp.Context(), fe.flowSlug).Query(fe.Params.Encode())
|
||||
challenge, _, err := req.Execute()
|
||||
if err != nil {
|
||||
return false, errors.New("failed to get challenge")
|
||||
|
@ -137,7 +138,9 @@ func (fe *FlowExecutor) solveFlowChallenge(depth int) (bool, error) {
|
|||
gcsp.SetTag("ak_component", ch.GetComponent())
|
||||
gcsp.Finish()
|
||||
|
||||
responseReq := fe.api.FlowsApi.FlowsExecutorSolve(context.Background(), fe.flowSlug).Query(fe.Params.Encode())
|
||||
// Resole challenge
|
||||
scsp := sentry.StartSpan(fe.Context, "authentik.outposts.flow_executor.solve_challenge")
|
||||
responseReq := fe.api.FlowsApi.FlowsExecutorSolve(scsp.Context(), fe.flowSlug).Query(fe.Params.Encode())
|
||||
switch ch.GetComponent() {
|
||||
case string(StageIdentification):
|
||||
responseReq = responseReq.FlowChallengeResponseRequest(api.IdentificationChallengeResponseRequestAsFlowChallengeResponseRequest(api.NewIdentificationChallengeResponseRequest(fe.getAnswer(StageIdentification))))
|
||||
|
@ -168,7 +171,6 @@ func (fe *FlowExecutor) solveFlowChallenge(depth int) (bool, error) {
|
|||
return false, fmt.Errorf("unsupported challenge type %s", ch.GetComponent())
|
||||
}
|
||||
|
||||
scsp := sentry.StartSpan(fe.Context, "authentik.outposts.flow_executor.solve_challenge")
|
||||
response, _, err := responseReq.Execute()
|
||||
ch = response.GetActualInstance().(ChallengeInt)
|
||||
fe.log.WithField("component", ch.GetComponent()).WithField("type", ch.GetType()).Debug("Got response")
|
||||
|
|
|
@ -23,7 +23,7 @@ type BindRequest struct {
|
|||
func (ls *LDAPServer) Bind(bindDN string, bindPW string, conn net.Conn) (ldap.LDAPResultCode, error) {
|
||||
span := sentry.StartSpan(context.TODO(), "authentik.providers.ldap.bind",
|
||||
sentry.TransactionName("authentik.providers.ldap.bind"))
|
||||
span.SetTag("user", bindDN)
|
||||
span.SetTag("user.username", bindDN)
|
||||
defer span.Finish()
|
||||
|
||||
bindDN = strings.ToLower(bindDN)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ldap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
@ -34,8 +33,8 @@ func (pi *ProviderInstance) Search(req SearchRequest) (ldap.ServerSearchResult,
|
|||
}
|
||||
|
||||
pi.boundUsersMutex.RLock()
|
||||
defer pi.boundUsersMutex.RUnlock()
|
||||
flags, ok := pi.boundUsers[req.BindDN]
|
||||
pi.boundUsersMutex.RUnlock()
|
||||
if !ok {
|
||||
pi.log.Debug("User info not cached")
|
||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied")
|
||||
|
@ -51,7 +50,7 @@ func (pi *ProviderInstance) Search(req SearchRequest) (ldap.ServerSearchResult,
|
|||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("Search Error: unhandled filter type: %s [%s]", filterEntity, req.Filter)
|
||||
case GroupObjectClass:
|
||||
gapisp := sentry.StartSpan(req.ctx, "authentik.providers.ldap.search.api_group")
|
||||
groups, _, err := pi.s.ac.Client.CoreApi.CoreGroupsList(context.Background()).Execute()
|
||||
groups, _, err := parseFilterForGroup(pi.s.ac.Client.CoreApi.CoreGroupsList(gapisp.Context()), req.Filter).Execute()
|
||||
gapisp.Finish()
|
||||
if err != nil {
|
||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("API Error: %s", err)
|
||||
|
@ -62,7 +61,9 @@ func (pi *ProviderInstance) Search(req SearchRequest) (ldap.ServerSearchResult,
|
|||
entries = append(entries, pi.GroupEntry(pi.APIGroupToLDAPGroup(g)))
|
||||
}
|
||||
|
||||
users, _, err := pi.s.ac.Client.CoreApi.CoreUsersList(context.Background()).Execute()
|
||||
uapisp := sentry.StartSpan(req.ctx, "authentik.providers.ldap.search.api_user")
|
||||
users, _, err := parseFilterForUser(pi.s.ac.Client.CoreApi.CoreUsersList(uapisp.Context()), req.Filter).Execute()
|
||||
uapisp.Finish()
|
||||
if err != nil {
|
||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("API Error: %s", err)
|
||||
}
|
||||
|
@ -72,7 +73,7 @@ func (pi *ProviderInstance) Search(req SearchRequest) (ldap.ServerSearchResult,
|
|||
}
|
||||
case UserObjectClass, "":
|
||||
uapisp := sentry.StartSpan(req.ctx, "authentik.providers.ldap.search.api_user")
|
||||
users, _, err := pi.s.ac.Client.CoreApi.CoreUsersList(context.Background()).Execute()
|
||||
users, _, err := parseFilterForUser(pi.s.ac.Client.CoreApi.CoreUsersList(uapisp.Context()), req.Filter).Execute()
|
||||
uapisp.Finish()
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package ldap
|
||||
|
||||
import (
|
||||
ber "github.com/nmcclain/asn1-ber"
|
||||
"github.com/nmcclain/ldap"
|
||||
"goauthentik.io/api"
|
||||
)
|
||||
|
||||
func parseFilterForGroup(req api.ApiCoreGroupsListRequest, filter string) api.ApiCoreGroupsListRequest {
|
||||
f, err := ldap.CompileFilter(filter)
|
||||
if err != nil {
|
||||
return req
|
||||
}
|
||||
switch f.Tag {
|
||||
case ldap.FilterEqualityMatch:
|
||||
return parseFilterForGroupSingle(req, f)
|
||||
case ldap.FilterAnd:
|
||||
for _, child := range f.Children {
|
||||
req = parseFilterForGroupSingle(req, child)
|
||||
}
|
||||
return req
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
func parseFilterForGroupSingle(req api.ApiCoreGroupsListRequest, f *ber.Packet) api.ApiCoreGroupsListRequest {
|
||||
v := f.Children[1].Value.(string)
|
||||
switch f.Children[0].Value.(string) {
|
||||
case "cn":
|
||||
return req.Name(v)
|
||||
}
|
||||
return req
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package ldap
|
||||
|
||||
import (
|
||||
ber "github.com/nmcclain/asn1-ber"
|
||||
"github.com/nmcclain/ldap"
|
||||
"goauthentik.io/api"
|
||||
)
|
||||
|
||||
func parseFilterForUser(req api.ApiCoreUsersListRequest, filter string) api.ApiCoreUsersListRequest {
|
||||
f, err := ldap.CompileFilter(filter)
|
||||
if err != nil {
|
||||
return req
|
||||
}
|
||||
switch f.Tag {
|
||||
case ldap.FilterEqualityMatch:
|
||||
return parseFilterForUserSingle(req, f)
|
||||
case ldap.FilterAnd:
|
||||
for _, child := range f.Children {
|
||||
req = parseFilterForUserSingle(req, child)
|
||||
}
|
||||
return req
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
func parseFilterForUserSingle(req api.ApiCoreUsersListRequest, f *ber.Packet) api.ApiCoreUsersListRequest {
|
||||
v := f.Children[1].Value.(string)
|
||||
switch f.Children[0].Value.(string) {
|
||||
case "cn":
|
||||
return req.Username(v)
|
||||
case "name":
|
||||
case "displayName":
|
||||
return req.Name(v)
|
||||
case "mail":
|
||||
return req.Email(v)
|
||||
}
|
||||
return req
|
||||
}
|
|
@ -24,7 +24,9 @@ type SearchRequest struct {
|
|||
|
||||
func (ls *LDAPServer) Search(bindDN string, searchReq ldap.SearchRequest, conn net.Conn) (ldap.ServerSearchResult, error) {
|
||||
span := sentry.StartSpan(context.TODO(), "authentik.providers.ldap.search", sentry.TransactionName("authentik.providers.ldap.search"))
|
||||
span.SetTag("user", bindDN)
|
||||
span.SetTag("user.username", bindDN)
|
||||
span.SetTag("ak_filter", searchReq.Filter)
|
||||
span.SetTag("ak_base_dn", searchReq.BaseDN)
|
||||
|
||||
defer span.Finish()
|
||||
|
||||
|
|
Reference in New Issue