[management,proxy,client] Add L4 capabilities (TLS/TCP/UDP) (#5530)

This commit is contained in:
Viktor Liu
2026-03-13 18:36:44 +01:00
committed by GitHub
parent fe9b844511
commit 3e6baea405
90 changed files with 9610 additions and 1396 deletions
+5 -4
View File
@@ -23,6 +23,7 @@ import (
"golang.org/x/crypto/acme/autocert"
"github.com/netbirdio/netbird/proxy/internal/certwatch"
"github.com/netbirdio/netbird/proxy/internal/types"
"github.com/netbirdio/netbird/shared/management/domain"
)
@@ -30,7 +31,7 @@ import (
var oidSCTList = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2}
type certificateNotifier interface {
NotifyCertificateIssued(ctx context.Context, accountID, serviceID, domain string) error
NotifyCertificateIssued(ctx context.Context, accountID types.AccountID, serviceID types.ServiceID, domain string) error
}
type domainState int
@@ -42,8 +43,8 @@ const (
)
type domainInfo struct {
accountID string
serviceID string
accountID types.AccountID
serviceID types.ServiceID
state domainState
err string
}
@@ -301,7 +302,7 @@ func (mgr *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate
// When AddDomain returns true the caller is responsible for sending any
// certificate-ready notifications after the surrounding operation (e.g.
// mapping update) has committed successfully.
func (mgr *Manager) AddDomain(d domain.Domain, accountID, serviceID string) (wildcardHit bool) {
func (mgr *Manager) AddDomain(d domain.Domain, accountID types.AccountID, serviceID types.ServiceID) (wildcardHit bool) {
name := d.PunycodeString()
if e := mgr.findWildcardEntry(name); e != nil {
mgr.mu.Lock()
+11 -9
View File
@@ -17,12 +17,14 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/netbirdio/netbird/proxy/internal/types"
)
func TestHostPolicy(t *testing.T) {
mgr, err := NewManager(ManagerConfig{CertDir: t.TempDir(), ACMEURL: "https://acme.example.com/directory"}, nil, nil, nil)
require.NoError(t, err)
mgr.AddDomain("example.com", "acc1", "rp1")
mgr.AddDomain("example.com", types.AccountID("acc1"), types.ServiceID("rp1"))
// Wait for the background prefetch goroutine to finish so the temp dir
// can be cleaned up without a race.
@@ -92,8 +94,8 @@ func TestDomainStates(t *testing.T) {
// AddDomain starts as pending, then the prefetch goroutine will fail
// (no real ACME server) and transition to failed.
mgr.AddDomain("a.example.com", "acc1", "rp1")
mgr.AddDomain("b.example.com", "acc1", "rp1")
mgr.AddDomain("a.example.com", types.AccountID("acc1"), types.ServiceID("rp1"))
mgr.AddDomain("b.example.com", types.AccountID("acc1"), types.ServiceID("rp1"))
assert.Equal(t, 2, mgr.TotalDomains(), "two domains registered")
@@ -209,12 +211,12 @@ func TestWildcardAddDomainSkipsACME(t *testing.T) {
require.NoError(t, err)
// Add a wildcard-matching domain — should be immediately ready.
mgr.AddDomain("foo.example.com", "acc1", "svc1")
mgr.AddDomain("foo.example.com", types.AccountID("acc1"), types.ServiceID("svc1"))
assert.Equal(t, 0, mgr.PendingCerts(), "wildcard domain should not be pending")
assert.Equal(t, []string{"foo.example.com"}, mgr.ReadyDomains())
// Add a non-wildcard domain — should go through ACME (pending then failed).
mgr.AddDomain("other.net", "acc2", "svc2")
mgr.AddDomain("other.net", types.AccountID("acc2"), types.ServiceID("svc2"))
assert.Equal(t, 2, mgr.TotalDomains())
// Wait for the ACME prefetch to fail.
@@ -234,7 +236,7 @@ func TestWildcardGetCertificate(t *testing.T) {
mgr, err := NewManager(ManagerConfig{CertDir: acmeDir, ACMEURL: "https://acme.example.com/directory", WildcardDir: wcDir}, nil, nil, nil)
require.NoError(t, err)
mgr.AddDomain("foo.example.com", "acc1", "svc1")
mgr.AddDomain("foo.example.com", types.AccountID("acc1"), types.ServiceID("svc1"))
// GetCertificate for a wildcard-matching domain should return the static cert.
cert, err := mgr.GetCertificate(&tls.ClientHelloInfo{ServerName: "foo.example.com"})
@@ -255,8 +257,8 @@ func TestMultipleWildcards(t *testing.T) {
assert.ElementsMatch(t, []string{"*.example.com", "*.other.org"}, mgr.WildcardPatterns())
// Both wildcards should resolve.
mgr.AddDomain("foo.example.com", "acc1", "svc1")
mgr.AddDomain("bar.other.org", "acc2", "svc2")
mgr.AddDomain("foo.example.com", types.AccountID("acc1"), types.ServiceID("svc1"))
mgr.AddDomain("bar.other.org", types.AccountID("acc2"), types.ServiceID("svc2"))
assert.Equal(t, 0, mgr.PendingCerts())
assert.ElementsMatch(t, []string{"foo.example.com", "bar.other.org"}, mgr.ReadyDomains())
@@ -271,7 +273,7 @@ func TestMultipleWildcards(t *testing.T) {
assert.Contains(t, cert2.Leaf.DNSNames, "*.other.org")
// Non-matching domain falls through to ACME.
mgr.AddDomain("custom.net", "acc3", "svc3")
mgr.AddDomain("custom.net", types.AccountID("acc3"), types.ServiceID("svc3"))
assert.Eventually(t, func() bool {
return mgr.PendingCerts() == 0
}, 30*time.Second, 100*time.Millisecond)