From 7f11e3205d0bbafb697008b6073784e1ad3ce8f7 Mon Sep 17 00:00:00 2001 From: Viktor Liu Date: Sun, 8 Feb 2026 23:42:07 +0800 Subject: [PATCH] Validate target id --- .../modules/reverseproxy/manager/manager.go | 31 +++++++++++++++++++ .../modules/reverseproxy/reverseproxy.go | 10 ++++++ 2 files changed, 41 insertions(+) diff --git a/management/internals/modules/reverseproxy/manager/manager.go b/management/internals/modules/reverseproxy/manager/manager.go index 060ee52a8..487ee463b 100644 --- a/management/internals/modules/reverseproxy/manager/manager.go +++ b/management/internals/modules/reverseproxy/manager/manager.go @@ -110,6 +110,10 @@ func (m *managerImpl) CreateReverseProxy(ctx context.Context, accountID, userID return status.Errorf(status.AlreadyExists, "reverse proxy with domain %s already exists", reverseProxy.Domain) } + if err = validateTargetReferences(ctx, transaction, accountID, reverseProxy.Targets); err != nil { + return err + } + if err = transaction.CreateReverseProxy(ctx, reverseProxy); err != nil { return fmt.Errorf("failed to create reverse proxy: %w", err) } @@ -181,6 +185,10 @@ func (m *managerImpl) UpdateReverseProxy(ctx context.Context, accountID, userID reverseProxy.SessionPrivateKey = existingReverseProxy.SessionPrivateKey reverseProxy.SessionPublicKey = existingReverseProxy.SessionPublicKey + if err = validateTargetReferences(ctx, transaction, accountID, reverseProxy.Targets); err != nil { + return err + } + if err = transaction.UpdateReverseProxy(ctx, reverseProxy); err != nil { return fmt.Errorf("update reverse proxy: %w", err) } @@ -208,6 +216,29 @@ func (m *managerImpl) UpdateReverseProxy(ctx context.Context, accountID, userID return reverseProxy, nil } +// validateTargetReferences checks that all target IDs reference existing peers or resources in the account. +func validateTargetReferences(ctx context.Context, transaction store.Store, accountID string, targets []reverseproxy.Target) error { + for _, target := range targets { + switch target.TargetType { + case reverseproxy.TargetTypePeer: + if _, err := transaction.GetPeerByID(ctx, store.LockingStrengthShare, accountID, target.TargetId); err != nil { + if sErr, ok := status.FromError(err); ok && sErr.Type() == status.NotFound { + return status.Errorf(status.InvalidArgument, "peer target %q not found in account", target.TargetId) + } + return fmt.Errorf("look up peer target %q: %w", target.TargetId, err) + } + case reverseproxy.TargetTypeResource: + if _, err := transaction.GetNetworkResourceByID(ctx, store.LockingStrengthShare, accountID, target.TargetId); err != nil { + if sErr, ok := status.FromError(err); ok && sErr.Type() == status.NotFound { + return status.Errorf(status.InvalidArgument, "resource target %q not found in account", target.TargetId) + } + return fmt.Errorf("look up resource target %q: %w", target.TargetId, err) + } + } + } + return nil +} + func (m *managerImpl) DeleteReverseProxy(ctx context.Context, accountID, userID, reverseProxyID string) error { ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Delete) if err != nil { diff --git a/management/internals/modules/reverseproxy/reverseproxy.go b/management/internals/modules/reverseproxy/reverseproxy.go index b6bf1ef3f..e48b4d4ed 100644 --- a/management/internals/modules/reverseproxy/reverseproxy.go +++ b/management/internals/modules/reverseproxy/reverseproxy.go @@ -2,6 +2,7 @@ package reverseproxy import ( "errors" + "fmt" "net" "net/url" "strconv" @@ -328,6 +329,15 @@ func (r *ReverseProxy) Validate() error { return errors.New("at least one target is required") } + for i, target := range r.Targets { + if target.TargetType != TargetTypePeer && target.TargetType != TargetTypeResource { + return fmt.Errorf("target %d has invalid target_type %q, must be %q or %q", i, target.TargetType, TargetTypePeer, TargetTypeResource) + } + if target.TargetId == "" { + return fmt.Errorf("target %d has empty target_id", i) + } + } + return nil }