Skip to content

Commit

Permalink
add filter state IP matcher
Browse files Browse the repository at this point in the history
Signed-off-by: antoniovleonti <[email protected]>
  • Loading branch information
antoniovleonti committed Dec 13, 2024
1 parent ab9ff8e commit 1cd6e9e
Show file tree
Hide file tree
Showing 12 changed files with 258 additions and 20 deletions.
5 changes: 5 additions & 0 deletions api/envoy/type/matcher/v3/filter_state.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package envoy.type.matcher.v3;

import "envoy/type/matcher/v3/string.proto";

import "xds/core/v3/cidr.proto";

import "udpa/annotations/status.proto";
import "validate/validate.proto";

Expand All @@ -25,5 +27,8 @@ message FilterStateMatcher {

// Matches the filter state object as a string value.
StringMatcher string_match = 2;

// Matchers the filter state object as a ip Instance.
xds.core.v3.CidrRange ip_range = 3;
}
}
5 changes: 5 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,11 @@ new_features:
- area: grpc-json
change: |
Added a new http filter for :ref:`gRPC to JSON transcoding <config_http_filters_grpc_json_reverse_transcoder>`.
- area: matchers
change: |
Added new filter state matcher
:ref:`ip_range <envoy_api_msg_type.matcher.v3.FilterStateMatcher.ip_range>` which attempts to cast
the filter state object to an IP and match it against a CIDR range.
deprecated:
- area: rbac
Expand Down
1 change: 1 addition & 0 deletions envoy/network/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ envoy_cc_library(
deps = [
"//envoy/common:base_includes",
"//envoy/common:pure_lib",
"//envoy/stream_info:filter_state_interface",
],
)

Expand Down
14 changes: 14 additions & 0 deletions envoy/network/address.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "envoy/common/platform.h"
#include "envoy/common/pure.h"
#include "envoy/stream_info/filter_state.h"

#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
Expand Down Expand Up @@ -238,6 +239,19 @@ class Instance {
virtual const Network::SocketInterface& socketInterface() const PURE;
};

