allow LDAP users (and linked peers) to be automatically re-enabled (#345)

This commit is contained in:
Christoph Haas 2025-01-21 18:03:30 +01:00
parent a04eaa4bfb
commit f6c8cd5ea8
5 changed files with 36 additions and 10 deletions

View File

@ -134,6 +134,7 @@ The following configuration options are available:
| login_filter | auth/ldap | | LDAP filters for users that should be allowed to log in. {{login_identifier}} will be replaced with the login username. | | login_filter | auth/ldap | | LDAP filters for users that should be allowed to log in. {{login_identifier}} will be replaced with the login username. |
| admin_group | auth/ldap | | Users in this group are marked as administrators. | | admin_group | auth/ldap | | Users in this group are marked as administrators. |
| disable_missing | auth/ldap | | If synchronization is enabled, missing LDAP users will be disabled in WireGuard Portal. | | disable_missing | auth/ldap | | If synchronization is enabled, missing LDAP users will be disabled in WireGuard Portal. |
| auto_re_enable | auth/ldap | | If auto re-enable is true, users that where disabled because they were missing will be re-enabled once they are found again. |
| sync_filter | auth/ldap | | LDAP filters for users that should be synchronized to WireGuard Portal. | | sync_filter | auth/ldap | | LDAP filters for users that should be synchronized to WireGuard Portal. |
| sync_interval | auth/ldap | | The time interval after which users will be synchronized from LDAP. Empty value or `0` disables synchronization. | | sync_interval | auth/ldap | | The time interval after which users will be synchronized from LDAP. Empty value or `0` disables synchronization. |
| registration_enabled | auth/ldap | | If registration is enabled, new user accounts will created in WireGuard Portal. | | registration_enabled | auth/ldap | | If registration is enabled, new user accounts will created in WireGuard Portal. |

View File

@ -444,6 +444,10 @@ Below are the properties for each LDAP provider entry inside `auth.ldap`:
- **Default:** *(empty)* - **Default:** *(empty)*
- **Description:** If `true`, any user **not** found in LDAP (during sync) is disabled in WireGuard Portal. - **Description:** If `true`, any user **not** found in LDAP (during sync) is disabled in WireGuard Portal.
#### `auto_re_enable`
- **Default:** *(empty)*
- **Description:** If `true`, users that where disabled because they were missing (see `disable_missing`) will be re-enabled once they are found again.
#### `registration_enabled` #### `registration_enabled`
- **Default:** *(empty)* - **Default:** *(empty)*
- **Description:** If `true`, new user accounts are created in WireGuard Portal upon first login. - **Description:** If `true`, new user accounts are created in WireGuard Portal upon first login.

View File

@ -71,5 +71,9 @@ func userChangedInLdap(dbUser, ldapUser *domain.User) bool {
return true return true
} }
if dbUser.ProviderName != ldapUser.ProviderName {
return true
}
return false return false
} }

View File

