diff --git a/.changelog/11293.txt b/.changelog/11293.txt new file mode 100644 index 000000000..f5a5daf59 --- /dev/null +++ b/.changelog/11293.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: service-resolver subset filters are validated for valid go-bexpr syntax on write +``` diff --git a/agent/structs/config_entry_discoverychain.go b/agent/structs/config_entry_discoverychain.go index 0a8567d67..35287f442 100644 --- a/agent/structs/config_entry_discoverychain.go +++ b/agent/structs/config_entry_discoverychain.go @@ -11,6 +11,7 @@ import ( "strings" "time" + "github.com/hashicorp/go-bexpr" "github.com/mitchellh/copystructure" "github.com/mitchellh/hashstructure" @@ -901,13 +902,18 @@ func (e *ServiceResolverConfigEntry) Validate() error { } if len(e.Subsets) > 0 { - for name := range e.Subsets { + for name, subset := range e.Subsets { if name == "" { return fmt.Errorf("Subset defined with empty name") } if err := validateServiceSubset(name); err != nil { return fmt.Errorf("Subset %q is invalid: %v", name, err) } + if subset.Filter != "" { + if _, err := bexpr.CreateEvaluator(subset.Filter, nil); err != nil { + return fmt.Errorf("Filter for subset %q is not a valid expression: %v", name, err) + } + } } } diff --git a/agent/structs/config_entry_discoverychain_test.go b/agent/structs/config_entry_discoverychain_test.go index 5cc43e468..37f41e925 100644 --- a/agent/structs/config_entry_discoverychain_test.go +++ b/agent/structs/config_entry_discoverychain_test.go @@ -552,6 +552,17 @@ func TestServiceResolverConfigEntry(t *testing.T) { }, validateErr: "Subset defined with empty name", }, + { + name: "invalid boolean expression subset filter", + entry: &ServiceResolverConfigEntry{ + Kind: ServiceResolver, + Name: "test", + Subsets: map[string]ServiceResolverSubset{ + "v1": {Filter: "random string"}, + }, + }, + validateErr: `Filter for subset "v1" is not a valid expression`, + }, { name: "default subset does not exist", entry: &ServiceResolverConfigEntry{