Files
Bridge-and-Join-s/internal/lkgateway/adfailover_test.go
T
fontvielle 6ada4855ce AD-вход: перебор резервных контроллеров и повтор при сбое сети
Раньше вход по AD бил в один контроллер (adDial → один DialURL) одной попыткой: любой
кратковременный сбой TLS/сети к DC выглядел для пользователя как неверный пароль, вход
был нестабилен. Теперь:
- ad_server может перечислять несколько контроллеров (запятая/пробел/перенос строки) —
  перебираются по порядку как резерв;
- единственный контроллер пробуется дважды, чтобы одиночный сетевой сбой не ронял вход;
- повтор только на временных сбоях (сеть/TLS/контроллер недоступен). Неверный пароль,
  блокировка/отключение учётки, истёкший пароль, нет пользователя/группы — окончательны
  (adFinalError/adNoGroupError/errADNotFound), повтора нет и домен-недоступен не маскирует их.
adDial (проверки/мастер) тоже получил перебор резерва. Тесты: adServerURLs, adErrTransient.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-13 11:22:44 +03:00

63 lines
1.8 KiB
Go

package lkgateway
import (
"errors"
"fmt"
"testing"
"github.com/go-ldap/ldap/v3"
)
func TestADServerURLs(t *testing.T) {
cases := []struct {
in string
want []string
}{
{"", nil},
{"ldaps://dc1:636", []string{"ldaps://dc1:636"}},
{" ldaps://dc1:636 ", []string{"ldaps://dc1:636"}},
{"dc1, dc2 dc3", []string{"dc1", "dc2", "dc3"}},
{"ldaps://dc1:636\nldaps://dc2:636; ldaps://dc3:636", []string{"ldaps://dc1:636", "ldaps://dc2:636", "ldaps://dc3:636"}},
}
for _, c := range cases {
got := adServerURLs(AuthSettings{ADServer: c.in})
if len(got) != len(c.want) {
t.Fatalf("adServerURLs(%q) = %v, want %v", c.in, got, c.want)
}
for i := range got {
if got[i] != c.want[i] {
t.Fatalf("adServerURLs(%q)[%d] = %q, want %q", c.in, i, got[i], c.want[i])
}
}
}
}
func TestADErrTransient(t *testing.T) {
// окончательные отказы — повтор не нужен
final := []error{
&adFinalError{"неверный пароль"},
fmt.Errorf("обёртка: %w", &adFinalError{"нет пользователя"}),
errADNotFound,
&adNoGroupError{sam: "ivanov"},
}
for _, e := range final {
if adErrTransient(e) {
t.Errorf("adErrTransient(%v) = true, ожидался окончательный отказ", e)
}
}
// сетевые/прочие — можно повторить/перейти на резерв
transient := []error{
fmt.Errorf("подключение к ldaps://dc1:636: i/o timeout"),
fmt.Errorf("AD bind: %v", ldap.NewError(ldap.ErrorNetwork, errors.New("connection reset"))),
errors.New("StartTLS: handshake failure"),
}
for _, e := range transient {
if !adErrTransient(e) {
t.Errorf("adErrTransient(%v) = false, ожидался временный сбой", e)
}
}
if adErrTransient(nil) {
t.Error("adErrTransient(nil) должно быть false")
}
}