feat(auth): konfigurierbare TLS-Mindestversion fuer den Verzeichnisdienst
Domain Controller auf Windows Server 2012 R2 koennen TLS 1.2 per Registry deaktiviert haben. ad.min_tls_version (Default 1.2) erlaubt es, fuer solche Altsysteme auf 1.0/1.1 herunterzugehen; das Portal warnt dann bei jedem Start. Die Zertifikatspruefung bleibt in jedem Fall aktiv — fuer LDAP gibt es weiterhin keine Insecure-Option. Im Legacy-Modus kommen lediglich die CBC-SHA256-Suiten hinzu, die Go als unsicher einstuft; RC4, 3DES und Suiten ohne Forward Secrecy werden nie angeboten. README dokumentiert zusaetzlich die beiden anderen 2012-R2-Stolpersteine: SHA-1-signierte DC-Zertifikate (seit Go 1.24 nicht mehr umgehbar) und RSA-Schluesselaustausch (nur ueber GODEBUG=tlsrsakex=1). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBHF4R9EAejDJUMdwr6C68
This commit is contained in:
parent
a2bce25424
commit
0fc2d8808b
10 changed files with 299 additions and 25 deletions
48
README.md
48
README.md
|
|
@ -315,6 +315,54 @@ Für die Fehlersuche lässt sich `logging.level` vorübergehend auf `debug`
|
|||
setzen — dann werden auch die verglichenen CNs protokolliert. **Im
|
||||
Normalbetrieb wieder auf `info` zurückstellen.**
|
||||
|
||||
### Alte Domain Controller (Windows Server 2012 R2 und älter)
|
||||
|
||||
Fehlendes TLS 1.3 ist **kein** Problem — das Portal verlangt mindestens
|
||||
TLS 1.2 und handelt automatisch herunter. Server 2012 R2 beherrscht TLS 1.2
|
||||
für Schannel standardmäßig. Scheitert die Verbindung trotzdem, ist fast immer
|
||||
eine dieser drei Ursachen im Spiel. Die Fehlermeldung von `vpnportal check`
|
||||
sagt, welche:
|
||||
|
||||
| Fehlermeldung enthält | Ursache | Behebung |
|
||||
|---|---|---|
|
||||
| `protocol version not supported`, `handshake failure` | TLS 1.2 ist auf dem DC per Registry deaktiviert | `ad.min_tls_version: "1.0"` setzen (siehe unten) |
|
||||
| `insecure algorithm SHA1-RSA`, `certificate signed by unknown authority` | DC-Zertifikat ist mit SHA-1 signiert | **Zertifikat neu ausstellen** — siehe Kasten |
|
||||
| `tls: no cipher suite supported by both` | DC bietet nur RSA-Schlüsselaustausch | `GODEBUG=tlsrsakex=1` in der Unit setzen |
|
||||
|
||||
**TLS-Mindestversion herabsetzen:**
|
||||
|
||||
```yaml
|
||||
ad:
|
||||
min_tls_version: "1.0" # Default ist 1.2
|
||||
```
|
||||
|
||||
Das Portal warnt dann bei jedem Start. Die **Zertifikatsprüfung bleibt aktiv** —
|
||||
für LDAP gibt es bewusst keine Möglichkeit, sie abzuschalten. Herabgesetzt
|
||||
werden nur die zulässigen Protokollversionen und die angebotenen
|
||||
Cipher-Suiten; RC4 und 3DES werden auch dann nie angeboten.
|
||||
|
||||
> **SHA-1-Zertifikate lassen sich nicht mehr umgehen.** Go 1.24 hat den
|
||||
> Notausgang `GODEBUG=x509sha1=1` ersatzlos entfernt. Ist das LDAPS-Zertifikat
|
||||
> des Domain Controllers mit SHA-1 signiert — bei ADCS-Vorlagen aus der
|
||||
> 2012-R2-Ära der Normalfall — hilft nur, es mit SHA-256 neu auszustellen.
|
||||
> Prüfen lässt sich das so:
|
||||
>
|
||||
> ```bash
|
||||
> openssl s_client -connect dc01.firma.local:636 -showcerts </dev/null 2>/dev/null \
|
||||
> | openssl x509 -noout -text | grep -i "signature algorithm"
|
||||
> ```
|
||||
>
|
||||
> Steht dort `sha1WithRSAEncryption`, muss das Zertifikat getauscht werden.
|
||||
|
||||
**RSA-Schlüsselaustausch erzwingen** (letzte Rettung, keine Forward Secrecy).
|
||||
Go schaltet diese Suiten seit 1.22 ab; sie lassen sich nur global per GODEBUG
|
||||
reaktivieren. In der systemd-Unit:
|
||||
|
||||
```ini
|
||||
[Service]
|
||||
Environment=GODEBUG=tlsrsakex=1
|
||||
```
|
||||
|
||||
### Passwort abgelaufen
|
||||
|
||||
Das Portal kann keine Passwörter ändern. Ist ein AD-Passwort abgelaufen
|
||||
|
|
|
|||
|
|
@ -63,15 +63,16 @@ func buildBackends(cfg *config.Config) (*opnsense.Client, *auth.AD, error) {
|
|||
return nil, nil, err
|
||||
}
|
||||
ad, err := auth.NewAD(auth.Options{
|
||||
Servers: cfg.AD.Servers,
|
||||
Port: cfg.AD.Port,
|
||||
TLSMode: cfg.AD.TLSMode,
|
||||
BaseDN: cfg.EffectiveBaseDN(),
|
||||
BindUser: cfg.AD.BindUser,
|
||||
BindPassword: cfg.AD.BindPassword,
|
||||
VPNGroup: cfg.AD.VPNGroup,
|
||||
CAFile: cfg.AD.CAFile,
|
||||
Timeout: time.Duration(cfg.AD.Timeout),
|
||||
Servers: cfg.AD.Servers,
|
||||
Port: cfg.AD.Port,
|
||||
TLSMode: cfg.AD.TLSMode,
|
||||
BaseDN: cfg.EffectiveBaseDN(),
|
||||
BindUser: cfg.AD.BindUser,
|
||||
BindPassword: cfg.AD.BindPassword,
|
||||
VPNGroup: cfg.AD.VPNGroup,
|
||||
CAFile: cfg.AD.CAFile,
|
||||
MinTLSVersion: auth.ParseTLSVersion(cfg.AD.MinTLSVersion),
|
||||
Timeout: time.Duration(cfg.AD.Timeout),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
|
|||
|
|
@ -78,6 +78,13 @@ func runServe(args []string, stdout, stderr io.Writer) int {
|
|||
"WARNUNG: opnsense.insecure_skip_verify ist aktiv — "+
|
||||
"die TLS-Verbindung zur Firewall wird NICHT geprüft. Nur für Tests verwenden.")
|
||||
}
|
||||
if cfg.AD.MinTLSVersionIsWeak() {
|
||||
fmt.Fprintf(stderr,
|
||||
"WARNUNG: ad.min_tls_version ist auf %s gesetzt — die Verbindung zum "+
|
||||
"Verzeichnisdienst erlaubt veraltetes TLS. Die Zertifikatsprüfung bleibt "+
|
||||
"aktiv, aber bitte die Domain Controller auf TLS 1.2 heben.\n",
|
||||
cfg.AD.MinTLSVersion)
|
||||
}
|
||||
|
||||
fw, ad, err := buildBackends(cfg)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -76,6 +76,15 @@ ad:
|
|||
# port: 636
|
||||
# tls_mode: "ldaps"
|
||||
|
||||
# Niedrigste akzeptierte TLS-Version zum Verzeichnisdienst.
|
||||
# Default 1.2. Erlaubt: 1.0, 1.1, 1.2, 1.3.
|
||||
#
|
||||
# Nur herabsetzen, wenn die Domain Controller nachweislich kein TLS 1.2
|
||||
# können (z. B. Windows Server 2012 R2 mit deaktiviertem TLS 1.2). Das
|
||||
# Portal warnt dann bei jedem Start. Die Zertifikatsprüfung bleibt in jedem
|
||||
# Fall aktiv — die lässt sich für LDAP bewusst nicht abschalten.
|
||||
# min_tls_version: "1.2"
|
||||
|
||||
# Unprivilegierter Domain-Benutzer genügt — er muss nur lesen dürfen.
|
||||
bind_user: "svc-vpnportal@firma.local"
|
||||
bind_password: "BITTE-ERSETZEN"
|
||||
|
|
|
|||
|
|
@ -31,7 +31,10 @@ type Options struct {
|
|||
BindPassword string
|
||||
VPNGroup string
|
||||
CAFile string
|
||||
Timeout time.Duration
|
||||
// MinTLSVersion ist die niedrigste akzeptierte TLS-Version (Konstante aus
|
||||
// crypto/tls). 0 bedeutet TLS 1.2.
|
||||
MinTLSVersion uint16
|
||||
Timeout time.Duration
|
||||
|
||||
// Dial ist injizierbar; nil = echte LDAP-Verbindung.
|
||||
Dial func(ctx context.Context, server string) (conn, error)
|
||||
|
|
@ -73,7 +76,7 @@ func NewAD(opts Options) (*AD, error) {
|
|||
opts.Port = 636
|
||||
}
|
||||
if opts.Dial == nil {
|
||||
opts.Dial = realDialer(opts.Port, opts.TLSMode, opts.CAFile, opts.Timeout)
|
||||
opts.Dial = realDialer(opts.Port, opts.TLSMode, opts.CAFile, opts.MinTLSVersion, opts.Timeout)
|
||||
}
|
||||
a := &AD{opts: opts}
|
||||
if opts.OnFailover != nil {
|
||||
|
|
|
|||
|
|
@ -26,10 +26,36 @@ type ldapConn struct{ *ldap.Conn }
|
|||
|
||||
func (c ldapConn) Close() error { c.Conn.Close(); return nil }
|
||||
|
||||
// tlsConfigFor baut die TLS-Konfiguration. Verifikation ist immer aktiv —
|
||||
// für LDAP gibt es bewusst keine Insecure-Option.
|
||||
func tlsConfigFor(server, caFile string) (*tls.Config, error) {
|
||||
cfg := &tls.Config{ServerName: server, MinVersion: tls.VersionTLS12}
|
||||
// ParseTLSVersion übersetzt "1.0".."1.3" in die Konstante von crypto/tls.
|
||||
// Ein leerer oder unbekannter Wert ergibt TLS 1.2 — im Zweifel das Sichere.
|
||||
func ParseTLSVersion(s string) uint16 {
|
||||
switch s {
|
||||
case "1.0":
|
||||
return tls.VersionTLS10
|
||||
case "1.1":
|
||||
return tls.VersionTLS11
|
||||
case "1.3":
|
||||
return tls.VersionTLS13
|
||||
default:
|
||||
return tls.VersionTLS12
|
||||
}
|
||||
}
|
||||
|
||||
// tlsConfigFor baut die TLS-Konfiguration. Die Zertifikatsprüfung ist immer
|
||||
// aktiv — für LDAP gibt es bewusst keine Insecure-Option. Lediglich die
|
||||
// Protokoll-Mindestversion ist konfigurierbar, damit Altsysteme wie ein
|
||||
// Windows Server 2012 R2 ohne TLS 1.2 erreichbar bleiben.
|
||||
func tlsConfigFor(server, caFile string, minVersion uint16) (*tls.Config, error) {
|
||||
if minVersion == 0 {
|
||||
minVersion = tls.VersionTLS12
|
||||
}
|
||||
cfg := &tls.Config{ServerName: server, MinVersion: minVersion}
|
||||
if minVersion < tls.VersionTLS12 {
|
||||
// Go bietet die CBC-Suiten alter Schannel-Stacks nicht mehr von sich
|
||||
// aus an. Ohne sie scheitert der Handshake mit einem 2012 R2, der auf
|
||||
// TLS 1.0/1.1 festgenagelt ist, bereits an der Cipher-Auswahl.
|
||||
cfg.CipherSuites = legacyCipherSuites()
|
||||
}
|
||||
if caFile == "" {
|
||||
return cfg, nil
|
||||
}
|
||||
|
|
@ -45,10 +71,32 @@ func tlsConfigFor(server, caFile string) (*tls.Config, error) {
|
|||
return cfg, nil
|
||||
}
|
||||
|
||||
// legacyCipherSuites ergänzt Gos sichere Vorgaben um die CBC-SHA256-Suiten,
|
||||
// die Go als unsicher einstuft und deshalb nicht von sich aus anbietet, die
|
||||
// aber auf alten Schannel-Stacks vorkommen.
|
||||
//
|
||||
// Die Suiten mit reinem RSA-Schlüsselaustausch (TLS_RSA_*) sind bewusst NICHT
|
||||
// dabei: Go schaltet sie seit 1.22 unabhängig von dieser Liste ab. Braucht ein
|
||||
// Domain Controller sie zwingend, hilft nur GODEBUG=tlsrsakex=1 in der
|
||||
// systemd-Unit — siehe README.
|
||||
//
|
||||
// Wird nur benutzt, wenn der Betreiber die Mindestversion ausdrücklich unter
|
||||
// TLS 1.2 gesetzt hat.
|
||||
func legacyCipherSuites() []uint16 {
|
||||
out := make([]uint16, 0, len(tls.CipherSuites())+2)
|
||||
for _, cs := range tls.CipherSuites() {
|
||||
out = append(out, cs.ID)
|
||||
}
|
||||
return append(out,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
)
|
||||
}
|
||||
|
||||
// realDialer erzeugt die Dial-Funktion für den Produktivbetrieb.
|
||||
func realDialer(port int, tlsMode, caFile string, timeout time.Duration) func(context.Context, string) (conn, error) {
|
||||
func realDialer(port int, tlsMode, caFile string, minVersion uint16, timeout time.Duration) func(context.Context, string) (conn, error) {
|
||||
return func(ctx context.Context, server string) (conn, error) {
|
||||
tlsCfg, err := tlsConfigFor(server, caFile)
|
||||
tlsCfg, err := tlsConfigFor(server, caFile, minVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
98
internal/auth/dial_test.go
Normal file
98
internal/auth/dial_test.go
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseTLSVersion(t *testing.T) {
|
||||
cases := map[string]uint16{
|
||||
"1.0": tls.VersionTLS10,
|
||||
"1.1": tls.VersionTLS11,
|
||||
"1.2": tls.VersionTLS12,
|
||||
"1.3": tls.VersionTLS13,
|
||||
}
|
||||
for in, want := range cases {
|
||||
if got := ParseTLSVersion(in); got != want {
|
||||
t.Errorf("ParseTLSVersion(%q) = %#04x, want %#04x", in, got, want)
|
||||
}
|
||||
}
|
||||
// Unbekanntes oder leeres Eingaben fallen auf das Sichere zurück.
|
||||
for _, in := range []string{"", "1.4", "unsinn", "TLSv1"} {
|
||||
if got := ParseTLSVersion(in); got != tls.VersionTLS12 {
|
||||
t.Errorf("ParseTLSVersion(%q) = %#04x, want TLS 1.2", in, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSConfigDefaultsToTLS12(t *testing.T) {
|
||||
cfg, err := tlsConfigFor("dc01.firma.local", "", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if cfg.MinVersion != tls.VersionTLS12 {
|
||||
t.Errorf("MinVersion = %#04x, want TLS 1.2", cfg.MinVersion)
|
||||
}
|
||||
if cfg.ServerName != "dc01.firma.local" {
|
||||
t.Errorf("ServerName = %q", cfg.ServerName)
|
||||
}
|
||||
if cfg.InsecureSkipVerify {
|
||||
t.Error("die Zertifikatspruefung darf fuer LDAP niemals abschaltbar sein")
|
||||
}
|
||||
if cfg.CipherSuites != nil {
|
||||
t.Error("bei TLS 1.2+ sollen Gos sichere Vorgaben gelten, keine eigene Liste")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSConfigLegacyAddsCBCSuites(t *testing.T) {
|
||||
cfg, err := tlsConfigFor("dc01.firma.local", "", tls.VersionTLS10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if cfg.MinVersion != tls.VersionTLS10 {
|
||||
t.Errorf("MinVersion = %#04x, want TLS 1.0", cfg.MinVersion)
|
||||
}
|
||||
if cfg.InsecureSkipVerify {
|
||||
t.Error("auch im Legacy-Modus bleibt die Zertifikatspruefung aktiv")
|
||||
}
|
||||
has := func(id uint16) bool {
|
||||
for _, got := range cfg.CipherSuites {
|
||||
if got == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Die CBC-SHA256-Suite fuehrt Go als unsicher und bietet sie sonst nicht an.
|
||||
if !has(tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) {
|
||||
t.Error("ECDHE_RSA_AES_128_CBC_SHA256 fehlt in der Legacy-Liste")
|
||||
}
|
||||
// Die CBC-SHA1-Suiten eines 2012 R2 stecken schon in Gos Vorgaben.
|
||||
if !has(tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) {
|
||||
t.Error("ECDHE_RSA_AES_256_CBC_SHA fehlt — die braucht ein 2012 R2 unter TLS 1.0")
|
||||
}
|
||||
// Die modernen Suiten duerfen im Legacy-Modus nicht wegfallen.
|
||||
if !has(tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) {
|
||||
t.Error("die modernen Suiten duerfen im Legacy-Modus nicht wegfallen")
|
||||
}
|
||||
// Kein reiner RSA-Schluesselaustausch: keine Forward Secrecy, und Go
|
||||
// filtert die Suiten ohnehin weg.
|
||||
for _, id := range []uint16{tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA} {
|
||||
if has(id) {
|
||||
t.Errorf("Suite %#04x ohne Forward Secrecy gehoert nicht in die Liste", id)
|
||||
}
|
||||
}
|
||||
// RC4 und 3DES niemals.
|
||||
for _, id := range []uint16{tls.TLS_RSA_WITH_RC4_128_SHA, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA} {
|
||||
if has(id) {
|
||||
t.Errorf("veraltete Suite %#04x darf nie angeboten werden", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSConfigRejectsBadCAFile(t *testing.T) {
|
||||
if _, err := tlsConfigFor("dc01", "/gibt/es/nicht.pem", tls.VersionTLS12); err == nil {
|
||||
t.Fatal("fehlende CA-Datei muss abgelehnt werden")
|
||||
}
|
||||
}
|
||||
|
|
@ -59,11 +59,15 @@ type OPNsenseConfig struct {
|
|||
}
|
||||
|
||||
type ADConfig struct {
|
||||
Domain string `yaml:"domain"`
|
||||
BaseDN string `yaml:"base_dn"`
|
||||
Servers []string `yaml:"servers"`
|
||||
Port int `yaml:"port"`
|
||||
TLSMode string `yaml:"tls_mode"` // "ldaps" (Default) oder "starttls"
|
||||
Domain string `yaml:"domain"`
|
||||
BaseDN string `yaml:"base_dn"`
|
||||
Servers []string `yaml:"servers"`
|
||||
Port int `yaml:"port"`
|
||||
TLSMode string `yaml:"tls_mode"` // "ldaps" (Default) oder "starttls"
|
||||
// MinTLSVersion ist die niedrigste akzeptierte TLS-Version zum
|
||||
// Verzeichnisdienst: "1.0", "1.1", "1.2" (Default) oder "1.3".
|
||||
// Unter 1.2 nur für Altsysteme, die nichts Besseres können.
|
||||
MinTLSVersion string `yaml:"min_tls_version"`
|
||||
BindUser string `yaml:"bind_user"`
|
||||
BindPassword string `yaml:"bind_password"`
|
||||
BindPasswordFile string `yaml:"bind_password_file"`
|
||||
|
|
@ -94,9 +98,10 @@ func Defaults() *Config {
|
|||
Title: "VPN-Portal",
|
||||
},
|
||||
AD: ADConfig{
|
||||
Port: 636,
|
||||
TLSMode: "ldaps",
|
||||
Timeout: Duration(8 * time.Second),
|
||||
Port: 636,
|
||||
TLSMode: "ldaps",
|
||||
MinTLSVersion: "1.2",
|
||||
Timeout: Duration(8 * time.Second),
|
||||
},
|
||||
Matching: MatchingConfig{CNPattern: "{username}"},
|
||||
Logging: LoggingConfig{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,15 @@ import (
|
|||
// UsernamePlaceholder ist der Platzhalter in matching.cn_pattern.
|
||||
const UsernamePlaceholder = "{username}"
|
||||
|
||||
// MinTLSVersions sind die zulässigen Werte für ad.min_tls_version.
|
||||
var MinTLSVersions = []string{"1.0", "1.1", "1.2", "1.3"}
|
||||
|
||||
// MinTLSVersionIsWeak meldet, ob die konfigurierte Mindestversion unter dem
|
||||
// heutigen Stand der Technik liegt. Das Portal warnt dann bei jedem Start.
|
||||
func (a ADConfig) MinTLSVersionIsWeak() bool {
|
||||
return a.MinTLSVersion == "1.0" || a.MinTLSVersion == "1.1"
|
||||
}
|
||||
|
||||
// BaseDNFromDomain leitet DC=firma,DC=local aus firma.local ab.
|
||||
func BaseDNFromDomain(domain string) (string, error) {
|
||||
domain = strings.Trim(strings.TrimSpace(domain), ".")
|
||||
|
|
@ -101,6 +110,10 @@ func (c *Config) Validate() error {
|
|||
if !slices.Contains([]string{"ldaps", "starttls"}, c.AD.TLSMode) {
|
||||
errs = append(errs, fmt.Errorf("ad.tls_mode %q ist ungültig (erlaubt: ldaps, starttls)", c.AD.TLSMode))
|
||||
}
|
||||
if !slices.Contains(MinTLSVersions, c.AD.MinTLSVersion) {
|
||||
errs = append(errs, fmt.Errorf("ad.min_tls_version %q ist ungültig (erlaubt: %s)",
|
||||
c.AD.MinTLSVersion, strings.Join(MinTLSVersions, ", ")))
|
||||
}
|
||||
if c.AD.Port <= 0 || c.AD.Port > 65535 {
|
||||
errs = append(errs, fmt.Errorf("ad.port %d liegt außerhalb 1–65535", c.AD.Port))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,48 @@ func TestValidateCollectsMultipleErrors(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestMinTLSVersionDefaultsTo12(t *testing.T) {
|
||||
cfg := validCfg(t)
|
||||
if cfg.AD.MinTLSVersion != "1.2" {
|
||||
t.Errorf("MinTLSVersion = %q, want Default 1.2", cfg.AD.MinTLSVersion)
|
||||
}
|
||||
if err := cfg.Validate(); err != nil {
|
||||
t.Fatalf("Default muss gültig sein: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateAcceptsLegacyMinTLSVersions(t *testing.T) {
|
||||
// Alte Domain Controller (z. B. Windows Server 2012 R2 mit abgeschaltetem
|
||||
// TLS 1.2) müssen erreichbar bleiben.
|
||||
for _, v := range []string{"1.0", "1.1", "1.2", "1.3"} {
|
||||
cfg := validCfg(t)
|
||||
cfg.AD.MinTLSVersion = v
|
||||
if err := cfg.Validate(); err != nil {
|
||||
t.Errorf("min_tls_version %q muss zulässig sein: %v", v, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRejectsUnknownMinTLSVersion(t *testing.T) {
|
||||
for _, v := range []string{"1.4", "tls1.2", "TLSv1", "", "12"} {
|
||||
cfg := validCfg(t)
|
||||
cfg.AD.MinTLSVersion = v
|
||||
if err := cfg.Validate(); err == nil {
|
||||
t.Errorf("min_tls_version %q muss abgelehnt werden", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinTLSVersionIsWeakBelow12(t *testing.T) {
|
||||
cfg := validCfg(t)
|
||||
for v, wantWeak := range map[string]bool{"1.0": true, "1.1": true, "1.2": false, "1.3": false} {
|
||||
cfg.AD.MinTLSVersion = v
|
||||
if got := cfg.AD.MinTLSVersionIsWeak(); got != wantWeak {
|
||||
t.Errorf("MinTLSVersionIsWeak() für %q = %v, want %v", v, got, wantWeak)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRejectsPatternWithoutPlaceholder(t *testing.T) {
|
||||
cfg := validCfg(t)
|
||||
cfg.Matching.CNPattern = "fester-cn"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue