refactor(authentication): add trace logs for the user/group baseDN (#1904)

This logs the baseDN for user and group searching on startup as well as the users filter (with just input remaining). Additionally refactors the location of a few log messages, and exposes the logger to the provider to reduce calls to logging.Logger().
pull/1906/head
James Elliott 2021-04-12 11:10:50 +10:00 committed by GitHub
parent 1a385947bc
commit 9e7b73bd56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 22 deletions

View File

@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/go-ldap/ldap/v3" "github.com/go-ldap/ldap/v3"
"github.com/sirupsen/logrus"
"golang.org/x/text/encoding/unicode" "golang.org/x/text/encoding/unicode"
"github.com/authelia/authelia/internal/configuration/schema" "github.com/authelia/authelia/internal/configuration/schema"
@ -19,9 +20,10 @@ type LDAPUserProvider struct {
configuration schema.LDAPAuthenticationBackendConfiguration configuration schema.LDAPAuthenticationBackendConfiguration
tlsConfig *tls.Config tlsConfig *tls.Config
dialOpts ldap.DialOpt dialOpts ldap.DialOpt
logger *logrus.Logger
connectionFactory LDAPConnectionFactory connectionFactory LDAPConnectionFactory
usersDN string usersBaseDN string
groupsDN string groupsBaseDN string
} }
// NewLDAPUserProvider creates a new instance of LDAPUserProvider. // NewLDAPUserProvider creates a new instance of LDAPUserProvider.
@ -42,6 +44,7 @@ func NewLDAPUserProvider(configuration schema.LDAPAuthenticationBackendConfigura
configuration: configuration, configuration: configuration,
tlsConfig: tlsConfig, tlsConfig: tlsConfig,
dialOpts: dialOpts, dialOpts: dialOpts,
logger: logging.Logger(),
connectionFactory: NewLDAPConnectionFactoryImpl(), connectionFactory: NewLDAPConnectionFactoryImpl(),
} }
@ -59,25 +62,23 @@ func NewLDAPUserProviderWithFactory(configuration schema.LDAPAuthenticationBacke
} }
func (p *LDAPUserProvider) parseDynamicConfiguration() { func (p *LDAPUserProvider) parseDynamicConfiguration() {
logger := logging.Logger() // Deprecated: This is temporary for deprecation notice purposes. TODO: Remove in 4.28.
// Deprecated: This is temporary for deprecation notice purposes. TODO: Remove in 4.28. // Deprecated: This is temporary for deprecation notice purposes. TODO: Remove in 4.28.
if strings.Contains(p.configuration.UsersFilter, "{0}") { if strings.Contains(p.configuration.UsersFilter, "{0}") {
logger.Warnf("DEPRECATION NOTICE: LDAP Users Filter will no longer support replacing `{0}` in 4.28.0. Please use `{input}` instead.") p.logger.Warnf("DEPRECATION NOTICE: LDAP Users Filter will no longer support replacing `{0}` in 4.28.0. Please use `{input}` instead.")
p.configuration.UsersFilter = strings.ReplaceAll(p.configuration.UsersFilter, "{0}", "{input}") p.configuration.UsersFilter = strings.ReplaceAll(p.configuration.UsersFilter, "{0}", "{input}")
} }
// Deprecated: This is temporary for deprecation notice purposes. TODO: Remove in 4.28. // Deprecated: This is temporary for deprecation notice purposes. TODO: Remove in 4.28.
if strings.Contains(p.configuration.GroupsFilter, "{0}") { if strings.Contains(p.configuration.GroupsFilter, "{0}") {
logger.Warnf("DEPRECATION NOTICE: LDAP Groups Filter will no longer support replacing `{0}` in 4.28.0. Please use `{input}` instead.") p.logger.Warnf("DEPRECATION NOTICE: LDAP Groups Filter will no longer support replacing `{0}` in 4.28.0. Please use `{input}` instead.")
p.configuration.GroupsFilter = strings.ReplaceAll(p.configuration.GroupsFilter, "{0}", "{input}") p.configuration.GroupsFilter = strings.ReplaceAll(p.configuration.GroupsFilter, "{0}", "{input}")
} }
// Deprecated: This is temporary for deprecation notice purposes. TODO: Remove in 4.28. // Deprecated: This is temporary for deprecation notice purposes. TODO: Remove in 4.28.
if strings.Contains(p.configuration.GroupsFilter, "{1}") { if strings.Contains(p.configuration.GroupsFilter, "{1}") {
logger.Warnf("DEPRECATION NOTICE: LDAP Groups Filter will no longer support replacing `{1}` in 4.28.0. Please use `{username}` instead.") p.logger.Warnf("DEPRECATION NOTICE: LDAP Groups Filter will no longer support replacing `{1}` in 4.28.0. Please use `{username}` instead.")
p.configuration.GroupsFilter = strings.ReplaceAll(p.configuration.GroupsFilter, "{1}", "{username}") p.configuration.GroupsFilter = strings.ReplaceAll(p.configuration.GroupsFilter, "{1}", "{username}")
} }
@ -86,17 +87,23 @@ func (p *LDAPUserProvider) parseDynamicConfiguration() {
p.configuration.UsersFilter = strings.ReplaceAll(p.configuration.UsersFilter, "{mail_attribute}", p.configuration.MailAttribute) p.configuration.UsersFilter = strings.ReplaceAll(p.configuration.UsersFilter, "{mail_attribute}", p.configuration.MailAttribute)
p.configuration.UsersFilter = strings.ReplaceAll(p.configuration.UsersFilter, "{display_name_attribute}", p.configuration.DisplayNameAttribute) p.configuration.UsersFilter = strings.ReplaceAll(p.configuration.UsersFilter, "{display_name_attribute}", p.configuration.DisplayNameAttribute)
p.logger.Tracef("Dynamically generated users filter is %s", p.configuration.UsersFilter)
if p.configuration.AdditionalUsersDN != "" { if p.configuration.AdditionalUsersDN != "" {
p.usersDN = p.configuration.AdditionalUsersDN + "," + p.configuration.BaseDN p.usersBaseDN = p.configuration.AdditionalUsersDN + "," + p.configuration.BaseDN
} else { } else {
p.usersDN = p.configuration.BaseDN p.usersBaseDN = p.configuration.BaseDN
} }
p.logger.Tracef("Dynamically generated users BaseDN is %s", p.usersBaseDN)
if p.configuration.AdditionalGroupsDN != "" { if p.configuration.AdditionalGroupsDN != "" {
p.groupsDN = p.configuration.AdditionalGroupsDN + "," + p.configuration.BaseDN p.groupsBaseDN = ldap.EscapeFilter(p.configuration.AdditionalGroupsDN + "," + p.configuration.BaseDN)
} else { } else {
p.groupsDN = p.configuration.BaseDN p.groupsBaseDN = p.configuration.BaseDN
} }
p.logger.Tracef("Dynamically generated groups BaseDN is %s", p.groupsBaseDN)
} }
func (p *LDAPUserProvider) connect(userDN string, password string) (LDAPConnection, error) { func (p *LDAPUserProvider) connect(userDN string, password string) (LDAPConnection, error) {
@ -162,13 +169,13 @@ func (p *LDAPUserProvider) resolveUsersFilter(userFilter string, inputUsername s
// The {input} placeholder is replaced by the users username input. // The {input} placeholder is replaced by the users username input.
userFilter = strings.ReplaceAll(userFilter, "{input}", inputUsername) userFilter = strings.ReplaceAll(userFilter, "{input}", inputUsername)
p.logger.Tracef("Computed user filter is %s", userFilter)
return userFilter return userFilter
} }
func (p *LDAPUserProvider) getUserProfile(conn LDAPConnection, inputUsername string) (*ldapUserProfile, error) { func (p *LDAPUserProvider) getUserProfile(conn LDAPConnection, inputUsername string) (*ldapUserProfile, error) {
logger := logging.Logger()
userFilter := p.resolveUsersFilter(p.configuration.UsersFilter, inputUsername) userFilter := p.resolveUsersFilter(p.configuration.UsersFilter, inputUsername)
logger.Tracef("Computed user filter is %s", userFilter)
attributes := []string{"dn", attributes := []string{"dn",
p.configuration.DisplayNameAttribute, p.configuration.DisplayNameAttribute,
@ -177,7 +184,7 @@ func (p *LDAPUserProvider) getUserProfile(conn LDAPConnection, inputUsername str
// Search for the given username. // Search for the given username.
searchRequest := ldap.NewSearchRequest( searchRequest := ldap.NewSearchRequest(
p.usersDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, p.usersBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
1, 0, false, userFilter, attributes, nil, 1, 0, false, userFilter, attributes, nil,
) )
@ -235,13 +242,13 @@ func (p *LDAPUserProvider) resolveGroupsFilter(inputUsername string, profile *ld
groupFilter = strings.ReplaceAll(groupFilter, "{dn}", ldap.EscapeFilter(profile.DN)) groupFilter = strings.ReplaceAll(groupFilter, "{dn}", ldap.EscapeFilter(profile.DN))
} }
p.logger.Tracef("Computed groups filter is %s", groupFilter)
return groupFilter, nil return groupFilter, nil
} }
// GetDetails retrieve the groups a user belongs to. // GetDetails retrieve the groups a user belongs to.
func (p *LDAPUserProvider) GetDetails(inputUsername string) (*UserDetails, error) { func (p *LDAPUserProvider) GetDetails(inputUsername string) (*UserDetails, error) {
logger := logging.Logger()
conn, err := p.connect(p.configuration.User, p.configuration.Password) conn, err := p.connect(p.configuration.User, p.configuration.Password)
if err != nil { if err != nil {
return nil, err return nil, err
@ -258,11 +265,9 @@ func (p *LDAPUserProvider) GetDetails(inputUsername string) (*UserDetails, error
return nil, fmt.Errorf("Unable to create group filter for user %s. Cause: %s", inputUsername, err) return nil, fmt.Errorf("Unable to create group filter for user %s. Cause: %s", inputUsername, err)
} }
logger.Tracef("Computed groups filter is %s", groupsFilter)
// Search for the given username. // Search for the given username.
searchGroupRequest := ldap.NewSearchRequest( searchGroupRequest := ldap.NewSearchRequest(
p.groupsDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, p.groupsBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
0, 0, false, groupsFilter, []string{p.configuration.GroupNameAttribute}, nil, 0, 0, false, groupsFilter, []string{p.configuration.GroupNameAttribute}, nil,
) )
@ -276,7 +281,7 @@ func (p *LDAPUserProvider) GetDetails(inputUsername string) (*UserDetails, error
for _, res := range sr.Entries { for _, res := range sr.Entries {
if len(res.Attributes) == 0 { if len(res.Attributes) == 0 {
logger.Warningf("No groups retrieved from LDAP for user %s", inputUsername) p.logger.Warningf("No groups retrieved from LDAP for user %s", inputUsername)
break break
} }
// Append all values of the document. Normally there should be only one per document. // Append all values of the document. Normally there should be only one per document.

View File

@ -725,8 +725,8 @@ func TestShouldParseDynamicConfiguration(t *testing.T) {
assert.Equal(t, "(&(|(uid={input})(mail={input})(displayname={input}))(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(!pwdLastSet=0))", ldapClient.configuration.UsersFilter) assert.Equal(t, "(&(|(uid={input})(mail={input})(displayname={input}))(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(!pwdLastSet=0))", ldapClient.configuration.UsersFilter)
assert.Equal(t, "(&(|(member={dn})(member={input})(member={username}))(objectClass=group))", ldapClient.configuration.GroupsFilter) assert.Equal(t, "(&(|(member={dn})(member={input})(member={username}))(objectClass=group))", ldapClient.configuration.GroupsFilter)
assert.Equal(t, "ou=users,dc=example,dc=com", ldapClient.usersDN) assert.Equal(t, "ou=users,dc=example,dc=com", ldapClient.usersBaseDN)
assert.Equal(t, "ou=groups,dc=example,dc=com", ldapClient.groupsDN) assert.Equal(t, "ou=groups,dc=example,dc=com", ldapClient.groupsBaseDN)
} }
func TestShouldCallStartTLSWithInsecureSkipVerifyWhenSkipVerifyTrue(t *testing.T) { func TestShouldCallStartTLSWithInsecureSkipVerifyWhenSkipVerifyTrue(t *testing.T) {