feat(ldap): make group sync configurable
This commit is contained in:
parent
a3b19a7b3c
commit
216df5bedc
|
|
@ -765,6 +765,16 @@
|
|||
"default_value": "",
|
||||
"comment": "The password of the account used to search the LDAP directory."
|
||||
},
|
||||
{
|
||||
"key": "groupsyncenabled",
|
||||
"default_value": "false",
|
||||
"comment": "If enabled, Vikunja will automagically add users to teams in Vikunja matching `groupsyncfilter`. The teams will be automatically created and kept in sync by Vikunja."
|
||||
},
|
||||
{
|
||||
"key": "groupsyncfilter",
|
||||
"default_value": "(&(objectclass=*)(|(objectclass=group)(objectclass=groupOfNames)))",
|
||||
"comment": "The filter to search for group objects in the ldap directory. Only used when `groupsyncenabled` is set to `true`."
|
||||
},
|
||||
{
|
||||
"key": "attribute",
|
||||
"default_value": "",
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ const (
|
|||
AuthLdapBindDN Key = `auth.ldap.binddn`
|
||||
// #nosec G101
|
||||
AuthLdapBindPassword Key = `auth.ldap.bindpassword`
|
||||
AuthLdapGroupSyncEnabled Key = `auth.ldap.groupsyncenabled`
|
||||
AuthLdapGroupSyncFilter Key = `auth.ldap.groupsyncfilter`
|
||||
AuthLdapAttributeUsername Key = `auth.ldap.attribute.username`
|
||||
AuthLdapAttributeEmail Key = `auth.ldap.attribute.email`
|
||||
AuthLdapAttributeDisplayname Key = `auth.ldap.attribute.displayname`
|
||||
|
|
@ -352,6 +354,8 @@ func InitDefaultConfig() {
|
|||
AuthLdapPort.setDefault(389)
|
||||
AuthLdapUseTLS.setDefault(true)
|
||||
AuthLdapVerifyTLS.setDefault(true)
|
||||
AuthLdapGroupSyncEnabled.setDefault(false)
|
||||
AuthLdapGroupSyncFilter.setDefault("(&(objectclass=*)(|(objectclass=group)(objectclass=groupOfNames)))")
|
||||
AuthLdapAttributeUsername.setDefault("uid")
|
||||
AuthLdapAttributeEmail.setDefault("mail")
|
||||
AuthLdapAttributeDisplayname.setDefault("displayName")
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ func sanitizedUserQuery(username string) (string, bool) {
|
|||
return fmt.Sprintf(config.AuthLdapUserFilter.GetString(), username), true
|
||||
}
|
||||
|
||||
func AuthenticateUserInLDAP(s *xorm.Session, username, password string) (u *user.User, err error) {
|
||||
func AuthenticateUserInLDAP(s *xorm.Session, username, password string, syncGroups bool) (u *user.User, err error) {
|
||||
if password == "" || username == "" {
|
||||
return nil, user.ErrNoUsernamePassword{}
|
||||
}
|
||||
|
|
@ -169,6 +169,10 @@ func AuthenticateUserInLDAP(s *xorm.Session, username, password string) (u *user
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if !syncGroups {
|
||||
return
|
||||
}
|
||||
|
||||
err = syncUserGroups(l, u, userdn)
|
||||
|
||||
return u, err
|
||||
|
|
@ -211,7 +215,7 @@ func syncUserGroups(l *ldap.Conn, u *user.User, userdn string) (err error) {
|
|||
searchRequest := ldap.NewSearchRequest(
|
||||
config.AuthLdapBaseDN.GetString(),
|
||||
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||
"(&(objectclass=*)(|(objectclass=group)(objectclass=groupOfNames)))",
|
||||
config.AuthLdapGroupSyncFilter.GetString(),
|
||||
[]string{
|
||||
"dn",
|
||||
"cn",
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ func TestLdapLogin(t *testing.T) {
|
|||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
user, err := AuthenticateUserInLDAP(s, "professor", "professor")
|
||||
user, err := AuthenticateUserInLDAP(s, "professor", "professor", false)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "professor", user.Username)
|
||||
|
|
@ -48,6 +48,9 @@ func TestLdapLogin(t *testing.T) {
|
|||
"username": "professor",
|
||||
"issuer": "ldap",
|
||||
}, false)
|
||||
db.AssertMissing(t, "teams", map[string]interface{}{
|
||||
"issuer": "ldap",
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("should not create account for wrong password", func(t *testing.T) {
|
||||
|
|
@ -55,7 +58,7 @@ func TestLdapLogin(t *testing.T) {
|
|||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
_, err := AuthenticateUserInLDAP(s, "professor", "wrongpassword")
|
||||
_, err := AuthenticateUserInLDAP(s, "professor", "wrongpassword", false)
|
||||
|
||||
require.Error(t, err)
|
||||
assert.True(t, user2.IsErrWrongUsernameOrPassword(err))
|
||||
|
|
@ -66,9 +69,34 @@ func TestLdapLogin(t *testing.T) {
|
|||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
_, err := AuthenticateUserInLDAP(s, "gnome", "professor")
|
||||
_, err := AuthenticateUserInLDAP(s, "gnome", "professor", false)
|
||||
|
||||
require.Error(t, err)
|
||||
assert.True(t, user2.IsErrWrongUsernameOrPassword(err))
|
||||
})
|
||||
|
||||
t.Run("should sync groups", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
user, err := AuthenticateUserInLDAP(s, "professor", "professor", true)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "professor", user.Username)
|
||||
db.AssertExists(t, "users", map[string]interface{}{
|
||||
"username": "professor",
|
||||
"issuer": "ldap",
|
||||
}, false)
|
||||
db.AssertExists(t, "teams", map[string]interface{}{
|
||||
"name": "admin_staff (LDAP)",
|
||||
"issuer": "ldap",
|
||||
"external_id": "cn=admin_staff,ou=people,dc=planetexpress,dc=com",
|
||||
}, false)
|
||||
db.AssertExists(t, "teams", map[string]interface{}{
|
||||
"name": "git (LDAP)",
|
||||
"issuer": "ldap",
|
||||
"external_id": "cn=git,ou=people,dc=planetexpress,dc=com",
|
||||
}, false)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ func Login(c echo.Context) (err error) {
|
|||
|
||||
var user *user2.User
|
||||
if config.AuthLdapEnabled.GetBool() {
|
||||
user, err = ldap.AuthenticateUserInLDAP(s, u.Username, u.Password)
|
||||
user, err = ldap.AuthenticateUserInLDAP(s, u.Username, u.Password, config.AuthLdapGroupSyncEnabled.GetBool())
|
||||
if err != nil && !user2.IsErrWrongUsernameOrPassword(err) {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err)
|
||||
|
|
|
|||
Loading…
Reference in New Issue