HTTP API закрыт за вход через OIDC у Authelia
- шаг схемы закрывает поверхность, которую хранилище приносит открытой: собственную регистрацию, вход по паролю и одноразовый код — без этого закрытие приёма обходилось двумя запросами - продление сессии выключено, срок семь суток: иначе отзыв доступа у провайдера до сервиса не доходит никогда - файл записи отдаётся вошедшему по токену файла — пересмотр ADR-2026-08-12-file-link-open-but-not-logged
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Проверка входа — единственная страховка от того, чтобы сервис поднялся с
|
||||
// молча выключенным входом, то есть открытым наружу. До этих проверок она не
|
||||
// исполнялась ни разу.
|
||||
|
||||
func validAuthConfig() AuthConfig {
|
||||
return AuthConfig{
|
||||
AuthURL: "https://auth.example.com/api/oidc/authorization",
|
||||
TokenURL: "https://auth.example.com/api/oidc/token",
|
||||
UserInfoURL: "https://auth.example.com/api/oidc/userinfo",
|
||||
ClientID: "transcriber",
|
||||
ClientSecret: "secret-value",
|
||||
RedirectURL: "https://transcriber.example.com/auth/callback",
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthConfigValidateAcceptsFilled(t *testing.T) {
|
||||
if err := validAuthConfig().Validate(); err != nil {
|
||||
t.Fatalf("заполненный конфиг отвергнут: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthConfigValidateNamesEveryMissingKey(t *testing.T) {
|
||||
cases := map[string]func(*AuthConfig){
|
||||
"auth_url": func(c *AuthConfig) { c.AuthURL = "" },
|
||||
"token_url": func(c *AuthConfig) { c.TokenURL = "" },
|
||||
"user_info_url": func(c *AuthConfig) { c.UserInfoURL = "" },
|
||||
"client_id": func(c *AuthConfig) { c.ClientID = "" },
|
||||
"client_secret": func(c *AuthConfig) { c.ClientSecret = "" },
|
||||
"redirect_url": func(c *AuthConfig) { c.RedirectURL = "" },
|
||||
}
|
||||
|
||||
for key, clear := range cases {
|
||||
t.Run(key, func(t *testing.T) {
|
||||
cfg := validAuthConfig()
|
||||
clear(&cfg)
|
||||
|
||||
err := cfg.Validate()
|
||||
if err == nil {
|
||||
t.Fatalf("пустой ключ %s пропущен — сервис поднимется с выключенным входом", key)
|
||||
}
|
||||
if !strings.Contains(err.Error(), key) {
|
||||
t.Fatalf("имя ключа %s не названо: %v", key, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestAuthConfigValidateHidesSecretValue: сообщение об отказе уезжает в журнал,
|
||||
// и значения секрета в нём быть не должно — только имя ключа.
|
||||
func TestAuthConfigValidateHidesSecretValue(t *testing.T) {
|
||||
cfg := validAuthConfig()
|
||||
cfg.ClientSecret = "super-secret-value"
|
||||
cfg.AuthURL = ""
|
||||
|
||||
err := cfg.Validate()
|
||||
if err == nil {
|
||||
t.Fatal("отказа нет")
|
||||
}
|
||||
if strings.Contains(err.Error(), "super-secret-value") {
|
||||
t.Fatalf("значение секрета попало в текст отказа: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestAuthConfigValidateRejectsMalformedURL: непустая строка, не похожая на
|
||||
// адрес, отвергается здесь, а не позже — хранилище отказало бы уже из хука
|
||||
// подъёма, до регистрации пробы здоровья, и сервис упал бы молча целиком.
|
||||
func TestAuthConfigValidateRejectsMalformedURL(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"без схемы": "auth.example.com/api/oidc/authorization",
|
||||
"пробел спереди": " https://auth.example.com/authorize",
|
||||
"чужая схема": "ftp://auth.example.com/authorize",
|
||||
"пустой хост": "https:///authorize",
|
||||
"не адрес вовсе": "todo: заполнить",
|
||||
}
|
||||
|
||||
for name, value := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
cfg := validAuthConfig()
|
||||
cfg.AuthURL = value
|
||||
|
||||
err := cfg.Validate()
|
||||
if err == nil {
|
||||
t.Fatalf("негодный адрес %q пропущен", value)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "auth_url") {
|
||||
t.Fatalf("имя ключа не названо: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user