
* remove search_group Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make api operations cleaerer Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix migration Signed-off-by: Jens Langhammer <jens@goauthentik.io> * actually use get Signed-off-by: Jens Langhammer <jens@goauthentik.io> * use correct api client for ldap Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix migration Signed-off-by: Jens Langhammer <jens@goauthentik.io> * unrelated: fix migration warning Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add docs Signed-off-by: Jens Langhammer <jens@goauthentik.io> * update docs Signed-off-by: Jens Langhammer <jens@goauthentik.io> * unrelated: fix styling issue in dark mode Signed-off-by: Jens Langhammer <jens@goauthentik.io> * unrelated-ish fix button order in wizard Signed-off-by: Jens Langhammer <jens@goauthentik.io> * unrelated: fix missing css import Signed-off-by: Jens Langhammer <jens@goauthentik.io> * Optimised images with calibre/image-actions * Update index.md Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com> Signed-off-by: Jens L. <jens@beryju.org> * Update index.md Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com> Signed-off-by: Jens L. <jens@beryju.org> * Apply suggestions from code review Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com> Signed-off-by: Jens L. <jens@beryju.org> * update release notes based on new template Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io> Signed-off-by: Jens L. <jens@beryju.org> Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com> Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
117 lines
3.9 KiB
Go
117 lines
3.9 KiB
Go
package ldap
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"goauthentik.io/api/v3"
|
|
"goauthentik.io/internal/outpost/ak"
|
|
"goauthentik.io/internal/outpost/ldap/bind"
|
|
directbind "goauthentik.io/internal/outpost/ldap/bind/direct"
|
|
memorybind "goauthentik.io/internal/outpost/ldap/bind/memory"
|
|
"goauthentik.io/internal/outpost/ldap/constants"
|
|
"goauthentik.io/internal/outpost/ldap/flags"
|
|
directsearch "goauthentik.io/internal/outpost/ldap/search/direct"
|
|
memorysearch "goauthentik.io/internal/outpost/ldap/search/memory"
|
|
)
|
|
|
|
func (ls *LDAPServer) getCurrentProvider(pk int32) *ProviderInstance {
|
|
for _, p := range ls.providers {
|
|
if p.providerPk == pk {
|
|
return p
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ls *LDAPServer) getInvalidationFlow() string {
|
|
req, _, err := ls.ac.Client.CoreApi.CoreBrandsCurrentRetrieve(context.Background()).Execute()
|
|
if err != nil {
|
|
ls.log.WithError(err).Warning("failed to fetch brand config")
|
|
return ""
|
|
}
|
|
flow := req.GetFlowInvalidation()
|
|
return flow
|
|
}
|
|
|
|
func (ls *LDAPServer) Refresh() error {
|
|
apiProviders, err := ak.Paginator(ls.ac.Client.OutpostsApi.OutpostsLdapList(context.Background()), ak.PaginatorOptions{
|
|
PageSize: 100,
|
|
Logger: ls.log,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(apiProviders) < 1 {
|
|
return errors.New("no ldap provider defined")
|
|
}
|
|
providers := make([]*ProviderInstance, len(apiProviders))
|
|
invalidationFlow := ls.getInvalidationFlow()
|
|
for idx, provider := range apiProviders {
|
|
userDN := strings.ToLower(fmt.Sprintf("ou=%s,%s", constants.OUUsers, *provider.BaseDn))
|
|
groupDN := strings.ToLower(fmt.Sprintf("ou=%s,%s", constants.OUGroups, *provider.BaseDn))
|
|
virtualGroupDN := strings.ToLower(fmt.Sprintf("ou=%s,%s", constants.OUVirtualGroups, *provider.BaseDn))
|
|
logger := log.WithField("logger", "authentik.outpost.ldap").WithField("provider", provider.Name)
|
|
|
|
// Get existing instance so we can transfer boundUsers
|
|
existing := ls.getCurrentProvider(provider.Pk)
|
|
usersMutex := &sync.RWMutex{}
|
|
users := make(map[string]*flags.UserFlags)
|
|
if existing != nil {
|
|
usersMutex = existing.boundUsersMutex
|
|
// Shallow copy, no need to lock
|
|
users = existing.boundUsers
|
|
}
|
|
|
|
providers[idx] = &ProviderInstance{
|
|
BaseDN: provider.GetBaseDn(),
|
|
VirtualGroupDN: virtualGroupDN,
|
|
GroupDN: groupDN,
|
|
UserDN: userDN,
|
|
appSlug: provider.ApplicationSlug,
|
|
authenticationFlowSlug: provider.BindFlowSlug,
|
|
invalidationFlowSlug: invalidationFlow,
|
|
boundUsersMutex: usersMutex,
|
|
boundUsers: users,
|
|
s: ls,
|
|
log: logger,
|
|
tlsServerName: provider.TlsServerName,
|
|
uidStartNumber: provider.GetUidStartNumber(),
|
|
gidStartNumber: provider.GetGidStartNumber(),
|
|
mfaSupport: provider.GetMfaSupport(),
|
|
outpostName: ls.ac.Outpost.Name,
|
|
providerPk: provider.Pk,
|
|
}
|
|
if kp := provider.Certificate.Get(); kp != nil {
|
|
err := ls.cs.AddKeypair(*kp)
|
|
if err != nil {
|
|
ls.log.WithError(err).Warning("Failed to initially fetch certificate")
|
|
}
|
|
providers[idx].cert = ls.cs.Get(*kp)
|
|
providers[idx].certUUID = *kp
|
|
}
|
|
if *provider.SearchMode.Ptr() == api.LDAPAPIACCESSMODE_CACHED {
|
|
providers[idx].searcher = memorysearch.NewMemorySearcher(providers[idx])
|
|
} else if *provider.SearchMode.Ptr() == api.LDAPAPIACCESSMODE_DIRECT {
|
|
providers[idx].searcher = directsearch.NewDirectSearcher(providers[idx])
|
|
}
|
|
if *provider.BindMode.Ptr() == api.LDAPAPIACCESSMODE_CACHED {
|
|
var oldBinder bind.Binder
|
|
if existing != nil {
|
|
oldBinder = existing.binder
|
|
}
|
|
providers[idx].binder = memorybind.NewSessionBinder(providers[idx], oldBinder)
|
|
} else if *provider.BindMode.Ptr() == api.LDAPAPIACCESSMODE_DIRECT {
|
|
providers[idx].binder = directbind.NewDirectBinder(providers[idx])
|
|
}
|
|
}
|
|
ls.providers = providers
|
|
ls.log.Info("Update providers")
|
|
return nil
|
|
}
|