mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 08:16:39 +00:00
rename reverse proxy to services
This commit is contained in:
@@ -115,8 +115,8 @@ type DefaultAccountManager struct {
|
||||
|
||||
var _ account.Manager = (*DefaultAccountManager)(nil)
|
||||
|
||||
func (am *DefaultAccountManager) SetReverseProxyManager(reverseProxyManager reverseproxy.Manager) {
|
||||
am.reverseProxyManager = reverseProxyManager
|
||||
func (am *DefaultAccountManager) SetServiceManager(serviceManager reverseproxy.Manager) {
|
||||
am.reverseProxyManager = serviceManager
|
||||
}
|
||||
|
||||
func isUniqueConstraintError(err error) bool {
|
||||
@@ -327,8 +327,8 @@ func (am *DefaultAccountManager) UpdateAccountSettings(ctx context.Context, acco
|
||||
if err = am.reallocateAccountPeerIPs(ctx, transaction, accountID, newSettings.NetworkRange); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = am.reverseProxyManager.ReloadAllReverseProxiesForAccount(ctx, accountID); err != nil {
|
||||
log.WithContext(ctx).Warnf("failed to reload all reverse proxy for account %s: %v", accountID, err)
|
||||
if err = am.reverseProxyManager.ReloadAllServicesForAccount(ctx, accountID); err != nil {
|
||||
log.WithContext(ctx).Warnf("failed to reload all services for account %s: %v", accountID, err)
|
||||
}
|
||||
updateAccountPeers = true
|
||||
}
|
||||
|
||||
@@ -140,5 +140,5 @@ type Manager interface {
|
||||
CreatePeerJob(ctx context.Context, accountID, peerID, userID string, job *types.Job) error
|
||||
GetAllPeerJobs(ctx context.Context, accountID, userID, peerID string) ([]*types.Job, error)
|
||||
GetPeerJobByID(ctx context.Context, accountID, userID, peerID, jobID string) (*types.Job, error)
|
||||
SetReverseProxyManager(reverseProxyManager reverseproxy.Manager)
|
||||
SetServiceManager(serviceManager reverseproxy.Manager)
|
||||
}
|
||||
|
||||
@@ -204,9 +204,9 @@ const (
|
||||
UserInviteLinkRegenerated Activity = 106
|
||||
UserInviteLinkDeleted Activity = 107
|
||||
|
||||
ReverseProxyCreated Activity = 108
|
||||
ReverseProxyUpdated Activity = 109
|
||||
ReverseProxyDeleted Activity = 110
|
||||
ServiceCreated Activity = 108
|
||||
ServiceUpdated Activity = 109
|
||||
ServiceDeleted Activity = 110
|
||||
|
||||
AccountDeleted Activity = 99999
|
||||
)
|
||||
@@ -342,9 +342,9 @@ var activityMap = map[Activity]Code{
|
||||
UserInviteLinkRegenerated: {"User invite link regenerated", "user.invite.link.regenerate"},
|
||||
UserInviteLinkDeleted: {"User invite link deleted", "user.invite.link.delete"},
|
||||
|
||||
ReverseProxyCreated: {"Reverse proxy created", "reverseproxy.create"},
|
||||
ReverseProxyUpdated: {"Reverse proxy updated", "reverseproxy.update"},
|
||||
ReverseProxyDeleted: {"Reverse proxy deleted", "reverseproxy.delete"},
|
||||
ServiceCreated: {"Service created", "service.create"},
|
||||
ServiceUpdated: {"Service updated", "service.update"},
|
||||
ServiceDeleted: {"Service deleted", "service.delete"},
|
||||
}
|
||||
|
||||
// StringCode returns a string code of the activity
|
||||
|
||||
@@ -198,7 +198,7 @@ func setupAuthCallbackTest(t *testing.T) *testSetup {
|
||||
usersManager,
|
||||
)
|
||||
|
||||
proxyService.SetProxyManager(&testReverseProxyManager{store: testStore})
|
||||
proxyService.SetProxyManager(&testServiceManager{store: testStore})
|
||||
|
||||
handler := NewAuthCallbackHandler(proxyService)
|
||||
|
||||
@@ -227,7 +227,7 @@ func createTestReverseProxies(t *testing.T, ctx context.Context, testStore store
|
||||
pubKey := base64.StdEncoding.EncodeToString(pub)
|
||||
privKey := base64.StdEncoding.EncodeToString(priv)
|
||||
|
||||
testProxy := &reverseproxy.ReverseProxy{
|
||||
testProxy := &reverseproxy.Service{
|
||||
ID: "testProxyId",
|
||||
AccountID: "testAccountId",
|
||||
Name: "Test Proxy",
|
||||
@@ -251,9 +251,9 @@ func createTestReverseProxies(t *testing.T, ctx context.Context, testStore store
|
||||
SessionPrivateKey: privKey,
|
||||
SessionPublicKey: pubKey,
|
||||
}
|
||||
require.NoError(t, testStore.CreateReverseProxy(ctx, testProxy))
|
||||
require.NoError(t, testStore.CreateService(ctx, testProxy))
|
||||
|
||||
restrictedProxy := &reverseproxy.ReverseProxy{
|
||||
restrictedProxy := &reverseproxy.Service{
|
||||
ID: "restrictedProxyId",
|
||||
AccountID: "testAccountId",
|
||||
Name: "Restricted Proxy",
|
||||
@@ -277,9 +277,9 @@ func createTestReverseProxies(t *testing.T, ctx context.Context, testStore store
|
||||
SessionPrivateKey: privKey,
|
||||
SessionPublicKey: pubKey,
|
||||
}
|
||||
require.NoError(t, testStore.CreateReverseProxy(ctx, restrictedProxy))
|
||||
require.NoError(t, testStore.CreateService(ctx, restrictedProxy))
|
||||
|
||||
noAuthProxy := &reverseproxy.ReverseProxy{
|
||||
noAuthProxy := &reverseproxy.Service{
|
||||
ID: "noAuthProxyId",
|
||||
AccountID: "testAccountId",
|
||||
Name: "No Auth Proxy",
|
||||
@@ -302,7 +302,7 @@ func createTestReverseProxies(t *testing.T, ctx context.Context, testStore store
|
||||
SessionPrivateKey: privKey,
|
||||
SessionPublicKey: pubKey,
|
||||
}
|
||||
require.NoError(t, testStore.CreateReverseProxy(ctx, noAuthProxy))
|
||||
require.NoError(t, testStore.CreateService(ctx, noAuthProxy))
|
||||
}
|
||||
|
||||
func strPtr(s string) *string {
|
||||
@@ -340,60 +340,60 @@ func createTestAccountsAndUsers(t *testing.T, ctx context.Context, testStore sto
|
||||
require.NoError(t, testStore.SaveUser(ctx, allowedUser))
|
||||
}
|
||||
|
||||
// testReverseProxyManager is a minimal implementation for testing.
|
||||
type testReverseProxyManager struct {
|
||||
// testServiceManager is a minimal implementation for testing.
|
||||
type testServiceManager struct {
|
||||
store store.Store
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) GetAllReverseProxies(_ context.Context, _, _ string) ([]*reverseproxy.ReverseProxy, error) {
|
||||
func (m *testServiceManager) GetAllServices(_ context.Context, _, _ string) ([]*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) GetReverseProxy(_ context.Context, _, _, _ string) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *testServiceManager) GetService(_ context.Context, _, _, _ string) (*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) CreateReverseProxy(_ context.Context, _, _ string, _ *reverseproxy.ReverseProxy) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *testServiceManager) CreateService(_ context.Context, _, _ string, _ *reverseproxy.Service) (*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) UpdateReverseProxy(_ context.Context, _, _ string, _ *reverseproxy.ReverseProxy) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *testServiceManager) UpdateService(_ context.Context, _, _ string, _ *reverseproxy.Service) (*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) DeleteReverseProxy(_ context.Context, _, _, _ string) error {
|
||||
func (m *testServiceManager) DeleteService(_ context.Context, _, _, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) SetCertificateIssuedAt(_ context.Context, _, _ string) error {
|
||||
func (m *testServiceManager) SetCertificateIssuedAt(_ context.Context, _, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) SetStatus(_ context.Context, _, _ string, _ reverseproxy.ProxyStatus) error {
|
||||
func (m *testServiceManager) SetStatus(_ context.Context, _, _ string, _ reverseproxy.ProxyStatus) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) ReloadAllReverseProxiesForAccount(_ context.Context, _ string) error {
|
||||
func (m *testServiceManager) ReloadAllServicesForAccount(_ context.Context, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) ReloadReverseProxy(_ context.Context, _, _ string) error {
|
||||
func (m *testServiceManager) ReloadService(_ context.Context, _, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) GetGlobalReverseProxies(ctx context.Context) ([]*reverseproxy.ReverseProxy, error) {
|
||||
func (m *testServiceManager) GetGlobalServices(ctx context.Context) ([]*reverseproxy.Service, error) {
|
||||
return m.store.GetReverseProxies(ctx, store.LockingStrengthNone)
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) GetProxyByID(ctx context.Context, accountID, proxyID string) (*reverseproxy.ReverseProxy, error) {
|
||||
return m.store.GetReverseProxyByID(ctx, store.LockingStrengthNone, accountID, proxyID)
|
||||
func (m *testServiceManager) GetServiceByID(ctx context.Context, accountID, proxyID string) (*reverseproxy.Service, error) {
|
||||
return m.store.GetServiceByID(ctx, store.LockingStrengthNone, accountID, proxyID)
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) GetAccountReverseProxies(ctx context.Context, accountID string) ([]*reverseproxy.ReverseProxy, error) {
|
||||
return m.store.GetAccountReverseProxies(ctx, store.LockingStrengthNone, accountID)
|
||||
func (m *testServiceManager) GetAccountServices(ctx context.Context, accountID string) ([]*reverseproxy.Service, error) {
|
||||
return m.store.GetAccountServices(ctx, store.LockingStrengthNone, accountID)
|
||||
}
|
||||
|
||||
func (m *testReverseProxyManager) GetProxyIDByTargetID(_ context.Context, _, _ string) (string, error) {
|
||||
func (m *testServiceManager) GetServiceIDByTargetID(_ context.Context, _, _ string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -446,7 +446,7 @@ func TestAuthCallback_ProxyNotFound(t *testing.T) {
|
||||
|
||||
state := createTestState(t, setup.proxyService, "https://test-proxy.example.com/")
|
||||
|
||||
require.NoError(t, setup.store.DeleteReverseProxy(context.Background(), "testAccountId", "testProxyId"))
|
||||
require.NoError(t, setup.store.DeleteService(context.Background(), "testAccountId", "testProxyId"))
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/reverse-proxy/callback?code=test-auth-code&state="+url.QueryEscape(state), nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
nbdns "github.com/netbirdio/netbird/dns"
|
||||
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy"
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
"github.com/netbirdio/netbird/management/server/activity"
|
||||
"github.com/netbirdio/netbird/management/server/idp"
|
||||
@@ -147,6 +148,10 @@ type MockAccountManager struct {
|
||||
DeleteUserInviteFunc func(ctx context.Context, accountID, initiatorUserID, inviteID string) error
|
||||
}
|
||||
|
||||
func (am *MockAccountManager) SetServiceManager(serviceManager reverseproxy.Manager) {
|
||||
// Mock implementation - no-op
|
||||
}
|
||||
|
||||
func (am *MockAccountManager) CreatePeerJob(ctx context.Context, accountID, peerID, userID string, job *types.Job) error {
|
||||
if am.CreatePeerJobFunc != nil {
|
||||
return am.CreatePeerJobFunc(ctx, accountID, peerID, userID, job)
|
||||
|
||||
@@ -264,7 +264,7 @@ func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resourc
|
||||
|
||||
// TODO: optimize to only reload reverse proxies that are affected by the resource update instead of all of them
|
||||
go func() {
|
||||
err := m.reverseProxyManager.ReloadAllReverseProxiesForAccount(ctx, resource.AccountID)
|
||||
err := m.reverseProxyManager.ReloadAllServicesForAccount(ctx, resource.AccountID)
|
||||
if err != nil {
|
||||
log.WithContext(ctx).Warnf("failed to reload all proxies for account: %v", err)
|
||||
}
|
||||
@@ -322,12 +322,12 @@ func (m *managerImpl) DeleteResource(ctx context.Context, accountID, userID, net
|
||||
return status.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
proxyID, err := m.reverseProxyManager.GetProxyIDByTargetID(ctx, accountID, resourceID)
|
||||
serviceID, err := m.reverseProxyManager.GetServiceIDByTargetID(ctx, accountID, resourceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check if resource is used by reverse proxy: %w", err)
|
||||
return fmt.Errorf("failed to check if resource is used by service: %w", err)
|
||||
}
|
||||
if proxyID != "" {
|
||||
return status.NewResourceInUseError(resourceID, proxyID)
|
||||
if serviceID != "" {
|
||||
return status.NewResourceInUseError(resourceID, serviceID)
|
||||
}
|
||||
|
||||
var events []func()
|
||||
|
||||
@@ -489,12 +489,12 @@ func (am *DefaultAccountManager) DeletePeer(ctx context.Context, accountID, peer
|
||||
var settings *types.Settings
|
||||
var eventsToStore []func()
|
||||
|
||||
proxyID, err := am.reverseProxyManager.GetProxyIDByTargetID(ctx, accountID, peerID)
|
||||
serviceID, err := am.reverseProxyManager.GetServiceIDByTargetID(ctx, accountID, peerID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check if resource is used by reverse proxy: %w", err)
|
||||
return fmt.Errorf("failed to check if resource is used by service: %w", err)
|
||||
}
|
||||
if proxyID != "" {
|
||||
return status.NewPeerInUseError(peerID, proxyID)
|
||||
if serviceID != "" {
|
||||
return status.NewPeerInUseError(peerID, serviceID)
|
||||
}
|
||||
|
||||
err = am.Store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
|
||||
@@ -131,7 +131,7 @@ func NewSqlStore(ctx context.Context, db *gorm.DB, storeEngine types.Engine, met
|
||||
&types.Account{}, &types.Policy{}, &types.PolicyRule{}, &route.Route{}, &nbdns.NameServerGroup{},
|
||||
&installation{}, &types.ExtraSettings{}, &posture.Checks{}, &nbpeer.NetworkAddress{},
|
||||
&networkTypes.Network{}, &routerTypes.NetworkRouter{}, &resourceTypes.NetworkResource{}, &types.AccountOnboarding{},
|
||||
&types.Job{}, &zones.Zone{}, &records.Record{}, &types.UserInviteRecord{}, &reverseproxy.ReverseProxy{}, &reverseproxy.Target{}, &domain.Domain{},
|
||||
&types.Job{}, &zones.Zone{}, &records.Record{}, &types.UserInviteRecord{}, &reverseproxy.Service{}, &reverseproxy.Target{}, &domain.Domain{},
|
||||
&accesslogs.AccessLogEntry{},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -1281,12 +1281,12 @@ func (s *SqlStore) getAccountPgx(ctx context.Context, accountID string) (*types.
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
proxies, err := s.getProxies(ctx, accountID)
|
||||
services, err := s.getServices(ctx, accountID)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
account.ReverseProxies = proxies
|
||||
account.Services = services
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
@@ -2063,39 +2063,39 @@ func (s *SqlStore) getPostureChecks(ctx context.Context, accountID string) ([]*p
|
||||
return checks, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) getProxies(ctx context.Context, accountID string) ([]*reverseproxy.ReverseProxy, error) {
|
||||
const proxyQuery = `SELECT id, account_id, name, domain, enabled, auth,
|
||||
func (s *SqlStore) getServices(ctx context.Context, accountID string) ([]*reverseproxy.Service, error) {
|
||||
const serviceQuery = `SELECT id, account_id, name, domain, enabled, auth,
|
||||
meta_created_at, meta_certificate_issued_at, meta_status, proxy_cluster,
|
||||
pass_host_header, rewrite_redirects, session_private_key, session_public_key
|
||||
FROM reverse_proxies WHERE account_id = $1`
|
||||
FROM services WHERE account_id = $1`
|
||||
|
||||
const targetsQuery = `SELECT id, account_id, reverse_proxy_id, path, host, port, protocol,
|
||||
const targetsQuery = `SELECT id, account_id, service_id, path, host, port, protocol,
|
||||
target_id, target_type, enabled
|
||||
FROM targets WHERE reverse_proxy_id = ANY($1)`
|
||||
FROM targets WHERE service_id = ANY($1)`
|
||||
|
||||
proxyRows, err := s.pool.Query(ctx, proxyQuery, accountID)
|
||||
serviceRows, err := s.pool.Query(ctx, serviceQuery, accountID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
proxies, err := pgx.CollectRows(proxyRows, func(row pgx.CollectableRow) (*reverseproxy.ReverseProxy, error) {
|
||||
var p reverseproxy.ReverseProxy
|
||||
services, err := pgx.CollectRows(serviceRows, func(row pgx.CollectableRow) (*reverseproxy.Service, error) {
|
||||
var s reverseproxy.Service
|
||||
var auth []byte
|
||||
var createdAt, certIssuedAt sql.NullTime
|
||||
var status, proxyCluster, sessionPrivateKey, sessionPublicKey sql.NullString
|
||||
err := row.Scan(
|
||||
&p.ID,
|
||||
&p.AccountID,
|
||||
&p.Name,
|
||||
&p.Domain,
|
||||
&p.Enabled,
|
||||
&s.ID,
|
||||
&s.AccountID,
|
||||
&s.Name,
|
||||
&s.Domain,
|
||||
&s.Enabled,
|
||||
&auth,
|
||||
&createdAt,
|
||||
&certIssuedAt,
|
||||
&status,
|
||||
&proxyCluster,
|
||||
&p.PassHostHeader,
|
||||
&p.RewriteRedirects,
|
||||
&s.PassHostHeader,
|
||||
&s.RewriteRedirects,
|
||||
&sessionPrivateKey,
|
||||
&sessionPublicKey,
|
||||
)
|
||||
@@ -2104,50 +2104,50 @@ func (s *SqlStore) getProxies(ctx context.Context, accountID string) ([]*reverse
|
||||
}
|
||||
|
||||
if auth != nil {
|
||||
if err := json.Unmarshal(auth, &p.Auth); err != nil {
|
||||
if err := json.Unmarshal(auth, &s.Auth); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
p.Meta = reverseproxy.ReverseProxyMeta{}
|
||||
s.Meta = reverseproxy.ServiceMeta{}
|
||||
if createdAt.Valid {
|
||||
p.Meta.CreatedAt = createdAt.Time
|
||||
s.Meta.CreatedAt = createdAt.Time
|
||||
}
|
||||
if certIssuedAt.Valid {
|
||||
p.Meta.CertificateIssuedAt = certIssuedAt.Time
|
||||
s.Meta.CertificateIssuedAt = certIssuedAt.Time
|
||||
}
|
||||
if status.Valid {
|
||||
p.Meta.Status = status.String
|
||||
s.Meta.Status = status.String
|
||||
}
|
||||
if proxyCluster.Valid {
|
||||
p.ProxyCluster = proxyCluster.String
|
||||
s.ProxyCluster = proxyCluster.String
|
||||
}
|
||||
if sessionPrivateKey.Valid {
|
||||
p.SessionPrivateKey = sessionPrivateKey.String
|
||||
s.SessionPrivateKey = sessionPrivateKey.String
|
||||
}
|
||||
if sessionPublicKey.Valid {
|
||||
p.SessionPublicKey = sessionPublicKey.String
|
||||
s.SessionPublicKey = sessionPublicKey.String
|
||||
}
|
||||
|
||||
p.Targets = []*reverseproxy.Target{}
|
||||
return &p, nil
|
||||
s.Targets = []*reverseproxy.Target{}
|
||||
return &s, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(proxies) == 0 {
|
||||
return proxies, nil
|
||||
if len(services) == 0 {
|
||||
return services, nil
|
||||
}
|
||||
|
||||
proxyIDs := make([]string, len(proxies))
|
||||
proxyMap := make(map[string]*reverseproxy.ReverseProxy)
|
||||
for i, p := range proxies {
|
||||
proxyIDs[i] = p.ID
|
||||
proxyMap[p.ID] = p
|
||||
serviceIDs := make([]string, len(services))
|
||||
serviceMap := make(map[string]*reverseproxy.Service)
|
||||
for i, s := range services {
|
||||
serviceIDs[i] = s.ID
|
||||
serviceMap[s.ID] = s
|
||||
}
|
||||
|
||||
targetRows, err := s.pool.Query(ctx, targetsQuery, proxyIDs)
|
||||
targetRows, err := s.pool.Query(ctx, targetsQuery, serviceIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2158,7 +2158,7 @@ func (s *SqlStore) getProxies(ctx context.Context, accountID string) ([]*reverse
|
||||
err := row.Scan(
|
||||
&t.ID,
|
||||
&t.AccountID,
|
||||
&t.ReverseProxyID,
|
||||
&t.ServiceID,
|
||||
&path,
|
||||
&t.Host,
|
||||
&t.Port,
|
||||
@@ -2180,12 +2180,12 @@ func (s *SqlStore) getProxies(ctx context.Context, accountID string) ([]*reverse
|
||||
}
|
||||
|
||||
for _, target := range targets {
|
||||
if proxy, ok := proxyMap[target.ReverseProxyID]; ok {
|
||||
proxy.Targets = append(proxy.Targets, target)
|
||||
if service, ok := serviceMap[target.ServiceID]; ok {
|
||||
service.Targets = append(service.Targets, target)
|
||||
}
|
||||
}
|
||||
|
||||
return proxies, nil
|
||||
return services, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) getNetworks(ctx context.Context, accountID string) ([]*networkTypes.Network, error) {
|
||||
@@ -4825,35 +4825,35 @@ func (s *SqlStore) GetPeerIDByKey(ctx context.Context, lockStrength LockingStren
|
||||
return peerID, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) CreateReverseProxy(ctx context.Context, proxy *reverseproxy.ReverseProxy) error {
|
||||
proxyCopy := proxy.Copy()
|
||||
if err := proxyCopy.EncryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return fmt.Errorf("encrypt reverse proxy data: %w", err)
|
||||
func (s *SqlStore) CreateService(ctx context.Context, service *reverseproxy.Service) error {
|
||||
serviceCopy := service.Copy()
|
||||
if err := serviceCopy.EncryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return fmt.Errorf("encrypt service data: %w", err)
|
||||
}
|
||||
result := s.db.Create(proxyCopy)
|
||||
result := s.db.Create(serviceCopy)
|
||||
if result.Error != nil {
|
||||
log.WithContext(ctx).Errorf("failed to create reverse proxy to store: %v", result.Error)
|
||||
return status.Errorf(status.Internal, "failed to create reverse proxy to store")
|
||||
log.WithContext(ctx).Errorf("failed to create service to store: %v", result.Error)
|
||||
return status.Errorf(status.Internal, "failed to create service to store")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) UpdateReverseProxy(ctx context.Context, proxy *reverseproxy.ReverseProxy) error {
|
||||
proxyCopy := proxy.Copy()
|
||||
if err := proxyCopy.EncryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return fmt.Errorf("encrypt reverse proxy data: %w", err)
|
||||
func (s *SqlStore) UpdateService(ctx context.Context, service *reverseproxy.Service) error {
|
||||
serviceCopy := service.Copy()
|
||||
if err := serviceCopy.EncryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return fmt.Errorf("encrypt service data: %w", err)
|
||||
}
|
||||
|
||||
// Use a transaction to ensure atomic updates of the proxy and its targets
|
||||
// Use a transaction to ensure atomic updates of the service and its targets
|
||||
err := s.db.Transaction(func(tx *gorm.DB) error {
|
||||
// Delete existing targets
|
||||
if err := tx.Where("reverse_proxy_id = ?", proxyCopy.ID).Delete(&reverseproxy.Target{}).Error; err != nil {
|
||||
if err := tx.Where("service_id = ?", serviceCopy.ID).Delete(&reverseproxy.Target{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update the proxy and create new targets
|
||||
if err := tx.Session(&gorm.Session{FullSaveAssociations: true}).Save(proxyCopy).Error; err != nil {
|
||||
// Update the service and create new targets
|
||||
if err := tx.Session(&gorm.Session{FullSaveAssociations: true}).Save(serviceCopy).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4861,112 +4861,112 @@ func (s *SqlStore) UpdateReverseProxy(ctx context.Context, proxy *reverseproxy.R
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.WithContext(ctx).Errorf("failed to update reverse proxy to store: %v", err)
|
||||
return status.Errorf(status.Internal, "failed to update reverse proxy to store")
|
||||
log.WithContext(ctx).Errorf("failed to update service to store: %v", err)
|
||||
return status.Errorf(status.Internal, "failed to update service to store")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) DeleteReverseProxy(ctx context.Context, accountID, proxyID string) error {
|
||||
result := s.db.Delete(&reverseproxy.ReverseProxy{}, accountAndIDQueryCondition, accountID, proxyID)
|
||||
func (s *SqlStore) DeleteService(ctx context.Context, accountID, serviceID string) error {
|
||||
result := s.db.Delete(&reverseproxy.Service{}, accountAndIDQueryCondition, accountID, serviceID)
|
||||
if result.Error != nil {
|
||||
log.WithContext(ctx).Errorf("failed to delete reverse proxy from store: %v", result.Error)
|
||||
return status.Errorf(status.Internal, "failed to delete reverse proxy from store")
|
||||
log.WithContext(ctx).Errorf("failed to delete service from store: %v", result.Error)
|
||||
return status.Errorf(status.Internal, "failed to delete service from store")
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return status.Errorf(status.NotFound, "reverse proxy %s not found", proxyID)
|
||||
return status.Errorf(status.NotFound, "service %s not found", serviceID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetReverseProxyByID(ctx context.Context, lockStrength LockingStrength, accountID, proxyID string) (*reverseproxy.ReverseProxy, error) {
|
||||
func (s *SqlStore) GetServiceByID(ctx context.Context, lockStrength LockingStrength, accountID, serviceID string) (*reverseproxy.Service, error) {
|
||||
tx := s.db.Preload("Targets")
|
||||
if lockStrength != LockingStrengthNone {
|
||||
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
|
||||
}
|
||||
|
||||
var proxy *reverseproxy.ReverseProxy
|
||||
result := tx.Take(&proxy, accountAndIDQueryCondition, accountID, proxyID)
|
||||
var service *reverseproxy.Service
|
||||
result := tx.Take(&service, accountAndIDQueryCondition, accountID, serviceID)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, status.Errorf(status.NotFound, "reverse proxy %s not found", proxyID)
|
||||
return nil, status.Errorf(status.NotFound, "service %s not found", serviceID)
|
||||
}
|
||||
|
||||
log.WithContext(ctx).Errorf("failed to get reverse proxy from store: %v", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get reverse proxy from store")
|
||||
log.WithContext(ctx).Errorf("failed to get service from store: %v", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get service from store")
|
||||
}
|
||||
|
||||
if err := proxy.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return nil, fmt.Errorf("decrypt reverse proxy data: %w", err)
|
||||
if err := service.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return nil, fmt.Errorf("decrypt service data: %w", err)
|
||||
}
|
||||
|
||||
return proxy, nil
|
||||
return service, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetReverseProxyByDomain(ctx context.Context, accountID, domain string) (*reverseproxy.ReverseProxy, error) {
|
||||
var proxy *reverseproxy.ReverseProxy
|
||||
result := s.db.Preload("Targets").Where("account_id = ? AND domain = ?", accountID, domain).First(&proxy)
|
||||
func (s *SqlStore) GetServiceByDomain(ctx context.Context, accountID, domain string) (*reverseproxy.Service, error) {
|
||||
var service *reverseproxy.Service
|
||||
result := s.db.Preload("Targets").Where("account_id = ? AND domain = ?", accountID, domain).First(&service)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, status.Errorf(status.NotFound, "reverse proxy with domain %s not found", domain)
|
||||
return nil, status.Errorf(status.NotFound, "service with domain %s not found", domain)
|
||||
}
|
||||
|
||||
log.WithContext(ctx).Errorf("failed to get reverse proxy by domain from store: %v", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get reverse proxy by domain from store")
|
||||
log.WithContext(ctx).Errorf("failed to get service by domain from store: %v", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get service by domain from store")
|
||||
}
|
||||
|
||||
if err := proxy.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return nil, fmt.Errorf("decrypt reverse proxy data: %w", err)
|
||||
if err := service.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return nil, fmt.Errorf("decrypt service data: %w", err)
|
||||
}
|
||||
|
||||
return proxy, nil
|
||||
return service, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetReverseProxies(ctx context.Context, lockStrength LockingStrength) ([]*reverseproxy.ReverseProxy, error) {
|
||||
func (s *SqlStore) GetServices(ctx context.Context, lockStrength LockingStrength) ([]*reverseproxy.Service, error) {
|
||||
tx := s.db.Preload("Targets")
|
||||
if lockStrength != LockingStrengthNone {
|
||||
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
|
||||
}
|
||||
|
||||
var proxyList []*reverseproxy.ReverseProxy
|
||||
result := tx.Find(&proxyList)
|
||||
var serviceList []*reverseproxy.Service
|
||||
result := tx.Find(&serviceList)
|
||||
if result.Error != nil {
|
||||
log.WithContext(ctx).Errorf("failed to get reverse proxy from the store: %s", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get reverse proxy from store")
|
||||
log.WithContext(ctx).Errorf("failed to get services from the store: %s", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get services from store")
|
||||
}
|
||||
|
||||
for _, proxy := range proxyList {
|
||||
if err := proxy.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return nil, fmt.Errorf("decrypt reverse proxy data: %w", err)
|
||||
for _, service := range serviceList {
|
||||
if err := service.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return nil, fmt.Errorf("decrypt service data: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return proxyList, nil
|
||||
return serviceList, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetAccountReverseProxies(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*reverseproxy.ReverseProxy, error) {
|
||||
func (s *SqlStore) GetAccountServices(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*reverseproxy.Service, error) {
|
||||
tx := s.db.Preload("Targets")
|
||||
if lockStrength != LockingStrengthNone {
|
||||
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
|
||||
}
|
||||
|
||||
var proxyList []*reverseproxy.ReverseProxy
|
||||
result := tx.Find(&proxyList, accountIDCondition, accountID)
|
||||
var serviceList []*reverseproxy.Service
|
||||
result := tx.Find(&serviceList, accountIDCondition, accountID)
|
||||
if result.Error != nil {
|
||||
log.WithContext(ctx).Errorf("failed to get reverse proxy from the store: %s", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get reverse proxy from store")
|
||||
log.WithContext(ctx).Errorf("failed to get services from the store: %s", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get services from store")
|
||||
}
|
||||
|
||||
for _, proxy := range proxyList {
|
||||
if err := proxy.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return nil, fmt.Errorf("decrypt reverse proxy data: %w", err)
|
||||
for _, service := range serviceList {
|
||||
if err := service.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
||||
return nil, fmt.Errorf("decrypt service data: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return proxyList, nil
|
||||
return serviceList, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetCustomDomain(ctx context.Context, accountID string, domainID string) (*domain.Domain, error) {
|
||||
@@ -4976,11 +4976,11 @@ func (s *SqlStore) GetCustomDomain(ctx context.Context, accountID string, domain
|
||||
result := tx.Take(&customDomain, accountAndIDQueryCondition, accountID, domainID)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, status.Errorf(status.NotFound, "reverse proxy custom domain %s not found", domainID)
|
||||
return nil, status.Errorf(status.NotFound, "custom domain %s not found", domainID)
|
||||
}
|
||||
|
||||
log.WithContext(ctx).Errorf("failed to get reverse proxy custom domain from store: %v", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get reverse proxy custom domain from store")
|
||||
log.WithContext(ctx).Errorf("failed to get custom domain from store: %v", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get custom domain from store")
|
||||
}
|
||||
|
||||
return customDomain, nil
|
||||
@@ -5051,10 +5051,10 @@ func (s *SqlStore) CreateAccessLog(ctx context.Context, logEntry *accesslogs.Acc
|
||||
result := s.db.Create(logEntry)
|
||||
if result.Error != nil {
|
||||
log.WithContext(ctx).WithFields(log.Fields{
|
||||
"proxy_id": logEntry.ProxyID,
|
||||
"method": logEntry.Method,
|
||||
"host": logEntry.Host,
|
||||
"path": logEntry.Path,
|
||||
"service_id": logEntry.ServiceID,
|
||||
"method": logEntry.Method,
|
||||
"host": logEntry.Host,
|
||||
"path": logEntry.Path,
|
||||
}).Errorf("failed to create access log entry in store: %v", result.Error)
|
||||
return status.Errorf(status.Internal, "failed to create access log entry in store")
|
||||
}
|
||||
@@ -5154,7 +5154,7 @@ func (s *SqlStore) applyAccessLogFilters(query *gorm.DB, filter accesslogs.Acces
|
||||
return query
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetReverseProxyTargetByTargetID(ctx context.Context, lockStrength LockingStrength, accountID string, targetID string) (*reverseproxy.Target, error) {
|
||||
func (s *SqlStore) GetServiceTargetByTargetID(ctx context.Context, lockStrength LockingStrength, accountID string, targetID string) (*reverseproxy.Target, error) {
|
||||
tx := s.db
|
||||
if lockStrength != LockingStrengthNone {
|
||||
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
|
||||
@@ -5164,11 +5164,11 @@ func (s *SqlStore) GetReverseProxyTargetByTargetID(ctx context.Context, lockStre
|
||||
result := tx.Take(&target, "account_id = ? AND target_id = ?", accountID, targetID)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, status.Errorf(status.NotFound, "reverse proxy target with ID %s not found", targetID)
|
||||
return nil, status.Errorf(status.NotFound, "service target with ID %s not found", targetID)
|
||||
}
|
||||
|
||||
log.WithContext(ctx).Errorf("failed to get reverse proxy target from store: %v", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get reverse proxy target from store")
|
||||
log.WithContext(ctx).Errorf("failed to get service target from store: %v", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get service target from store")
|
||||
}
|
||||
|
||||
return target, nil
|
||||
|
||||
@@ -250,13 +250,13 @@ type Store interface {
|
||||
MarkAllPendingJobsAsFailed(ctx context.Context, accountID, peerID, reason string) error
|
||||
GetPeerIDByKey(ctx context.Context, lockStrength LockingStrength, key string) (string, error)
|
||||
|
||||
CreateReverseProxy(ctx context.Context, service *reverseproxy.ReverseProxy) error
|
||||
UpdateReverseProxy(ctx context.Context, service *reverseproxy.ReverseProxy) error
|
||||
DeleteReverseProxy(ctx context.Context, accountID, serviceID string) error
|
||||
GetReverseProxyByID(ctx context.Context, lockStrength LockingStrength, accountID, serviceID string) (*reverseproxy.ReverseProxy, error)
|
||||
GetReverseProxyByDomain(ctx context.Context, accountID, domain string) (*reverseproxy.ReverseProxy, error)
|
||||
GetReverseProxies(ctx context.Context, lockStrength LockingStrength) ([]*reverseproxy.ReverseProxy, error)
|
||||
GetAccountReverseProxies(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*reverseproxy.ReverseProxy, error)
|
||||
CreateService(ctx context.Context, service *reverseproxy.Service) error
|
||||
UpdateService(ctx context.Context, service *reverseproxy.Service) error
|
||||
DeleteService(ctx context.Context, accountID, serviceID string) error
|
||||
GetServiceByID(ctx context.Context, lockStrength LockingStrength, accountID, serviceID string) (*reverseproxy.Service, error)
|
||||
GetServiceByDomain(ctx context.Context, accountID, domain string) (*reverseproxy.Service, error)
|
||||
GetServices(ctx context.Context, lockStrength LockingStrength) ([]*reverseproxy.Service, error)
|
||||
GetAccountServices(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*reverseproxy.Service, error)
|
||||
|
||||
GetCustomDomain(ctx context.Context, accountID string, domainID string) (*domain.Domain, error)
|
||||
ListFreeDomains(ctx context.Context, accountID string) ([]string, error)
|
||||
@@ -267,7 +267,7 @@ type Store interface {
|
||||
|
||||
CreateAccessLog(ctx context.Context, log *accesslogs.AccessLogEntry) error
|
||||
GetAccountAccessLogs(ctx context.Context, lockStrength LockingStrength, accountID string, filter accesslogs.AccessLogFilter) ([]*accesslogs.AccessLogEntry, int64, error)
|
||||
GetReverseProxyTargetByTargetID(ctx context.Context, lockStrength LockingStrength, accountID string, targetID string) (*reverseproxy.Target, error)
|
||||
GetServiceTargetByTargetID(ctx context.Context, lockStrength LockingStrength, accountID string, targetID string) (*reverseproxy.Target, error)
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -100,7 +100,7 @@ type Account struct {
|
||||
NameServerGroupsG []nbdns.NameServerGroup `json:"-" gorm:"foreignKey:AccountID;references:id"`
|
||||
DNSSettings DNSSettings `gorm:"embedded;embeddedPrefix:dns_settings_"`
|
||||
PostureChecks []*posture.Checks `gorm:"foreignKey:AccountID;references:id"`
|
||||
ReverseProxies []*reverseproxy.ReverseProxy `gorm:"foreignKey:AccountID;references:id"`
|
||||
Services []*reverseproxy.Service `gorm:"foreignKey:AccountID;references:id"`
|
||||
// Settings is a dictionary of Account settings
|
||||
Settings *Settings `gorm:"embedded;embeddedPrefix:settings_"`
|
||||
Networks []*networkTypes.Network `gorm:"foreignKey:AccountID;references:id"`
|
||||
@@ -377,7 +377,7 @@ func (a *Account) GetPeerNetworkMap(
|
||||
// GetProxyConnectionResources returns ACL peers for the proxy-embedded peer based on exposed services.
|
||||
// No firewall rules are generated here; the proxy peer is always a new on-demand client with a stateful
|
||||
// firewall, so OUT rules are unnecessary. Inbound rules are handled on the target/router peer side.
|
||||
func (a *Account) GetProxyConnectionResources(ctx context.Context, exposedServices map[string][]*reverseproxy.ReverseProxy) []*nbpeer.Peer {
|
||||
func (a *Account) GetProxyConnectionResources(ctx context.Context, exposedServices map[string][]*reverseproxy.Service) []*nbpeer.Peer {
|
||||
var aclPeers []*nbpeer.Peer
|
||||
|
||||
for _, peerServices := range exposedServices {
|
||||
@@ -406,7 +406,7 @@ func (a *Account) GetProxyConnectionResources(ctx context.Context, exposedServic
|
||||
// GetPeerProxyResources returns ACL peers and inbound firewall rules for a peer that is targeted by reverse proxy services.
|
||||
// Only IN rules are generated; OUT rules are omitted since proxy peers are always new clients with stateful firewalls.
|
||||
// Rules use PortRange only (not the legacy Port field) as this feature only targets current peer versions.
|
||||
func (a *Account) GetPeerProxyResources(peerID string, services []*reverseproxy.ReverseProxy, proxyPeers []*nbpeer.Peer) ([]*nbpeer.Peer, []*FirewallRule) {
|
||||
func (a *Account) GetPeerProxyResources(peerID string, services []*reverseproxy.Service, proxyPeers []*nbpeer.Peer) ([]*nbpeer.Peer, []*FirewallRule) {
|
||||
var aclPeers []*nbpeer.Peer
|
||||
var firewallRules []*FirewallRule
|
||||
|
||||
@@ -1858,7 +1858,7 @@ func (a *Account) GetProxyPeers() map[string][]*nbpeer.Peer {
|
||||
return proxyPeers
|
||||
}
|
||||
|
||||
func (a *Account) GetPeerProxyRoutes(ctx context.Context, peer *nbpeer.Peer, proxies map[string][]*reverseproxy.ReverseProxy, resourcesMap map[string]*resourceTypes.NetworkResource, routers map[string]map[string]*routerTypes.NetworkRouter, proxyPeers []*nbpeer.Peer) ([]*route.Route, []*RouteFirewallRule, []*nbpeer.Peer) {
|
||||
func (a *Account) GetPeerProxyRoutes(ctx context.Context, peer *nbpeer.Peer, proxies map[string][]*reverseproxy.Service, resourcesMap map[string]*resourceTypes.NetworkResource, routers map[string]map[string]*routerTypes.NetworkRouter, proxyPeers []*nbpeer.Peer) ([]*route.Route, []*RouteFirewallRule, []*nbpeer.Peer) {
|
||||
sourceRanges := make([]string, 0, len(proxyPeers))
|
||||
for _, proxyPeer := range proxyPeers {
|
||||
sourceRanges = append(sourceRanges, fmt.Sprintf(AllowedIPsFormat, proxyPeer.IP))
|
||||
@@ -1924,7 +1924,7 @@ func (a *Account) GetResourcesMap() map[string]*resourceTypes.NetworkResource {
|
||||
}
|
||||
|
||||
func (a *Account) InjectProxyPolicies(ctx context.Context) {
|
||||
if len(a.ReverseProxies) == 0 {
|
||||
if len(a.Services) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1933,7 +1933,7 @@ func (a *Account) InjectProxyPolicies(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, service := range a.ReverseProxies {
|
||||
for _, service := range a.Services {
|
||||
if !service.Enabled {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1,409 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy"
|
||||
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
||||
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
)
|
||||
|
||||
func TestGetProxyConnectionResources_PeerTarget(t *testing.T) {
|
||||
account := &Account{
|
||||
Peers: map[string]*nbpeer.Peer{
|
||||
"target-peer": {ID: "target-peer", IP: net.ParseIP("100.64.0.1")},
|
||||
},
|
||||
}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"target-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "target-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
aclPeers := account.GetProxyConnectionResources(context.Background(), exposedServices)
|
||||
|
||||
require.Len(t, aclPeers, 1)
|
||||
assert.Equal(t, "target-peer", aclPeers[0].ID)
|
||||
}
|
||||
|
||||
func TestGetProxyConnectionResources_DisabledService(t *testing.T) {
|
||||
account := &Account{
|
||||
Peers: map[string]*nbpeer.Peer{
|
||||
"target-peer": {ID: "target-peer", IP: net.ParseIP("100.64.0.1")},
|
||||
},
|
||||
}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"target-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: false,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "target-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
aclPeers := account.GetProxyConnectionResources(context.Background(), exposedServices)
|
||||
assert.Empty(t, aclPeers)
|
||||
}
|
||||
|
||||
func TestGetProxyConnectionResources_ResourceTargetSkipped(t *testing.T) {
|
||||
account := &Account{
|
||||
Peers: map[string]*nbpeer.Peer{
|
||||
"router-peer": {ID: "router-peer", IP: net.ParseIP("100.64.0.2")},
|
||||
},
|
||||
}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"router-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
aclPeers := account.GetProxyConnectionResources(context.Background(), exposedServices)
|
||||
assert.Empty(t, aclPeers, "resource targets should not add ACL peers via GetProxyConnectionResources")
|
||||
}
|
||||
|
||||
func TestGetPeerProxyResources_PeerTarget(t *testing.T) {
|
||||
proxyPeers := []*nbpeer.Peer{
|
||||
{ID: "proxy-peer-1", IP: net.ParseIP("100.64.0.10")},
|
||||
{ID: "proxy-peer-2", IP: net.ParseIP("100.64.0.11")},
|
||||
}
|
||||
|
||||
services := []*reverseproxy.ReverseProxy{
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "target-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
account := &Account{}
|
||||
aclPeers, fwRules := account.GetPeerProxyResources("target-peer", services, proxyPeers)
|
||||
|
||||
require.Len(t, aclPeers, 2, "should include all proxy peers")
|
||||
require.Len(t, fwRules, 2, "should have one IN rule per proxy peer")
|
||||
|
||||
for i, rule := range fwRules {
|
||||
assert.Equal(t, "proxy-proxy-1", rule.PolicyID)
|
||||
assert.Equal(t, proxyPeers[i].IP.String(), rule.PeerIP)
|
||||
assert.Equal(t, FirewallRuleDirectionIN, rule.Direction)
|
||||
assert.Equal(t, "allow", rule.Action)
|
||||
assert.Equal(t, string(PolicyRuleProtocolTCP), rule.Protocol)
|
||||
assert.Equal(t, uint16(8080), rule.PortRange.Start)
|
||||
assert.Equal(t, uint16(8080), rule.PortRange.End)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPeerProxyResources_PeerTargetMismatch(t *testing.T) {
|
||||
proxyPeers := []*nbpeer.Peer{
|
||||
{ID: "proxy-peer-1", IP: net.ParseIP("100.64.0.10")},
|
||||
}
|
||||
|
||||
services := []*reverseproxy.ReverseProxy{
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "other-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
account := &Account{}
|
||||
aclPeers, fwRules := account.GetPeerProxyResources("target-peer", services, proxyPeers)
|
||||
|
||||
require.Len(t, aclPeers, 1, "should still add proxy peers to ACL")
|
||||
assert.Empty(t, fwRules, "should not generate rules when target doesn't match this peer")
|
||||
}
|
||||
|
||||
func TestGetPeerProxyResources_ResourceAccessLocal(t *testing.T) {
|
||||
proxyPeers := []*nbpeer.Peer{
|
||||
{ID: "proxy-peer-1", IP: net.ParseIP("100.64.0.10")},
|
||||
}
|
||||
|
||||
services := []*reverseproxy.ReverseProxy{
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
AccessLocal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
account := &Account{}
|
||||
aclPeers, fwRules := account.GetPeerProxyResources("router-peer", services, proxyPeers)
|
||||
|
||||
require.Len(t, aclPeers, 1, "should include proxy peers in ACL")
|
||||
require.Len(t, fwRules, 1, "should generate IN rule for AccessLocal resource")
|
||||
|
||||
rule := fwRules[0]
|
||||
assert.Equal(t, "proxy-proxy-1", rule.PolicyID)
|
||||
assert.Equal(t, "100.64.0.10", rule.PeerIP)
|
||||
assert.Equal(t, FirewallRuleDirectionIN, rule.Direction)
|
||||
assert.Equal(t, uint16(443), rule.PortRange.Start)
|
||||
}
|
||||
|
||||
func TestGetPeerProxyResources_ResourceWithoutAccessLocal(t *testing.T) {
|
||||
proxyPeers := []*nbpeer.Peer{
|
||||
{ID: "proxy-peer-1", IP: net.ParseIP("100.64.0.10")},
|
||||
}
|
||||
|
||||
services := []*reverseproxy.ReverseProxy{
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
AccessLocal: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
account := &Account{}
|
||||
aclPeers, fwRules := account.GetPeerProxyResources("router-peer", services, proxyPeers)
|
||||
|
||||
require.Len(t, aclPeers, 1, "should still include proxy peers in ACL")
|
||||
assert.Empty(t, fwRules, "should not generate peer rules when AccessLocal is false")
|
||||
}
|
||||
|
||||
func TestGetPeerProxyResources_MixedTargets(t *testing.T) {
|
||||
proxyPeers := []*nbpeer.Peer{
|
||||
{ID: "proxy-peer-1", IP: net.ParseIP("100.64.0.10")},
|
||||
}
|
||||
|
||||
services := []*reverseproxy.ReverseProxy{
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "target-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
AccessLocal: true,
|
||||
},
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-2",
|
||||
Port: 8443,
|
||||
Enabled: true,
|
||||
AccessLocal: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
account := &Account{}
|
||||
aclPeers, fwRules := account.GetPeerProxyResources("target-peer", services, proxyPeers)
|
||||
|
||||
require.Len(t, aclPeers, 1)
|
||||
require.Len(t, fwRules, 2, "should have rules for peer target + AccessLocal resource")
|
||||
|
||||
ports := []uint16{fwRules[0].PortRange.Start, fwRules[1].PortRange.Start}
|
||||
assert.Contains(t, ports, uint16(8080), "should include peer target port")
|
||||
assert.Contains(t, ports, uint16(443), "should include AccessLocal resource port")
|
||||
}
|
||||
|
||||
func newProxyRoutesTestAccount() *Account {
|
||||
return &Account{
|
||||
Peers: map[string]*nbpeer.Peer{
|
||||
"router-peer": {ID: "router-peer", Key: "router-key", IP: net.ParseIP("100.64.0.2")},
|
||||
"proxy-peer": {ID: "proxy-peer", Key: "proxy-key", IP: net.ParseIP("100.64.0.10")},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPeerProxyRoutes_ResourceWithoutAccessLocal(t *testing.T) {
|
||||
account := newProxyRoutesTestAccount()
|
||||
proxyPeers := []*nbpeer.Peer{account.Peers["proxy-peer"]}
|
||||
|
||||
resourcesMap := map[string]*resourceTypes.NetworkResource{
|
||||
"resource-1": {
|
||||
ID: "resource-1",
|
||||
AccountID: "accountID",
|
||||
NetworkID: "net-1",
|
||||
Name: "web-service",
|
||||
Type: resourceTypes.Host,
|
||||
Prefix: netip.MustParsePrefix("192.168.1.100/32"),
|
||||
Enabled: true,
|
||||
},
|
||||
}
|
||||
routers := map[string]map[string]*routerTypes.NetworkRouter{
|
||||
"net-1": {
|
||||
"router-peer": {ID: "router-1", NetworkID: "net-1", Peer: "router-peer", Masquerade: true, Metric: 100},
|
||||
},
|
||||
}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"router-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
AccessLocal: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
routes, routeFwRules, aclPeers := account.GetPeerProxyRoutes(context.Background(), account.Peers["proxy-peer"], exposedServices, resourcesMap, routers, proxyPeers)
|
||||
|
||||
require.NotEmpty(t, routes, "should generate routes for non-AccessLocal resource")
|
||||
require.NotEmpty(t, routeFwRules, "should generate route firewall rules for non-AccessLocal resource")
|
||||
require.NotEmpty(t, aclPeers, "should include router peer in ACL")
|
||||
|
||||
assert.Equal(t, uint16(443), routeFwRules[0].PortRange.Start)
|
||||
assert.Equal(t, "192.168.1.100/32", routeFwRules[0].Destination)
|
||||
}
|
||||
|
||||
func TestGetPeerProxyRoutes_ResourceWithAccessLocal(t *testing.T) {
|
||||
account := newProxyRoutesTestAccount()
|
||||
proxyPeers := []*nbpeer.Peer{account.Peers["proxy-peer"]}
|
||||
|
||||
resourcesMap := map[string]*resourceTypes.NetworkResource{
|
||||
"resource-1": {
|
||||
ID: "resource-1",
|
||||
AccountID: "accountID",
|
||||
NetworkID: "net-1",
|
||||
Name: "local-service",
|
||||
Type: resourceTypes.Host,
|
||||
Prefix: netip.MustParsePrefix("192.168.1.100/32"),
|
||||
Enabled: true,
|
||||
},
|
||||
}
|
||||
routers := map[string]map[string]*routerTypes.NetworkRouter{
|
||||
"net-1": {
|
||||
"router-peer": {ID: "router-1", NetworkID: "net-1", Peer: "router-peer", Masquerade: true, Metric: 100},
|
||||
},
|
||||
}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"router-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypeResource,
|
||||
TargetId: "resource-1",
|
||||
Port: 443,
|
||||
Enabled: true,
|
||||
AccessLocal: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
routes, routeFwRules, aclPeers := account.GetPeerProxyRoutes(context.Background(), account.Peers["proxy-peer"], exposedServices, resourcesMap, routers, proxyPeers)
|
||||
|
||||
require.NotEmpty(t, routes, "should generate routes for AccessLocal resource")
|
||||
require.NotEmpty(t, routeFwRules, "should generate route firewall rules for AccessLocal resource")
|
||||
require.NotEmpty(t, aclPeers, "should include router peer in ACL for AccessLocal resource")
|
||||
|
||||
assert.Equal(t, uint16(443), routeFwRules[0].PortRange.Start)
|
||||
assert.Equal(t, "192.168.1.100/32", routeFwRules[0].Destination)
|
||||
}
|
||||
|
||||
func TestGetPeerProxyRoutes_PeerTargetSkipped(t *testing.T) {
|
||||
account := newProxyRoutesTestAccount()
|
||||
proxyPeers := []*nbpeer.Peer{account.Peers["proxy-peer"]}
|
||||
|
||||
exposedServices := map[string][]*reverseproxy.ReverseProxy{
|
||||
"router-peer": {
|
||||
{
|
||||
ID: "proxy-1",
|
||||
Enabled: true,
|
||||
Targets: []reverseproxy.Target{
|
||||
{
|
||||
TargetType: reverseproxy.TargetTypePeer,
|
||||
TargetId: "target-peer",
|
||||
Port: 8080,
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
routes, routeFwRules, aclPeers := account.GetPeerProxyRoutes(context.Background(), account.Peers["proxy-peer"], exposedServices, nil, nil, proxyPeers)
|
||||
|
||||
assert.Empty(t, routes, "should NOT generate routes for peer targets")
|
||||
assert.Empty(t, routeFwRules, "should NOT generate route firewall rules for peer targets")
|
||||
assert.Empty(t, aclPeers)
|
||||
}
|
||||
Reference in New Issue
Block a user