add status confirmation for certs and tunnel creation

This commit is contained in:
pascal
2026-02-03 16:58:14 +01:00
parent 3af4543e80
commit bffb25bea7
11 changed files with 636 additions and 104 deletions
+38 -10
View File
@@ -5,20 +5,34 @@ import (
"fmt"
"sync"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/acme"
"golang.org/x/crypto/acme/autocert"
)
type certificateNotifier interface {
NotifyCertificateIssued(ctx context.Context, accountID, reverseProxyID, domain string) error
}
type Manager struct {
*autocert.Manager
domainsMux sync.RWMutex
domains map[string]struct{}
domains map[string]struct {
accountID string
reverseProxyID string
}
certNotifier certificateNotifier
}
func NewManager(certDir, acmeURL string) *Manager {
func NewManager(certDir, acmeURL string, notifier certificateNotifier) *Manager {
mgr := &Manager{
domains: make(map[string]struct{}),
domains: make(map[string]struct {
accountID string
reverseProxyID string
}),
certNotifier: notifier,
}
mgr.Manager = &autocert.Manager{
Prompt: autocert.AcceptTOS,
@@ -31,19 +45,33 @@ func NewManager(certDir, acmeURL string) *Manager {
return mgr
}
func (mgr *Manager) hostPolicy(_ context.Context, domain string) error {
func (mgr *Manager) hostPolicy(ctx context.Context, domain string) error {
mgr.domainsMux.RLock()
defer mgr.domainsMux.RUnlock()
if _, exists := mgr.domains[domain]; exists {
return nil
info, exists := mgr.domains[domain]
mgr.domainsMux.RUnlock()
if !exists {
return fmt.Errorf("unknown domain %q", domain)
}
return fmt.Errorf("unknown domain %q", domain)
if mgr.certNotifier != nil {
if err := mgr.certNotifier.NotifyCertificateIssued(ctx, info.accountID, info.reverseProxyID, domain); err != nil {
log.Warnf("failed to notify certificate issued for domain %q: %v", domain, err)
}
}
return nil
}
func (mgr *Manager) AddDomain(domain string) {
func (mgr *Manager) AddDomain(domain, accountID, reverseProxyID string) {
mgr.domainsMux.Lock()
defer mgr.domainsMux.Unlock()
mgr.domains[domain] = struct{}{}
mgr.domains[domain] = struct {
accountID string
reverseProxyID string
}{
accountID: accountID,
reverseProxyID: reverseProxyID,
}
}
func (mgr *Manager) RemoveDomain(domain string) {
+33 -6
View File
@@ -17,6 +17,10 @@ import (
const deviceNamePrefix = "ingress-"
type statusNotifier interface {
NotifyStatus(ctx context.Context, accountID, reverseProxyID, domain string, connected bool) error
}
// NetBird provides an http.RoundTripper implementation
// backed by underlying NetBird connections.
type NetBird struct {
@@ -25,20 +29,23 @@ type NetBird struct {
clientsMux sync.RWMutex
clients map[string]*embed.Client
statusNotifier statusNotifier
}
func NewNetBird(mgmtAddr string, logger *log.Logger) *NetBird {
func NewNetBird(mgmtAddr string, logger *log.Logger, notifier statusNotifier) *NetBird {
if logger == nil {
logger = log.StandardLogger()
}
return &NetBird{
mgmtAddr: mgmtAddr,
logger: logger,
clients: make(map[string]*embed.Client),
mgmtAddr: mgmtAddr,
logger: logger,
clients: make(map[string]*embed.Client),
statusNotifier: notifier,
}
}
func (n *NetBird) AddPeer(ctx context.Context, domain, key string) error {
func (n *NetBird) AddPeer(ctx context.Context, domain, key, accountID, reverseProxyID string) error {
client, err := embed.New(embed.Options{
DeviceName: deviceNamePrefix + domain,
ManagementURL: n.mgmtAddr,
@@ -64,6 +71,16 @@ func (n *NetBird) AddPeer(ctx context.Context, domain, key string) error {
return
case err != nil:
n.logger.WithField("domain", domain).WithError(err).Error("Unable to start netbird client, will try again later.")
return
}
// Notify management that tunnel is now active
if n.statusNotifier != nil {
if err := n.statusNotifier.NotifyStatus(ctx, accountID, reverseProxyID, domain, true); err != nil {
n.logger.WithField("domain", domain).WithError(err).Warn("Failed to notify management about tunnel connection")
} else {
n.logger.WithField("domain", domain).Info("Successfully notified management about tunnel connection")
}
}
}()
@@ -73,7 +90,7 @@ func (n *NetBird) AddPeer(ctx context.Context, domain, key string) error {
return nil
}
func (n *NetBird) RemovePeer(ctx context.Context, domain string) error {
func (n *NetBird) RemovePeer(ctx context.Context, domain, accountID, reverseProxyID string) error {
n.clientsMux.RLock()
client, exists := n.clients[domain]
n.clientsMux.RUnlock()
@@ -84,6 +101,16 @@ func (n *NetBird) RemovePeer(ctx context.Context, domain string) error {
if err := client.Stop(ctx); err != nil {
return fmt.Errorf("stop netbird client: %w", err)
}
// Notify management that tunnel is disconnected
if n.statusNotifier != nil {
if err := n.statusNotifier.NotifyStatus(ctx, accountID, reverseProxyID, domain, false); err != nil {
n.logger.WithField("domain", domain).WithError(err).Warn("Failed to notify management about tunnel disconnection")
} else {
n.logger.WithField("domain", domain).Info("Successfully notified management about tunnel disconnection")
}
}
n.clientsMux.Lock()
defer n.clientsMux.Unlock()
delete(n.clients, domain)