Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ext_proc: send attributes #31090

Merged
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
87cf9ba
extract attributes changes from #29069
jbohanon Nov 8, 2023
45ec23d
fix ordering test constructor
jbohanon Nov 8, 2023
0a9f228
don't do CEL stuff if no attributes are configured
jbohanon Nov 16, 2023
6826a1c
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Nov 16, 2023
9857119
fix variable shadowing
jbohanon Nov 17, 2023
c26d44c
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Nov 17, 2023
db599b9
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Nov 27, 2023
a4454be
refactor matching utils out
jbohanon Nov 28, 2023
34b8fbc
refactor matching utils out
jbohanon Nov 28, 2023
d5ce702
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Nov 28, 2023
3631683
fix pointer/references
jbohanon Nov 29, 2023
47c2b46
where are my CEL objects going
jbohanon Nov 30, 2023
86ae01f
fix lifetime issue and clean up
jbohanon Nov 30, 2023
0d8f5d4
fix runtime feature format
jbohanon Nov 30, 2023
dc692e1
declare iter as reference
jbohanon Nov 30, 2023
8a28f0d
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Nov 30, 2023
8d34e78
fix tests and clean up
jbohanon Nov 30, 2023
fd598b9
skip fuzzing request and response attributes on ASAN_FUZZER due to un…
jbohanon Dec 1, 2023
2954fc7
use unique_ptr instead of absl::optional for struct, reference for ac…
jbohanon Dec 4, 2023
520d511
use object to store pair of parsed, compiled expression
jbohanon Dec 5, 2023
2778b97
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Dec 5, 2023
f6bbcf7
inline CelExpression initialization into emplace call
jbohanon Dec 15, 2023
fbdbfb4
raw ptr working
jbohanon Dec 15, 2023
5192143
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Dec 15, 2023
58faac1
update dep allowlist
jbohanon Dec 15, 2023
19fdb00
use serverFactoryContext to get builder singleton
jbohanon Dec 15, 2023
8948d0f
update dep allowlist
jbohanon Dec 15, 2023
fe68f15
PR comments
jbohanon Dec 15, 2023
d6cb932
kick CI
jbohanon Dec 15, 2023
ca13534
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Dec 19, 2023
ae4258d
plumb through local info
jbohanon Dec 19, 2023
8e02036
kick CI -- RBE cache error in iOS
jbohanon Dec 19, 2023
d4d94e6
add inludes for MockLocalInfo
jbohanon Dec 19, 2023
906183f
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Dec 20, 2023
ebd053c
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Jan 8, 2024
7019dd1
kick CI
jbohanon Jan 8, 2024
defdd94
kick CI
jbohanon Jan 9, 2024
c86a731
kick CI
jbohanon Jan 9, 2024
0b3e715
kick CI
jbohanon Jan 15, 2024
374770f
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Jan 15, 2024
a3e689f
revert unwanted local build change
jbohanon Jan 15, 2024
2c716b7
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Jan 15, 2024
9948c57
add skip_on_windows due to recent CEL bump
jbohanon Jan 16, 2024
7d58055
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Jan 16, 2024
fcaa5af
fix BUILD
jbohanon Jan 16, 2024
5fac8a5
skip client build on windows
jbohanon Jan 17, 2024
970fb4d
MORE SKIP ON WINDOWS
jbohanon Jan 17, 2024
a43136e
add filter to windows skip in bazel/repositories.bzl
jbohanon Jan 18, 2024
cfe7006
Merge branch 'main' into feature/ext_proc/request-response-attributes
jbohanon Jan 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions source/extensions/filters/http/ext_proc/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ envoy_cc_library(
],
deps = [
":client_interface",
":matching_utils_lib",
":mutation_utils_lib",
"//envoy/event:timer_interface",
"//envoy/http:filter_interface",
Expand Down Expand Up @@ -80,6 +81,31 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "matching_utils_lib",
srcs = ["matching_utils.cc"],
hdrs = ["matching_utils.h"],
copts = select({
"//bazel:windows_x86_64": [],
"//conditions:default": [
"-DUSE_CEL_PARSER",
],
}),
deps = [
"//envoy/http:header_map_interface",
"//source/common/protobuf",
"//source/extensions/filters/common/expr:evaluator_lib",
"@com_google_cel_cpp//eval/public:cel_expr_builder_factory",
] + select(
{
"//bazel:windows_x86_64": [],
"//conditions:default": [
"@com_google_cel_cpp//parser",
],
},
),
)

