2021-04-19 22:30:27 +00:00
|
|
|
package ldap
|
|
|
|
|
|
|
|
import (
|
2021-05-16 19:07:01 +00:00
|
|
|
"context"
|
2021-04-26 09:53:06 +00:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
2021-05-08 18:59:31 +00:00
|
|
|
"sync"
|
2021-04-26 09:53:06 +00:00
|
|
|
|
2021-05-04 22:03:19 +00:00
|
|
|
"github.com/go-openapi/strfmt"
|
2021-04-19 22:30:27 +00:00
|
|
|
log "github.com/sirupsen/logrus"
|
2022-03-03 09:40:07 +00:00
|
|
|
"goauthentik.io/api/v3"
|
2022-06-05 16:51:01 +00:00
|
|
|
"goauthentik.io/internal/outpost/ldap/bind"
|
2021-11-05 09:37:30 +00:00
|
|
|
directbind "goauthentik.io/internal/outpost/ldap/bind/direct"
|
2022-05-08 14:48:53 +00:00
|
|
|
memorybind "goauthentik.io/internal/outpost/ldap/bind/memory"
|
2021-11-05 09:37:30 +00:00
|
|
|
"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"
|
2021-08-21 15:53:09 +00:00
|
|
|
)
|
|
|
|
|
2021-11-12 23:26:01 +00:00
|
|
|
func (ls *LDAPServer) getCurrentProvider(pk int32) *ProviderInstance {
|
|
|
|
for _, p := range ls.providers {
|
|
|
|
if p.outpostPk == pk {
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-01-23 19:36:30 +00:00
|
|
|
func (ls *LDAPServer) getInvalidationFlow() string {
|
|
|
|
req, _, err := ls.ac.Client.CoreApi.CoreTenantsCurrentRetrieve(context.Background()).Execute()
|
|
|
|
if err != nil {
|
|
|
|
ls.log.WithError(err).Warning("failed to fetch tenant config")
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
flow := req.GetFlowInvalidation()
|
|
|
|
return flow
|
|
|
|
}
|
|
|
|
|
2021-04-19 22:30:27 +00:00
|
|
|
func (ls *LDAPServer) Refresh() error {
|
2021-05-16 19:35:23 +00:00
|
|
|
outposts, _, err := ls.ac.Client.OutpostsApi.OutpostsLdapList(context.Background()).Execute()
|
2021-04-26 09:53:06 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-05-16 19:07:01 +00:00
|
|
|
if len(outposts.Results) < 1 {
|
2021-04-26 09:53:06 +00:00
|
|
|
return errors.New("no ldap provider defined")
|
|
|
|
}
|
2021-05-16 19:07:01 +00:00
|
|
|
providers := make([]*ProviderInstance, len(outposts.Results))
|
2023-01-23 19:36:30 +00:00
|
|
|
invalidationFlow := ls.getInvalidationFlow()
|
2021-05-16 19:07:01 +00:00
|
|
|
for idx, provider := range outposts.Results {
|
2021-11-05 09:37:30 +00:00
|
|
|
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))
|
2021-07-13 16:24:18 +00:00
|
|
|
logger := log.WithField("logger", "authentik.outpost.ldap").WithField("provider", provider.Name)
|
2021-11-12 23:26:01 +00:00
|
|
|
|
|
|
|
// Get existing instance so we can transfer boundUsers
|
|
|
|
existing := ls.getCurrentProvider(provider.Pk)
|
2022-05-21 13:48:50 +00:00
|
|
|
users := make(map[string]*flags.UserFlags)
|
2021-11-12 23:26:01 +00:00
|
|
|
if existing != nil {
|
2021-11-18 18:36:27 +00:00
|
|
|
existing.boundUsersMutex.RLock()
|
2021-11-12 23:26:01 +00:00
|
|
|
users = existing.boundUsers
|
2021-11-18 18:36:27 +00:00
|
|
|
existing.boundUsersMutex.RUnlock()
|
2021-11-12 23:26:01 +00:00
|
|
|
}
|
|
|
|
|
2021-04-26 09:53:06 +00:00
|
|
|
providers[idx] = &ProviderInstance{
|
2023-01-23 19:36:30 +00:00
|
|
|
BaseDN: *provider.BaseDn,
|
|
|
|
VirtualGroupDN: virtualGroupDN,
|
|
|
|
GroupDN: groupDN,
|
|
|
|
UserDN: userDN,
|
|
|
|
appSlug: provider.ApplicationSlug,
|
|
|
|
authenticationFlowSlug: provider.BindFlowSlug,
|
|
|
|
invalidationFlowSlug: invalidationFlow,
|
|
|
|
searchAllowedGroups: []*strfmt.UUID{(*strfmt.UUID)(provider.SearchGroup.Get())},
|
|
|
|
boundUsersMutex: sync.RWMutex{},
|
|
|
|
boundUsers: users,
|
|
|
|
s: ls,
|
|
|
|
log: logger,
|
|
|
|
tlsServerName: provider.TlsServerName,
|
|
|
|
uidStartNumber: *provider.UidStartNumber,
|
|
|
|
gidStartNumber: *provider.GidStartNumber,
|
|
|
|
outpostName: ls.ac.Outpost.Name,
|
|
|
|
outpostPk: provider.Pk,
|
2021-07-13 16:24:18 +00:00
|
|
|
}
|
2022-12-28 18:15:29 +00:00
|
|
|
if kp := provider.Certificate.Get(); kp != nil {
|
2021-07-21 21:53:43 +00:00
|
|
|
err := ls.cs.AddKeypair(*kp)
|
2021-07-13 16:24:18 +00:00
|
|
|
if err != nil {
|
2021-07-21 21:53:43 +00:00
|
|
|
ls.log.WithError(err).Warning("Failed to initially fetch certificate")
|
2021-07-13 16:24:18 +00:00
|
|
|
}
|
2021-07-21 21:53:43 +00:00
|
|
|
providers[idx].cert = ls.cs.Get(*kp)
|
2022-12-28 18:15:29 +00:00
|
|
|
providers[idx].certUUID = *kp
|
2021-04-26 09:53:06 +00:00
|
|
|
}
|
2022-05-10 18:33:19 +00:00
|
|
|
if *provider.SearchMode.Ptr() == api.LDAPAPIACCESSMODE_CACHED {
|
2021-11-05 09:37:30 +00:00
|
|
|
providers[idx].searcher = memorysearch.NewMemorySearcher(providers[idx])
|
2022-05-10 18:33:19 +00:00
|
|
|
} else if *provider.SearchMode.Ptr() == api.LDAPAPIACCESSMODE_DIRECT {
|
2021-11-05 09:37:30 +00:00
|
|
|
providers[idx].searcher = directsearch.NewDirectSearcher(providers[idx])
|
|
|
|
}
|
2022-05-10 18:33:19 +00:00
|
|
|
if *provider.BindMode.Ptr() == api.LDAPAPIACCESSMODE_CACHED {
|
2022-06-05 16:51:01 +00:00
|
|
|
var oldBinder bind.Binder
|
|
|
|
if existing != nil {
|
|
|
|
oldBinder = existing.binder
|
|
|
|
}
|
|
|
|
providers[idx].binder = memorybind.NewSessionBinder(providers[idx], oldBinder)
|
2022-05-10 18:33:19 +00:00
|
|
|
} else if *provider.BindMode.Ptr() == api.LDAPAPIACCESSMODE_DIRECT {
|
2022-05-08 14:48:53 +00:00
|
|
|
providers[idx].binder = directbind.NewDirectBinder(providers[idx])
|
|
|
|
}
|
2021-04-26 09:53:06 +00:00
|
|
|
}
|
|
|
|
ls.providers = providers
|
|
|
|
ls.log.Info("Update providers")
|
2021-04-19 22:30:27 +00:00
|
|
|
return nil
|
|
|
|
}
|