mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 07:16:38 +00:00
rename reverse proxy to services
This commit is contained in:
@@ -13,7 +13,7 @@ import (
|
||||
type AccessLogEntry struct {
|
||||
ID string `gorm:"primaryKey"`
|
||||
AccountID string `gorm:"index"`
|
||||
ProxyID string `gorm:"index"`
|
||||
ServiceID string `gorm:"index"`
|
||||
Timestamp time.Time `gorm:"index"`
|
||||
GeoLocation peer.Location `gorm:"embedded;embeddedPrefix:location_"`
|
||||
Method string `gorm:"index"`
|
||||
@@ -27,28 +27,28 @@ type AccessLogEntry struct {
|
||||
}
|
||||
|
||||
// FromProto creates an AccessLogEntry from a proto.AccessLog
|
||||
func (a *AccessLogEntry) FromProto(proxyLog *proto.AccessLog) {
|
||||
a.ID = proxyLog.GetLogId()
|
||||
a.ProxyID = proxyLog.GetServiceId()
|
||||
a.Timestamp = proxyLog.GetTimestamp().AsTime()
|
||||
a.Method = proxyLog.GetMethod()
|
||||
a.Host = proxyLog.GetHost()
|
||||
a.Path = proxyLog.GetPath()
|
||||
a.Duration = time.Duration(proxyLog.GetDurationMs()) * time.Millisecond
|
||||
a.StatusCode = int(proxyLog.GetResponseCode())
|
||||
a.UserId = proxyLog.GetUserId()
|
||||
a.AuthMethodUsed = proxyLog.GetAuthMechanism()
|
||||
a.AccountID = proxyLog.GetAccountId()
|
||||
func (a *AccessLogEntry) FromProto(serviceLog *proto.AccessLog) {
|
||||
a.ID = serviceLog.GetLogId()
|
||||
a.ServiceID = serviceLog.GetServiceId()
|
||||
a.Timestamp = serviceLog.GetTimestamp().AsTime()
|
||||
a.Method = serviceLog.GetMethod()
|
||||
a.Host = serviceLog.GetHost()
|
||||
a.Path = serviceLog.GetPath()
|
||||
a.Duration = time.Duration(serviceLog.GetDurationMs()) * time.Millisecond
|
||||
a.StatusCode = int(serviceLog.GetResponseCode())
|
||||
a.UserId = serviceLog.GetUserId()
|
||||
a.AuthMethodUsed = serviceLog.GetAuthMechanism()
|
||||
a.AccountID = serviceLog.GetAccountId()
|
||||
|
||||
if sourceIP := proxyLog.GetSourceIp(); sourceIP != "" {
|
||||
if sourceIP := serviceLog.GetSourceIp(); sourceIP != "" {
|
||||
if ip, err := netip.ParseAddr(sourceIP); err == nil {
|
||||
a.GeoLocation.ConnectionIP = net.IP(ip.AsSlice())
|
||||
}
|
||||
}
|
||||
|
||||
if !proxyLog.GetAuthSuccess() {
|
||||
if !serviceLog.GetAuthSuccess() {
|
||||
a.Reason = "Authentication failed"
|
||||
} else if proxyLog.GetResponseCode() >= 400 {
|
||||
} else if serviceLog.GetResponseCode() >= 400 {
|
||||
a.Reason = "Request failed"
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ func (a *AccessLogEntry) ToAPIResponse() *api.ProxyAccessLog {
|
||||
|
||||
return &api.ProxyAccessLog{
|
||||
Id: a.ID,
|
||||
ProxyId: a.ProxyID,
|
||||
ServiceId: a.ServiceID,
|
||||
Timestamp: a.Timestamp,
|
||||
Method: a.Method,
|
||||
Host: a.Host,
|
||||
|
||||
@@ -44,11 +44,11 @@ func (m *managerImpl) SaveAccessLog(ctx context.Context, logEntry *accesslogs.Ac
|
||||
|
||||
if err := m.store.CreateAccessLog(ctx, logEntry); err != nil {
|
||||
log.WithContext(ctx).WithFields(log.Fields{
|
||||
"proxy_id": logEntry.ProxyID,
|
||||
"method": logEntry.Method,
|
||||
"host": logEntry.Host,
|
||||
"path": logEntry.Path,
|
||||
"status": logEntry.StatusCode,
|
||||
"service_id": logEntry.ServiceID,
|
||||
"method": logEntry.Method,
|
||||
"host": logEntry.Host,
|
||||
"path": logEntry.Path,
|
||||
"status": logEntry.StatusCode,
|
||||
}).Errorf("failed to save access log: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@ import (
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
GetAllReverseProxies(ctx context.Context, accountID, userID string) ([]*ReverseProxy, error)
|
||||
GetReverseProxy(ctx context.Context, accountID, userID, reverseProxyID string) (*ReverseProxy, error)
|
||||
CreateReverseProxy(ctx context.Context, accountID, userID string, reverseProxy *ReverseProxy) (*ReverseProxy, error)
|
||||
UpdateReverseProxy(ctx context.Context, accountID, userID string, reverseProxy *ReverseProxy) (*ReverseProxy, error)
|
||||
DeleteReverseProxy(ctx context.Context, accountID, userID, reverseProxyID string) error
|
||||
SetCertificateIssuedAt(ctx context.Context, accountID, reverseProxyID string) error
|
||||
SetStatus(ctx context.Context, accountID, reverseProxyID string, status ProxyStatus) error
|
||||
ReloadAllReverseProxiesForAccount(ctx context.Context, accountID string) error
|
||||
ReloadReverseProxy(ctx context.Context, accountID, reverseProxyID string) error
|
||||
GetGlobalReverseProxies(ctx context.Context) ([]*ReverseProxy, error)
|
||||
GetProxyByID(ctx context.Context, accountID, reverseProxyID string) (*ReverseProxy, error)
|
||||
GetAccountReverseProxies(ctx context.Context, accountID string) ([]*ReverseProxy, error)
|
||||
GetProxyIDByTargetID(ctx context.Context, accountID string, resourceID string) (string, error)
|
||||
GetAllServices(ctx context.Context, accountID, userID string) ([]*Service, error)
|
||||
GetService(ctx context.Context, accountID, userID, serviceID string) (*Service, error)
|
||||
CreateService(ctx context.Context, accountID, userID string, service *Service) (*Service, error)
|
||||
UpdateService(ctx context.Context, accountID, userID string, service *Service) (*Service, error)
|
||||
DeleteService(ctx context.Context, accountID, userID, serviceID string) error
|
||||
SetCertificateIssuedAt(ctx context.Context, accountID, serviceID string) error
|
||||
SetStatus(ctx context.Context, accountID, serviceID string, status ProxyStatus) error
|
||||
ReloadAllServicesForAccount(ctx context.Context, accountID string) error
|
||||
ReloadService(ctx context.Context, accountID, serviceID string) error
|
||||
GetGlobalServices(ctx context.Context) ([]*Service, error)
|
||||
GetServiceByID(ctx context.Context, accountID, serviceID string) (*Service, error)
|
||||
GetAccountServices(ctx context.Context, accountID string) ([]*Service, error)
|
||||
GetServiceIDByTargetID(ctx context.Context, accountID string, resourceID string) (string, error)
|
||||
}
|
||||
|
||||
@@ -20,148 +20,148 @@ type handler struct {
|
||||
manager reverseproxy.Manager
|
||||
}
|
||||
|
||||
// RegisterEndpoints registers all reverse proxy HTTP endpoints.
|
||||
// RegisterEndpoints registers all service HTTP endpoints.
|
||||
func RegisterEndpoints(manager reverseproxy.Manager, domainManager domain.Manager, accessLogsManager accesslogs.Manager, router *mux.Router) {
|
||||
h := &handler{
|
||||
manager: manager,
|
||||
}
|
||||
|
||||
domainRouter := router.PathPrefix("/reverse-proxies").Subrouter()
|
||||
domainRouter := router.PathPrefix("/services").Subrouter()
|
||||
domain.RegisterEndpoints(domainRouter, domainManager)
|
||||
|
||||
accesslogsmanager.RegisterEndpoints(router, accessLogsManager)
|
||||
|
||||
router.HandleFunc("/reverse-proxies", h.getAllReverseProxies).Methods("GET", "OPTIONS")
|
||||
router.HandleFunc("/reverse-proxies", h.createReverseProxy).Methods("POST", "OPTIONS")
|
||||
router.HandleFunc("/reverse-proxies/{proxyId}", h.getReverseProxy).Methods("GET", "OPTIONS")
|
||||
router.HandleFunc("/reverse-proxies/{proxyId}", h.updateReverseProxy).Methods("PUT", "OPTIONS")
|
||||
router.HandleFunc("/reverse-proxies/{proxyId}", h.deleteReverseProxy).Methods("DELETE", "OPTIONS")
|
||||
router.HandleFunc("/services", h.getAllServices).Methods("GET", "OPTIONS")
|
||||
router.HandleFunc("/services", h.createService).Methods("POST", "OPTIONS")
|
||||
router.HandleFunc("/services/{serviceId}", h.getService).Methods("GET", "OPTIONS")
|
||||
router.HandleFunc("/services/{serviceId}", h.updateService).Methods("PUT", "OPTIONS")
|
||||
router.HandleFunc("/services/{serviceId}", h.deleteService).Methods("DELETE", "OPTIONS")
|
||||
}
|
||||
|
||||
func (h *handler) getAllReverseProxies(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *handler) getAllServices(w http.ResponseWriter, r *http.Request) {
|
||||
userAuth, err := nbcontext.GetUserAuthFromContext(r.Context())
|
||||
if err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
return
|
||||
}
|
||||
|
||||
allReverseProxies, err := h.manager.GetAllReverseProxies(r.Context(), userAuth.AccountId, userAuth.UserId)
|
||||
allServices, err := h.manager.GetAllServices(r.Context(), userAuth.AccountId, userAuth.UserId)
|
||||
if err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
return
|
||||
}
|
||||
|
||||
apiReverseProxies := make([]*api.ReverseProxy, 0, len(allReverseProxies))
|
||||
for _, reverseProxy := range allReverseProxies {
|
||||
apiReverseProxies = append(apiReverseProxies, reverseProxy.ToAPIResponse())
|
||||
apiServices := make([]*api.Service, 0, len(allServices))
|
||||
for _, service := range allServices {
|
||||
apiServices = append(apiServices, service.ToAPIResponse())
|
||||
}
|
||||
|
||||
util.WriteJSONObject(r.Context(), w, apiReverseProxies)
|
||||
util.WriteJSONObject(r.Context(), w, apiServices)
|
||||
}
|
||||
|
||||
func (h *handler) createReverseProxy(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *handler) createService(w http.ResponseWriter, r *http.Request) {
|
||||
userAuth, err := nbcontext.GetUserAuthFromContext(r.Context())
|
||||
if err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
return
|
||||
}
|
||||
|
||||
var req api.ReverseProxyRequest
|
||||
var req api.ServiceRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w)
|
||||
return
|
||||
}
|
||||
|
||||
reverseProxy := new(reverseproxy.ReverseProxy)
|
||||
reverseProxy.FromAPIRequest(&req, userAuth.AccountId)
|
||||
service := new(reverseproxy.Service)
|
||||
service.FromAPIRequest(&req, userAuth.AccountId)
|
||||
|
||||
if err = reverseProxy.Validate(); err != nil {
|
||||
if err = service.Validate(); err != nil {
|
||||
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "%s", err.Error()), w)
|
||||
return
|
||||
}
|
||||
|
||||
createdReverseProxy, err := h.manager.CreateReverseProxy(r.Context(), userAuth.AccountId, userAuth.UserId, reverseProxy)
|
||||
createdService, err := h.manager.CreateService(r.Context(), userAuth.AccountId, userAuth.UserId, service)
|
||||
if err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
return
|
||||
}
|
||||
|
||||
util.WriteJSONObject(r.Context(), w, createdReverseProxy.ToAPIResponse())
|
||||
util.WriteJSONObject(r.Context(), w, createdService.ToAPIResponse())
|
||||
}
|
||||
|
||||
func (h *handler) getReverseProxy(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *handler) getService(w http.ResponseWriter, r *http.Request) {
|
||||
userAuth, err := nbcontext.GetUserAuthFromContext(r.Context())
|
||||
if err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
return
|
||||
}
|
||||
|
||||
reverseProxyID := mux.Vars(r)["proxyId"]
|
||||
if reverseProxyID == "" {
|
||||
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "reverse proxy ID is required"), w)
|
||||
serviceID := mux.Vars(r)["serviceId"]
|
||||
if serviceID == "" {
|
||||
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "service ID is required"), w)
|
||||
return
|
||||
}
|
||||
|
||||
reverseProxy, err := h.manager.GetReverseProxy(r.Context(), userAuth.AccountId, userAuth.UserId, reverseProxyID)
|
||||
service, err := h.manager.GetService(r.Context(), userAuth.AccountId, userAuth.UserId, serviceID)
|
||||
if err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
return
|
||||
}
|
||||
|
||||
util.WriteJSONObject(r.Context(), w, reverseProxy.ToAPIResponse())
|
||||
util.WriteJSONObject(r.Context(), w, service.ToAPIResponse())
|
||||
}
|
||||
|
||||
func (h *handler) updateReverseProxy(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *handler) updateService(w http.ResponseWriter, r *http.Request) {
|
||||
userAuth, err := nbcontext.GetUserAuthFromContext(r.Context())
|
||||
if err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
return
|
||||
}
|
||||
|
||||
reverseProxyID := mux.Vars(r)["proxyId"]
|
||||
if reverseProxyID == "" {
|
||||
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "reverse proxy ID is required"), w)
|
||||
serviceID := mux.Vars(r)["serviceId"]
|
||||
if serviceID == "" {
|
||||
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "service ID is required"), w)
|
||||
return
|
||||
}
|
||||
|
||||
var req api.ReverseProxyRequest
|
||||
var req api.ServiceRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w)
|
||||
return
|
||||
}
|
||||
|
||||
reverseProxy := new(reverseproxy.ReverseProxy)
|
||||
reverseProxy.ID = reverseProxyID
|
||||
reverseProxy.FromAPIRequest(&req, userAuth.AccountId)
|
||||
service := new(reverseproxy.Service)
|
||||
service.ID = serviceID
|
||||
service.FromAPIRequest(&req, userAuth.AccountId)
|
||||
|
||||
if err = reverseProxy.Validate(); err != nil {
|
||||
if err = service.Validate(); err != nil {
|
||||
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "%s", err.Error()), w)
|
||||
return
|
||||
}
|
||||
|
||||
updatedReverseProxy, err := h.manager.UpdateReverseProxy(r.Context(), userAuth.AccountId, userAuth.UserId, reverseProxy)
|
||||
updatedService, err := h.manager.UpdateService(r.Context(), userAuth.AccountId, userAuth.UserId, service)
|
||||
if err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
return
|
||||
}
|
||||
|
||||
util.WriteJSONObject(r.Context(), w, updatedReverseProxy.ToAPIResponse())
|
||||
util.WriteJSONObject(r.Context(), w, updatedService.ToAPIResponse())
|
||||
}
|
||||
|
||||
func (h *handler) deleteReverseProxy(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *handler) deleteService(w http.ResponseWriter, r *http.Request) {
|
||||
userAuth, err := nbcontext.GetUserAuthFromContext(r.Context())
|
||||
if err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
return
|
||||
}
|
||||
|
||||
reverseProxyID := mux.Vars(r)["proxyId"]
|
||||
if reverseProxyID == "" {
|
||||
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "reverse proxy ID is required"), w)
|
||||
serviceID := mux.Vars(r)["serviceId"]
|
||||
if serviceID == "" {
|
||||
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "service ID is required"), w)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.manager.DeleteReverseProxy(r.Context(), userAuth.AccountId, userAuth.UserId, reverseProxyID); err != nil {
|
||||
if err := h.manager.DeleteService(r.Context(), userAuth.AccountId, userAuth.UserId, serviceID); err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ type managerImpl struct {
|
||||
clusterDeriver ClusterDeriver
|
||||
}
|
||||
|
||||
// NewManager creates a new reverse proxy manager.
|
||||
// NewManager creates a new service manager.
|
||||
func NewManager(store store.Store, accountManager account.Manager, permissionsManager permissions.Manager, proxyGRPCServer *nbgrpc.ProxyServiceServer, tokenStore *nbgrpc.OneTimeTokenStore, clusterDeriver ClusterDeriver) reverseproxy.Manager {
|
||||
return &managerImpl{
|
||||
store: store,
|
||||
@@ -47,7 +47,7 @@ func NewManager(store store.Store, accountManager account.Manager, permissionsMa
|
||||
}
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetAllReverseProxies(ctx context.Context, accountID, userID string) ([]*reverseproxy.ReverseProxy, error) {
|
||||
func (m *managerImpl) GetAllServices(ctx context.Context, accountID, userID string) ([]*reverseproxy.Service, error) {
|
||||
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Read)
|
||||
if err != nil {
|
||||
return nil, status.NewPermissionValidationError(err)
|
||||
@@ -56,28 +56,28 @@ func (m *managerImpl) GetAllReverseProxies(ctx context.Context, accountID, userI
|
||||
return nil, status.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
proxies, err := m.store.GetAccountReverseProxies(ctx, store.LockingStrengthNone, accountID)
|
||||
services, err := m.store.GetAccountServices(ctx, store.LockingStrengthNone, accountID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get reverse proxies: %w", err)
|
||||
return nil, fmt.Errorf("failed to get services: %w", err)
|
||||
}
|
||||
|
||||
for _, proxy := range proxies {
|
||||
err = m.replaceHostByLookup(ctx, accountID, proxy)
|
||||
for _, service := range services {
|
||||
err = m.replaceHostByLookup(ctx, accountID, service)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for proxy %s: %w", proxy.ID, err)
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for service %s: %w", service.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return proxies, nil
|
||||
return services, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) replaceHostByLookup(ctx context.Context, accountID string, proxy *reverseproxy.ReverseProxy) error {
|
||||
for _, target := range proxy.Targets {
|
||||
func (m *managerImpl) replaceHostByLookup(ctx context.Context, accountID string, service *reverseproxy.Service) error {
|
||||
for _, target := range service.Targets {
|
||||
switch target.TargetType {
|
||||
case reverseproxy.TargetTypePeer:
|
||||
peer, err := m.store.GetPeerByID(ctx, store.LockingStrengthNone, accountID, target.TargetId)
|
||||
if err != nil {
|
||||
log.WithContext(ctx).Warnf("failed to get peer by id %s for reverse proxy %s: %v", target.TargetId, proxy.ID, err)
|
||||
log.WithContext(ctx).Warnf("failed to get peer by id %s for service %s: %v", target.TargetId, service.ID, err)
|
||||
target.Host = unknownHostPlaceholder
|
||||
continue
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func (m *managerImpl) replaceHostByLookup(ctx context.Context, accountID string,
|
||||
case reverseproxy.TargetTypeHost:
|
||||
resource, err := m.store.GetNetworkResourceByID(ctx, store.LockingStrengthNone, accountID, target.TargetId)
|
||||
if err != nil {
|
||||
log.WithContext(ctx).Warnf("failed to get resource by id %s for reverse proxy %s: %v", target.TargetId, proxy.ID, err)
|
||||
log.WithContext(ctx).Warnf("failed to get resource by id %s for service %s: %v", target.TargetId, service.ID, err)
|
||||
target.Host = unknownHostPlaceholder
|
||||
continue
|
||||
}
|
||||
@@ -93,7 +93,7 @@ func (m *managerImpl) replaceHostByLookup(ctx context.Context, accountID string,
|
||||
case reverseproxy.TargetTypeDomain:
|
||||
resource, err := m.store.GetNetworkResourceByID(ctx, store.LockingStrengthNone, accountID, target.TargetId)
|
||||
if err != nil {
|
||||
log.WithContext(ctx).Warnf("failed to get resource by id %s for reverse proxy %s: %v", target.TargetId, proxy.ID, err)
|
||||
log.WithContext(ctx).Warnf("failed to get resource by id %s for service %s: %v", target.TargetId, service.ID, err)
|
||||
target.Host = unknownHostPlaceholder
|
||||
continue
|
||||
}
|
||||
@@ -107,7 +107,7 @@ func (m *managerImpl) replaceHostByLookup(ctx context.Context, accountID string,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetReverseProxy(ctx context.Context, accountID, userID, reverseProxyID string) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *managerImpl) GetService(ctx context.Context, accountID, userID, serviceID string) (*reverseproxy.Service, error) {
|
||||
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Read)
|
||||
if err != nil {
|
||||
return nil, status.NewPermissionValidationError(err)
|
||||
@@ -116,19 +116,19 @@ func (m *managerImpl) GetReverseProxy(ctx context.Context, accountID, userID, re
|
||||
return nil, status.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
proxy, err := m.store.GetReverseProxyByID(ctx, store.LockingStrengthNone, accountID, reverseProxyID)
|
||||
service, err := m.store.GetServiceByID(ctx, store.LockingStrengthNone, accountID, serviceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get reverse proxy: %w", err)
|
||||
return nil, fmt.Errorf("failed to get service: %w", err)
|
||||
}
|
||||
|
||||
err = m.replaceHostByLookup(ctx, accountID, proxy)
|
||||
err = m.replaceHostByLookup(ctx, accountID, service)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for proxy %s: %w", proxy.ID, err)
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for service %s: %w", service.ID, err)
|
||||
}
|
||||
return proxy, nil
|
||||
return service, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) CreateReverseProxy(ctx context.Context, accountID, userID string, reverseProxy *reverseproxy.ReverseProxy) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *managerImpl) CreateService(ctx context.Context, accountID, userID string, service *reverseproxy.Service) (*reverseproxy.Service, error) {
|
||||
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Create)
|
||||
if err != nil {
|
||||
return nil, status.NewPermissionValidationError(err)
|
||||
@@ -139,16 +139,16 @@ func (m *managerImpl) CreateReverseProxy(ctx context.Context, accountID, userID
|
||||
|
||||
var proxyCluster string
|
||||
if m.clusterDeriver != nil {
|
||||
proxyCluster, err = m.clusterDeriver.DeriveClusterFromDomain(ctx, reverseProxy.Domain)
|
||||
proxyCluster, err = m.clusterDeriver.DeriveClusterFromDomain(ctx, service.Domain)
|
||||
if err != nil {
|
||||
log.WithError(err).Warnf("could not derive cluster from domain %s, updates will broadcast to all proxies", reverseProxy.Domain)
|
||||
log.WithError(err).Warnf("could not derive cluster from domain %s, updates will broadcast to all proxy servers", service.Domain)
|
||||
}
|
||||
}
|
||||
|
||||
reverseProxy.AccountID = accountID
|
||||
reverseProxy.ProxyCluster = proxyCluster
|
||||
reverseProxy.InitNewRecord()
|
||||
err = reverseProxy.Auth.HashSecrets()
|
||||
service.AccountID = accountID
|
||||
service.ProxyCluster = proxyCluster
|
||||
service.InitNewRecord()
|
||||
err = service.Auth.HashSecrets()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("hash secrets: %w", err)
|
||||
}
|
||||
@@ -158,27 +158,27 @@ func (m *managerImpl) CreateReverseProxy(ctx context.Context, accountID, userID
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generate session keys: %w", err)
|
||||
}
|
||||
reverseProxy.SessionPrivateKey = keyPair.PrivateKey
|
||||
reverseProxy.SessionPublicKey = keyPair.PublicKey
|
||||
service.SessionPrivateKey = keyPair.PrivateKey
|
||||
service.SessionPublicKey = keyPair.PublicKey
|
||||
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
// Check for duplicate domain
|
||||
existingReverseProxy, err := transaction.GetReverseProxyByDomain(ctx, accountID, reverseProxy.Domain)
|
||||
existingService, err := transaction.GetServiceByDomain(ctx, accountID, service.Domain)
|
||||
if err != nil {
|
||||
if sErr, ok := status.FromError(err); !ok || sErr.Type() != status.NotFound {
|
||||
return fmt.Errorf("failed to check existing reverse proxy: %w", err)
|
||||
return fmt.Errorf("failed to check existing service: %w", err)
|
||||
}
|
||||
}
|
||||
if existingReverseProxy != nil {
|
||||
return status.Errorf(status.AlreadyExists, "reverse proxy with domain %s already exists", reverseProxy.Domain)
|
||||
if existingService != nil {
|
||||
return status.Errorf(status.AlreadyExists, "service with domain %s already exists", service.Domain)
|
||||
}
|
||||
|
||||
if err = validateTargetReferences(ctx, transaction, accountID, reverseProxy.Targets); err != nil {
|
||||
if err = validateTargetReferences(ctx, transaction, accountID, service.Targets); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = transaction.CreateReverseProxy(ctx, reverseProxy); err != nil {
|
||||
return fmt.Errorf("failed to create reverse proxy: %w", err)
|
||||
if err = transaction.CreateService(ctx, service); err != nil {
|
||||
return fmt.Errorf("failed to create service: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -187,26 +187,26 @@ func (m *managerImpl) CreateReverseProxy(ctx context.Context, accountID, userID
|
||||
return nil, err
|
||||
}
|
||||
|
||||
token, err := m.tokenStore.GenerateToken(accountID, reverseProxy.ID, 5*time.Minute)
|
||||
token, err := m.tokenStore.GenerateToken(accountID, service.ID, 5*time.Minute)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate authentication token: %w", err)
|
||||
}
|
||||
|
||||
m.accountManager.StoreEvent(ctx, userID, reverseProxy.ID, accountID, activity.ReverseProxyCreated, reverseProxy.EventMeta())
|
||||
m.accountManager.StoreEvent(ctx, userID, service.ID, accountID, activity.ServiceCreated, service.EventMeta())
|
||||
|
||||
err = m.replaceHostByLookup(ctx, accountID, reverseProxy)
|
||||
err = m.replaceHostByLookup(ctx, accountID, service)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for proxy %s: %w", reverseProxy.ID, err)
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for service %s: %w", service.ID, err)
|
||||
}
|
||||
|
||||
m.proxyGRPCServer.SendReverseProxyUpdateToCluster(reverseProxy.ToProtoMapping(reverseproxy.Create, token, m.proxyGRPCServer.GetOIDCValidationConfig()), reverseProxy.ProxyCluster)
|
||||
m.proxyGRPCServer.SendServiceUpdateToCluster(service.ToProtoMapping(reverseproxy.Create, token, m.proxyGRPCServer.GetOIDCValidationConfig()), service.ProxyCluster)
|
||||
|
||||
m.accountManager.UpdateAccountPeers(ctx, accountID)
|
||||
|
||||
return reverseProxy, nil
|
||||
return service, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) UpdateReverseProxy(ctx context.Context, accountID, userID string, reverseProxy *reverseproxy.ReverseProxy) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *managerImpl) UpdateService(ctx context.Context, accountID, userID string, service *reverseproxy.Service) (*reverseproxy.Service, error) {
|
||||
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Update)
|
||||
if err != nil {
|
||||
return nil, status.NewPermissionValidationError(err)
|
||||
@@ -217,67 +217,67 @@ func (m *managerImpl) UpdateReverseProxy(ctx context.Context, accountID, userID
|
||||
|
||||
var oldCluster string
|
||||
var domainChanged bool
|
||||
var reverseProxyEnabledChanged bool
|
||||
var serviceEnabledChanged bool
|
||||
|
||||
err = reverseProxy.Auth.HashSecrets()
|
||||
err = service.Auth.HashSecrets()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("hash secrets: %w", err)
|
||||
}
|
||||
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
existingReverseProxy, err := transaction.GetReverseProxyByID(ctx, store.LockingStrengthUpdate, accountID, reverseProxy.ID)
|
||||
existingService, err := transaction.GetServiceByID(ctx, store.LockingStrengthUpdate, accountID, service.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oldCluster = existingReverseProxy.ProxyCluster
|
||||
oldCluster = existingService.ProxyCluster
|
||||
|
||||
if existingReverseProxy.Domain != reverseProxy.Domain {
|
||||
if existingService.Domain != service.Domain {
|
||||
domainChanged = true
|
||||
conflictReverseProxy, err := transaction.GetReverseProxyByDomain(ctx, accountID, reverseProxy.Domain)
|
||||
conflictService, err := transaction.GetServiceByDomain(ctx, accountID, service.Domain)
|
||||
if err != nil {
|
||||
if sErr, ok := status.FromError(err); !ok || sErr.Type() != status.NotFound {
|
||||
return fmt.Errorf("check existing reverse proxy: %w", err)
|
||||
return fmt.Errorf("check existing service: %w", err)
|
||||
}
|
||||
}
|
||||
if conflictReverseProxy != nil && conflictReverseProxy.ID != reverseProxy.ID {
|
||||
return status.Errorf(status.AlreadyExists, "reverse proxy with domain %s already exists", reverseProxy.Domain)
|
||||
if conflictService != nil && conflictService.ID != service.ID {
|
||||
return status.Errorf(status.AlreadyExists, "service with domain %s already exists", service.Domain)
|
||||
}
|
||||
|
||||
if m.clusterDeriver != nil {
|
||||
newCluster, err := m.clusterDeriver.DeriveClusterFromDomain(ctx, reverseProxy.Domain)
|
||||
newCluster, err := m.clusterDeriver.DeriveClusterFromDomain(ctx, service.Domain)
|
||||
if err != nil {
|
||||
log.WithError(err).Warnf("could not derive cluster from domain %s", reverseProxy.Domain)
|
||||
log.WithError(err).Warnf("could not derive cluster from domain %s", service.Domain)
|
||||
}
|
||||
reverseProxy.ProxyCluster = newCluster
|
||||
service.ProxyCluster = newCluster
|
||||
}
|
||||
} else {
|
||||
reverseProxy.ProxyCluster = existingReverseProxy.ProxyCluster
|
||||
service.ProxyCluster = existingService.ProxyCluster
|
||||
}
|
||||
|
||||
if reverseProxy.Auth.PasswordAuth != nil && reverseProxy.Auth.PasswordAuth.Enabled &&
|
||||
existingReverseProxy.Auth.PasswordAuth != nil && existingReverseProxy.Auth.PasswordAuth.Enabled &&
|
||||
reverseProxy.Auth.PasswordAuth.Password == "" {
|
||||
reverseProxy.Auth.PasswordAuth = existingReverseProxy.Auth.PasswordAuth
|
||||
if service.Auth.PasswordAuth != nil && service.Auth.PasswordAuth.Enabled &&
|
||||
existingService.Auth.PasswordAuth != nil && existingService.Auth.PasswordAuth.Enabled &&
|
||||
service.Auth.PasswordAuth.Password == "" {
|
||||
service.Auth.PasswordAuth = existingService.Auth.PasswordAuth
|
||||
}
|
||||
|
||||
if reverseProxy.Auth.PinAuth != nil && reverseProxy.Auth.PinAuth.Enabled &&
|
||||
existingReverseProxy.Auth.PinAuth != nil && existingReverseProxy.Auth.PinAuth.Enabled &&
|
||||
reverseProxy.Auth.PinAuth.Pin == "" {
|
||||
reverseProxy.Auth.PinAuth = existingReverseProxy.Auth.PinAuth
|
||||
if service.Auth.PinAuth != nil && service.Auth.PinAuth.Enabled &&
|
||||
existingService.Auth.PinAuth != nil && existingService.Auth.PinAuth.Enabled &&
|
||||
service.Auth.PinAuth.Pin == "" {
|
||||
service.Auth.PinAuth = existingService.Auth.PinAuth
|
||||
}
|
||||
|
||||
reverseProxy.Meta = existingReverseProxy.Meta
|
||||
reverseProxy.SessionPrivateKey = existingReverseProxy.SessionPrivateKey
|
||||
reverseProxy.SessionPublicKey = existingReverseProxy.SessionPublicKey
|
||||
reverseProxyEnabledChanged = existingReverseProxy.Enabled != reverseProxy.Enabled
|
||||
service.Meta = existingService.Meta
|
||||
service.SessionPrivateKey = existingService.SessionPrivateKey
|
||||
service.SessionPublicKey = existingService.SessionPublicKey
|
||||
serviceEnabledChanged = existingService.Enabled != service.Enabled
|
||||
|
||||
if err = validateTargetReferences(ctx, transaction, accountID, reverseProxy.Targets); err != nil {
|
||||
if err = validateTargetReferences(ctx, transaction, accountID, service.Targets); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = transaction.UpdateReverseProxy(ctx, reverseProxy); err != nil {
|
||||
return fmt.Errorf("update reverse proxy: %w", err)
|
||||
if err = transaction.UpdateService(ctx, service); err != nil {
|
||||
return fmt.Errorf("update service: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -286,33 +286,33 @@ func (m *managerImpl) UpdateReverseProxy(ctx context.Context, accountID, userID
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.accountManager.StoreEvent(ctx, userID, reverseProxy.ID, accountID, activity.ReverseProxyUpdated, reverseProxy.EventMeta())
|
||||
m.accountManager.StoreEvent(ctx, userID, service.ID, accountID, activity.ServiceUpdated, service.EventMeta())
|
||||
|
||||
err = m.replaceHostByLookup(ctx, accountID, reverseProxy)
|
||||
err = m.replaceHostByLookup(ctx, accountID, service)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for proxy %s: %w", reverseProxy.ID, err)
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for service %s: %w", service.ID, err)
|
||||
}
|
||||
|
||||
token, err := m.tokenStore.GenerateToken(accountID, reverseProxy.ID, 5*time.Minute)
|
||||
token, err := m.tokenStore.GenerateToken(accountID, service.ID, 5*time.Minute)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate authentication token: %w", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case domainChanged && oldCluster != reverseProxy.ProxyCluster:
|
||||
m.proxyGRPCServer.SendReverseProxyUpdateToCluster(reverseProxy.ToProtoMapping(reverseproxy.Delete, "", m.proxyGRPCServer.GetOIDCValidationConfig()), oldCluster)
|
||||
m.proxyGRPCServer.SendReverseProxyUpdateToCluster(reverseProxy.ToProtoMapping(reverseproxy.Create, token, m.proxyGRPCServer.GetOIDCValidationConfig()), reverseProxy.ProxyCluster)
|
||||
case !reverseProxy.Enabled && reverseProxyEnabledChanged:
|
||||
m.proxyGRPCServer.SendReverseProxyUpdateToCluster(reverseProxy.ToProtoMapping(reverseproxy.Delete, "", m.proxyGRPCServer.GetOIDCValidationConfig()), reverseProxy.ProxyCluster)
|
||||
case reverseProxy.Enabled && reverseProxyEnabledChanged:
|
||||
m.proxyGRPCServer.SendReverseProxyUpdateToCluster(reverseProxy.ToProtoMapping(reverseproxy.Create, token, m.proxyGRPCServer.GetOIDCValidationConfig()), reverseProxy.ProxyCluster)
|
||||
case domainChanged && oldCluster != service.ProxyCluster:
|
||||
m.proxyGRPCServer.SendServiceUpdateToCluster(service.ToProtoMapping(reverseproxy.Delete, "", m.proxyGRPCServer.GetOIDCValidationConfig()), oldCluster)
|
||||
m.proxyGRPCServer.SendServiceUpdateToCluster(service.ToProtoMapping(reverseproxy.Create, token, m.proxyGRPCServer.GetOIDCValidationConfig()), service.ProxyCluster)
|
||||
case !service.Enabled && serviceEnabledChanged:
|
||||
m.proxyGRPCServer.SendServiceUpdateToCluster(service.ToProtoMapping(reverseproxy.Delete, "", m.proxyGRPCServer.GetOIDCValidationConfig()), service.ProxyCluster)
|
||||
case service.Enabled && serviceEnabledChanged:
|
||||
m.proxyGRPCServer.SendServiceUpdateToCluster(service.ToProtoMapping(reverseproxy.Create, token, m.proxyGRPCServer.GetOIDCValidationConfig()), service.ProxyCluster)
|
||||
default:
|
||||
m.proxyGRPCServer.SendReverseProxyUpdateToCluster(reverseProxy.ToProtoMapping(reverseproxy.Update, "", m.proxyGRPCServer.GetOIDCValidationConfig()), reverseProxy.ProxyCluster)
|
||||
m.proxyGRPCServer.SendServiceUpdateToCluster(service.ToProtoMapping(reverseproxy.Update, "", m.proxyGRPCServer.GetOIDCValidationConfig()), service.ProxyCluster)
|
||||
|
||||
}
|
||||
m.accountManager.UpdateAccountPeers(ctx, accountID)
|
||||
|
||||
return reverseProxy, nil
|
||||
return service, nil
|
||||
}
|
||||
|
||||
// validateTargetReferences checks that all target IDs reference existing peers or resources in the account.
|
||||
@@ -338,7 +338,7 @@ func validateTargetReferences(ctx context.Context, transaction store.Store, acco
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) DeleteReverseProxy(ctx context.Context, accountID, userID, reverseProxyID string) error {
|
||||
func (m *managerImpl) DeleteService(ctx context.Context, accountID, userID, serviceID string) error {
|
||||
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Delete)
|
||||
if err != nil {
|
||||
return status.NewPermissionValidationError(err)
|
||||
@@ -347,16 +347,16 @@ func (m *managerImpl) DeleteReverseProxy(ctx context.Context, accountID, userID,
|
||||
return status.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
var reverseProxy *reverseproxy.ReverseProxy
|
||||
var service *reverseproxy.Service
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
var err error
|
||||
reverseProxy, err = transaction.GetReverseProxyByID(ctx, store.LockingStrengthUpdate, accountID, reverseProxyID)
|
||||
service, err = transaction.GetServiceByID(ctx, store.LockingStrengthUpdate, accountID, serviceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = transaction.DeleteReverseProxy(ctx, accountID, reverseProxyID); err != nil {
|
||||
return fmt.Errorf("failed to delete reverse proxy: %w", err)
|
||||
if err = transaction.DeleteService(ctx, accountID, serviceID); err != nil {
|
||||
return fmt.Errorf("failed to delete service: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -365,9 +365,9 @@ func (m *managerImpl) DeleteReverseProxy(ctx context.Context, accountID, userID,
|
||||
return err
|
||||
}
|
||||
|
||||
m.accountManager.StoreEvent(ctx, userID, reverseProxyID, accountID, activity.ReverseProxyDeleted, reverseProxy.EventMeta())
|
||||
m.accountManager.StoreEvent(ctx, userID, serviceID, accountID, activity.ServiceDeleted, service.EventMeta())
|
||||
|
||||
m.proxyGRPCServer.SendReverseProxyUpdateToCluster(reverseProxy.ToProtoMapping(reverseproxy.Delete, "", m.proxyGRPCServer.GetOIDCValidationConfig()), reverseProxy.ProxyCluster)
|
||||
m.proxyGRPCServer.SendServiceUpdateToCluster(service.ToProtoMapping(reverseproxy.Delete, "", m.proxyGRPCServer.GetOIDCValidationConfig()), service.ProxyCluster)
|
||||
|
||||
m.accountManager.UpdateAccountPeers(ctx, accountID)
|
||||
|
||||
@@ -376,71 +376,71 @@ func (m *managerImpl) DeleteReverseProxy(ctx context.Context, accountID, userID,
|
||||
|
||||
// SetCertificateIssuedAt sets the certificate issued timestamp to the current time.
|
||||
// Call this when receiving a gRPC notification that the certificate was issued.
|
||||
func (m *managerImpl) SetCertificateIssuedAt(ctx context.Context, accountID, reverseProxyID string) error {
|
||||
func (m *managerImpl) SetCertificateIssuedAt(ctx context.Context, accountID, serviceID string) error {
|
||||
return m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
proxy, err := transaction.GetReverseProxyByID(ctx, store.LockingStrengthUpdate, accountID, reverseProxyID)
|
||||
service, err := transaction.GetServiceByID(ctx, store.LockingStrengthUpdate, accountID, serviceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get reverse proxy: %w", err)
|
||||
return fmt.Errorf("failed to get service: %w", err)
|
||||
}
|
||||
|
||||
proxy.Meta.CertificateIssuedAt = time.Now()
|
||||
service.Meta.CertificateIssuedAt = time.Now()
|
||||
|
||||
if err = transaction.UpdateReverseProxy(ctx, proxy); err != nil {
|
||||
return fmt.Errorf("failed to update reverse proxy certificate timestamp: %w", err)
|
||||
if err = transaction.UpdateService(ctx, service); err != nil {
|
||||
return fmt.Errorf("failed to update service certificate timestamp: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// SetStatus updates the status of the reverse proxy (e.g., "active", "tunnel_not_created", etc.)
|
||||
func (m *managerImpl) SetStatus(ctx context.Context, accountID, reverseProxyID string, status reverseproxy.ProxyStatus) error {
|
||||
// SetStatus updates the status of the service (e.g., "active", "tunnel_not_created", etc.)
|
||||
func (m *managerImpl) SetStatus(ctx context.Context, accountID, serviceID string, status reverseproxy.ProxyStatus) error {
|
||||
return m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
proxy, err := transaction.GetReverseProxyByID(ctx, store.LockingStrengthUpdate, accountID, reverseProxyID)
|
||||
service, err := transaction.GetServiceByID(ctx, store.LockingStrengthUpdate, accountID, serviceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get reverse proxy: %w", err)
|
||||
return fmt.Errorf("failed to get service: %w", err)
|
||||
}
|
||||
|
||||
proxy.Meta.Status = string(status)
|
||||
service.Meta.Status = string(status)
|
||||
|
||||
if err = transaction.UpdateReverseProxy(ctx, proxy); err != nil {
|
||||
return fmt.Errorf("failed to update reverse proxy status: %w", err)
|
||||
if err = transaction.UpdateService(ctx, service); err != nil {
|
||||
return fmt.Errorf("failed to update service status: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (m *managerImpl) ReloadReverseProxy(ctx context.Context, accountID, reverseProxyID string) error {
|
||||
proxy, err := m.store.GetReverseProxyByID(ctx, store.LockingStrengthNone, accountID, reverseProxyID)
|
||||
func (m *managerImpl) ReloadService(ctx context.Context, accountID, serviceID string) error {
|
||||
service, err := m.store.GetServiceByID(ctx, store.LockingStrengthNone, accountID, serviceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get reverse proxy: %w", err)
|
||||
return fmt.Errorf("failed to get service: %w", err)
|
||||
}
|
||||
|
||||
err = m.replaceHostByLookup(ctx, accountID, proxy)
|
||||
err = m.replaceHostByLookup(ctx, accountID, service)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to replace host by lookup for proxy %s: %w", proxy.ID, err)
|
||||
return fmt.Errorf("failed to replace host by lookup for service %s: %w", service.ID, err)
|
||||
}
|
||||
|
||||
m.proxyGRPCServer.SendReverseProxyUpdateToCluster(proxy.ToProtoMapping(reverseproxy.Update, "", m.proxyGRPCServer.GetOIDCValidationConfig()), proxy.ProxyCluster)
|
||||
m.proxyGRPCServer.SendServiceUpdateToCluster(service.ToProtoMapping(reverseproxy.Update, "", m.proxyGRPCServer.GetOIDCValidationConfig()), service.ProxyCluster)
|
||||
|
||||
m.accountManager.UpdateAccountPeers(ctx, accountID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) ReloadAllReverseProxiesForAccount(ctx context.Context, accountID string) error {
|
||||
proxies, err := m.store.GetAccountReverseProxies(ctx, store.LockingStrengthNone, accountID)
|
||||
func (m *managerImpl) ReloadAllServicesForAccount(ctx context.Context, accountID string) error {
|
||||
services, err := m.store.GetAccountServices(ctx, store.LockingStrengthNone, accountID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get reverse proxies: %w", err)
|
||||
return fmt.Errorf("failed to get services: %w", err)
|
||||
}
|
||||
|
||||
for _, proxy := range proxies {
|
||||
err = m.replaceHostByLookup(ctx, accountID, proxy)
|
||||
for _, service := range services {
|
||||
err = m.replaceHostByLookup(ctx, accountID, service)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to replace host by lookup for proxy %s: %w", proxy.ID, err)
|
||||
return fmt.Errorf("failed to replace host by lookup for service %s: %w", service.ID, err)
|
||||
}
|
||||
m.proxyGRPCServer.SendReverseProxyUpdateToCluster(proxy.ToProtoMapping(reverseproxy.Update, "", m.proxyGRPCServer.GetOIDCValidationConfig()), proxy.ProxyCluster)
|
||||
m.proxyGRPCServer.SendServiceUpdateToCluster(service.ToProtoMapping(reverseproxy.Update, "", m.proxyGRPCServer.GetOIDCValidationConfig()), service.ProxyCluster)
|
||||
}
|
||||
|
||||
m.accountManager.UpdateAccountPeers(ctx, accountID)
|
||||
@@ -448,61 +448,61 @@ func (m *managerImpl) ReloadAllReverseProxiesForAccount(ctx context.Context, acc
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetGlobalReverseProxies(ctx context.Context) ([]*reverseproxy.ReverseProxy, error) {
|
||||
proxies, err := m.store.GetReverseProxies(ctx, store.LockingStrengthNone)
|
||||
func (m *managerImpl) GetGlobalServices(ctx context.Context) ([]*reverseproxy.Service, error) {
|
||||
services, err := m.store.GetServices(ctx, store.LockingStrengthNone)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get reverse proxies: %w", err)
|
||||
return nil, fmt.Errorf("failed to get services: %w", err)
|
||||
}
|
||||
|
||||
for _, proxy := range proxies {
|
||||
err = m.replaceHostByLookup(ctx, proxy.AccountID, proxy)
|
||||
for _, service := range services {
|
||||
err = m.replaceHostByLookup(ctx, service.AccountID, service)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for proxy %s: %w", proxy.ID, err)
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for service %s: %w", service.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return proxies, nil
|
||||
return services, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetProxyByID(ctx context.Context, accountID, reverseProxyID string) (*reverseproxy.ReverseProxy, error) {
|
||||
proxy, err := m.store.GetReverseProxyByID(ctx, store.LockingStrengthNone, accountID, reverseProxyID)
|
||||
func (m *managerImpl) GetServiceByID(ctx context.Context, accountID, serviceID string) (*reverseproxy.Service, error) {
|
||||
service, err := m.store.GetServiceByID(ctx, store.LockingStrengthNone, accountID, serviceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get reverse proxy: %w", err)
|
||||
return nil, fmt.Errorf("failed to get service: %w", err)
|
||||
}
|
||||
|
||||
err = m.replaceHostByLookup(ctx, accountID, proxy)
|
||||
err = m.replaceHostByLookup(ctx, accountID, service)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for proxy %s: %w", proxy.ID, err)
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for service %s: %w", service.ID, err)
|
||||
}
|
||||
|
||||
return proxy, nil
|
||||
return service, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetAccountReverseProxies(ctx context.Context, accountID string) ([]*reverseproxy.ReverseProxy, error) {
|
||||
proxies, err := m.store.GetAccountReverseProxies(ctx, store.LockingStrengthNone, accountID)
|
||||
func (m *managerImpl) GetAccountServices(ctx context.Context, accountID string) ([]*reverseproxy.Service, error) {
|
||||
services, err := m.store.GetAccountServices(ctx, store.LockingStrengthNone, accountID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get reverse proxies: %w", err)
|
||||
return nil, fmt.Errorf("failed to get services: %w", err)
|
||||
}
|
||||
|
||||
for _, proxy := range proxies {
|
||||
err = m.replaceHostByLookup(ctx, accountID, proxy)
|
||||
for _, service := range services {
|
||||
err = m.replaceHostByLookup(ctx, accountID, service)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for proxy %s: %w", proxy.ID, err)
|
||||
return nil, fmt.Errorf("failed to replace host by lookup for service %s: %w", service.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return proxies, nil
|
||||
return services, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetProxyIDByTargetID(ctx context.Context, accountID string, resourceID string) (string, error) {
|
||||
target, err := m.store.GetReverseProxyTargetByTargetID(ctx, store.LockingStrengthNone, accountID, resourceID)
|
||||
func (m *managerImpl) GetServiceIDByTargetID(ctx context.Context, accountID string, resourceID string) (string, error) {
|
||||
target, err := m.store.GetServiceTargetByTargetID(ctx, store.LockingStrengthNone, accountID, resourceID)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get reverse proxy target by resource ID: %w", err)
|
||||
return "", fmt.Errorf("failed to get service target by resource ID: %w", err)
|
||||
}
|
||||
|
||||
if target == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return target.ReverseProxyID, nil
|
||||
return target.ServiceID, nil
|
||||
}
|
||||
|
||||
@@ -43,16 +43,16 @@ const (
|
||||
)
|
||||
|
||||
type Target struct {
|
||||
ID uint `gorm:"primaryKey" json:"-"`
|
||||
AccountID string `gorm:"index:idx_target_account;not null" json:"-"`
|
||||
ReverseProxyID string `gorm:"index:idx_reverse_proxy_targets;not null" json:"-"`
|
||||
Path *string `json:"path,omitempty"`
|
||||
Host string `json:"host"` // the Host field is only used for subnet targets, otherwise ignored
|
||||
Port int `gorm:"index:idx_target_port" json:"port"`
|
||||
Protocol string `gorm:"index:idx_target_protocol" json:"protocol"`
|
||||
TargetId string `gorm:"index:idx_target_id" json:"target_id"`
|
||||
TargetType string `gorm:"index:idx_target_type" json:"target_type"`
|
||||
Enabled bool `gorm:"index:idx_target_enabled" json:"enabled"`
|
||||
ID uint `gorm:"primaryKey" json:"-"`
|
||||
AccountID string `gorm:"index:idx_target_account;not null" json:"-"`
|
||||
ServiceID string `gorm:"index:idx_service_targets;not null" json:"-"`
|
||||
Path *string `json:"path,omitempty"`
|
||||
Host string `json:"host"` // the Host field is only used for subnet targets, otherwise ignored
|
||||
Port int `gorm:"index:idx_target_port" json:"port"`
|
||||
Protocol string `gorm:"index:idx_target_protocol" json:"protocol"`
|
||||
TargetId string `gorm:"index:idx_target_id" json:"target_id"`
|
||||
TargetType string `gorm:"index:idx_target_type" json:"target_type"`
|
||||
Enabled bool `gorm:"index:idx_target_enabled" json:"enabled"`
|
||||
}
|
||||
|
||||
type PasswordAuthConfig struct {
|
||||
@@ -112,34 +112,34 @@ type OIDCValidationConfig struct {
|
||||
MaxTokenAgeSeconds int64
|
||||
}
|
||||
|
||||
type ReverseProxyMeta struct {
|
||||
type ServiceMeta struct {
|
||||
CreatedAt time.Time
|
||||
CertificateIssuedAt time.Time
|
||||
Status string
|
||||
}
|
||||
|
||||
type ReverseProxy struct {
|
||||
type Service struct {
|
||||
ID string `gorm:"primaryKey"`
|
||||
AccountID string `gorm:"index"`
|
||||
Name string
|
||||
Domain string `gorm:"index"`
|
||||
ProxyCluster string `gorm:"index"`
|
||||
Targets []*Target `gorm:"foreignKey:ReverseProxyID;constraint:OnDelete:CASCADE"`
|
||||
Targets []*Target `gorm:"foreignKey:ServiceID;constraint:OnDelete:CASCADE"`
|
||||
Enabled bool
|
||||
PassHostHeader bool
|
||||
RewriteRedirects bool
|
||||
Auth AuthConfig `gorm:"serializer:json"`
|
||||
Meta ReverseProxyMeta `gorm:"embedded;embeddedPrefix:meta_"`
|
||||
SessionPrivateKey string `gorm:"column:session_private_key"`
|
||||
SessionPublicKey string `gorm:"column:session_public_key"`
|
||||
Auth AuthConfig `gorm:"serializer:json"`
|
||||
Meta ServiceMeta `gorm:"embedded;embeddedPrefix:meta_"`
|
||||
SessionPrivateKey string `gorm:"column:session_private_key"`
|
||||
SessionPublicKey string `gorm:"column:session_public_key"`
|
||||
}
|
||||
|
||||
func NewReverseProxy(accountID, name, domain, proxyCluster string, targets []*Target, enabled bool) *ReverseProxy {
|
||||
func NewService(accountID, name, domain, proxyCluster string, targets []*Target, enabled bool) *Service {
|
||||
for _, target := range targets {
|
||||
target.AccountID = accountID
|
||||
}
|
||||
|
||||
rp := &ReverseProxy{
|
||||
s := &Service{
|
||||
AccountID: accountID,
|
||||
Name: name,
|
||||
Domain: domain,
|
||||
@@ -147,92 +147,92 @@ func NewReverseProxy(accountID, name, domain, proxyCluster string, targets []*Ta
|
||||
Targets: targets,
|
||||
Enabled: enabled,
|
||||
}
|
||||
rp.InitNewRecord()
|
||||
return rp
|
||||
s.InitNewRecord()
|
||||
return s
|
||||
}
|
||||
|
||||
// InitNewRecord generates a new unique ID and resets metadata for a newly created
|
||||
// ReverseProxy record. This overwrites any existing ID and Meta fields and should
|
||||
// Service record. This overwrites any existing ID and Meta fields and should
|
||||
// only be called during initial creation, not for updates.
|
||||
func (r *ReverseProxy) InitNewRecord() {
|
||||
r.ID = xid.New().String()
|
||||
r.Meta = ReverseProxyMeta{
|
||||
func (s *Service) InitNewRecord() {
|
||||
s.ID = xid.New().String()
|
||||
s.Meta = ServiceMeta{
|
||||
CreatedAt: time.Now(),
|
||||
Status: string(StatusPending),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ReverseProxy) ToAPIResponse() *api.ReverseProxy {
|
||||
r.Auth.ClearSecrets()
|
||||
func (s *Service) ToAPIResponse() *api.Service {
|
||||
s.Auth.ClearSecrets()
|
||||
|
||||
authConfig := api.ReverseProxyAuthConfig{}
|
||||
authConfig := api.ServiceAuthConfig{}
|
||||
|
||||
if r.Auth.PasswordAuth != nil {
|
||||
if s.Auth.PasswordAuth != nil {
|
||||
authConfig.PasswordAuth = &api.PasswordAuthConfig{
|
||||
Enabled: r.Auth.PasswordAuth.Enabled,
|
||||
Password: r.Auth.PasswordAuth.Password,
|
||||
Enabled: s.Auth.PasswordAuth.Enabled,
|
||||
Password: s.Auth.PasswordAuth.Password,
|
||||
}
|
||||
}
|
||||
|
||||
if r.Auth.PinAuth != nil {
|
||||
if s.Auth.PinAuth != nil {
|
||||
authConfig.PinAuth = &api.PINAuthConfig{
|
||||
Enabled: r.Auth.PinAuth.Enabled,
|
||||
Pin: r.Auth.PinAuth.Pin,
|
||||
Enabled: s.Auth.PinAuth.Enabled,
|
||||
Pin: s.Auth.PinAuth.Pin,
|
||||
}
|
||||
}
|
||||
|
||||
if r.Auth.BearerAuth != nil {
|
||||
if s.Auth.BearerAuth != nil {
|
||||
authConfig.BearerAuth = &api.BearerAuthConfig{
|
||||
Enabled: r.Auth.BearerAuth.Enabled,
|
||||
DistributionGroups: &r.Auth.BearerAuth.DistributionGroups,
|
||||
Enabled: s.Auth.BearerAuth.Enabled,
|
||||
DistributionGroups: &s.Auth.BearerAuth.DistributionGroups,
|
||||
}
|
||||
}
|
||||
|
||||
// Convert internal targets to API targets
|
||||
apiTargets := make([]api.ReverseProxyTarget, 0, len(r.Targets))
|
||||
for _, target := range r.Targets {
|
||||
apiTargets = append(apiTargets, api.ReverseProxyTarget{
|
||||
apiTargets := make([]api.ServiceTarget, 0, len(s.Targets))
|
||||
for _, target := range s.Targets {
|
||||
apiTargets = append(apiTargets, api.ServiceTarget{
|
||||
Path: target.Path,
|
||||
Host: &target.Host,
|
||||
Port: target.Port,
|
||||
Protocol: api.ReverseProxyTargetProtocol(target.Protocol),
|
||||
Protocol: api.ServiceTargetProtocol(target.Protocol),
|
||||
TargetId: target.TargetId,
|
||||
TargetType: api.ReverseProxyTargetTargetType(target.TargetType),
|
||||
TargetType: api.ServiceTargetTargetType(target.TargetType),
|
||||
Enabled: target.Enabled,
|
||||
})
|
||||
}
|
||||
|
||||
meta := api.ReverseProxyMeta{
|
||||
CreatedAt: r.Meta.CreatedAt,
|
||||
Status: api.ReverseProxyMetaStatus(r.Meta.Status),
|
||||
meta := api.ServiceMeta{
|
||||
CreatedAt: s.Meta.CreatedAt,
|
||||
Status: api.ServiceMetaStatus(s.Meta.Status),
|
||||
}
|
||||
|
||||
if !r.Meta.CertificateIssuedAt.IsZero() {
|
||||
meta.CertificateIssuedAt = &r.Meta.CertificateIssuedAt
|
||||
if !s.Meta.CertificateIssuedAt.IsZero() {
|
||||
meta.CertificateIssuedAt = &s.Meta.CertificateIssuedAt
|
||||
}
|
||||
|
||||
resp := &api.ReverseProxy{
|
||||
Id: r.ID,
|
||||
Name: r.Name,
|
||||
Domain: r.Domain,
|
||||
resp := &api.Service{
|
||||
Id: s.ID,
|
||||
Name: s.Name,
|
||||
Domain: s.Domain,
|
||||
Targets: apiTargets,
|
||||
Enabled: r.Enabled,
|
||||
PassHostHeader: &r.PassHostHeader,
|
||||
RewriteRedirects: &r.RewriteRedirects,
|
||||
Enabled: s.Enabled,
|
||||
PassHostHeader: &s.PassHostHeader,
|
||||
RewriteRedirects: &s.RewriteRedirects,
|
||||
Auth: authConfig,
|
||||
Meta: meta,
|
||||
}
|
||||
|
||||
if r.ProxyCluster != "" {
|
||||
resp.ProxyCluster = &r.ProxyCluster
|
||||
if s.ProxyCluster != "" {
|
||||
resp.ProxyCluster = &s.ProxyCluster
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
func (r *ReverseProxy) ToProtoMapping(operation Operation, authToken string, oidcConfig OIDCValidationConfig) *proto.ProxyMapping {
|
||||
pathMappings := make([]*proto.PathMapping, 0, len(r.Targets))
|
||||
for _, target := range r.Targets {
|
||||
func (s *Service) ToProtoMapping(operation Operation, authToken string, oidcConfig OIDCValidationConfig) *proto.ProxyMapping {
|
||||
pathMappings := make([]*proto.PathMapping, 0, len(s.Targets))
|
||||
for _, target := range s.Targets {
|
||||
if !target.Enabled {
|
||||
continue
|
||||
}
|
||||
@@ -260,32 +260,32 @@ func (r *ReverseProxy) ToProtoMapping(operation Operation, authToken string, oid
|
||||
}
|
||||
|
||||
auth := &proto.Authentication{
|
||||
SessionKey: r.SessionPublicKey,
|
||||
SessionKey: s.SessionPublicKey,
|
||||
MaxSessionAgeSeconds: int64((time.Hour * 24).Seconds()),
|
||||
}
|
||||
|
||||
if r.Auth.PasswordAuth != nil && r.Auth.PasswordAuth.Enabled {
|
||||
if s.Auth.PasswordAuth != nil && s.Auth.PasswordAuth.Enabled {
|
||||
auth.Password = true
|
||||
}
|
||||
|
||||
if r.Auth.PinAuth != nil && r.Auth.PinAuth.Enabled {
|
||||
if s.Auth.PinAuth != nil && s.Auth.PinAuth.Enabled {
|
||||
auth.Pin = true
|
||||
}
|
||||
|
||||
if r.Auth.BearerAuth != nil && r.Auth.BearerAuth.Enabled {
|
||||
if s.Auth.BearerAuth != nil && s.Auth.BearerAuth.Enabled {
|
||||
auth.Oidc = true
|
||||
}
|
||||
|
||||
return &proto.ProxyMapping{
|
||||
Type: operationToProtoType(operation),
|
||||
Id: r.ID,
|
||||
Domain: r.Domain,
|
||||
Id: s.ID,
|
||||
Domain: s.Domain,
|
||||
Path: pathMappings,
|
||||
AuthToken: authToken,
|
||||
Auth: auth,
|
||||
AccountId: r.AccountID,
|
||||
PassHostHeader: r.PassHostHeader,
|
||||
RewriteRedirects: r.RewriteRedirects,
|
||||
AccountId: s.AccountID,
|
||||
PassHostHeader: s.PassHostHeader,
|
||||
RewriteRedirects: s.RewriteRedirects,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,10 +309,10 @@ func isDefaultPort(scheme string, port int) bool {
|
||||
return (scheme == "https" && port == 443) || (scheme == "http" && port == 80)
|
||||
}
|
||||
|
||||
func (r *ReverseProxy) FromAPIRequest(req *api.ReverseProxyRequest, accountID string) {
|
||||
r.Name = req.Name
|
||||
r.Domain = req.Domain
|
||||
r.AccountID = accountID
|
||||
func (s *Service) FromAPIRequest(req *api.ServiceRequest, accountID string) {
|
||||
s.Name = req.Name
|
||||
s.Domain = req.Domain
|
||||
s.AccountID = accountID
|
||||
|
||||
targets := make([]*Target, 0, len(req.Targets))
|
||||
for _, apiTarget := range req.Targets {
|
||||
@@ -330,27 +330,27 @@ func (r *ReverseProxy) FromAPIRequest(req *api.ReverseProxyRequest, accountID st
|
||||
}
|
||||
targets = append(targets, target)
|
||||
}
|
||||
r.Targets = targets
|
||||
s.Targets = targets
|
||||
|
||||
r.Enabled = req.Enabled
|
||||
s.Enabled = req.Enabled
|
||||
|
||||
if req.PassHostHeader != nil {
|
||||
r.PassHostHeader = *req.PassHostHeader
|
||||
s.PassHostHeader = *req.PassHostHeader
|
||||
}
|
||||
|
||||
if req.RewriteRedirects != nil {
|
||||
r.RewriteRedirects = *req.RewriteRedirects
|
||||
s.RewriteRedirects = *req.RewriteRedirects
|
||||
}
|
||||
|
||||
if req.Auth.PasswordAuth != nil {
|
||||
r.Auth.PasswordAuth = &PasswordAuthConfig{
|
||||
s.Auth.PasswordAuth = &PasswordAuthConfig{
|
||||
Enabled: req.Auth.PasswordAuth.Enabled,
|
||||
Password: req.Auth.PasswordAuth.Password,
|
||||
}
|
||||
}
|
||||
|
||||
if req.Auth.PinAuth != nil {
|
||||
r.Auth.PinAuth = &PINAuthConfig{
|
||||
s.Auth.PinAuth = &PINAuthConfig{
|
||||
Enabled: req.Auth.PinAuth.Enabled,
|
||||
Pin: req.Auth.PinAuth.Pin,
|
||||
}
|
||||
@@ -363,27 +363,27 @@ func (r *ReverseProxy) FromAPIRequest(req *api.ReverseProxyRequest, accountID st
|
||||
if req.Auth.BearerAuth.DistributionGroups != nil {
|
||||
bearerAuth.DistributionGroups = *req.Auth.BearerAuth.DistributionGroups
|
||||
}
|
||||
r.Auth.BearerAuth = bearerAuth
|
||||
s.Auth.BearerAuth = bearerAuth
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ReverseProxy) Validate() error {
|
||||
if r.Name == "" {
|
||||
return errors.New("reverse proxy name is required")
|
||||
func (s *Service) Validate() error {
|
||||
if s.Name == "" {
|
||||
return errors.New("service name is required")
|
||||
}
|
||||
if len(r.Name) > 255 {
|
||||
return errors.New("reverse proxy name exceeds maximum length of 255 characters")
|
||||
if len(s.Name) > 255 {
|
||||
return errors.New("service name exceeds maximum length of 255 characters")
|
||||
}
|
||||
|
||||
if r.Domain == "" {
|
||||
return errors.New("reverse proxy domain is required")
|
||||
if s.Domain == "" {
|
||||
return errors.New("service domain is required")
|
||||
}
|
||||
|
||||
if len(r.Targets) == 0 {
|
||||
if len(s.Targets) == 0 {
|
||||
return errors.New("at least one target is required")
|
||||
}
|
||||
|
||||
for i, target := range r.Targets {
|
||||
for i, target := range s.Targets {
|
||||
switch target.TargetType {
|
||||
case TargetTypePeer, TargetTypeHost, TargetTypeDomain:
|
||||
// host field will be ignored
|
||||
@@ -402,42 +402,42 @@ func (r *ReverseProxy) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReverseProxy) EventMeta() map[string]any {
|
||||
return map[string]any{"name": r.Name, "domain": r.Domain, "proxy_cluster": r.ProxyCluster}
|
||||
func (s *Service) EventMeta() map[string]any {
|
||||
return map[string]any{"name": s.Name, "domain": s.Domain, "proxy_cluster": s.ProxyCluster}
|
||||
}
|
||||
|
||||
func (r *ReverseProxy) Copy() *ReverseProxy {
|
||||
targets := make([]*Target, len(r.Targets))
|
||||
for i, target := range r.Targets {
|
||||
func (s *Service) Copy() *Service {
|
||||
targets := make([]*Target, len(s.Targets))
|
||||
for i, target := range s.Targets {
|
||||
targetCopy := *target
|
||||
targets[i] = &targetCopy
|
||||
}
|
||||
|
||||
return &ReverseProxy{
|
||||
ID: r.ID,
|
||||
AccountID: r.AccountID,
|
||||
Name: r.Name,
|
||||
Domain: r.Domain,
|
||||
ProxyCluster: r.ProxyCluster,
|
||||
return &Service{
|
||||
ID: s.ID,
|
||||
AccountID: s.AccountID,
|
||||
Name: s.Name,
|
||||
Domain: s.Domain,
|
||||
ProxyCluster: s.ProxyCluster,
|
||||
Targets: targets,
|
||||
Enabled: r.Enabled,
|
||||
PassHostHeader: r.PassHostHeader,
|
||||
RewriteRedirects: r.RewriteRedirects,
|
||||
Auth: r.Auth,
|
||||
Meta: r.Meta,
|
||||
SessionPrivateKey: r.SessionPrivateKey,
|
||||
SessionPublicKey: r.SessionPublicKey,
|
||||
Enabled: s.Enabled,
|
||||
PassHostHeader: s.PassHostHeader,
|
||||
RewriteRedirects: s.RewriteRedirects,
|
||||
Auth: s.Auth,
|
||||
Meta: s.Meta,
|
||||
SessionPrivateKey: s.SessionPrivateKey,
|
||||
SessionPublicKey: s.SessionPublicKey,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ReverseProxy) EncryptSensitiveData(enc *crypt.FieldEncrypt) error {
|
||||
func (s *Service) EncryptSensitiveData(enc *crypt.FieldEncrypt) error {
|
||||
if enc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if r.SessionPrivateKey != "" {
|
||||
if s.SessionPrivateKey != "" {
|
||||
var err error
|
||||
r.SessionPrivateKey, err = enc.Encrypt(r.SessionPrivateKey)
|
||||
s.SessionPrivateKey, err = enc.Encrypt(s.SessionPrivateKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -446,14 +446,14 @@ func (r *ReverseProxy) EncryptSensitiveData(enc *crypt.FieldEncrypt) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReverseProxy) DecryptSensitiveData(enc *crypt.FieldEncrypt) error {
|
||||
func (s *Service) DecryptSensitiveData(enc *crypt.FieldEncrypt) error {
|
||||
if enc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if r.SessionPrivateKey != "" {
|
||||
if s.SessionPrivateKey != "" {
|
||||
var err error
|
||||
r.SessionPrivateKey, err = enc.Decrypt(r.SessionPrivateKey)
|
||||
s.SessionPrivateKey, err = enc.Decrypt(s.SessionPrivateKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
"github.com/netbirdio/netbird/shared/management/proto"
|
||||
)
|
||||
|
||||
func validProxy() *ReverseProxy {
|
||||
return &ReverseProxy{
|
||||
func validProxy() *Service {
|
||||
return &Service{
|
||||
Name: "test",
|
||||
Domain: "example.com",
|
||||
Targets: []*Target{
|
||||
@@ -170,7 +170,7 @@ func TestToProtoMapping_PortInTargetURL(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
rp := &ReverseProxy{
|
||||
rp := &Service{
|
||||
ID: "test-id",
|
||||
AccountID: "acc-1",
|
||||
Domain: "example.com",
|
||||
@@ -193,7 +193,7 @@ func TestToProtoMapping_PortInTargetURL(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestToProtoMapping_DisabledTargetSkipped(t *testing.T) {
|
||||
rp := &ReverseProxy{
|
||||
rp := &Service{
|
||||
ID: "test-id",
|
||||
AccountID: "acc-1",
|
||||
Domain: "example.com",
|
||||
|
||||
@@ -103,7 +103,7 @@ func (s *BaseServer) AccountManager() account.Manager {
|
||||
}
|
||||
|
||||
s.AfterInit(func(s *BaseServer) {
|
||||
accountManager.SetReverseProxyManager(s.ReverseProxyManager())
|
||||
accountManager.SetServiceManager(s.ReverseProxyManager())
|
||||
})
|
||||
|
||||
return accountManager
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
// OneTimeTokenStore manages short-lived, single-use authentication tokens
|
||||
// for proxy-to-management RPC authentication. Tokens are generated when
|
||||
// a reverse proxy is created and must be used exactly once by the proxy
|
||||
// a service is created and must be used exactly once by the proxy
|
||||
// to authenticate a subsequent RPC call.
|
||||
type OneTimeTokenStore struct {
|
||||
tokens map[string]*tokenMetadata
|
||||
@@ -24,10 +24,10 @@ type OneTimeTokenStore struct {
|
||||
|
||||
// tokenMetadata stores information about a one-time token
|
||||
type tokenMetadata struct {
|
||||
ReverseProxyID string
|
||||
AccountID string
|
||||
ExpiresAt time.Time
|
||||
CreatedAt time.Time
|
||||
ServiceID string
|
||||
AccountID string
|
||||
ExpiresAt time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// NewOneTimeTokenStore creates a new token store with automatic cleanup
|
||||
@@ -48,10 +48,10 @@ func NewOneTimeTokenStore(cleanupInterval time.Duration) *OneTimeTokenStore {
|
||||
|
||||
// GenerateToken creates a new cryptographically secure one-time token
|
||||
// with the specified TTL. The token is associated with a specific
|
||||
// accountID and reverseProxyID for validation purposes.
|
||||
// accountID and serviceID for validation purposes.
|
||||
//
|
||||
// Returns the generated token string or an error if random generation fails.
|
||||
func (s *OneTimeTokenStore) GenerateToken(accountID, reverseProxyID string, ttl time.Duration) (string, error) {
|
||||
func (s *OneTimeTokenStore) GenerateToken(accountID, serviceID string, ttl time.Duration) (string, error) {
|
||||
// Generate 32 bytes (256 bits) of cryptographically secure random data
|
||||
randomBytes := make([]byte, 32)
|
||||
if _, err := rand.Read(randomBytes); err != nil {
|
||||
@@ -65,20 +65,20 @@ func (s *OneTimeTokenStore) GenerateToken(accountID, reverseProxyID string, ttl
|
||||
defer s.mu.Unlock()
|
||||
|
||||
s.tokens[token] = &tokenMetadata{
|
||||
ReverseProxyID: reverseProxyID,
|
||||
AccountID: accountID,
|
||||
ExpiresAt: time.Now().Add(ttl),
|
||||
CreatedAt: time.Now(),
|
||||
ServiceID: serviceID,
|
||||
AccountID: accountID,
|
||||
ExpiresAt: time.Now().Add(ttl),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
log.Debugf("Generated one-time token for proxy %s in account %s (expires in %s)",
|
||||
reverseProxyID, accountID, ttl)
|
||||
serviceID, accountID, ttl)
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
||||
// ValidateAndConsume verifies the token against the provided accountID and
|
||||
// reverseProxyID, checks expiration, and then deletes it to enforce single-use.
|
||||
// serviceID, checks expiration, and then deletes it to enforce single-use.
|
||||
//
|
||||
// This method uses constant-time comparison to prevent timing attacks.
|
||||
//
|
||||
@@ -87,14 +87,14 @@ func (s *OneTimeTokenStore) GenerateToken(accountID, reverseProxyID string, ttl
|
||||
// - Token has expired
|
||||
// - Account ID doesn't match
|
||||
// - Reverse proxy ID doesn't match
|
||||
func (s *OneTimeTokenStore) ValidateAndConsume(token, accountID, reverseProxyID string) error {
|
||||
func (s *OneTimeTokenStore) ValidateAndConsume(token, accountID, serviceID string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
metadata, exists := s.tokens[token]
|
||||
if !exists {
|
||||
log.Warnf("Token validation failed: token not found (proxy: %s, account: %s)",
|
||||
reverseProxyID, accountID)
|
||||
serviceID, accountID)
|
||||
return fmt.Errorf("invalid token")
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func (s *OneTimeTokenStore) ValidateAndConsume(token, accountID, reverseProxyID
|
||||
if time.Now().After(metadata.ExpiresAt) {
|
||||
delete(s.tokens, token)
|
||||
log.Warnf("Token validation failed: token expired (proxy: %s, account: %s)",
|
||||
reverseProxyID, accountID)
|
||||
serviceID, accountID)
|
||||
return fmt.Errorf("token expired")
|
||||
}
|
||||
|
||||
@@ -113,18 +113,18 @@ func (s *OneTimeTokenStore) ValidateAndConsume(token, accountID, reverseProxyID
|
||||
return fmt.Errorf("account ID mismatch")
|
||||
}
|
||||
|
||||
// Validate reverse proxy ID using constant-time comparison
|
||||
if subtle.ConstantTimeCompare([]byte(metadata.ReverseProxyID), []byte(reverseProxyID)) != 1 {
|
||||
log.Warnf("Token validation failed: reverse proxy ID mismatch (expected: %s, got: %s)",
|
||||
metadata.ReverseProxyID, reverseProxyID)
|
||||
return fmt.Errorf("reverse proxy ID mismatch")
|
||||
// Validate service ID using constant-time comparison
|
||||
if subtle.ConstantTimeCompare([]byte(metadata.ServiceID), []byte(serviceID)) != 1 {
|
||||
log.Warnf("Token validation failed: service ID mismatch (expected: %s, got: %s)",
|
||||
metadata.ServiceID, serviceID)
|
||||
return fmt.Errorf("service ID mismatch")
|
||||
}
|
||||
|
||||
// Delete token immediately to enforce single-use
|
||||
delete(s.tokens, token)
|
||||
|
||||
log.Infof("Token validated and consumed for proxy %s in account %s",
|
||||
reverseProxyID, accountID)
|
||||
serviceID, accountID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -176,39 +176,39 @@ func (s *ProxyServiceServer) GetMappingUpdate(req *proto.GetMappingUpdateRequest
|
||||
}
|
||||
}
|
||||
|
||||
// sendSnapshot sends the initial snapshot of reverse proxies to the connecting proxy.
|
||||
// Only reverse proxies matching the proxy's cluster address are sent.
|
||||
// sendSnapshot sends the initial snapshot of services to the connecting proxy.
|
||||
// Only services matching the proxy's cluster address are sent.
|
||||
func (s *ProxyServiceServer) sendSnapshot(ctx context.Context, conn *proxyConnection) error {
|
||||
reverseProxies, err := s.reverseProxyManager.GetGlobalReverseProxies(ctx)
|
||||
services, err := s.reverseProxyManager.GetGlobalServices(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get reverse proxies from store: %w", err)
|
||||
return fmt.Errorf("get services from store: %w", err)
|
||||
}
|
||||
|
||||
proxyClusterAddr := extractClusterAddr(conn.address)
|
||||
|
||||
for _, rp := range reverseProxies {
|
||||
if !rp.Enabled {
|
||||
for _, service := range services {
|
||||
if !service.Enabled {
|
||||
continue
|
||||
}
|
||||
|
||||
if rp.ProxyCluster != "" && proxyClusterAddr != "" && rp.ProxyCluster != proxyClusterAddr {
|
||||
if service.ProxyCluster != "" && proxyClusterAddr != "" && service.ProxyCluster != proxyClusterAddr {
|
||||
continue
|
||||
}
|
||||
|
||||
// Generate one-time authentication token for each proxy in the snapshot
|
||||
// Generate one-time authentication token for each service in the snapshot
|
||||
// Tokens are not persistent on the proxy, so we need to generate new ones on reconnection
|
||||
token, err := s.tokenStore.GenerateToken(rp.AccountID, rp.ID, 5*time.Minute)
|
||||
token, err := s.tokenStore.GenerateToken(service.AccountID, service.ID, 5*time.Minute)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"proxy": rp.Name,
|
||||
"account": rp.AccountID,
|
||||
"service": service.Name,
|
||||
"account": service.AccountID,
|
||||
}).WithError(err).Error("Failed to generate auth token for snapshot")
|
||||
continue
|
||||
}
|
||||
|
||||
if err := conn.stream.Send(&proto.GetMappingUpdateResponse{
|
||||
Mapping: []*proto.ProxyMapping{
|
||||
rp.ToProtoMapping(
|
||||
service.ToProtoMapping(
|
||||
reverseproxy.Create, // Initial snapshot, all records are "new" for the proxy.
|
||||
token,
|
||||
s.GetOIDCValidationConfig(),
|
||||
@@ -260,10 +260,10 @@ func (s *ProxyServiceServer) SendAccessLog(ctx context.Context, req *proto.SendA
|
||||
accessLog := req.GetLog()
|
||||
|
||||
fields := log.Fields{
|
||||
"reverse_proxy_id": accessLog.GetServiceId(),
|
||||
"account_id": accessLog.GetAccountId(),
|
||||
"host": accessLog.GetHost(),
|
||||
"source_ip": accessLog.GetSourceIp(),
|
||||
"service_id": accessLog.GetServiceId(),
|
||||
"account_id": accessLog.GetAccountId(),
|
||||
"host": accessLog.GetHost(),
|
||||
"source_ip": accessLog.GetSourceIp(),
|
||||
}
|
||||
if mechanism := accessLog.GetAuthMechanism(); mechanism != "" {
|
||||
fields["auth_mechanism"] = mechanism
|
||||
@@ -292,18 +292,18 @@ func (s *ProxyServiceServer) SendAccessLog(ctx context.Context, req *proto.SendA
|
||||
return &proto.SendAccessLogResponse{}, nil
|
||||
}
|
||||
|
||||
// SendReverseProxyUpdate broadcasts a reverse proxy update to all connected proxies.
|
||||
// Management should call this when reverse proxies are created/updated/removed
|
||||
func (s *ProxyServiceServer) SendReverseProxyUpdate(update *proto.ProxyMapping) {
|
||||
// Send it to all connected proxies
|
||||
log.Debugf("Broadcasting reverse proxy update to all connected proxies")
|
||||
// SendServiceUpdate broadcasts a service update to all connected proxy servers.
|
||||
// Management should call this when services are created/updated/removed
|
||||
func (s *ProxyServiceServer) SendServiceUpdate(update *proto.ProxyMapping) {
|
||||
// Send it to all connected proxy servers
|
||||
log.Debugf("Broadcasting service update to all connected proxy servers")
|
||||
s.connectedProxies.Range(func(key, value interface{}) bool {
|
||||
conn := value.(*proxyConnection)
|
||||
select {
|
||||
case conn.sendChan <- update:
|
||||
log.Debugf("Sent reverse proxy update with id %s to proxy %s", update.Id, conn.proxyID)
|
||||
log.Debugf("Sent service update with id %s to proxy server %s", update.Id, conn.proxyID)
|
||||
default:
|
||||
log.Warnf("Failed to send reverse proxy update to proxy %s (channel full)", conn.proxyID)
|
||||
log.Warnf("Failed to send service update to proxy server %s (channel full)", conn.proxyID)
|
||||
}
|
||||
return true
|
||||
})
|
||||
@@ -366,11 +366,11 @@ func (s *ProxyServiceServer) removeFromCluster(clusterAddr, proxyID string) {
|
||||
}
|
||||
}
|
||||
|
||||
// SendReverseProxyUpdateToCluster sends a reverse proxy update to all proxies in a specific cluster.
|
||||
// If clusterAddr is empty, broadcasts to all connected proxies (backward compatibility).
|
||||
func (s *ProxyServiceServer) SendReverseProxyUpdateToCluster(update *proto.ProxyMapping, clusterAddr string) {
|
||||
// SendServiceUpdateToCluster sends a service update to all proxy servers in a specific cluster.
|
||||
// If clusterAddr is empty, broadcasts to all connected proxy servers (backward compatibility).
|
||||
func (s *ProxyServiceServer) SendServiceUpdateToCluster(update *proto.ProxyMapping, clusterAddr string) {
|
||||
if clusterAddr == "" {
|
||||
s.SendReverseProxyUpdate(update)
|
||||
s.SendServiceUpdate(update)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -380,16 +380,16 @@ func (s *ProxyServiceServer) SendReverseProxyUpdateToCluster(update *proto.Proxy
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("Sending reverse proxy update to cluster %s", clusterAddr)
|
||||
log.Debugf("Sending service update to cluster %s", clusterAddr)
|
||||
proxySet.(*sync.Map).Range(func(key, _ interface{}) bool {
|
||||
proxyID := key.(string)
|
||||
if connVal, ok := s.connectedProxies.Load(proxyID); ok {
|
||||
conn := connVal.(*proxyConnection)
|
||||
select {
|
||||
case conn.sendChan <- update:
|
||||
log.Debugf("Sent reverse proxy update with id %s to proxy %s in cluster %s", update.Id, proxyID, clusterAddr)
|
||||
log.Debugf("Sent service update with id %s to proxy %s in cluster %s", update.Id, proxyID, clusterAddr)
|
||||
default:
|
||||
log.Warnf("Failed to send reverse proxy update to proxy %s in cluster %s (channel full)", proxyID, clusterAddr)
|
||||
log.Warnf("Failed to send service update to proxy %s in cluster %s (channel full)", proxyID, clusterAddr)
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -424,10 +424,10 @@ func (s *ProxyServiceServer) GetAvailableClusters() []ClusterInfo {
|
||||
}
|
||||
|
||||
func (s *ProxyServiceServer) Authenticate(ctx context.Context, req *proto.AuthenticateRequest) (*proto.AuthenticateResponse, error) {
|
||||
proxy, err := s.reverseProxyManager.GetProxyByID(ctx, req.GetAccountId(), req.GetId())
|
||||
service, err := s.reverseProxyManager.GetServiceByID(ctx, req.GetAccountId(), req.GetId())
|
||||
if err != nil {
|
||||
// TODO: log the error
|
||||
return nil, status.Errorf(codes.FailedPrecondition, "failed to get reverse proxy from store: %v", err)
|
||||
return nil, status.Errorf(codes.FailedPrecondition, "failed to get service from store: %v", err)
|
||||
}
|
||||
|
||||
var authenticated bool
|
||||
@@ -435,7 +435,7 @@ func (s *ProxyServiceServer) Authenticate(ctx context.Context, req *proto.Authen
|
||||
var method proxyauth.Method
|
||||
switch v := req.GetRequest().(type) {
|
||||
case *proto.AuthenticateRequest_Pin:
|
||||
auth := proxy.Auth.PinAuth
|
||||
auth := service.Auth.PinAuth
|
||||
if auth == nil || !auth.Enabled {
|
||||
// TODO: log
|
||||
// Break here and use the default authenticated == false.
|
||||
@@ -454,7 +454,7 @@ func (s *ProxyServiceServer) Authenticate(ctx context.Context, req *proto.Authen
|
||||
userId = "pin-user"
|
||||
method = proxyauth.MethodPIN
|
||||
case *proto.AuthenticateRequest_Password:
|
||||
auth := proxy.Auth.PasswordAuth
|
||||
auth := service.Auth.PasswordAuth
|
||||
if auth == nil || !auth.Enabled {
|
||||
// TODO: log
|
||||
// Break here and use the default authenticated == false.
|
||||
@@ -475,11 +475,11 @@ func (s *ProxyServiceServer) Authenticate(ctx context.Context, req *proto.Authen
|
||||
}
|
||||
|
||||
var token string
|
||||
if authenticated && proxy.SessionPrivateKey != "" {
|
||||
if authenticated && service.SessionPrivateKey != "" {
|
||||
token, err = sessionkey.SignToken(
|
||||
proxy.SessionPrivateKey,
|
||||
service.SessionPrivateKey,
|
||||
userId,
|
||||
proxy.Domain,
|
||||
service.Domain,
|
||||
method,
|
||||
proxyauth.DefaultSessionExpiry,
|
||||
)
|
||||
@@ -498,45 +498,45 @@ func (s *ProxyServiceServer) Authenticate(ctx context.Context, req *proto.Authen
|
||||
// SendStatusUpdate handles status updates from proxy clients
|
||||
func (s *ProxyServiceServer) SendStatusUpdate(ctx context.Context, req *proto.SendStatusUpdateRequest) (*proto.SendStatusUpdateResponse, error) {
|
||||
accountID := req.GetAccountId()
|
||||
reverseProxyID := req.GetReverseProxyId()
|
||||
serviceID := req.GetServiceId()
|
||||
protoStatus := req.GetStatus()
|
||||
certificateIssued := req.GetCertificateIssued()
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"service_id": serviceID,
|
||||
"account_id": accountID,
|
||||
"status": protoStatus,
|
||||
"certificate_issued": certificateIssued,
|
||||
"error_message": req.GetErrorMessage(),
|
||||
}).Debug("Status update from proxy")
|
||||
}).Debug("Status update from proxy server")
|
||||
|
||||
if reverseProxyID == "" || accountID == "" {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "reverse_proxy_id and account_id are required")
|
||||
if serviceID == "" || accountID == "" {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "service_id and account_id are required")
|
||||
}
|
||||
|
||||
if certificateIssued {
|
||||
if err := s.reverseProxyManager.SetCertificateIssuedAt(ctx, accountID, reverseProxyID); err != nil {
|
||||
if err := s.reverseProxyManager.SetCertificateIssuedAt(ctx, accountID, serviceID); err != nil {
|
||||
log.WithContext(ctx).WithError(err).Error("Failed to set certificate issued timestamp")
|
||||
return nil, status.Errorf(codes.Internal, "failed to update certificate timestamp: %v", err)
|
||||
}
|
||||
log.WithFields(log.Fields{
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"account_id": accountID,
|
||||
"service_id": serviceID,
|
||||
"account_id": accountID,
|
||||
}).Info("Certificate issued timestamp updated")
|
||||
}
|
||||
|
||||
internalStatus := protoStatusToInternal(protoStatus)
|
||||
|
||||
if err := s.reverseProxyManager.SetStatus(ctx, accountID, reverseProxyID, internalStatus); err != nil {
|
||||
log.WithContext(ctx).WithError(err).Error("Failed to set proxy status")
|
||||
return nil, status.Errorf(codes.Internal, "failed to update proxy status: %v", err)
|
||||
if err := s.reverseProxyManager.SetStatus(ctx, accountID, serviceID, internalStatus); err != nil {
|
||||
log.WithContext(ctx).WithError(err).Error("Failed to set service status")
|
||||
return nil, status.Errorf(codes.Internal, "failed to update service status: %v", err)
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"account_id": accountID,
|
||||
"status": internalStatus,
|
||||
}).Info("Proxy status updated")
|
||||
"service_id": serviceID,
|
||||
"account_id": accountID,
|
||||
"status": internalStatus,
|
||||
}).Info("Service status updated")
|
||||
|
||||
return &proto.SendStatusUpdateResponse{}, nil
|
||||
}
|
||||
@@ -563,30 +563,30 @@ func protoStatusToInternal(protoStatus proto.ProxyStatus) reverseproxy.ProxyStat
|
||||
|
||||
// CreateProxyPeer handles proxy peer creation with one-time token authentication
|
||||
func (s *ProxyServiceServer) CreateProxyPeer(ctx context.Context, req *proto.CreateProxyPeerRequest) (*proto.CreateProxyPeerResponse, error) {
|
||||
reverseProxyID := req.GetReverseProxyId()
|
||||
serviceID := req.GetServiceId()
|
||||
accountID := req.GetAccountId()
|
||||
token := req.GetToken()
|
||||
cluster := req.GetCluster()
|
||||
key := req.WireguardPublicKey
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"account_id": accountID,
|
||||
"cluster": cluster,
|
||||
"service_id": serviceID,
|
||||
"account_id": accountID,
|
||||
"cluster": cluster,
|
||||
}).Debug("CreateProxyPeer request received")
|
||||
|
||||
if reverseProxyID == "" || accountID == "" || token == "" {
|
||||
if serviceID == "" || accountID == "" || token == "" {
|
||||
log.Warn("CreateProxyPeer: missing required fields")
|
||||
return &proto.CreateProxyPeerResponse{
|
||||
Success: false,
|
||||
ErrorMessage: strPtr("missing required fields: reverse_proxy_id, account_id, and token are required"),
|
||||
ErrorMessage: strPtr("missing required fields: service_id, account_id, and token are required"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
if err := s.tokenStore.ValidateAndConsume(token, accountID, reverseProxyID); err != nil {
|
||||
if err := s.tokenStore.ValidateAndConsume(token, accountID, serviceID); err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"account_id": accountID,
|
||||
"service_id": serviceID,
|
||||
"account_id": accountID,
|
||||
}).WithError(err).Warn("CreateProxyPeer: token validation failed")
|
||||
return &proto.CreateProxyPeerResponse{
|
||||
Success: false,
|
||||
@@ -597,8 +597,8 @@ func (s *ProxyServiceServer) CreateProxyPeer(ctx context.Context, req *proto.Cre
|
||||
err := s.peersManager.CreateProxyPeer(ctx, accountID, key, cluster)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"account_id": accountID,
|
||||
"service_id": serviceID,
|
||||
"account_id": accountID,
|
||||
}).WithError(err).Error("CreateProxyPeer: failed to create proxy peer")
|
||||
return &proto.CreateProxyPeerResponse{
|
||||
Success: false,
|
||||
@@ -622,22 +622,22 @@ func (s *ProxyServiceServer) GetOIDCURL(ctx context.Context, req *proto.GetOIDCU
|
||||
// TODO: log
|
||||
return nil, status.Errorf(codes.InvalidArgument, "failed to parse redirect url: %v", err)
|
||||
}
|
||||
// Validate redirectURL against known proxy endpoints to avoid abuse of OIDC redirection.
|
||||
proxies, err := s.reverseProxyManager.GetAccountReverseProxies(ctx, req.GetAccountId())
|
||||
// Validate redirectURL against known service endpoints to avoid abuse of OIDC redirection.
|
||||
services, err := s.reverseProxyManager.GetAccountServices(ctx, req.GetAccountId())
|
||||
if err != nil {
|
||||
// TODO: log
|
||||
return nil, status.Errorf(codes.FailedPrecondition, "failed to get reverse proxy from store: %v", err)
|
||||
return nil, status.Errorf(codes.FailedPrecondition, "failed to get services from store: %v", err)
|
||||
}
|
||||
var found bool
|
||||
for _, proxy := range proxies {
|
||||
if proxy.Domain == redirectURL.Hostname() {
|
||||
for _, service := range services {
|
||||
if service.Domain == redirectURL.Hostname() {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
// TODO: log
|
||||
return nil, status.Errorf(codes.FailedPrecondition, "reverse proxy not found in store")
|
||||
return nil, status.Errorf(codes.FailedPrecondition, "service not found in store")
|
||||
}
|
||||
|
||||
provider, err := oidc.NewProvider(ctx, s.oidcConfig.Issuer)
|
||||
@@ -728,29 +728,29 @@ func (s *ProxyServiceServer) ValidateState(state string) (verifier, redirectURL
|
||||
|
||||
// GenerateSessionToken creates a signed session JWT for the given domain and user.
|
||||
func (s *ProxyServiceServer) GenerateSessionToken(ctx context.Context, domain, userID string, method proxyauth.Method) (string, error) {
|
||||
// Find the proxy by domain to get its signing key
|
||||
proxies, err := s.reverseProxyManager.GetGlobalReverseProxies(ctx)
|
||||
// Find the service by domain to get its signing key
|
||||
services, err := s.reverseProxyManager.GetGlobalServices(ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("get reverse proxies: %w", err)
|
||||
return "", fmt.Errorf("get services: %w", err)
|
||||
}
|
||||
|
||||
var proxy *reverseproxy.ReverseProxy
|
||||
for _, p := range proxies {
|
||||
if p.Domain == domain {
|
||||
proxy = p
|
||||
var service *reverseproxy.Service
|
||||
for _, svc := range services {
|
||||
if svc.Domain == domain {
|
||||
service = svc
|
||||
break
|
||||
}
|
||||
}
|
||||
if proxy == nil {
|
||||
return "", fmt.Errorf("reverse proxy not found for domain: %s", domain)
|
||||
if service == nil {
|
||||
return "", fmt.Errorf("service not found for domain: %s", domain)
|
||||
}
|
||||
|
||||
if proxy.SessionPrivateKey == "" {
|
||||
if service.SessionPrivateKey == "" {
|
||||
return "", fmt.Errorf("no session key configured for domain: %s", domain)
|
||||
}
|
||||
|
||||
return sessionkey.SignToken(
|
||||
proxy.SessionPrivateKey,
|
||||
service.SessionPrivateKey,
|
||||
userID,
|
||||
domain,
|
||||
method,
|
||||
@@ -758,8 +758,8 @@ func (s *ProxyServiceServer) GenerateSessionToken(ctx context.Context, domain, u
|
||||
)
|
||||
}
|
||||
|
||||
// ValidateUserGroupAccess checks if a user has access to a reverse proxy.
|
||||
// It looks up the proxy within the user's account only, then optionally checks
|
||||
// ValidateUserGroupAccess checks if a user has access to a service.
|
||||
// It looks up the service within the user's account only, then optionally checks
|
||||
// group membership if BearerAuth with DistributionGroups is configured.
|
||||
func (s *ProxyServiceServer) ValidateUserGroupAccess(ctx context.Context, domain, userID string) error {
|
||||
user, err := s.usersManager.GetUser(ctx, userID)
|
||||
@@ -767,16 +767,16 @@ func (s *ProxyServiceServer) ValidateUserGroupAccess(ctx context.Context, domain
|
||||
return fmt.Errorf("user not found: %s", userID)
|
||||
}
|
||||
|
||||
proxy, err := s.getAccountProxyByDomain(ctx, user.AccountID, domain)
|
||||
service, err := s.getAccountServiceByDomain(ctx, user.AccountID, domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if proxy.Auth.BearerAuth == nil || !proxy.Auth.BearerAuth.Enabled {
|
||||
if service.Auth.BearerAuth == nil || !service.Auth.BearerAuth.Enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
allowedGroups := proxy.Auth.BearerAuth.DistributionGroups
|
||||
allowedGroups := service.Auth.BearerAuth.DistributionGroups
|
||||
if len(allowedGroups) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -800,19 +800,19 @@ func (s *ProxyServiceServer) ValidateUserGroupAccess(ctx context.Context, domain
|
||||
return fmt.Errorf("user %s not in allowed groups for domain %s", user.Id, domain)
|
||||
}
|
||||
|
||||
func (s *ProxyServiceServer) getAccountProxyByDomain(ctx context.Context, accountID, domain string) (*reverseproxy.ReverseProxy, error) {
|
||||
proxies, err := s.reverseProxyManager.GetAccountReverseProxies(ctx, accountID)
|
||||
func (s *ProxyServiceServer) getAccountServiceByDomain(ctx context.Context, accountID, domain string) (*reverseproxy.Service, error) {
|
||||
services, err := s.reverseProxyManager.GetAccountServices(ctx, accountID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get account reverse proxies: %w", err)
|
||||
return nil, fmt.Errorf("get account services: %w", err)
|
||||
}
|
||||
|
||||
for _, proxy := range proxies {
|
||||
if proxy.Domain == domain {
|
||||
return proxy, nil
|
||||
for _, service := range services {
|
||||
if service.Domain == domain {
|
||||
return service, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("reverse proxy not found for domain %s in account %s", domain, accountID)
|
||||
return nil, fmt.Errorf("service not found for domain %s in account %s", domain, accountID)
|
||||
}
|
||||
|
||||
// ValidateSession validates a session token and checks if the user has access to the domain.
|
||||
@@ -827,19 +827,19 @@ func (s *ProxyServiceServer) ValidateSession(ctx context.Context, req *proto.Val
|
||||
}, nil
|
||||
}
|
||||
|
||||
proxy, err := s.getProxyByDomain(ctx, domain)
|
||||
service, err := s.getServiceByDomain(ctx, domain)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"domain": domain,
|
||||
"error": err.Error(),
|
||||
}).Debug("ValidateSession: proxy not found")
|
||||
}).Debug("ValidateSession: service not found")
|
||||
return &proto.ValidateSessionResponse{
|
||||
Valid: false,
|
||||
DeniedReason: "proxy_not_found",
|
||||
DeniedReason: "service_not_found",
|
||||
}, nil
|
||||
}
|
||||
|
||||
pubKeyBytes, err := base64.StdEncoding.DecodeString(proxy.SessionPublicKey)
|
||||
pubKeyBytes, err := base64.StdEncoding.DecodeString(service.SessionPublicKey)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"domain": domain,
|
||||
@@ -847,7 +847,7 @@ func (s *ProxyServiceServer) ValidateSession(ctx context.Context, req *proto.Val
|
||||
}).Error("ValidateSession: decode public key")
|
||||
return &proto.ValidateSessionResponse{
|
||||
Valid: false,
|
||||
DeniedReason: "invalid_proxy_config",
|
||||
DeniedReason: "invalid_service_config",
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -876,12 +876,12 @@ func (s *ProxyServiceServer) ValidateSession(ctx context.Context, req *proto.Val
|
||||
}, nil
|
||||
}
|
||||
|
||||
if user.AccountID != proxy.AccountID {
|
||||
if user.AccountID != service.AccountID {
|
||||
log.WithFields(log.Fields{
|
||||
"domain": domain,
|
||||
"user_id": userID,
|
||||
"user_account": user.AccountID,
|
||||
"proxy_account": proxy.AccountID,
|
||||
"domain": domain,
|
||||
"user_id": userID,
|
||||
"user_account": user.AccountID,
|
||||
"service_account": service.AccountID,
|
||||
}).Debug("ValidateSession: user account mismatch")
|
||||
return &proto.ValidateSessionResponse{
|
||||
Valid: false,
|
||||
@@ -889,7 +889,7 @@ func (s *ProxyServiceServer) ValidateSession(ctx context.Context, req *proto.Val
|
||||
}, nil
|
||||
}
|
||||
|
||||
if err := s.checkGroupAccess(proxy, user); err != nil {
|
||||
if err := s.checkGroupAccess(service, user); err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"domain": domain,
|
||||
"user_id": userID,
|
||||
@@ -916,27 +916,27 @@ func (s *ProxyServiceServer) ValidateSession(ctx context.Context, req *proto.Val
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *ProxyServiceServer) getProxyByDomain(ctx context.Context, domain string) (*reverseproxy.ReverseProxy, error) {
|
||||
proxies, err := s.reverseProxyManager.GetGlobalReverseProxies(ctx)
|
||||
func (s *ProxyServiceServer) getServiceByDomain(ctx context.Context, domain string) (*reverseproxy.Service, error) {
|
||||
services, err := s.reverseProxyManager.GetGlobalServices(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get reverse proxies: %w", err)
|
||||
return nil, fmt.Errorf("get services: %w", err)
|
||||
}
|
||||
|
||||
for _, proxy := range proxies {
|
||||
if proxy.Domain == domain {
|
||||
return proxy, nil
|
||||
for _, service := range services {
|
||||
if service.Domain == domain {
|
||||
return service, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("reverse proxy not found for domain: %s", domain)
|
||||
return nil, fmt.Errorf("service not found for domain: %s", domain)
|
||||
}
|
||||
|
||||
func (s *ProxyServiceServer) checkGroupAccess(proxy *reverseproxy.ReverseProxy, user *types.User) error {
|
||||
if proxy.Auth.BearerAuth == nil || !proxy.Auth.BearerAuth.Enabled {
|
||||
func (s *ProxyServiceServer) checkGroupAccess(service *reverseproxy.Service, user *types.User) error {
|
||||
if service.Auth.BearerAuth == nil || !service.Auth.BearerAuth.Enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
allowedGroups := proxy.Auth.BearerAuth.DistributionGroups
|
||||
allowedGroups := service.Auth.BearerAuth.DistributionGroups
|
||||
if len(allowedGroups) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -13,38 +13,38 @@ import (
|
||||
)
|
||||
|
||||
type mockReverseProxyManager struct {
|
||||
proxiesByAccount map[string][]*reverseproxy.ReverseProxy
|
||||
proxiesByAccount map[string][]*reverseproxy.Service
|
||||
err error
|
||||
}
|
||||
|
||||
func (m *mockReverseProxyManager) GetAccountReverseProxies(ctx context.Context, accountID string) ([]*reverseproxy.ReverseProxy, error) {
|
||||
func (m *mockReverseProxyManager) GetAccountServices(ctx context.Context, accountID string) ([]*reverseproxy.Service, error) {
|
||||
if m.err != nil {
|
||||
return nil, m.err
|
||||
}
|
||||
return m.proxiesByAccount[accountID], nil
|
||||
}
|
||||
|
||||
func (m *mockReverseProxyManager) GetGlobalReverseProxies(ctx context.Context) ([]*reverseproxy.ReverseProxy, error) {
|
||||
func (m *mockReverseProxyManager) GetGlobalServices(ctx context.Context) ([]*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockReverseProxyManager) GetAllReverseProxies(ctx context.Context, accountID, userID string) ([]*reverseproxy.ReverseProxy, error) {
|
||||
func (m *mockReverseProxyManager) GetAllServices(ctx context.Context, accountID, userID string) ([]*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockReverseProxyManager) GetReverseProxy(ctx context.Context, accountID, userID, reverseProxyID string) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *mockReverseProxyManager) GetService(ctx context.Context, accountID, userID, reverseProxyID string) (*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockReverseProxyManager) CreateReverseProxy(ctx context.Context, accountID, userID string, rp *reverseproxy.ReverseProxy) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *mockReverseProxyManager) CreateService(ctx context.Context, accountID, userID string, rp *reverseproxy.Service) (*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockReverseProxyManager) UpdateReverseProxy(ctx context.Context, accountID, userID string, rp *reverseproxy.ReverseProxy) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *mockReverseProxyManager) UpdateService(ctx context.Context, accountID, userID string, rp *reverseproxy.Service) (*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockReverseProxyManager) DeleteReverseProxy(ctx context.Context, accountID, userID, reverseProxyID string) error {
|
||||
func (m *mockReverseProxyManager) DeleteService(ctx context.Context, accountID, userID, reverseProxyID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -56,19 +56,19 @@ func (m *mockReverseProxyManager) SetStatus(ctx context.Context, accountID, reve
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockReverseProxyManager) ReloadAllReverseProxiesForAccount(ctx context.Context, accountID string) error {
|
||||
func (m *mockReverseProxyManager) ReloadAllServicesForAccount(ctx context.Context, accountID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockReverseProxyManager) ReloadReverseProxy(ctx context.Context, accountID, reverseProxyID string) error {
|
||||
func (m *mockReverseProxyManager) ReloadService(ctx context.Context, accountID, reverseProxyID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockReverseProxyManager) GetProxyByID(ctx context.Context, accountID, reverseProxyID string) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *mockReverseProxyManager) GetServiceByID(ctx context.Context, accountID, reverseProxyID string) (*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockReverseProxyManager) GetProxyIDByTargetID(_ context.Context, _, _ string) (string, error) {
|
||||
func (m *mockReverseProxyManager) GetServiceIDByTargetID(_ context.Context, _, _ string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ func TestValidateUserGroupAccess(t *testing.T) {
|
||||
name string
|
||||
domain string
|
||||
userID string
|
||||
proxiesByAccount map[string][]*reverseproxy.ReverseProxy
|
||||
proxiesByAccount map[string][]*reverseproxy.Service
|
||||
users map[string]*types.User
|
||||
proxyErr error
|
||||
userErr error
|
||||
@@ -104,7 +104,7 @@ func TestValidateUserGroupAccess(t *testing.T) {
|
||||
name: "user not found",
|
||||
domain: "app.example.com",
|
||||
userID: "unknown-user",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{
|
||||
"account1": {{Domain: "app.example.com", AccountID: "account1"}},
|
||||
},
|
||||
users: map[string]*types.User{},
|
||||
@@ -115,7 +115,7 @@ func TestValidateUserGroupAccess(t *testing.T) {
|
||||
name: "proxy not found in user's account",
|
||||
domain: "app.example.com",
|
||||
userID: "user1",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{},
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{},
|
||||
users: map[string]*types.User{
|
||||
"user1": {Id: "user1", AccountID: "account1"},
|
||||
},
|
||||
@@ -126,7 +126,7 @@ func TestValidateUserGroupAccess(t *testing.T) {
|
||||
name: "proxy exists in different account - not accessible",
|
||||
domain: "app.example.com",
|
||||
userID: "user1",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{
|
||||
"account2": {{Domain: "app.example.com", AccountID: "account2"}},
|
||||
},
|
||||
users: map[string]*types.User{
|
||||
@@ -139,7 +139,7 @@ func TestValidateUserGroupAccess(t *testing.T) {
|
||||
name: "no bearer auth configured - same account allows access",
|
||||
domain: "app.example.com",
|
||||
userID: "user1",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{
|
||||
"account1": {{Domain: "app.example.com", AccountID: "account1", Auth: reverseproxy.AuthConfig{}}},
|
||||
},
|
||||
users: map[string]*types.User{
|
||||
@@ -151,7 +151,7 @@ func TestValidateUserGroupAccess(t *testing.T) {
|
||||
name: "bearer auth disabled - same account allows access",
|
||||
domain: "app.example.com",
|
||||
userID: "user1",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{
|
||||
"account1": {{
|
||||
Domain: "app.example.com",
|
||||
AccountID: "account1",
|
||||
@@ -169,7 +169,7 @@ func TestValidateUserGroupAccess(t *testing.T) {
|
||||
name: "bearer auth enabled but no groups configured - same account allows access",
|
||||
domain: "app.example.com",
|
||||
userID: "user1",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{
|
||||
"account1": {{
|
||||
Domain: "app.example.com",
|
||||
AccountID: "account1",
|
||||
@@ -190,7 +190,7 @@ func TestValidateUserGroupAccess(t *testing.T) {
|
||||
name: "user not in allowed groups",
|
||||
domain: "app.example.com",
|
||||
userID: "user1",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{
|
||||
"account1": {{
|
||||
Domain: "app.example.com",
|
||||
AccountID: "account1",
|
||||
@@ -212,7 +212,7 @@ func TestValidateUserGroupAccess(t *testing.T) {
|
||||
name: "user in one of the allowed groups - allow access",
|
||||
domain: "app.example.com",
|
||||
userID: "user1",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{
|
||||
"account1": {{
|
||||
Domain: "app.example.com",
|
||||
AccountID: "account1",
|
||||
@@ -233,7 +233,7 @@ func TestValidateUserGroupAccess(t *testing.T) {
|
||||
name: "user in all allowed groups - allow access",
|
||||
domain: "app.example.com",
|
||||
userID: "user1",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{
|
||||
"account1": {{
|
||||
Domain: "app.example.com",
|
||||
AccountID: "account1",
|
||||
@@ -266,7 +266,7 @@ func TestValidateUserGroupAccess(t *testing.T) {
|
||||
name: "multiple proxies in account - finds correct one",
|
||||
domain: "app2.example.com",
|
||||
userID: "user1",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{
|
||||
"account1": {
|
||||
{Domain: "app1.example.com", AccountID: "account1"},
|
||||
{Domain: "app2.example.com", AccountID: "account1", Auth: reverseproxy.AuthConfig{}},
|
||||
@@ -310,7 +310,7 @@ func TestGetAccountProxyByDomain(t *testing.T) {
|
||||
name string
|
||||
accountID string
|
||||
domain string
|
||||
proxiesByAccount map[string][]*reverseproxy.ReverseProxy
|
||||
proxiesByAccount map[string][]*reverseproxy.Service
|
||||
err error
|
||||
expectProxy bool
|
||||
expectErr bool
|
||||
@@ -319,7 +319,7 @@ func TestGetAccountProxyByDomain(t *testing.T) {
|
||||
name: "proxy found",
|
||||
accountID: "account1",
|
||||
domain: "app.example.com",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{
|
||||
"account1": {
|
||||
{Domain: "other.example.com", AccountID: "account1"},
|
||||
{Domain: "app.example.com", AccountID: "account1"},
|
||||
@@ -332,7 +332,7 @@ func TestGetAccountProxyByDomain(t *testing.T) {
|
||||
name: "proxy not found in account",
|
||||
accountID: "account1",
|
||||
domain: "unknown.example.com",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{
|
||||
"account1": {{Domain: "app.example.com", AccountID: "account1"}},
|
||||
},
|
||||
expectProxy: false,
|
||||
@@ -342,7 +342,7 @@ func TestGetAccountProxyByDomain(t *testing.T) {
|
||||
name: "empty proxy list for account",
|
||||
accountID: "account1",
|
||||
domain: "app.example.com",
|
||||
proxiesByAccount: map[string][]*reverseproxy.ReverseProxy{},
|
||||
proxiesByAccount: map[string][]*reverseproxy.Service{},
|
||||
expectProxy: false,
|
||||
expectErr: true,
|
||||
},
|
||||
|
||||
@@ -54,7 +54,7 @@ func createTestProxies(t *testing.T, ctx context.Context, testStore store.Store)
|
||||
|
||||
pubKey, privKey := generateSessionKeyPair(t)
|
||||
|
||||
testProxy := &reverseproxy.ReverseProxy{
|
||||
testProxy := &reverseproxy.Service{
|
||||
ID: "testProxyId",
|
||||
AccountID: "testAccountId",
|
||||
Name: "Test Proxy",
|
||||
@@ -68,9 +68,9 @@ func createTestProxies(t *testing.T, ctx context.Context, testStore store.Store)
|
||||
},
|
||||
},
|
||||
}
|
||||
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",
|
||||
@@ -85,7 +85,7 @@ func createTestProxies(t *testing.T, ctx context.Context, testStore store.Store)
|
||||
},
|
||||
},
|
||||
}
|
||||
require.NoError(t, testStore.CreateReverseProxy(ctx, restrictedProxy))
|
||||
require.NoError(t, testStore.CreateService(ctx, restrictedProxy))
|
||||
}
|
||||
|
||||
func generateSessionKeyPair(t *testing.T) (string, string) {
|
||||
@@ -106,7 +106,7 @@ func TestValidateSession_UserAllowed(t *testing.T) {
|
||||
setup := setupValidateSessionTest(t)
|
||||
defer setup.cleanup()
|
||||
|
||||
proxy, err := setup.store.GetReverseProxyByID(context.Background(), store.LockingStrengthNone, "testAccountId", "testProxyId")
|
||||
proxy, err := setup.store.GetServiceByID(context.Background(), store.LockingStrengthNone, "testAccountId", "testProxyId")
|
||||
require.NoError(t, err)
|
||||
|
||||
token := createSessionToken(t, proxy.SessionPrivateKey, "allowedUserId", "test-proxy.example.com")
|
||||
@@ -126,7 +126,7 @@ func TestValidateSession_UserNotInAllowedGroup(t *testing.T) {
|
||||
setup := setupValidateSessionTest(t)
|
||||
defer setup.cleanup()
|
||||
|
||||
proxy, err := setup.store.GetReverseProxyByID(context.Background(), store.LockingStrengthNone, "testAccountId", "restrictedProxyId")
|
||||
proxy, err := setup.store.GetServiceByID(context.Background(), store.LockingStrengthNone, "testAccountId", "restrictedProxyId")
|
||||
require.NoError(t, err)
|
||||
|
||||
token := createSessionToken(t, proxy.SessionPrivateKey, "nonGroupUserId", "restricted-proxy.example.com")
|
||||
@@ -146,7 +146,7 @@ func TestValidateSession_UserInDifferentAccount(t *testing.T) {
|
||||
setup := setupValidateSessionTest(t)
|
||||
defer setup.cleanup()
|
||||
|
||||
proxy, err := setup.store.GetReverseProxyByID(context.Background(), store.LockingStrengthNone, "testAccountId", "testProxyId")
|
||||
proxy, err := setup.store.GetServiceByID(context.Background(), store.LockingStrengthNone, "testAccountId", "testProxyId")
|
||||
require.NoError(t, err)
|
||||
|
||||
token := createSessionToken(t, proxy.SessionPrivateKey, "otherAccountUserId", "test-proxy.example.com")
|
||||
@@ -165,7 +165,7 @@ func TestValidateSession_UserNotFound(t *testing.T) {
|
||||
setup := setupValidateSessionTest(t)
|
||||
defer setup.cleanup()
|
||||
|
||||
proxy, err := setup.store.GetReverseProxyByID(context.Background(), store.LockingStrengthNone, "testAccountId", "testProxyId")
|
||||
proxy, err := setup.store.GetServiceByID(context.Background(), store.LockingStrengthNone, "testAccountId", "testProxyId")
|
||||
require.NoError(t, err)
|
||||
|
||||
token := createSessionToken(t, proxy.SessionPrivateKey, "nonExistentUserId", "test-proxy.example.com")
|
||||
@@ -184,7 +184,7 @@ func TestValidateSession_ProxyNotFound(t *testing.T) {
|
||||
setup := setupValidateSessionTest(t)
|
||||
defer setup.cleanup()
|
||||
|
||||
proxy, err := setup.store.GetReverseProxyByID(context.Background(), store.LockingStrengthNone, "testAccountId", "testProxyId")
|
||||
proxy, err := setup.store.GetServiceByID(context.Background(), store.LockingStrengthNone, "testAccountId", "testProxyId")
|
||||
require.NoError(t, err)
|
||||
|
||||
token := createSessionToken(t, proxy.SessionPrivateKey, "allowedUserId", "unknown-proxy.example.com")
|
||||
@@ -243,23 +243,23 @@ type testValidateSessionProxyManager struct {
|
||||
store store.Store
|
||||
}
|
||||
|
||||
func (m *testValidateSessionProxyManager) GetAllReverseProxies(_ context.Context, _, _ string) ([]*reverseproxy.ReverseProxy, error) {
|
||||
func (m *testValidateSessionProxyManager) GetAllServices(_ context.Context, _, _ string) ([]*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *testValidateSessionProxyManager) GetReverseProxy(_ context.Context, _, _, _ string) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *testValidateSessionProxyManager) GetService(_ context.Context, _, _, _ string) (*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *testValidateSessionProxyManager) CreateReverseProxy(_ context.Context, _, _ string, _ *reverseproxy.ReverseProxy) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *testValidateSessionProxyManager) CreateService(_ context.Context, _, _ string, _ *reverseproxy.Service) (*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *testValidateSessionProxyManager) UpdateReverseProxy(_ context.Context, _, _ string, _ *reverseproxy.ReverseProxy) (*reverseproxy.ReverseProxy, error) {
|
||||
func (m *testValidateSessionProxyManager) UpdateService(_ context.Context, _, _ string, _ *reverseproxy.Service) (*reverseproxy.Service, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *testValidateSessionProxyManager) DeleteReverseProxy(_ context.Context, _, _, _ string) error {
|
||||
func (m *testValidateSessionProxyManager) DeleteService(_ context.Context, _, _, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -271,27 +271,27 @@ func (m *testValidateSessionProxyManager) SetStatus(_ context.Context, _, _ stri
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *testValidateSessionProxyManager) ReloadAllReverseProxiesForAccount(_ context.Context, _ string) error {
|
||||
func (m *testValidateSessionProxyManager) ReloadAllServicesForAccount(_ context.Context, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *testValidateSessionProxyManager) ReloadReverseProxy(_ context.Context, _, _ string) error {
|
||||
func (m *testValidateSessionProxyManager) ReloadService(_ context.Context, _, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *testValidateSessionProxyManager) GetGlobalReverseProxies(ctx context.Context) ([]*reverseproxy.ReverseProxy, error) {
|
||||
return m.store.GetReverseProxies(ctx, store.LockingStrengthNone)
|
||||
func (m *testValidateSessionProxyManager) GetGlobalServices(ctx context.Context) ([]*reverseproxy.Service, error) {
|
||||
return m.store.GetServices(ctx, store.LockingStrengthNone)
|
||||
}
|
||||
|
||||
func (m *testValidateSessionProxyManager) GetProxyByID(ctx context.Context, accountID, proxyID string) (*reverseproxy.ReverseProxy, error) {
|
||||
return m.store.GetReverseProxyByID(ctx, store.LockingStrengthNone, accountID, proxyID)
|
||||
func (m *testValidateSessionProxyManager) GetServiceByID(ctx context.Context, accountID, proxyID string) (*reverseproxy.Service, error) {
|
||||
return m.store.GetServiceByID(ctx, store.LockingStrengthNone, accountID, proxyID)
|
||||
}
|
||||
|
||||
func (m *testValidateSessionProxyManager) GetAccountReverseProxies(ctx context.Context, accountID string) ([]*reverseproxy.ReverseProxy, error) {
|
||||
return m.store.GetAccountReverseProxies(ctx, store.LockingStrengthNone, accountID)
|
||||
func (m *testValidateSessionProxyManager) GetAccountServices(ctx context.Context, accountID string) ([]*reverseproxy.Service, error) {
|
||||
return m.store.GetAccountServices(ctx, store.LockingStrengthNone, accountID)
|
||||
}
|
||||
|
||||
func (m *testValidateSessionProxyManager) GetProxyIDByTargetID(_ context.Context, _, _ string) (string, error) {
|
||||
func (m *testValidateSessionProxyManager) GetServiceIDByTargetID(_ context.Context, _, _ string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
var oidSCTList = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2}
|
||||
|
||||
type certificateNotifier interface {
|
||||
NotifyCertificateIssued(ctx context.Context, accountID, reverseProxyID, domain string) error
|
||||
NotifyCertificateIssued(ctx context.Context, accountID, serviceID, domain string) error
|
||||
}
|
||||
|
||||
type domainState int
|
||||
@@ -35,10 +35,10 @@ const (
|
||||
)
|
||||
|
||||
type domainInfo struct {
|
||||
accountID string
|
||||
reverseProxyID string
|
||||
state domainState
|
||||
err string
|
||||
accountID string
|
||||
serviceID string
|
||||
state domainState
|
||||
err string
|
||||
}
|
||||
|
||||
// Manager wraps autocert.Manager with domain tracking and cross-replica
|
||||
@@ -95,12 +95,12 @@ func (mgr *Manager) hostPolicy(_ context.Context, host string) error {
|
||||
}
|
||||
|
||||
// AddDomain registers a domain for ACME certificate prefetching.
|
||||
func (mgr *Manager) AddDomain(d domain.Domain, accountID, reverseProxyID string) {
|
||||
func (mgr *Manager) AddDomain(d domain.Domain, accountID, serviceID string) {
|
||||
mgr.mu.Lock()
|
||||
mgr.domains[d] = &domainInfo{
|
||||
accountID: accountID,
|
||||
reverseProxyID: reverseProxyID,
|
||||
state: domainPending,
|
||||
accountID: accountID,
|
||||
serviceID: serviceID,
|
||||
state: domainPending,
|
||||
}
|
||||
mgr.mu.Unlock()
|
||||
|
||||
@@ -164,7 +164,7 @@ func (mgr *Manager) prefetchCertificate(d domain.Domain) {
|
||||
mgr.mu.RUnlock()
|
||||
|
||||
if info != nil && mgr.certNotifier != nil {
|
||||
if err := mgr.certNotifier.NotifyCertificateIssued(ctx, info.accountID, info.reverseProxyID, name); err != nil {
|
||||
if err := mgr.certNotifier.NotifyCertificateIssued(ctx, info.accountID, info.serviceID, name); err != nil {
|
||||
mgr.logger.Warnf("notify certificate ready for domain %q: %v", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ var (
|
||||
|
||||
// domainInfo holds metadata about a registered domain.
|
||||
type domainInfo struct {
|
||||
reverseProxyID string
|
||||
serviceID string
|
||||
}
|
||||
|
||||
// clientEntry holds an embedded NetBird client and tracks which domains use it.
|
||||
@@ -48,7 +48,7 @@ type clientEntry struct {
|
||||
}
|
||||
|
||||
type statusNotifier interface {
|
||||
NotifyStatus(ctx context.Context, accountID, reverseProxyID, domain string, connected bool) error
|
||||
NotifyStatus(ctx context.Context, accountID, serviceID, domain string, connected bool) error
|
||||
}
|
||||
|
||||
type managementClient interface {
|
||||
@@ -91,13 +91,13 @@ type accountIDContextKey struct{}
|
||||
// AddPeer registers a domain for an account. If the account doesn't have a client yet,
|
||||
// one is created by authenticating with the management server using the provided token.
|
||||
// Multiple domains can share the same client.
|
||||
func (n *NetBird) AddPeer(ctx context.Context, accountID types.AccountID, d domain.Domain, authToken, reverseProxyID string) error {
|
||||
func (n *NetBird) AddPeer(ctx context.Context, accountID types.AccountID, d domain.Domain, authToken, serviceID string) error {
|
||||
n.clientsMux.Lock()
|
||||
|
||||
entry, exists := n.clients[accountID]
|
||||
if exists {
|
||||
// Client already exists for this account, just register the domain
|
||||
entry.domains[d] = domainInfo{reverseProxyID: reverseProxyID}
|
||||
entry.domains[d] = domainInfo{serviceID: serviceID}
|
||||
started := entry.started
|
||||
n.clientsMux.Unlock()
|
||||
|
||||
@@ -108,7 +108,7 @@ func (n *NetBird) AddPeer(ctx context.Context, accountID types.AccountID, d doma
|
||||
|
||||
// If client is already started, notify this domain as connected immediately
|
||||
if started && n.statusNotifier != nil {
|
||||
if err := n.statusNotifier.NotifyStatus(ctx, string(accountID), reverseProxyID, string(d), true); err != nil {
|
||||
if err := n.statusNotifier.NotifyStatus(ctx, string(accountID), serviceID, string(d), true); err != nil {
|
||||
n.logger.WithFields(log.Fields{
|
||||
"account_id": accountID,
|
||||
"domain": d,
|
||||
@@ -119,8 +119,8 @@ func (n *NetBird) AddPeer(ctx context.Context, accountID types.AccountID, d doma
|
||||
}
|
||||
|
||||
n.logger.WithFields(log.Fields{
|
||||
"account_id": accountID,
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"account_id": accountID,
|
||||
"service_id": serviceID,
|
||||
}).Debug("generating WireGuard keypair for new peer")
|
||||
|
||||
privateKey, err := wgtypes.GeneratePrivateKey()
|
||||
@@ -131,14 +131,14 @@ func (n *NetBird) AddPeer(ctx context.Context, accountID types.AccountID, d doma
|
||||
publicKey := privateKey.PublicKey()
|
||||
|
||||
n.logger.WithFields(log.Fields{
|
||||
"account_id": accountID,
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"public_key": publicKey.String(),
|
||||
"account_id": accountID,
|
||||
"service_id": serviceID,
|
||||
"public_key": publicKey.String(),
|
||||
}).Debug("authenticating new proxy peer with management")
|
||||
|
||||
// Authenticate with management using the one-time token and send public key
|
||||
resp, err := n.mgmtClient.CreateProxyPeer(ctx, &proto.CreateProxyPeerRequest{
|
||||
ReverseProxyId: reverseProxyID,
|
||||
ServiceId: serviceID,
|
||||
AccountId: string(accountID),
|
||||
Token: authToken,
|
||||
WireguardPublicKey: publicKey.String(),
|
||||
@@ -158,9 +158,9 @@ func (n *NetBird) AddPeer(ctx context.Context, accountID types.AccountID, d doma
|
||||
}
|
||||
|
||||
n.logger.WithFields(log.Fields{
|
||||
"account_id": accountID,
|
||||
"reverse_proxy_id": reverseProxyID,
|
||||
"public_key": publicKey.String(),
|
||||
"account_id": accountID,
|
||||
"service_id": serviceID,
|
||||
"public_key": publicKey.String(),
|
||||
}).Info("proxy peer authenticated successfully with management")
|
||||
|
||||
n.initLogOnce.Do(func() {
|
||||
@@ -189,7 +189,7 @@ func (n *NetBird) AddPeer(ctx context.Context, accountID types.AccountID, d doma
|
||||
// not work with reverse proxied requests.
|
||||
entry = &clientEntry{
|
||||
client: client,
|
||||
domains: map[domain.Domain]domainInfo{d: {reverseProxyID: reverseProxyID}},
|
||||
domains: map[domain.Domain]domainInfo{d: {serviceID: serviceID}},
|
||||
transport: &http.Transport{
|
||||
DialContext: client.DialContext,
|
||||
ForceAttemptHTTP2: true,
|
||||
@@ -237,15 +237,15 @@ func (n *NetBird) AddPeer(ctx context.Context, accountID types.AccountID, d doma
|
||||
}
|
||||
// Copy domain info while holding lock
|
||||
var domainsToNotify []struct {
|
||||
domain domain.Domain
|
||||
reverseProxyID string
|
||||
domain domain.Domain
|
||||
serviceID string
|
||||
}
|
||||
if exists {
|
||||
for dom, info := range entry.domains {
|
||||
domainsToNotify = append(domainsToNotify, struct {
|
||||
domain domain.Domain
|
||||
reverseProxyID string
|
||||
}{domain: dom, reverseProxyID: info.reverseProxyID})
|
||||
domain domain.Domain
|
||||
serviceID string
|
||||
}{domain: dom, serviceID: info.serviceID})
|
||||
}
|
||||
}
|
||||
n.clientsMux.Unlock()
|
||||
@@ -253,7 +253,7 @@ func (n *NetBird) AddPeer(ctx context.Context, accountID types.AccountID, d doma
|
||||
// Notify all domains that they're connected
|
||||
if n.statusNotifier != nil {
|
||||
for _, domInfo := range domainsToNotify {
|
||||
if err := n.statusNotifier.NotifyStatus(ctx, string(accountID), domInfo.reverseProxyID, string(domInfo.domain), true); err != nil {
|
||||
if err := n.statusNotifier.NotifyStatus(ctx, string(accountID), domInfo.serviceID, string(domInfo.domain), true); err != nil {
|
||||
n.logger.WithFields(log.Fields{
|
||||
"account_id": accountID,
|
||||
"domain": domInfo.domain,
|
||||
@@ -303,7 +303,7 @@ func (n *NetBird) RemovePeer(ctx context.Context, accountID types.AccountID, d d
|
||||
|
||||
// Notify this domain as disconnected
|
||||
if n.statusNotifier != nil {
|
||||
if err := n.statusNotifier.NotifyStatus(ctx, string(accountID), domInfo.reverseProxyID, string(d), false); err != nil {
|
||||
if err := n.statusNotifier.NotifyStatus(ctx, string(accountID), domInfo.serviceID, string(d), false); err != nil {
|
||||
n.logger.WithFields(log.Fields{
|
||||
"account_id": accountID,
|
||||
"domain": d,
|
||||
@@ -325,7 +325,7 @@ func (n *NetBird) RemovePeer(ctx context.Context, accountID types.AccountID, d d
|
||||
|
||||
// Notify disconnection before stopping
|
||||
if n.statusNotifier != nil {
|
||||
if err := n.statusNotifier.NotifyStatus(ctx, string(accountID), domInfo.reverseProxyID, string(d), false); err != nil {
|
||||
if err := n.statusNotifier.NotifyStatus(ctx, string(accountID), domInfo.serviceID, string(d), false); err != nil {
|
||||
n.logger.WithFields(log.Fields{
|
||||
"account_id": accountID,
|
||||
"domain": d,
|
||||
|
||||
@@ -31,7 +31,7 @@ func BenchmarkHasClient(b *testing.B) {
|
||||
nb.clients[id] = &clientEntry{
|
||||
domains: map[domain.Domain]domainInfo{
|
||||
domain.Domain(rand.Text()): {
|
||||
reverseProxyID: rand.Text(),
|
||||
serviceID: rand.Text(),
|
||||
},
|
||||
},
|
||||
createdAt: time.Now(),
|
||||
@@ -72,7 +72,7 @@ func BenchmarkHasClientDuringAddPeer(b *testing.B) {
|
||||
nb.clients[id] = &clientEntry{
|
||||
domains: map[domain.Domain]domainInfo{
|
||||
domain.Domain(rand.Text()): {
|
||||
reverseProxyID: rand.Text(),
|
||||
serviceID: rand.Text(),
|
||||
},
|
||||
},
|
||||
createdAt: time.Now(),
|
||||
|
||||
@@ -106,14 +106,14 @@ type Server struct {
|
||||
}
|
||||
|
||||
// NotifyStatus sends a status update to management about tunnel connectivity
|
||||
func (s *Server) NotifyStatus(ctx context.Context, accountID, reverseProxyID, domain string, connected bool) error {
|
||||
func (s *Server) NotifyStatus(ctx context.Context, accountID, serviceID, domain string, connected bool) error {
|
||||
status := proto.ProxyStatus_PROXY_STATUS_TUNNEL_NOT_CREATED
|
||||
if connected {
|
||||
status = proto.ProxyStatus_PROXY_STATUS_ACTIVE
|
||||
}
|
||||
|
||||
_, err := s.mgmtClient.SendStatusUpdate(ctx, &proto.SendStatusUpdateRequest{
|
||||
ReverseProxyId: reverseProxyID,
|
||||
ServiceId: serviceID,
|
||||
AccountId: accountID,
|
||||
Status: status,
|
||||
CertificateIssued: false,
|
||||
@@ -122,9 +122,9 @@ func (s *Server) NotifyStatus(ctx context.Context, accountID, reverseProxyID, do
|
||||
}
|
||||
|
||||
// NotifyCertificateIssued sends a notification to management that a certificate was issued
|
||||
func (s *Server) NotifyCertificateIssued(ctx context.Context, accountID, reverseProxyID, domain string) error {
|
||||
func (s *Server) NotifyCertificateIssued(ctx context.Context, accountID, serviceID, domain string) error {
|
||||
_, err := s.mgmtClient.SendStatusUpdate(ctx, &proto.SendStatusUpdateRequest{
|
||||
ReverseProxyId: reverseProxyID,
|
||||
ServiceId: serviceID,
|
||||
AccountId: accountID,
|
||||
Status: proto.ProxyStatus_PROXY_STATUS_ACTIVE,
|
||||
CertificateIssued: true,
|
||||
@@ -523,14 +523,14 @@ func (s *Server) handleMappingStream(ctx context.Context, mappingClient proto.Pr
|
||||
func (s *Server) addMapping(ctx context.Context, mapping *proto.ProxyMapping) error {
|
||||
d := domain.Domain(mapping.GetDomain())
|
||||
accountID := types.AccountID(mapping.GetAccountId())
|
||||
reverseProxyID := mapping.GetId()
|
||||
serviceID := mapping.GetId()
|
||||
authToken := mapping.GetAuthToken()
|
||||
|
||||
if err := s.netbird.AddPeer(ctx, accountID, d, authToken, reverseProxyID); err != nil {
|
||||
if err := s.netbird.AddPeer(ctx, accountID, d, authToken, serviceID); err != nil {
|
||||
return fmt.Errorf("create peer for domain %q: %w", d, err)
|
||||
}
|
||||
if s.acme != nil {
|
||||
s.acme.AddDomain(d, string(accountID), reverseProxyID)
|
||||
s.acme.AddDomain(d, string(accountID), serviceID)
|
||||
}
|
||||
|
||||
// Pass the mapping through to the update function to avoid duplicating the
|
||||
|
||||
@@ -36,8 +36,8 @@ tags:
|
||||
x-cloud-only: true
|
||||
- name: Identity Providers
|
||||
description: Interact with and view information about identity providers.
|
||||
- name: Reverse Proxy
|
||||
description: Interact with and view information about reverse proxies.
|
||||
- name: Services
|
||||
description: Interact with and view information about reverse proxy services.
|
||||
- name: Instance
|
||||
description: Instance setup and status endpoints for initial configuration.
|
||||
- name: Jobs
|
||||
@@ -2711,9 +2711,9 @@ components:
|
||||
type: string
|
||||
description: "Unique identifier for the access log entry"
|
||||
example: "ch8i4ug6lnn4g9hqv7m0"
|
||||
proxy_id:
|
||||
service_id:
|
||||
type: string
|
||||
description: "ID of the reverse proxy that handled the request"
|
||||
description: "ID of the service that handled the request"
|
||||
example: "ch8i4ug6lnn4g9hqv7m0"
|
||||
timestamp:
|
||||
type: string
|
||||
@@ -2766,7 +2766,7 @@ components:
|
||||
example: "San Francisco"
|
||||
required:
|
||||
- id
|
||||
- proxy_id
|
||||
- service_id
|
||||
- timestamp
|
||||
- method
|
||||
- host
|
||||
@@ -2868,30 +2868,30 @@ components:
|
||||
- issuer
|
||||
- client_id
|
||||
- client_secret
|
||||
ReverseProxy:
|
||||
Service:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Reverse proxy ID
|
||||
description: Service ID
|
||||
name:
|
||||
type: string
|
||||
description: Reverse proxy name
|
||||
description: Service name
|
||||
domain:
|
||||
type: string
|
||||
description: Domain for the reverse proxy
|
||||
description: Domain for the service
|
||||
proxy_cluster:
|
||||
type: string
|
||||
description: The proxy cluster handling this reverse proxy (derived from domain)
|
||||
description: The proxy cluster handling this service (derived from domain)
|
||||
example: "eu.proxy.netbird.io"
|
||||
targets:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ReverseProxyTarget'
|
||||
description: List of target backends for this reverse proxy
|
||||
$ref: '#/components/schemas/ServiceTarget'
|
||||
description: List of target backends for this service
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether the reverse proxy is enabled
|
||||
description: Whether the service is enabled
|
||||
pass_host_header:
|
||||
type: boolean
|
||||
description: When true, the original client Host header is passed through to the backend instead of being rewritten to the backend's address
|
||||
@@ -2899,9 +2899,9 @@ components:
|
||||
type: boolean
|
||||
description: When true, Location headers in backend responses are rewritten to replace the backend address with the public-facing domain
|
||||
auth:
|
||||
$ref: '#/components/schemas/ReverseProxyAuthConfig'
|
||||
$ref: '#/components/schemas/ServiceAuthConfig'
|
||||
meta:
|
||||
$ref: '#/components/schemas/ReverseProxyMeta'
|
||||
$ref: '#/components/schemas/ServiceMeta'
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
@@ -2910,13 +2910,13 @@ components:
|
||||
- enabled
|
||||
- auth
|
||||
- meta
|
||||
ReverseProxyMeta:
|
||||
ServiceMeta:
|
||||
type: object
|
||||
properties:
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Timestamp when the reverse proxy was created
|
||||
description: Timestamp when the service was created
|
||||
example: "2024-02-03T10:30:00Z"
|
||||
certificate_issued_at:
|
||||
type: string
|
||||
@@ -2932,28 +2932,28 @@ components:
|
||||
- certificate_pending
|
||||
- certificate_failed
|
||||
- error
|
||||
description: Current status of the reverse proxy
|
||||
description: Current status of the service
|
||||
example: "active"
|
||||
required:
|
||||
- created_at
|
||||
- status
|
||||
ReverseProxyRequest:
|
||||
ServiceRequest:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: Reverse proxy name
|
||||
description: Service name
|
||||
domain:
|
||||
type: string
|
||||
description: Domain for the reverse proxy
|
||||
description: Domain for the service
|
||||
targets:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ReverseProxyTarget'
|
||||
description: List of target backends for this reverse proxy
|
||||
$ref: '#/components/schemas/ServiceTarget'
|
||||
description: List of target backends for this service
|
||||
enabled:
|
||||
type: boolean
|
||||
description: Whether the reverse proxy is enabled
|
||||
description: Whether the service is enabled
|
||||
default: true
|
||||
pass_host_header:
|
||||
type: boolean
|
||||
@@ -2962,14 +2962,14 @@ components:
|
||||
type: boolean
|
||||
description: When true, Location headers in backend responses are rewritten to replace the backend address with the public-facing domain
|
||||
auth:
|
||||
$ref: '#/components/schemas/ReverseProxyAuthConfig'
|
||||
$ref: '#/components/schemas/ServiceAuthConfig'
|
||||
required:
|
||||
- name
|
||||
- domain
|
||||
- targets
|
||||
- auth
|
||||
- enabled
|
||||
ReverseProxyTarget:
|
||||
ServiceTarget:
|
||||
type: object
|
||||
properties:
|
||||
target_id:
|
||||
@@ -3001,7 +3001,7 @@ components:
|
||||
- protocol
|
||||
- port
|
||||
- enabled
|
||||
ReverseProxyAuthConfig:
|
||||
ServiceAuthConfig:
|
||||
type: object
|
||||
properties:
|
||||
password_auth:
|
||||
@@ -6803,23 +6803,23 @@ paths:
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/reverse-proxies:
|
||||
/api/reverse-proxies/services:
|
||||
get:
|
||||
summary: List all Reverse Proxies
|
||||
description: Returns a list of all reverse proxies
|
||||
tags: [ Reverse Proxy ]
|
||||
summary: List all Services
|
||||
description: Returns a list of all reverse proxy services
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
responses:
|
||||
'200':
|
||||
description: A JSON Array of reverse proxies
|
||||
description: A JSON Array of services
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ReverseProxy'
|
||||
$ref: '#/components/schemas/Service'
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
@@ -6827,25 +6827,25 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a Reverse Proxy
|
||||
description: Creates a new reverse proxy
|
||||
tags: [ Reverse Proxy ]
|
||||
summary: Create a Service
|
||||
description: Creates a new reverse proxy service
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
requestBody:
|
||||
description: New reverse proxy request
|
||||
description: New service request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ReverseProxyRequest'
|
||||
$ref: '#/components/schemas/ServiceRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Reverse proxy created
|
||||
description: Service created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ReverseProxy'
|
||||
$ref: '#/components/schemas/Service'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
@@ -6858,7 +6858,7 @@ paths:
|
||||
get:
|
||||
summary: List available proxy clusters
|
||||
description: Returns a list of available proxy clusters with their connection status
|
||||
tags: [ Reverse Proxy ]
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
@@ -6877,28 +6877,28 @@ paths:
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/reverse-proxies/{proxyId}:
|
||||
/api/reverse-proxies/services/{serviceId}:
|
||||
get:
|
||||
summary: Retrieve a Reverse Proxy
|
||||
description: Get information about a specific reverse proxy
|
||||
tags: [ Reverse Proxy ]
|
||||
summary: Retrieve a Service
|
||||
description: Get information about a specific reverse proxy service
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: proxyId
|
||||
name: serviceId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The unique identifier of a reverse proxy
|
||||
description: The unique identifier of a service
|
||||
responses:
|
||||
'200':
|
||||
description: A reverse proxy object
|
||||
description: A service object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ReverseProxy'
|
||||
$ref: '#/components/schemas/Service'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
@@ -6910,32 +6910,32 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
put:
|
||||
summary: Update a Reverse Proxy
|
||||
description: Update an existing reverse proxy
|
||||
tags: [ Reverse Proxy ]
|
||||
summary: Update a Service
|
||||
description: Update an existing service
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: proxyId
|
||||
name: serviceId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The unique identifier of a reverse proxy
|
||||
description: The unique identifier of a service
|
||||
requestBody:
|
||||
description: Reverse proxy update request
|
||||
description: Service update request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ReverseProxyRequest'
|
||||
$ref: '#/components/schemas/ServiceRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Reverse proxy updated
|
||||
description: Service updated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ReverseProxy'
|
||||
$ref: '#/components/schemas/Service'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
@@ -6947,22 +6947,22 @@ paths:
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
delete:
|
||||
summary: Delete a Reverse Proxy
|
||||
description: Delete an existing reverse proxy
|
||||
tags: [ Reverse Proxy ]
|
||||
summary: Delete a Service
|
||||
description: Delete an existing service
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: proxyId
|
||||
name: serviceId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The unique identifier of a reverse proxy
|
||||
description: The unique identifier of a service
|
||||
responses:
|
||||
'200':
|
||||
description: Reverse proxy deleted
|
||||
description: Service deleted
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
@@ -6975,9 +6975,9 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/reverse-proxies/domains:
|
||||
get:
|
||||
summary: Retrieve Reverse Proxy Domains
|
||||
description: Get information about domains that can be used for Reverse Proxy endpoints.
|
||||
tags: [ Reverse Proxy ]
|
||||
summary: Retrieve Service Domains
|
||||
description: Get information about domains that can be used for service endpoints.
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
@@ -7002,8 +7002,8 @@ paths:
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
post:
|
||||
summary: Create a Custom domain
|
||||
description: Create a new Custom domain for use with Reverse Proxy endpoints, this will trigger an initial validation check
|
||||
tags: [ Reverse Proxy ]
|
||||
description: Create a new Custom domain for use with service endpoints, this will trigger an initial validation check
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
@@ -7015,11 +7015,11 @@ paths:
|
||||
$ref: '#/components/schemas/ReverseProxyDomainRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Reverse proxy created
|
||||
description: Service created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ReverseProxy'
|
||||
$ref: '#/components/schemas/Service'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
@@ -7030,11 +7030,11 @@ paths:
|
||||
"$ref": "#/components/responses/not_found"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/reverse-proxies/domains/{domainId}:
|
||||
/api/services/domains/{domainId}:
|
||||
delete:
|
||||
summary: Delete a Custom domain
|
||||
description: Delete an existing reverse proxy custom domain
|
||||
tags: [ Reverse Proxy ]
|
||||
description: Delete an existing service custom domain
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
@@ -7047,7 +7047,7 @@ paths:
|
||||
description: The custom domain ID
|
||||
responses:
|
||||
'204':
|
||||
description: Reverse proxy custom domain deleted
|
||||
description: Service custom domain deleted
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
@@ -7058,11 +7058,11 @@ paths:
|
||||
"$ref": "#/components/responses/not_found"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/reverse-proxies/domains/{domainId}/validate:
|
||||
/api/services/domains/{domainId}/validate:
|
||||
get:
|
||||
summary: Validate a custom domain
|
||||
description: Trigger domain ownership validation for a custom domain
|
||||
tags: [ Reverse Proxy ]
|
||||
tags: [ Services ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
|
||||
@@ -275,26 +275,26 @@ const (
|
||||
ReverseProxyDomainTypeFree ReverseProxyDomainType = "free"
|
||||
)
|
||||
|
||||
// Defines values for ReverseProxyMetaStatus.
|
||||
// Defines values for ServiceMetaStatus.
|
||||
const (
|
||||
ReverseProxyMetaStatusActive ReverseProxyMetaStatus = "active"
|
||||
ReverseProxyMetaStatusCertificateFailed ReverseProxyMetaStatus = "certificate_failed"
|
||||
ReverseProxyMetaStatusCertificatePending ReverseProxyMetaStatus = "certificate_pending"
|
||||
ReverseProxyMetaStatusError ReverseProxyMetaStatus = "error"
|
||||
ReverseProxyMetaStatusPending ReverseProxyMetaStatus = "pending"
|
||||
ReverseProxyMetaStatusTunnelNotCreated ReverseProxyMetaStatus = "tunnel_not_created"
|
||||
ServiceMetaStatusActive ServiceMetaStatus = "active"
|
||||
ServiceMetaStatusCertificateFailed ServiceMetaStatus = "certificate_failed"
|
||||
ServiceMetaStatusCertificatePending ServiceMetaStatus = "certificate_pending"
|
||||
ServiceMetaStatusError ServiceMetaStatus = "error"
|
||||
ServiceMetaStatusPending ServiceMetaStatus = "pending"
|
||||
ServiceMetaStatusTunnelNotCreated ServiceMetaStatus = "tunnel_not_created"
|
||||
)
|
||||
|
||||
// Defines values for ReverseProxyTargetProtocol.
|
||||
// Defines values for ServiceTargetProtocol.
|
||||
const (
|
||||
ReverseProxyTargetProtocolHttp ReverseProxyTargetProtocol = "http"
|
||||
ReverseProxyTargetProtocolHttps ReverseProxyTargetProtocol = "https"
|
||||
ServiceTargetProtocolHttp ServiceTargetProtocol = "http"
|
||||
ServiceTargetProtocolHttps ServiceTargetProtocol = "https"
|
||||
)
|
||||
|
||||
// Defines values for ReverseProxyTargetTargetType.
|
||||
// Defines values for ServiceTargetTargetType.
|
||||
const (
|
||||
ReverseProxyTargetTargetTypePeer ReverseProxyTargetTargetType = "peer"
|
||||
ReverseProxyTargetTargetTypeResource ReverseProxyTargetTargetType = "resource"
|
||||
ServiceTargetTargetTypePeer ServiceTargetTargetType = "peer"
|
||||
ServiceTargetTargetTypeResource ServiceTargetTargetType = "resource"
|
||||
)
|
||||
|
||||
// Defines values for UserStatus.
|
||||
@@ -330,6 +330,23 @@ const (
|
||||
GetApiEventsNetworkTrafficParamsDirectionINGRESS GetApiEventsNetworkTrafficParamsDirection = "INGRESS"
|
||||
)
|
||||
|
||||
// Defines values for GetApiEventsProxyParamsMethod.
|
||||
const (
|
||||
GetApiEventsProxyParamsMethodDELETE GetApiEventsProxyParamsMethod = "DELETE"
|
||||
GetApiEventsProxyParamsMethodGET GetApiEventsProxyParamsMethod = "GET"
|
||||
GetApiEventsProxyParamsMethodHEAD GetApiEventsProxyParamsMethod = "HEAD"
|
||||
GetApiEventsProxyParamsMethodOPTIONS GetApiEventsProxyParamsMethod = "OPTIONS"
|
||||
GetApiEventsProxyParamsMethodPATCH GetApiEventsProxyParamsMethod = "PATCH"
|
||||
GetApiEventsProxyParamsMethodPOST GetApiEventsProxyParamsMethod = "POST"
|
||||
GetApiEventsProxyParamsMethodPUT GetApiEventsProxyParamsMethod = "PUT"
|
||||
)
|
||||
|
||||
// Defines values for GetApiEventsProxyParamsStatus.
|
||||
const (
|
||||
GetApiEventsProxyParamsStatusFailed GetApiEventsProxyParamsStatus = "failed"
|
||||
GetApiEventsProxyParamsStatusSuccess GetApiEventsProxyParamsStatus = "success"
|
||||
)
|
||||
|
||||
// AccessiblePeer defines model for AccessiblePeer.
|
||||
type AccessiblePeer struct {
|
||||
// CityName Commonly used English name of the city
|
||||
@@ -1931,12 +1948,12 @@ type ProxyAccessLog struct {
|
||||
// Path Path of the request
|
||||
Path string `json:"path"`
|
||||
|
||||
// ProxyId ID of the reverse proxy that handled the request
|
||||
ProxyId string `json:"proxy_id"`
|
||||
|
||||
// Reason Reason for the request result (e.g., authentication failure)
|
||||
Reason *string `json:"reason,omitempty"`
|
||||
|
||||
// ServiceId ID of the service that handled the request
|
||||
ServiceId string `json:"service_id"`
|
||||
|
||||
// SourceIp Source IP address of the request
|
||||
SourceIp *string `json:"source_ip,omitempty"`
|
||||
|
||||
@@ -1987,44 +2004,6 @@ type Resource struct {
|
||||
// ResourceType defines model for ResourceType.
|
||||
type ResourceType string
|
||||
|
||||
// ReverseProxy defines model for ReverseProxy.
|
||||
type ReverseProxy struct {
|
||||
Auth ReverseProxyAuthConfig `json:"auth"`
|
||||
|
||||
// Domain Domain for the reverse proxy
|
||||
Domain string `json:"domain"`
|
||||
|
||||
// Enabled Whether the reverse proxy is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Id Reverse proxy ID
|
||||
Id string `json:"id"`
|
||||
Meta ReverseProxyMeta `json:"meta"`
|
||||
|
||||
// Name Reverse proxy name
|
||||
Name string `json:"name"`
|
||||
|
||||
// PassHostHeader When true, the original client Host header is passed through to the backend instead of being rewritten to the backend's address
|
||||
PassHostHeader *bool `json:"pass_host_header,omitempty"`
|
||||
|
||||
// ProxyCluster The proxy cluster handling this reverse proxy (derived from domain)
|
||||
ProxyCluster *string `json:"proxy_cluster,omitempty"`
|
||||
|
||||
// RewriteRedirects When true, Location headers in backend responses are rewritten to replace the backend address with the public-facing domain
|
||||
RewriteRedirects *bool `json:"rewrite_redirects,omitempty"`
|
||||
|
||||
// Targets List of target backends for this reverse proxy
|
||||
Targets []ReverseProxyTarget `json:"targets"`
|
||||
}
|
||||
|
||||
// ReverseProxyAuthConfig defines model for ReverseProxyAuthConfig.
|
||||
type ReverseProxyAuthConfig struct {
|
||||
BearerAuth *BearerAuthConfig `json:"bearer_auth,omitempty"`
|
||||
LinkAuth *LinkAuthConfig `json:"link_auth,omitempty"`
|
||||
PasswordAuth *PasswordAuthConfig `json:"password_auth,omitempty"`
|
||||
PinAuth *PINAuthConfig `json:"pin_auth,omitempty"`
|
||||
}
|
||||
|
||||
// ReverseProxyDomain defines model for ReverseProxyDomain.
|
||||
type ReverseProxyDomain struct {
|
||||
// Domain Domain name
|
||||
@@ -2055,74 +2034,6 @@ type ReverseProxyDomainRequest struct {
|
||||
// ReverseProxyDomainType Type of Reverse Proxy Domain
|
||||
type ReverseProxyDomainType string
|
||||
|
||||
// ReverseProxyMeta defines model for ReverseProxyMeta.
|
||||
type ReverseProxyMeta struct {
|
||||
// CertificateIssuedAt Timestamp when the certificate was issued (empty if not yet issued)
|
||||
CertificateIssuedAt *time.Time `json:"certificate_issued_at,omitempty"`
|
||||
|
||||
// CreatedAt Timestamp when the reverse proxy was created
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// Status Current status of the reverse proxy
|
||||
Status ReverseProxyMetaStatus `json:"status"`
|
||||
}
|
||||
|
||||
// ReverseProxyMetaStatus Current status of the reverse proxy
|
||||
type ReverseProxyMetaStatus string
|
||||
|
||||
// ReverseProxyRequest defines model for ReverseProxyRequest.
|
||||
type ReverseProxyRequest struct {
|
||||
Auth ReverseProxyAuthConfig `json:"auth"`
|
||||
|
||||
// Domain Domain for the reverse proxy
|
||||
Domain string `json:"domain"`
|
||||
|
||||
// Enabled Whether the reverse proxy is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Name Reverse proxy name
|
||||
Name string `json:"name"`
|
||||
|
||||
// PassHostHeader When true, the original client Host header is passed through to the backend instead of being rewritten to the backend's address
|
||||
PassHostHeader *bool `json:"pass_host_header,omitempty"`
|
||||
|
||||
// RewriteRedirects When true, Location headers in backend responses are rewritten to replace the backend address with the public-facing domain
|
||||
RewriteRedirects *bool `json:"rewrite_redirects,omitempty"`
|
||||
|
||||
// Targets List of target backends for this reverse proxy
|
||||
Targets []ReverseProxyTarget `json:"targets"`
|
||||
}
|
||||
|
||||
// ReverseProxyTarget defines model for ReverseProxyTarget.
|
||||
type ReverseProxyTarget struct {
|
||||
// Enabled Whether this target is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Host Backend ip or domain for this target
|
||||
Host *string `json:"host,omitempty"`
|
||||
|
||||
// Path URL path prefix for this target
|
||||
Path *string `json:"path,omitempty"`
|
||||
|
||||
// Port Backend port for this target. Use 0 or omit to use the scheme default (80 for http, 443 for https).
|
||||
Port int `json:"port"`
|
||||
|
||||
// Protocol Protocol to use when connecting to the backend
|
||||
Protocol ReverseProxyTargetProtocol `json:"protocol"`
|
||||
|
||||
// TargetId Target ID
|
||||
TargetId string `json:"target_id"`
|
||||
|
||||
// TargetType Target type (e.g., "peer", "resource")
|
||||
TargetType ReverseProxyTargetTargetType `json:"target_type"`
|
||||
}
|
||||
|
||||
// ReverseProxyTargetProtocol Protocol to use when connecting to the backend
|
||||
type ReverseProxyTargetProtocol string
|
||||
|
||||
// ReverseProxyTargetTargetType Target type (e.g., "peer", "resource")
|
||||
type ReverseProxyTargetTargetType string
|
||||
|
||||
// Route defines model for Route.
|
||||
type Route struct {
|
||||
// AccessControlGroups Access control group identifier associated with route.
|
||||
@@ -2222,6 +2133,112 @@ type RulePortRange struct {
|
||||
Start int `json:"start"`
|
||||
}
|
||||
|
||||
// Service defines model for Service.
|
||||
type Service struct {
|
||||
Auth ServiceAuthConfig `json:"auth"`
|
||||
|
||||
// Domain Domain for the service
|
||||
Domain string `json:"domain"`
|
||||
|
||||
// Enabled Whether the service is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Id Service ID
|
||||
Id string `json:"id"`
|
||||
Meta ServiceMeta `json:"meta"`
|
||||
|
||||
// Name Service name
|
||||
Name string `json:"name"`
|
||||
|
||||
// PassHostHeader When true, the original client Host header is passed through to the backend instead of being rewritten to the backend's address
|
||||
PassHostHeader *bool `json:"pass_host_header,omitempty"`
|
||||
|
||||
// ProxyCluster The proxy cluster handling this service (derived from domain)
|
||||
ProxyCluster *string `json:"proxy_cluster,omitempty"`
|
||||
|
||||
// RewriteRedirects When true, Location headers in backend responses are rewritten to replace the backend address with the public-facing domain
|
||||
RewriteRedirects *bool `json:"rewrite_redirects,omitempty"`
|
||||
|
||||
// Targets List of target backends for this service
|
||||
Targets []ServiceTarget `json:"targets"`
|
||||
}
|
||||
|
||||
// ServiceAuthConfig defines model for ServiceAuthConfig.
|
||||
type ServiceAuthConfig struct {
|
||||
BearerAuth *BearerAuthConfig `json:"bearer_auth,omitempty"`
|
||||
LinkAuth *LinkAuthConfig `json:"link_auth,omitempty"`
|
||||
PasswordAuth *PasswordAuthConfig `json:"password_auth,omitempty"`
|
||||
PinAuth *PINAuthConfig `json:"pin_auth,omitempty"`
|
||||
}
|
||||
|
||||
// ServiceMeta defines model for ServiceMeta.
|
||||
type ServiceMeta struct {
|
||||
// CertificateIssuedAt Timestamp when the certificate was issued (empty if not yet issued)
|
||||
CertificateIssuedAt *time.Time `json:"certificate_issued_at,omitempty"`
|
||||
|
||||
// CreatedAt Timestamp when the service was created
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// Status Current status of the service
|
||||
Status ServiceMetaStatus `json:"status"`
|
||||
}
|
||||
|
||||
// ServiceMetaStatus Current status of the service
|
||||
type ServiceMetaStatus string
|
||||
|
||||
// ServiceRequest defines model for ServiceRequest.
|
||||
type ServiceRequest struct {
|
||||
Auth ServiceAuthConfig `json:"auth"`
|
||||
|
||||
// Domain Domain for the service
|
||||
Domain string `json:"domain"`
|
||||
|
||||
// Enabled Whether the service is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Name Service name
|
||||
Name string `json:"name"`
|
||||
|
||||
// PassHostHeader When true, the original client Host header is passed through to the backend instead of being rewritten to the backend's address
|
||||
PassHostHeader *bool `json:"pass_host_header,omitempty"`
|
||||
|
||||
// RewriteRedirects When true, Location headers in backend responses are rewritten to replace the backend address with the public-facing domain
|
||||
RewriteRedirects *bool `json:"rewrite_redirects,omitempty"`
|
||||
|
||||
// Targets List of target backends for this service
|
||||
Targets []ServiceTarget `json:"targets"`
|
||||
}
|
||||
|
||||
// ServiceTarget defines model for ServiceTarget.
|
||||
type ServiceTarget struct {
|
||||
// Enabled Whether this target is enabled
|
||||
Enabled bool `json:"enabled"`
|
||||
|
||||
// Host Backend ip or domain for this target
|
||||
Host *string `json:"host,omitempty"`
|
||||
|
||||
// Path URL path prefix for this target
|
||||
Path *string `json:"path,omitempty"`
|
||||
|
||||
// Port Backend port for this target. Use 0 or omit to use the scheme default (80 for http, 443 for https).
|
||||
Port int `json:"port"`
|
||||
|
||||
// Protocol Protocol to use when connecting to the backend
|
||||
Protocol ServiceTargetProtocol `json:"protocol"`
|
||||
|
||||
// TargetId Target ID
|
||||
TargetId string `json:"target_id"`
|
||||
|
||||
// TargetType Target type (e.g., "peer", "resource")
|
||||
TargetType ServiceTargetTargetType `json:"target_type"`
|
||||
}
|
||||
|
||||
// ServiceTargetProtocol Protocol to use when connecting to the backend
|
||||
type ServiceTargetProtocol string
|
||||
|
||||
// ServiceTargetTargetType Target type (e.g., "peer", "resource")
|
||||
type ServiceTargetTargetType string
|
||||
|
||||
// SetupKey defines model for SetupKey.
|
||||
type SetupKey struct {
|
||||
// AllowExtraDnsLabels Allow extra DNS labels to be added to the peer
|
||||
@@ -2680,8 +2697,50 @@ type GetApiEventsProxyParams struct {
|
||||
|
||||
// PageSize Number of items per page (max 100)
|
||||
PageSize *int `form:"page_size,omitempty" json:"page_size,omitempty"`
|
||||
|
||||
// Search General search across request ID, host, path, source IP, user email, and user name
|
||||
Search *string `form:"search,omitempty" json:"search,omitempty"`
|
||||
|
||||
// SourceIp Filter by source IP address
|
||||
SourceIp *string `form:"source_ip,omitempty" json:"source_ip,omitempty"`
|
||||
|
||||
// Host Filter by host header
|
||||
Host *string `form:"host,omitempty" json:"host,omitempty"`
|
||||
|
||||
// Path Filter by request path (supports partial matching)
|
||||
Path *string `form:"path,omitempty" json:"path,omitempty"`
|
||||
|
||||
// UserId Filter by authenticated user ID
|
||||
UserId *string `form:"user_id,omitempty" json:"user_id,omitempty"`
|
||||
|
||||
// UserEmail Filter by user email (partial matching)
|
||||
UserEmail *string `form:"user_email,omitempty" json:"user_email,omitempty"`
|
||||
|
||||
// UserName Filter by user name (partial matching)
|
||||
UserName *string `form:"user_name,omitempty" json:"user_name,omitempty"`
|
||||
|
||||
// Method Filter by HTTP method
|
||||
Method *GetApiEventsProxyParamsMethod `form:"method,omitempty" json:"method,omitempty"`
|
||||
|
||||
// Status Filter by status (success = 2xx/3xx, failed = 1xx/4xx/5xx)
|
||||
Status *GetApiEventsProxyParamsStatus `form:"status,omitempty" json:"status,omitempty"`
|
||||
|
||||
// StatusCode Filter by HTTP status code
|
||||
StatusCode *int `form:"status_code,omitempty" json:"status_code,omitempty"`
|
||||
|
||||
// StartDate Filter by timestamp >= start_date (RFC3339 format)
|
||||
StartDate *time.Time `form:"start_date,omitempty" json:"start_date,omitempty"`
|
||||
|
||||
// EndDate Filter by timestamp <= end_date (RFC3339 format)
|
||||
EndDate *time.Time `form:"end_date,omitempty" json:"end_date,omitempty"`
|
||||
}
|
||||
|
||||
// GetApiEventsProxyParamsMethod defines parameters for GetApiEventsProxy.
|
||||
type GetApiEventsProxyParamsMethod string
|
||||
|
||||
// GetApiEventsProxyParamsStatus defines parameters for GetApiEventsProxy.
|
||||
type GetApiEventsProxyParamsStatus string
|
||||
|
||||
// GetApiGroupsParams defines parameters for GetApiGroups.
|
||||
type GetApiGroupsParams struct {
|
||||
// Name Filter groups by name (exact match)
|
||||
@@ -2796,14 +2855,14 @@ type PostApiPostureChecksJSONRequestBody = PostureCheckUpdate
|
||||
// PutApiPostureChecksPostureCheckIdJSONRequestBody defines body for PutApiPostureChecksPostureCheckId for application/json ContentType.
|
||||
type PutApiPostureChecksPostureCheckIdJSONRequestBody = PostureCheckUpdate
|
||||
|
||||
// PostApiReverseProxiesJSONRequestBody defines body for PostApiReverseProxies for application/json ContentType.
|
||||
type PostApiReverseProxiesJSONRequestBody = ReverseProxyRequest
|
||||
|
||||
// PostApiReverseProxiesDomainsJSONRequestBody defines body for PostApiReverseProxiesDomains for application/json ContentType.
|
||||
type PostApiReverseProxiesDomainsJSONRequestBody = ReverseProxyDomainRequest
|
||||
|
||||
// PutApiReverseProxiesProxyIdJSONRequestBody defines body for PutApiReverseProxiesProxyId for application/json ContentType.
|
||||
type PutApiReverseProxiesProxyIdJSONRequestBody = ReverseProxyRequest
|
||||
// PostApiReverseProxiesServicesJSONRequestBody defines body for PostApiReverseProxiesServices for application/json ContentType.
|
||||
type PostApiReverseProxiesServicesJSONRequestBody = ServiceRequest
|
||||
|
||||
// PutApiReverseProxiesServicesServiceIdJSONRequestBody defines body for PutApiReverseProxiesServicesServiceId for application/json ContentType.
|
||||
type PutApiReverseProxiesServicesServiceIdJSONRequestBody = ServiceRequest
|
||||
|
||||
// PostApiRoutesJSONRequestBody defines body for PostApiRoutes for application/json ContentType.
|
||||
type PostApiRoutesJSONRequestBody = RouteRequest
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v6.33.3
|
||||
// protoc v6.33.0
|
||||
// source: management.proto
|
||||
|
||||
package proto
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v6.33.3
|
||||
// protoc v6.33.0
|
||||
// source: proxy_service.proto
|
||||
|
||||
package proto
|
||||
@@ -981,7 +981,7 @@ type SendStatusUpdateRequest struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
ReverseProxyId string `protobuf:"bytes,1,opt,name=reverse_proxy_id,json=reverseProxyId,proto3" json:"reverse_proxy_id,omitempty"`
|
||||
ServiceId string `protobuf:"bytes,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
|
||||
AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
|
||||
Status ProxyStatus `protobuf:"varint,3,opt,name=status,proto3,enum=management.ProxyStatus" json:"status,omitempty"`
|
||||
CertificateIssued bool `protobuf:"varint,4,opt,name=certificate_issued,json=certificateIssued,proto3" json:"certificate_issued,omitempty"`
|
||||
@@ -1020,9 +1020,9 @@ func (*SendStatusUpdateRequest) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_service_proto_rawDescGZIP(), []int{12}
|
||||
}
|
||||
|
||||
func (x *SendStatusUpdateRequest) GetReverseProxyId() string {
|
||||
func (x *SendStatusUpdateRequest) GetServiceId() string {
|
||||
if x != nil {
|
||||
return x.ReverseProxyId
|
||||
return x.ServiceId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -1101,7 +1101,7 @@ type CreateProxyPeerRequest struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
ReverseProxyId string `protobuf:"bytes,1,opt,name=reverse_proxy_id,json=reverseProxyId,proto3" json:"reverse_proxy_id,omitempty"`
|
||||
ServiceId string `protobuf:"bytes,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
|
||||
AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
|
||||
Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"`
|
||||
WireguardPublicKey string `protobuf:"bytes,4,opt,name=wireguard_public_key,json=wireguardPublicKey,proto3" json:"wireguard_public_key,omitempty"`
|
||||
@@ -1140,9 +1140,9 @@ func (*CreateProxyPeerRequest) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_service_proto_rawDescGZIP(), []int{14}
|
||||
}
|
||||
|
||||
func (x *CreateProxyPeerRequest) GetReverseProxyId() string {
|
||||
func (x *CreateProxyPeerRequest) GetServiceId() string {
|
||||
if x != nil {
|
||||
return x.ReverseProxyId
|
||||
return x.ServiceId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -1580,127 +1580,126 @@ var file_proxy_service_proto_rawDesc = []byte{
|
||||
0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65,
|
||||
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22,
|
||||
0xfe, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70,
|
||||
0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x72,
|
||||
0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x50, 0x72,
|
||||
0x6f, 0x78, 0x79, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
|
||||
0x63, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x11, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x73,
|
||||
0x73, 0x75, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x65,
|
||||
0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x42, 0x10,
|
||||
0x0a, 0x0e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||
0x22, 0x1a, 0x0a, 0x18, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70,
|
||||
0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc3, 0x01, 0x0a,
|
||||
0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x65, 0x65, 0x72,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, 0x76, 0x65, 0x72,
|
||||
0x73, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x0e, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x49,
|
||||
0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64,
|
||||
0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x30, 0x0a, 0x14, 0x77, 0x69, 0x72, 0x65, 0x67, 0x75,
|
||||
0x61, 0x72, 0x64, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x77, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x50,
|
||||
0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73,
|
||||
0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74,
|
||||
0x65, 0x72, 0x22, 0x6f, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x78,
|
||||
0x79, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a,
|
||||
0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
|
||||
0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x28, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72,
|
||||
0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
|
||||
0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01,
|
||||
0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x22, 0x65, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4f, 0x49, 0x44, 0x43, 0x55, 0x52,
|
||||
0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x64, 0x69, 0x72,
|
||||
0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72,
|
||||
0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x6c, 0x22, 0x26, 0x0a, 0x12, 0x47, 0x65,
|
||||
0x74, 0x4f, 0x49, 0x44, 0x43, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75,
|
||||
0x72, 0x6c, 0x22, 0x55, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65,
|
||||
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f,
|
||||
0x6d, 0x61, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
|
||||
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x73,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x8c, 0x01, 0x0a, 0x17, 0x56, 0x61,
|
||||
0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75,
|
||||
0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73,
|
||||
0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61,
|
||||
0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d,
|
||||
0x61, 0x69, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x72, 0x65,
|
||||
0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x6e, 0x69,
|
||||
0x65, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x2a, 0x64, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x78,
|
||||
0x79, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x79,
|
||||
0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50,
|
||||
0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x55,
|
||||
0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x49, 0x46,
|
||||
0x49, 0x45, 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f,
|
||||
0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xc8,
|
||||
0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18,
|
||||
0x0a, 0x14, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50,
|
||||
0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x50, 0x52, 0x4f, 0x58,
|
||||
0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10,
|
||||
0x01, 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55,
|
||||
0x53, 0x5f, 0x54, 0x55, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x43, 0x52, 0x45,
|
||||
0x41, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f,
|
||||
0xf3, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70,
|
||||
0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
||||
0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x74, 0x61,
|
||||
0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
|
||||
0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74,
|
||||
0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x65,
|
||||
0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
||||
0x61, 0x74, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x0d, 0x65, 0x72, 0x72,
|
||||
0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
|
||||
0x48, 0x00, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||
0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61,
|
||||
0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0xb8, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x78,
|
||||
0x79, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61,
|
||||
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f,
|
||||
0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
|
||||
0x12, 0x30, 0x0a, 0x14, 0x77, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x5f, 0x70, 0x75,
|
||||
0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12,
|
||||
0x77, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b,
|
||||
0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x6f, 0x0a, 0x17,
|
||||
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x65, 0x65, 0x72, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65,
|
||||
0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73,
|
||||
0x73, 0x12, 0x28, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f,
|
||||
0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f,
|
||||
0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x65, 0x0a,
|
||||
0x11, 0x47, 0x65, 0x74, 0x4f, 0x49, 0x44, 0x43, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
|
||||
0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49,
|
||||
0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72,
|
||||
0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63,
|
||||
0x74, 0x55, 0x72, 0x6c, 0x22, 0x26, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4f, 0x49, 0x44, 0x43, 0x55,
|
||||
0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72,
|
||||
0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x55, 0x0a, 0x16,
|
||||
0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x23,
|
||||
0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f,
|
||||
0x6b, 0x65, 0x6e, 0x22, 0x8c, 0x01, 0x0a, 0x17, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65,
|
||||
0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05,
|
||||
0x76, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d,
|
||||
0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x23, 0x0a,
|
||||
0x0d, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x52, 0x65, 0x61, 0x73,
|
||||
0x6f, 0x6e, 0x2a, 0x64, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x61, 0x70, 0x70, 0x69,
|
||||
0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13,
|
||||
0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41,
|
||||
0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f,
|
||||
0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x01, 0x12,
|
||||
0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52,
|
||||
0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xc8, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x52, 0x4f, 0x58,
|
||||
0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47,
|
||||
0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54,
|
||||
0x55, 0x53, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x50,
|
||||
0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x54, 0x55, 0x4e, 0x4e,
|
||||
0x45, 0x4c, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x02,
|
||||
0x12, 0x24, 0x0a, 0x20, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53,
|
||||
0x5f, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x45, 0x4e,
|
||||
0x44, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f,
|
||||
0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41,
|
||||
0x54, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x23, 0x0a, 0x1f,
|
||||
0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x45, 0x52,
|
||||
0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10,
|
||||
0x04, 0x12, 0x16, 0x0a, 0x12, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55,
|
||||
0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x32, 0xfc, 0x04, 0x0a, 0x0c, 0x50, 0x72,
|
||||
0x6f, 0x78, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x10, 0x47, 0x65,
|
||||
0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x23,
|
||||
0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4d,
|
||||
0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x0d, 0x53,
|
||||
0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x12, 0x20, 0x2e, 0x6d,
|
||||
0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63,
|
||||
0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21,
|
||||
0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64,
|
||||
0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x51, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
|
||||
0x65, 0x12, 0x1f, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41,
|
||||
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x10, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74,
|
||||
0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
|
||||
0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x50,
|
||||
0x52, 0x4f, 0x58, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f,
|
||||
0x52, 0x10, 0x05, 0x32, 0xfc, 0x04, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69,
|
||||
0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
|
||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e,
|
||||
0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x50, 0x65, 0x65, 0x72, 0x12, 0x22, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50,
|
||||
0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x61, 0x6e,
|
||||
0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72,
|
||||
0x6f, 0x78, 0x79, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x4b, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4f, 0x49, 0x44, 0x43, 0x55, 0x52, 0x4c, 0x12, 0x1d, 0x2e,
|
||||
0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x49,
|
||||
0x44, 0x43, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d,
|
||||
0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x49, 0x44,
|
||||
0x43, 0x55, 0x52, 0x4c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0f,
|
||||
0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12,
|
||||
0x22, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x56, 0x61, 0x6c,
|
||||
0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61,
|
||||
0x70, 0x70, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63,
|
||||
0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x12, 0x20, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f,
|
||||
0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
|
||||
0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0c, 0x41,
|
||||
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x6d, 0x61,
|
||||
0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d,
|
||||
0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d,
|
||||
0x0a, 0x10, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x12, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55,
|
||||
0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a,
|
||||
0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x65, 0x65, 0x72,
|
||||
0x12, 0x22, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x72,
|
||||
0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x65, 0x65,
|
||||
0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0a, 0x47, 0x65, 0x74,
|
||||
0x4f, 0x49, 0x44, 0x43, 0x55, 0x52, 0x4c, 0x12, 0x1d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x49, 0x44, 0x43, 0x55, 0x52, 0x4c, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x49, 0x44, 0x43, 0x55, 0x52, 0x4c, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61,
|
||||
0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x6d, 0x61, 0x6e, 0x61,
|
||||
0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53,
|
||||
0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e,
|
||||
0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64,
|
||||
0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -133,7 +133,7 @@ enum ProxyStatus {
|
||||
|
||||
// SendStatusUpdateRequest is sent by the proxy to update its status
|
||||
message SendStatusUpdateRequest {
|
||||
string reverse_proxy_id = 1;
|
||||
string service_id = 1;
|
||||
string account_id = 2;
|
||||
ProxyStatus status = 3;
|
||||
bool certificate_issued = 4;
|
||||
@@ -146,7 +146,7 @@ message SendStatusUpdateResponse {}
|
||||
// CreateProxyPeerRequest is sent by the proxy to create a peer connection
|
||||
// The token is a one-time authentication token sent via ProxyMapping
|
||||
message CreateProxyPeerRequest {
|
||||
string reverse_proxy_id = 1;
|
||||
string service_id = 1;
|
||||
string account_id = 2;
|
||||
string token = 3;
|
||||
string wireguard_public_key = 4;
|
||||
|
||||
Reference in New Issue
Block a user