@ -469,7 +469,7 @@ func (m Manager) synchronizeLdapUsers(ctx context.Context, provider *config.Ldap
logrus.Tracef("fetched %d raw ldap users from provider %s...", len(rawUsers), provider.ProviderName) logrus.Tracef("fetched %d raw ldap users from provider %s...", len(rawUsers), provider.ProviderName)
// Update existing LDAP users // Update existing LDAP users
err = m.updateLdapUsers(ctx, provider.ProviderName, rawUsers, &provider.FieldMap, provider.ParsedAdminGroupDN) err = m.updateLdapUsers(ctx, provider, rawUsers, &provider.FieldMap, provider.ParsedAdminGroupDN)
if err != nil { if err != nil {
return err return err
} }
@ -487,13 +487,13 @@ func (m Manager) synchronizeLdapUsers(ctx context.Context, provider *config.Ldap
func (m Manager) updateLdapUsers( func (m Manager) updateLdapUsers(
ctx context.Context, ctx context.Context,
providerName string, provider *config.LdapProvider,
rawUsers []internal.RawLdapUser, rawUsers []internal.RawLdapUser,
fields *config.LdapFields, fields *config.LdapFields,
adminGroupDN *ldap.DN, adminGroupDN *ldap.DN,
) error { ) error {
for _, rawUser := range rawUsers { for _, rawUser := range rawUsers {
user, err := convertRawLdapUser(providerName, rawUser, fields, adminGroupDN) user, err := convertRawLdapUser(provider.ProviderName, rawUser, fields, adminGroupDN)
if err != nil && !errors.Is(err, domain.ErrNotFound) { if err != nil && !errors.Is(err, domain.ErrNotFound) {
return fmt.Errorf("failed to convert LDAP data for %v: %w", rawUser["dn"], err) return fmt.Errorf("failed to convert LDAP data for %v: %w", rawUser["dn"], err)
} }
@ -506,17 +506,27 @@ func (m Manager) updateLdapUsers(
tctx, cancel := context.WithTimeout(ctx, 30*time.Second) tctx, cancel := context.WithTimeout(ctx, 30*time.Second)
tctx = domain.SetUserInfo(tctx, domain.SystemAdminContextUserInfo()) tctx = domain.SetUserInfo(tctx, domain.SystemAdminContextUserInfo())
// create new user
if existingUser == nil { if existingUser == nil {
err := m.NewUser(tctx, user) err := m.NewUser(tctx, user)
if err != nil { if err != nil {
cancel() cancel()
return fmt.Errorf("create error for user id %s: %w", user.Identifier, err) return fmt.Errorf("create error for user id %s: %w", user.Identifier, err)
} }
cancel()
return nil
} }
if existingUser != nil && existingUser.Source == domain.UserSourceLdap && userChangedInLdap(existingUser, // update existing user
user) { if provider.AutoReEnable && existingUser.DisabledReason == domain.DisabledReasonLdapMissing {
user.Disabled = nil
user.DisabledReason = ""
} else {
user.Disabled = existingUser.Disabled
user.DisabledReason = existingUser.DisabledReason
}
if existingUser.Source == domain.UserSourceLdap && userChangedInLdap(existingUser, user) {
err := m.users.SaveUser(tctx, user.Identifier, func(u *domain.User) (*domain.User, error) { err := m.users.SaveUser(tctx, user.Identifier, func(u *domain.User) (*domain.User, error) {
u.UpdatedAt = time.Now() u.UpdatedAt = time.Now()
u.UpdatedBy = domain.CtxSystemLdapSyncer u.UpdatedBy = domain.CtxSystemLdapSyncer
@ -528,7 +538,8 @@ func (m Manager) updateLdapUsers(
u.Phone = user.Phone u.Phone = user.Phone
u.Department = user.Department u.Department = user.Department
u.IsAdmin = user.IsAdmin u.IsAdmin = user.IsAdmin
u.Disabled = user.Disabled u.Disabled = nil
u.DisabledReason = ""
return u, nil return u, nil
}) })
@ -536,6 +547,10 @@ func (m Manager) updateLdapUsers(
cancel() cancel()
return fmt.Errorf("update error for user id %s: %w", user.Identifier, err) return fmt.Errorf("update error for user id %s: %w", user.Identifier, err)
} }
if existingUser.IsDisabled() && !user.IsDisabled() {
m.bus.Publish(app.TopicUserEnabled, *user)
}
} }
cancel() cancel()

View File

@ -114,9 +114,11 @@ type LdapProvider struct {
ParsedAdminGroupDN *ldap.DN `yaml:"-"` ParsedAdminGroupDN *ldap.DN `yaml:"-"`
// If DisableMissing is true, missing users will be deactivated // If DisableMissing is true, missing users will be deactivated
DisableMissing bool `yaml:"disable_missing"` DisableMissing bool `yaml:"disable_missing"`
SyncFilter string `yaml:"sync_filter"` // If AutoReEnable is true, users that where disabled because they were missing will be re-enabled once they are found again
SyncInterval time.Duration `yaml:"sync_interval"` AutoReEnable bool `yaml:"auto_re_enable"`
SyncFilter string `yaml:"sync_filter"`
SyncInterval time.Duration `yaml:"sync_interval"`
// If RegistrationEnabled is set to true, wg-portal will create new users that do not exist in the database. // If RegistrationEnabled is set to true, wg-portal will create new users that do not exist in the database.
RegistrationEnabled bool `yaml:"registration_enabled"` RegistrationEnabled bool `yaml:"registration_enabled"`