From b501fc6a7df5bcd9ab6926d69b58990eb82a68b9 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Mon, 12 Jun 2023 16:54:23 +0200 Subject: [PATCH] libnetwork: handle id filter better By default we should do a standard prefix match. See https://github.com/containers/podman/issues/18471 for context. Also use the c/storage regex package to only compile the regex when needed. Signed-off-by: Paul Holzinger --- libnetwork/netavark/config_test.go | 4 ++-- libnetwork/types/define.go | 9 +++++++-- libnetwork/util/filters.go | 2 +- pkg/util/util.go | 21 +++++++++++++++++++++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/libnetwork/netavark/config_test.go b/libnetwork/netavark/config_test.go index 7b710388b..21c961fa3 100644 --- a/libnetwork/netavark/config_test.go +++ b/libnetwork/netavark/config_test.go @@ -1972,9 +1972,9 @@ var _ = Describe("Config", func() { Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge"))) }) - It("network list with filters (id)", func() { + It("network list with filters (id with regex)", func() { filters := map[string][]string{ - "id": {"3bed2cb3a3acf7b6a8ef408420cc682d5520e26976d354254f528c965612054f", "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121"}, + "id": {"3bed2cb3a3acf7b6a8ef40.*", "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121"}, } filterFuncs, err := util.GenerateNetworkFilters(filters) Expect(err).To(BeNil()) diff --git a/libnetwork/types/define.go b/libnetwork/types/define.go index f84221458..6e91ccda9 100644 --- a/libnetwork/types/define.go +++ b/libnetwork/types/define.go @@ -3,7 +3,8 @@ package types import ( "errors" "fmt" - "regexp" + + "github.com/containers/storage/pkg/regexp" ) var ( @@ -19,7 +20,11 @@ var ( // NameRegex is a regular expression to validate names. // This must NOT be changed. - NameRegex = regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9_.-]*$") + NameRegex = regexp.Delayed("^[a-zA-Z0-9][a-zA-Z0-9_.-]*$") // RegexError is thrown in presence of an invalid name. RegexError = fmt.Errorf("names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*: %w", ErrInvalidArg) // nolint:revive // This lint is new and we do not want to break the API. + + // NotHexRegex is a regular expression to check if a string is + // a hexadecimal string. + NotHexRegex = regexp.Delayed(`[^0-9a-fA-F]`) ) diff --git a/libnetwork/util/filters.go b/libnetwork/util/filters.go index 2f1e4a21f..1c259fa08 100644 --- a/libnetwork/util/filters.go +++ b/libnetwork/util/filters.go @@ -38,7 +38,7 @@ func createFilterFuncs(key string, filterValues []string) (types.FilterFunc, err case "id": // matches part of one id return func(net types.Network) bool { - return util.StringMatchRegexSlice(net.ID, filterValues) + return util.FilterId(net.ID, filterValues) }, nil // TODO: add dns enabled, internal filter diff --git a/pkg/util/util.go b/pkg/util/util.go index 44d4cda6e..0fc0e4b26 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -6,6 +6,8 @@ import ( "os/exec" "regexp" "strings" + + "github.com/containers/common/libnetwork/types" ) const ( @@ -110,3 +112,22 @@ func StringMatchRegexSlice(s string, re []string) bool { } return false } + +// FilterId is a function used to compare an id against a set of ids, if the +// input is hex we check if the prefix matches. Otherwise we assume it is a +// regex and try to match that. +// see https://github.com/containers/podman/issues/18471 for why we do this +func FilterId(id string, filters []string) bool { + for _, want := range filters { + isRegex := types.NotHexRegex.MatchString(want) + if isRegex { + match, err := regexp.MatchString(want, id) + if err == nil && match { + return true + } + } else if strings.HasPrefix(id, strings.ToLower(want)) { + return true + } + } + return false +}