Skip to content

Commit

Permalink
service: add extra validation for global services
Browse files Browse the repository at this point in the history
[ upstream commit fc969f6 ]

Add a validation function to prevent unmarshalling invalid
global service objects retrieved from the kvstore, which
could then possibly trigger unexpected behavior. Currently,
we check that the cluster ID is in the valid range, and
that IP addresses are valid.

Signed-off-by: Marco Iorio <marco.iorio@isovalent.com>
Signed-off-by: Jussi Maki <jussi@isovalent.com>
  • Loading branch information
giorio94 authored and joamaki committed Aug 9, 2023
1 parent 5817079 commit 2819d7c
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
31 changes: 31 additions & 0 deletions pkg/service/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ package store

import (
"encoding/json"
"net/netip"
"path"

cmtypes "github.com/cilium/cilium/pkg/clustermesh/types"
"github.com/cilium/cilium/pkg/kvstore"
"github.com/cilium/cilium/pkg/kvstore/store"
"github.com/cilium/cilium/pkg/loadbalancer"
"github.com/cilium/cilium/pkg/lock"
"github.com/cilium/cilium/pkg/logging/logfields"
"github.com/cilium/cilium/pkg/option"
)

var (
Expand Down Expand Up @@ -111,11 +114,39 @@ func (s *ClusterService) Unmarshal(_ string, data []byte) error {
return err
}

if err := newService.validate(); err != nil {
return err
}

*s = newService

return nil
}

func (s *ClusterService) validate() error {
// Skip the ClusterID check if it matches the local one, as we assume that
// it has already been validated, and to allow it to be zero.
if s.ClusterID != option.Config.ClusterID {
if err := cmtypes.ValidateClusterID(s.ClusterID); err != nil {
return err
}
}

for address := range s.Frontends {
if _, err := netip.ParseAddr(address); err != nil {
return err
}
}

for address := range s.Backends {
if _, err := netip.ParseAddr(address); err != nil {
return err
}
}

return nil
}

// NewClusterService returns a new cluster service definition
func NewClusterService(name, namespace string) ClusterService {
return ClusterService{
Expand Down
45 changes: 45 additions & 0 deletions pkg/service/store/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"

check "github.com/cilium/checkmate"
"github.com/stretchr/testify/assert"

"github.com/cilium/cilium/pkg/checker"
"github.com/cilium/cilium/pkg/loadbalancer"
Expand Down Expand Up @@ -100,3 +101,47 @@ func (s *ServiceGenericSuite) TestPortConfigurationDeepEqual(c *check.C) {
}
}
}

func TestClusterServiceValidate(t *testing.T) {
tests := []struct {
name string
svc ClusterService
assert assert.ErrorAssertionFunc
}{
{
name: "empty",
svc: ClusterService{},
assert: assert.NoError,
},
{
name: "valid",
svc: ClusterService{
ClusterID: 99,
Frontends: map[string]PortConfiguration{"10.1.2.3": {}, "abcd::0001": {}},
Backends: map[string]PortConfiguration{"10.3.2.1": {}, "dcba::0001": {}},
},
assert: assert.NoError,
},
{
name: "invalid cluster ID",
svc: ClusterService{ClusterID: 260},
assert: assert.Error,
},
{
name: "invalid frontend IP",
svc: ClusterService{Frontends: map[string]PortConfiguration{"10.1.2.3": {}, "invalid": {}}},
assert: assert.Error,
},
{
name: "invalid backend IP",
svc: ClusterService{Backends: map[string]PortConfiguration{"invalid": {}, "dcba::0001": {}}},
assert: assert.Error,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.assert(t, tt.svc.validate())
})
}
}

0 comments on commit 2819d7c

Please sign in to comment.