diff --git a/agent/rpc/peering/service.go b/agent/rpc/peering/service.go index 72add67b076..a738aa20d14 100644 --- a/agent/rpc/peering/service.go +++ b/agent/rpc/peering/service.go @@ -346,6 +346,11 @@ func (s *Server) Establish( return nil, err } + // we don't want to default req.Partition unlike because partitions are empty in OSS + if err := s.validatePeeringInPartition(tok.PeerID, req.Partition); err != nil { + return nil, err + } + var id string if peering == nil { id, err = lib.GenerateUUID(s.Backend.CheckPeeringUUID) @@ -395,6 +400,22 @@ func (s *Server) Establish( return resp, nil } +// validatePeeringInPartition makes sure that we don't create a peering in the same partition. We validate by looking at +// the remotePeerID from the PeeringToken and looking up for a peering in the partition. If there is one and the +// request partition is the same, then we are attempting to peer within the partition, which we shouldn't. +func (s *Server) validatePeeringInPartition(remotePeerID, partition string) error { + _, peering, err := s.Backend.Store().PeeringReadByID(nil, remotePeerID) + if err != nil { + return fmt.Errorf("cannot read peering by ID: %w", err) + } + + if peering != nil && peering.Partition == partition { + return fmt.Errorf("cannot create a peering within the same partition (ENT) or cluster (OSS)") + } + + return nil +} + // OPTIMIZE: Handle blocking queries func (s *Server) PeeringRead(ctx context.Context, req *pbpeering.PeeringReadRequest) (*pbpeering.PeeringReadResponse, error) { if !s.Config.PeeringEnabled { diff --git a/agent/rpc/peering/service_test.go b/agent/rpc/peering/service_test.go index ca3553a1bbc..883f4fcc055 100644 --- a/agent/rpc/peering/service_test.go +++ b/agent/rpc/peering/service_test.go @@ -314,6 +314,30 @@ func TestPeeringService_Establish(t *testing.T) { } } +// We define a valid peering by a peering that does not occur over the same server addresses +func TestPeeringService_Establish_validPeeringInPartition(t *testing.T) { + // TODO(peering): see note on newTestServer, refactor to not use this + s := newTestServer(t, nil) + client := pbpeering.NewPeeringServiceClient(s.ClientConn(t)) + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + t.Cleanup(cancel) + + req := pbpeering.GenerateTokenRequest{PeerName: "peerOne"} + resp, err := client.GenerateToken(ctx, &req) + require.NoError(t, err) + require.NotEmpty(t, resp) + + establishReq := &pbpeering.EstablishRequest{ + PeerName: "peerTwo", + PeeringToken: resp.PeeringToken} + + respE, errE := client.Establish(ctx, establishReq) + require.Error(t, errE) + require.Contains(t, errE.Error(), "cannot create a peering within the same partition (ENT) or cluster (OSS)") + require.Nil(t, respE) +} + func TestPeeringService_Establish_ACLEnforcement(t *testing.T) { validToken := peering.TestPeeringToken("83474a06-cca4-4ff4-99a4-4152929c8160") validTokenJSON, _ := json.Marshal(&validToken)