mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-20 20:39:08 +02:00
[management] Return the reason when custom domain validation fails (#8122)
* [management] Return the reason when custom domain validation fails The validate endpoint returned an empty 202 and ran the check in a goroutine, so a failed verification only reached the management log. Run the check in the request and return 204 or 412 with a classified reason. Resolver errors are not forwarded. * [management] Address review feedback on custom domain validation Pass the request context to the lookup and store calls now that the check runs in the request, compare the self-resolved name case-insensitively, document the 412 like the other entries, and check the returned error in the existing tests. * [management] Match custom domain CNAME targets case-insensitively DNS names are case-insensitive, so a CNAME pointing at the cluster in different casing should validate instead of failing as a mismatch. * [management] Add validation timeout --------- Co-authored-by: DevBot NetBird <91386968+netbirddev@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,8 @@ package domain_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain"
|
||||
@@ -36,6 +38,12 @@ func TestIsValid(t *testing.T) {
|
||||
accept: []string{"bar.example.com"},
|
||||
expect: false,
|
||||
},
|
||||
"match in other case": {
|
||||
resolver: resolver{"Bar.Example.COM."},
|
||||
domain: "foo.example.com",
|
||||
accept: []string{"bar.example.com"},
|
||||
expect: true,
|
||||
},
|
||||
"accept trailing dot": {
|
||||
resolver: resolver{"bar.example.com."},
|
||||
domain: "foo.example.com",
|
||||
@@ -54,3 +62,61 @@ func TestIsValid(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type errResolver struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (r errResolver) LookupCNAME(context.Context, string) (string, error) {
|
||||
return "", r.err
|
||||
}
|
||||
|
||||
func TestValidate_Reason(t *testing.T) {
|
||||
const notFound = "no CNAME record found for validation.foo.example.com; point it to eu.proxy.example.com"
|
||||
tests := map[string]struct {
|
||||
resolver interface {
|
||||
LookupCNAME(context.Context, string) (string, error)
|
||||
}
|
||||
reason domain.ValidationReason
|
||||
message string
|
||||
}{
|
||||
"mismatch": {
|
||||
resolver: resolver{"other.example.net."},
|
||||
reason: domain.ValidationReasonCNAMEMismatch,
|
||||
message: "CNAME record validation.foo.example.com points to other.example.net; point it to eu.proxy.example.com",
|
||||
},
|
||||
"no cname resolves to itself": {
|
||||
resolver: resolver{"validation.foo.example.com."},
|
||||
reason: domain.ValidationReasonCNAMENotFound,
|
||||
message: notFound,
|
||||
},
|
||||
"no cname resolves to itself in other case": {
|
||||
resolver: resolver{"Validation.Foo.example.com."},
|
||||
reason: domain.ValidationReasonCNAMENotFound,
|
||||
message: notFound,
|
||||
},
|
||||
"not found": {
|
||||
resolver: errResolver{&net.DNSError{Err: "no such host", Name: "validation.foo.example.com", Server: "10.0.0.2:53", IsNotFound: true}},
|
||||
reason: domain.ValidationReasonCNAMENotFound,
|
||||
message: notFound,
|
||||
},
|
||||
"other error is not forwarded": {
|
||||
resolver: errResolver{errors.New("dial udp 10.0.0.2:53: connect: network is unreachable")},
|
||||
reason: domain.ValidationReasonLookupFailed,
|
||||
message: "DNS lookup for validation.foo.example.com failed; retry the validation",
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
_, err := domain.NewValidator(test.resolver).Validate(t.Context(), "foo.example.com", []string{"eu.proxy.example.com"})
|
||||
var vErr *domain.ValidationError
|
||||
if !errors.As(err, &vErr) {
|
||||
t.Fatalf("expected a *domain.ValidationError, got %v", err)
|
||||
}
|
||||
if vErr.Reason != test.reason || vErr.Message != test.message {
|
||||
t.Errorf("expect %q %q, actual %q %q", test.reason, test.message, vErr.Reason, vErr.Message)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user