envoy_cc_library(
name = "client_lib",
srcs = ["client_impl.cc"],
Expand Down
14 changes: 8 additions & 6 deletions source/extensions/filters/http/ext_proc/config.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "source/extensions/filters/http/ext_proc/config.h"

#include "source/extensions/filters/common/expr/evaluator.h"
#include "source/extensions/filters/http/ext_proc/client_impl.h"
#include "source/extensions/filters/http/ext_proc/ext_proc.h"

Expand All @@ -15,9 +16,9 @@ Http::FilterFactoryCb ExternalProcessingFilterConfig::createFilterFactoryFromPro
PROTOBUF_GET_MS_OR_DEFAULT(proto_config, message_timeout, DefaultMessageTimeoutMs);
const uint32_t max_message_timeout_ms =
PROTOBUF_GET_MS_OR_DEFAULT(proto_config, max_message_timeout, DefaultMaxMessageTimeoutMs);
const auto filter_config =
std::make_shared<FilterConfig>(proto_config, std::chrono::milliseconds(message_timeout_ms),
max_message_timeout_ms, context.scope(), stats_prefix);
const auto filter_config = std::make_shared<FilterConfig>(
proto_config, std::chrono::milliseconds(message_timeout_ms), max_message_timeout_ms,
context.scope(), stats_prefix, Envoy::Extensions::Filters::Common::Expr::getBuilder(context));

return [filter_config, grpc_service = proto_config.grpc_service(),
&context](Http::FilterChainFactoryCallbacks& callbacks) {
Expand Down Expand Up @@ -45,9 +46,10 @@ ExternalProcessingFilterConfig::createFilterFactoryFromProtoWithServerContextTyp
PROTOBUF_GET_MS_OR_DEFAULT(proto_config, message_timeout, DefaultMessageTimeoutMs);
const uint32_t max_message_timeout_ms =
PROTOBUF_GET_MS_OR_DEFAULT(proto_config, max_message_timeout, DefaultMaxMessageTimeoutMs);
const auto filter_config =
std::make_shared<FilterConfig>(proto_config, std::chrono::milliseconds(message_timeout_ms),
max_message_timeout_ms, server_context.scope(), stats_prefix);
const auto filter_config = std::make_shared<FilterConfig>(
proto_config, std::chrono::milliseconds(message_timeout_ms), max_message_timeout_ms,
server_context.scope(), stats_prefix,
Envoy::Extensions::Filters::Common::Expr::getBuilder(server_context));

return [filter_config, grpc_service = proto_config.grpc_service(),
&server_context](Http::FilterChainFactoryCallbacks& callbacks) {
Expand Down
28 changes: 25 additions & 3 deletions source/extensions/filters/http/ext_proc/ext_proc.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "source/extensions/filters/http/ext_proc/ext_proc.h"

#include <typeinfo>

#include "envoy/config/common/mutation_rules/v3/mutation_rules.pb.h"

#include "source/common/http/utility.h"
Expand Down Expand Up @@ -201,7 +203,8 @@ void Filter::onDestroy() {
}

FilterHeadersStatus Filter::onHeaders(ProcessorState& state,
Http::RequestOrResponseHeaderMap& headers, bool end_stream) {
Http::RequestOrResponseHeaderMap& headers, bool end_stream,
absl::optional<ProtobufWkt::Struct> proto) {
jbohanon marked this conversation as resolved.
Show resolved Hide resolved
switch (openStream()) {
case StreamOpenState::Error:
return FilterHeadersStatus::StopIteration;
Expand All @@ -219,6 +222,9 @@ FilterHeadersStatus Filter::onHeaders(ProcessorState& state,
MutationUtils::headersToProto(headers, config_->allowedHeaders(), config_->disallowedHeaders(),
*headers_req->mutable_headers());
headers_req->set_end_of_stream(end_stream);
if (proto.has_value()) {
(*headers_req->mutable_attributes())[FilterName] = proto.value();
}
state.onStartProcessorCall(std::bind(&Filter::onMessageTimeout, this), config_->messageTimeout(),
ProcessorState::CallbackState::HeadersCallback);
ENVOY_LOG(debug, "Sending headers message");
Expand All @@ -237,7 +243,16 @@ FilterHeadersStatus Filter::decodeHeaders(RequestHeaderMap& headers, bool end_st

FilterHeadersStatus status = FilterHeadersStatus::Continue;
if (decoding_state_.sendHeaders()) {
status = onHeaders(decoding_state_, headers, end_stream);
absl::optional<Envoy::ProtobufWkt::Struct> proto;
if (config().hasRequestExpr()) {
auto activation_ptr = Filters::Common::Expr::createActivation(decoding_state_.streamInfo(),
&headers, nullptr, nullptr);
ExpressionManager::printExprPtrAndType(config().getExprPtr("request.path"),
"in decodeHeaders");
proto = config().evaluateRequestAttributes(std::move(activation_ptr));
}

status = onHeaders(decoding_state_, headers, end_stream, proto);
ENVOY_LOG(trace, "onHeaders returning {}", static_cast<int>(status));
} else {
ENVOY_LOG(trace, "decodeHeaders: Skipped header processing");
Expand Down Expand Up @@ -515,7 +530,14 @@ FilterHeadersStatus Filter::encodeHeaders(ResponseHeaderMap& headers, bool end_s

FilterHeadersStatus status = FilterHeadersStatus::Continue;
if (!processing_complete_ && encoding_state_.sendHeaders()) {
status = onHeaders(encoding_state_, headers, end_stream);
absl::optional<Envoy::ProtobufWkt::Struct> proto;
if (config_->hasResponseExpr()) {
auto activation_ptr = Filters::Common::Expr::createActivation(encoding_state_.streamInfo(),
nullptr, &headers, nullptr);
proto = config_->evaluateResponseAttributes(std::move(activation_ptr));
}

status = onHeaders(encoding_state_, headers, end_stream, proto);
ENVOY_LOG(trace, "onHeaders returns {}", static_cast<int>(status));
} else {
ENVOY_LOG(trace, "encodeHeaders: Skipped header processing");
Expand Down
59 changes: 43 additions & 16 deletions source/extensions/filters/http/ext_proc/ext_proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "source/extensions/filters/common/mutation_rules/mutation_rules.h"
#include "source/extensions/filters/http/common/pass_through_filter.h"
#include "source/extensions/filters/http/ext_proc/client.h"
#include "source/extensions/filters/http/ext_proc/matching_utils.h"
#include "source/extensions/filters/http/ext_proc/processor_state.h"

namespace Envoy {
Expand Down Expand Up @@ -126,7 +127,8 @@ class FilterConfig {
FilterConfig(const envoy::extensions::filters::http::ext_proc::v3::ExternalProcessor& config,
const std::chrono::milliseconds message_timeout,
const uint32_t max_message_timeout_ms, Stats::Scope& scope,
const std::string& stats_prefix)
const std::string& stats_prefix,
Extensions::Filters::Common::Expr::BuilderInstanceSharedPtr builder)
: failure_mode_allow_(config.failure_mode_allow()),
disable_clear_route_cache_(config.disable_clear_route_cache()),
message_timeout_(message_timeout), max_message_timeout_ms_(max_message_timeout_ms),
Expand All @@ -135,8 +137,19 @@ class FilterConfig {
filter_metadata_(config.filter_metadata()),
allow_mode_override_(config.allow_mode_override()),
disable_immediate_response_(config.disable_immediate_response()),
allowed_headers_(initHeaderMatchers(config.forward_rules().allowed_headers())),
disallowed_headers_(initHeaderMatchers(config.forward_rules().disallowed_headers())) {}
allowed_headers_(
MatchingUtils::initHeaderMatchers(config.forward_rules().allowed_headers())),
disallowed_headers_(
MatchingUtils::initHeaderMatchers(config.forward_rules().disallowed_headers())),
expression_manager_(builder, config.request_attributes(), config.response_attributes()) {
printExprPtrAndType("in FilterConfig constructor");
}

// TODO delete
void printExprPtrAndType(std::string location) {
expression_manager_.printExprPtrAndType(expression_manager_.getExprPtr("request.path"),
location);
}

bool failureModeAllow() const { return failure_mode_allow_; }

Expand Down Expand Up @@ -166,23 +179,31 @@ class FilterConfig {

const Envoy::ProtobufWkt::Struct& filterMetadata() const { return filter_metadata_; }

const absl::optional<ProtobufWkt::Struct>
evaluateRequestAttributes(const Filters::Common::Expr::ActivationPtr& activation) const {
return expression_manager_.evaluateRequestAttributes(std::move(activation));
}

const absl::optional<ProtobufWkt::Struct>
evaluateResponseAttributes(const Filters::Common::Expr::ActivationPtr& activation) const {
return expression_manager_.evaluateResponseAttributes(std::move(activation));
}

bool hasRequestExpr() const { return expression_manager_.hasRequestExpr(); }

bool hasResponseExpr() const { return expression_manager_.hasResponseExpr(); }
jbohanon marked this conversation as resolved.
Show resolved Hide resolved

// TODO: delete
const ExpressionManager::ExpressionPtrWithExpr& getExprPtr(std::string matcher) const {
return expression_manager_.getExprPtr(matcher);
}

private:
ExtProcFilterStats generateStats(const std::string& prefix,
const std::string& filter_stats_prefix, Stats::Scope& scope) {
const std::string final_prefix = absl::StrCat(prefix, "ext_proc.", filter_stats_prefix);
return {ALL_EXT_PROC_FILTER_STATS(POOL_COUNTER_PREFIX(scope, final_prefix))};
}
const std::vector<Matchers::StringMatcherPtr>
initHeaderMatchers(const envoy::type::matcher::v3::ListStringMatcher& header_list) {
std::vector<Matchers::StringMatcherPtr> header_matchers;
for (const auto& matcher : header_list.patterns()) {
header_matchers.push_back(
std::make_unique<Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>>(
matcher));
}
return header_matchers;
}

const bool failure_mode_allow_;
const bool disable_clear_route_cache_;
const std::chrono::milliseconds message_timeout_;
Expand All @@ -201,6 +222,8 @@ class FilterConfig {
const std::vector<Matchers::StringMatcherPtr> allowed_headers_;
// Empty disallowed_header_ means disallow nothing, i.e, allow all.
const std::vector<Matchers::StringMatcherPtr> disallowed_headers_;

const ExpressionManager expression_manager_;
};

using FilterConfigSharedPtr = std::shared_ptr<FilterConfig>;
Expand Down Expand Up @@ -248,7 +271,9 @@ class Filter : public Logger::Loggable<Logger::Id::ext_proc>,
: config_(config), client_(std::move(client)), stats_(config->stats()),
grpc_service_(grpc_service), config_with_hash_key_(grpc_service),
decoding_state_(*this, config->processingMode()),
encoding_state_(*this, config->processingMode()) {}
encoding_state_(*this, config->processingMode()) {
config_->printExprPtrAndType("in Filter constructor");
}

const FilterConfig& config() const { return *config_; }

Expand Down Expand Up @@ -300,7 +325,9 @@ class Filter : public Logger::Loggable<Logger::Id::ext_proc>,
void sendImmediateResponse(const envoy::service::ext_proc::v3::ImmediateResponse& response);

Http::FilterHeadersStatus onHeaders(ProcessorState& state,
Http::RequestOrResponseHeaderMap& headers, bool end_stream);
Http::RequestOrResponseHeaderMap& headers, bool end_stream,
absl::optional<ProtobufWkt::Struct> proto);

// Return a pair of whether to terminate returning the current result.
std::pair<bool, Http::FilterDataStatus> sendStreamChunk(ProcessorState& state);
Http::FilterDataStatus onData(ProcessorState& state, Buffer::Instance& data, bool end_stream);
Expand Down
47 changes: 47 additions & 0 deletions source/extensions/filters/http/ext_proc/matching_utils.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "source/extensions/filters/http/ext_proc/matching_utils.h"

#include <memory>
#include <typeinfo>

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
namespace ExternalProcessing {

absl::flat_hash_map<std::string, std::unique_ptr<ExpressionManager::ExpressionPtrWithExpr>>
ExpressionManager::initExpressions(const Protobuf::RepeatedPtrField<std::string>& matchers) const {
absl::flat_hash_map<std::string, std::unique_ptr<ExpressionManager::ExpressionPtrWithExpr>>
expressions;
#if defined(USE_CEL_PARSER)
for (const auto& matcher : matchers) {
auto parse_status = google::api::expr::parser::Parse(matcher);
jbohanon marked this conversation as resolved.
Show resolved Hide resolved
if (!parse_status.ok()) {
throw EnvoyException("Unable to parse descriptor expression: " +
parse_status.status().ToString());
}
const google::api::expr::v1alpha1::Expr& parse_status_expr = parse_status.value().expr();
const Filters::Common::Expr::ExpressionPtr& expression =
Extensions::Filters::Common::Expr::createExpression(builder_->builder(), parse_status_expr);
std::unique_ptr<ExpressionPtrWithExpr> expr =
std::make_unique<ExpressionPtrWithExpr>(parse_status_expr, std::move(expression.get()));
if (matcher == "request.path") {
ExpressionManager::printExprPtrAndType(*expr, "after construction");
}
expressions.try_emplace(matcher, std::move(expr));
if (matcher == "request.path") {
ExpressionManager::printExprPtrAndType(*expressions.at(matcher),
"after placing in container");
}
}
#else
ENVOY_LOG(warn, "CEL expression parsing is not available for use in this environment."
" Attempted to parse " +
std::to_string(matchers.size()) + " expressions");
#endif
return expressions;
}

} // namespace ExternalProcessing
} // namespace HttpFilters
} // namespace Extensions
} // namespace Envoy
Loading
Loading