/*
* Used to store Instance in filter state.
*/
class InstanceConstSharedPtrAccessor : public Envoy::StreamInfo::FilterState::Object {
public:
InstanceConstSharedPtrAccessor(InstanceConstSharedPtr ip) : ip_(std::move(ip)) {}

InstanceConstSharedPtr getIp() const { return ip_; }

private:
InstanceConstSharedPtr ip_;
};

} // namespace Address
} // namespace Network
} // namespace Envoy
14 changes: 14 additions & 0 deletions source/common/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ envoy_cc_library(
deps = [
":utility_lib",
"//envoy/common:matchers_interface",
"//source/common/common:filter_state_object_matchers_lib",
"//source/common/common:regex_lib",
"//source/common/config:metadata_lib",
"//source/common/config:utility_lib",
Expand All @@ -333,6 +334,19 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "filter_state_object_matchers_lib",
srcs = ["filter_state_object_matchers.cc"],
hdrs = ["filter_state_object_matchers.h"],
deps = [
"//envoy/common:exception_lib",
"//envoy/common:matchers_interface",
"//envoy/common:pure_lib",
"//source/common/network:cidr_range_interface",
"@com_google_absl//absl/status:statusor",
],
)

envoy_cc_library(
name = "random_generator_lib",
srcs = [
Expand Down
36 changes: 36 additions & 0 deletions source/common/common/filter_state_object_matchers.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "source/common/common/filter_state_object_matchers.h"

#include "envoy/common/exception.h"
#include "envoy/network/address.h"
#include "envoy/stream_info/filter_state.h"

#include "source/common/network/cidr_range.h"

#include "absl/status/statusor.h"
#include "xds/core/v3/cidr.pb.h"

namespace Envoy {
namespace Matchers {

FilterStateIpRangeMatcher::FilterStateIpRangeMatcher(const Network::Address::CidrRange& cidr_range)
: cidr_range_(cidr_range) {}

bool FilterStateIpRangeMatcher::match(const StreamInfo::FilterState::Object& object) const {
const Network::Address::InstanceConstSharedPtrAccessor* ip =
dynamic_cast<const Network::Address::InstanceConstSharedPtrAccessor*>(&object);
if (ip == nullptr) {
return false;
}
return cidr_range_.isInRange(*ip->getIp());
}

FilterStateStringMatcher::FilterStateStringMatcher(StringMatcherPtr&& string_matcher)
: string_matcher_(std::move(string_matcher)) {}

bool FilterStateStringMatcher::match(const StreamInfo::FilterState::Object& object) const {
const auto string_value = object.serializeAsString();
return string_value && string_matcher_->match(*string_value);
}

} // namespace Matchers
} // namespace Envoy
41 changes: 41 additions & 0 deletions source/common/common/filter_state_object_matchers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

#include <memory>

#include "envoy/common/matchers.h"
#include "envoy/common/pure.h"
#include "envoy/stream_info/filter_state.h"

#include "source/common/network/cidr_range.h"

namespace Envoy {
namespace Matchers {

class FilterStateObjectMatcher {
public:
virtual bool match(const StreamInfo::FilterState::Object& object) const PURE;
virtual ~FilterStateObjectMatcher(){};
};

using FilterStateObjectMatcherPtr = std::unique_ptr<FilterStateObjectMatcher>;

class FilterStateIpRangeMatcher : public FilterStateObjectMatcher {
public:
FilterStateIpRangeMatcher(const Network::Address::CidrRange& cidr_range);
bool match(const StreamInfo::FilterState::Object& object) const override;

private:
Envoy::Network::Address::CidrRange cidr_range_;
};

class FilterStateStringMatcher : public FilterStateObjectMatcher {
public:
FilterStateStringMatcher(StringMatcherPtr&& string_matcher);
bool match(const StreamInfo::FilterState::Object& object) const override;

private:
const StringMatcherPtr string_matcher_;
};

} // namespace Matchers
} // namespace Envoy
42 changes: 33 additions & 9 deletions source/common/common/matchers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
#include "envoy/type/matcher/v3/string.pb.h"
#include "envoy/type/matcher/v3/value.pb.h"

#include "source/common/common/filter_state_object_matchers.h"
#include "source/common/common/macros.h"
#include "source/common/common/regex.h"
#include "source/common/config/metadata.h"
#include "source/common/config/utility.h"
#include "source/common/http/path_utility.h"

#include "absl/status/statusor.h"
#include "absl/strings/match.h"
#include "filter_state_object_matchers.h"

namespace Envoy {
namespace Matchers {
Expand Down Expand Up @@ -122,31 +125,52 @@ MetadataMatcher::MetadataMatcher(const envoy::type::matcher::v3::MetadataMatcher
}

namespace {
StringMatcherPtr valueMatcherFromProto(const envoy::type::matcher::v3::FilterStateMatcher& matcher,
Server::Configuration::CommonFactoryContext& context) {

absl::StatusOr<FilterStateObjectMatcherPtr>
filterStateObjectMatcherFromProto(const envoy::type::matcher::v3::FilterStateMatcher& matcher,
Server::Configuration::CommonFactoryContext& context) {
switch (matcher.matcher_case()) {
case envoy::type::matcher::v3::FilterStateMatcher::MatcherCase::kStringMatch:
return std::make_unique<const StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>>(
matcher.string_match(), context);
return std::make_unique<FilterStateStringMatcher>(
std::make_unique<const StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>>(
matcher.string_match(), context));
break;
case envoy::type::matcher::v3::FilterStateMatcher::MatcherCase::kIpRange: {
auto ip_range = Network::Address::CidrRange::create(matcher.ip_range());
if (!ip_range.ok()) {
return ip_range.status();
}
return std::make_unique<FilterStateIpRangeMatcher>(*ip_range);
break;
}
default:
PANIC_DUE_TO_PROTO_UNSET;
}
}

} // namespace

FilterStateMatcher::FilterStateMatcher(const envoy::type::matcher::v3::FilterStateMatcher& matcher,
Server::Configuration::CommonFactoryContext& context)
: key_(matcher.key()), value_matcher_(valueMatcherFromProto(matcher, context)) {}
absl::StatusOr<FilterStateMatcherPtr>
FilterStateMatcher::create(const envoy::type::matcher::v3::FilterStateMatcher& config,
Server::Configuration::CommonFactoryContext& context) {
absl::StatusOr<FilterStateObjectMatcherPtr> matcher =
filterStateObjectMatcherFromProto(config, context);
if (!matcher.ok()) {
return matcher.status();
}
return std::make_unique<FilterStateMatcher>(config.key(), std::move(*matcher));
}

FilterStateMatcher::FilterStateMatcher(std::string key,
FilterStateObjectMatcherPtr&& object_matcher)
: key_(key), object_matcher_(std::move(object_matcher)) {}

bool FilterStateMatcher::match(const StreamInfo::FilterState& filter_state) const {
const auto* object = filter_state.getDataReadOnlyGeneric(key_);
if (object == nullptr) {
return false;
}
const auto string_value = object->serializeAsString();
return string_value && value_matcher_->match(*string_value);
return object_matcher_->match(*object);
}

PathMatcherConstSharedPtr
Expand Down
12 changes: 9 additions & 3 deletions source/common/common/matchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "envoy/type/matcher/v3/string.pb.h"
#include "envoy/type/matcher/v3/value.pb.h"

#include "source/common/common/filter_state_object_matchers.h"
#include "source/common/common/regex.h"
#include "source/common/common/utility.h"
#include "source/common/protobuf/protobuf.h"
Expand Down Expand Up @@ -239,8 +240,7 @@ class MetadataMatcher {

class FilterStateMatcher {
public:
FilterStateMatcher(const envoy::type::matcher::v3::FilterStateMatcher& matcher,
Server::Configuration::CommonFactoryContext& context);
FilterStateMatcher(std::string key, FilterStateObjectMatcherPtr&& object_matcher);

/**
* Check whether the filter state object is matched to the matcher.
Expand All @@ -249,11 +249,17 @@ class FilterStateMatcher {
*/
bool match(const StreamInfo::FilterState& filter_state) const;

static absl::StatusOr<std::unique_ptr<FilterStateMatcher>>
create(const envoy::type::matcher::v3::FilterStateMatcher& matcher,
Server::Configuration::CommonFactoryContext& context);

private:
const std::string key_;
const StringMatcherPtr value_matcher_;
const FilterStateObjectMatcherPtr object_matcher_;
};

using FilterStateMatcherPtr = std::unique_ptr<FilterStateMatcher>;

class PathMatcher : public StringMatcher {
public:
PathMatcher(const envoy::type::matcher::v3::PathMatcher& path,
Expand Down
7 changes: 6 additions & 1 deletion source/extensions/filters/common/rbac/matchers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,14 @@ bool MetadataMatcher::matches(const Network::Connection&, const Envoy::Http::Req
return matcher_.match(info.dynamicMetadata());
}

FilterStateMatcher::FilterStateMatcher(const envoy::type::matcher::v3::FilterStateMatcher& matcher,
Server::Configuration::CommonFactoryContext& context)
: matcher_(THROW_OR_RETURN_VALUE(Envoy::Matchers::FilterStateMatcher::create(matcher, context),
Envoy::Matchers::FilterStateMatcherPtr)) {}

bool FilterStateMatcher::matches(const Network::Connection&, const Envoy::Http::RequestHeaderMap&,
const StreamInfo::StreamInfo& info) const {
return matcher_.match(info.filterState());
return matcher_->match(info.filterState());
}

bool PolicyMatcher::matches(const Network::Connection& connection,
Expand Down
5 changes: 2 additions & 3 deletions source/extensions/filters/common/rbac/matchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,14 +263,13 @@ class MetadataMatcher : public Matcher {
class FilterStateMatcher : public Matcher {
public:
FilterStateMatcher(const envoy::type::matcher::v3::FilterStateMatcher& matcher,
Server::Configuration::CommonFactoryContext& context)
: matcher_(matcher, context) {}
Server::Configuration::CommonFactoryContext& context);

bool matches(const Network::Connection&, const Envoy::Http::RequestHeaderMap&,
const StreamInfo::StreamInfo& info) const override;

private:
const Envoy::Matchers::FilterStateMatcher matcher_;
const Envoy::Matchers::FilterStateMatcherPtr matcher_;
};

/**
Expand Down
Loading

0 comments on commit 1cd6e9e

Please sign in to comment.