6ada4855ce
Раньше вход по AD бил в один контроллер (adDial → один DialURL) одной попыткой: любой кратковременный сбой TLS/сети к DC выглядел для пользователя как неверный пароль, вход был нестабилен. Теперь: - ad_server может перечислять несколько контроллеров (запятая/пробел/перенос строки) — перебираются по порядку как резерв; - единственный контроллер пробуется дважды, чтобы одиночный сетевой сбой не ронял вход; - повтор только на временных сбоях (сеть/TLS/контроллер недоступен). Неверный пароль, блокировка/отключение учётки, истёкший пароль, нет пользователя/группы — окончательны (adFinalError/adNoGroupError/errADNotFound), повтора нет и домен-недоступен не маскирует их. adDial (проверки/мастер) тоже получил перебор резерва. Тесты: adServerURLs, adErrTransient. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
63 lines
1.8 KiB
Go
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")
|
|
}
|
|
}
|