From f077bea7ab69e2a1a0d248a13aa20b76df6937a8 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Wed, 10 Jun 2020 21:59:21 +0000 Subject: [PATCH 01/39] Enabled LOG action in RBAC filter Signed-off-by: davidraskin --- api/envoy/config/rbac/v3/rbac.proto | 2 + api/envoy/config/rbac/v4alpha/rbac.proto | 2 + .../envoy/config/rbac/v3/rbac.proto | 2 + .../envoy/config/rbac/v4alpha/rbac.proto | 2 + .../extensions/filters/common/rbac/engine.h | 28 +++++ .../filters/common/rbac/engine_impl.cc | 39 ++++++- .../filters/common/rbac/engine_impl.h | 7 ++ .../filters/http/rbac/rbac_filter.cc | 5 + .../filters/http/rbac/rbac_filter.h | 19 ++++ .../filters/common/rbac/engine_impl_test.cc | 107 ++++++++++++++++++ .../filters/http/rbac/rbac_filter_test.cc | 47 +++++++- tools/api/generate_go_protobuf.py | 9 +- 12 files changed, 259 insertions(+), 10 deletions(-) diff --git a/api/envoy/config/rbac/v3/rbac.proto b/api/envoy/config/rbac/v3/rbac.proto index 040f537d1f5c8..79d8f7126e5dd 100644 --- a/api/envoy/config/rbac/v3/rbac.proto +++ b/api/envoy/config/rbac/v3/rbac.proto @@ -73,6 +73,8 @@ message RBAC { // The policies deny access to principals. The rest is allowed. This is block-list style // access control. DENY = 1; + + LOG = 2; } // The action to take if a policy matches. The request is allowed if and only if: diff --git a/api/envoy/config/rbac/v4alpha/rbac.proto b/api/envoy/config/rbac/v4alpha/rbac.proto index 3ca9f7f08a72d..ba9da06908c29 100644 --- a/api/envoy/config/rbac/v4alpha/rbac.proto +++ b/api/envoy/config/rbac/v4alpha/rbac.proto @@ -73,6 +73,8 @@ message RBAC { // The policies deny access to principals. The rest is allowed. This is block-list style // access control. DENY = 1; + + LOG = 2; } // The action to take if a policy matches. The request is allowed if and only if: diff --git a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto index 040f537d1f5c8..79d8f7126e5dd 100644 --- a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto @@ -73,6 +73,8 @@ message RBAC { // The policies deny access to principals. The rest is allowed. This is block-list style // access control. DENY = 1; + + LOG = 2; } // The action to take if a policy matches. The request is allowed if and only if: diff --git a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto index 8bab830607b65..a700ef4fd88ce 100644 --- a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto @@ -73,6 +73,8 @@ message RBAC { // The policies deny access to principals. The rest is allowed. This is block-list style // access control. DENY = 1; + + LOG = 2; } // The action to take if a policy matches. The request is allowed if and only if: diff --git a/source/extensions/filters/common/rbac/engine.h b/source/extensions/filters/common/rbac/engine.h index a833867dd02a9..25e7027f1b066 100644 --- a/source/extensions/filters/common/rbac/engine.h +++ b/source/extensions/filters/common/rbac/engine.h @@ -45,6 +45,34 @@ class RoleBasedAccessControlEngine { */ virtual bool allowed(const Network::Connection& connection, const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const PURE; + + /** + * Returns whether or not the current action should be logged. + * + * @param connection the downstream connection used to identify the action/principal. + * @param headers the headers of the incoming request used to identify the action/principal. An + * empty map should be used if there are no headers available. + * @param info the per-request or per-connection stream info with additional information + * about the action/principal. + * @param effective_policy_id it will be filled by the matching policy's ID, + * which is used to identity the source of the allow/deny. + */ + virtual bool shouldLog(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const PURE; + + /** + * Returns whether or not the current action should be logged. + * + * @param connection the downstream connection used to identify the action/principal. + * @param info the per-request or per-connection stream info with additional information + * about the action/principal. + * @param effective_policy_id it will be filled by the matching policy's ID, + * which is used to identity the source of the allow/deny. + */ + virtual bool shouldLog(const Network::Connection& connection, const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const PURE; }; } // namespace RBAC diff --git a/source/extensions/filters/common/rbac/engine_impl.cc b/source/extensions/filters/common/rbac/engine_impl.cc index bd8a0a9cd0cac..70ceec4be70e2 100644 --- a/source/extensions/filters/common/rbac/engine_impl.cc +++ b/source/extensions/filters/common/rbac/engine_impl.cc @@ -12,7 +12,7 @@ namespace RBAC { RoleBasedAccessControlEngineImpl::RoleBasedAccessControlEngineImpl( const envoy::config::rbac::v3::RBAC& rules) - : allowed_if_matched_(rules.action() == envoy::config::rbac::v3::RBAC::ALLOW) { + : allowed_if_matched_(rules.action() == envoy::config::rbac::v3::RBAC::ALLOW), action_log_(rules.action() == envoy::config::rbac::v3::RBAC::LOG) { // guard expression builder by presence of a condition in policies for (const auto& policy : rules.policies()) { if (policy.second.has_condition()) { @@ -30,6 +30,11 @@ bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connec const Envoy::Http::RequestHeaderMap& headers, const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const { + // Automatically allow if LOG action + if(action_log_) { + return true; + } + bool matched = false; for (const auto& policy : policies_) { @@ -45,6 +50,7 @@ bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connec // only allowed if: // - matched and ALLOW action // - not matched and DENY action + // - LOG action return matched == allowed_if_matched_; } @@ -55,6 +61,37 @@ bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connec return allowed(connection, *empty_header, info, effective_policy_id); } +bool RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const { + if(!action_log_) { + return false; + } + + bool matched = false; + + for (const auto& policy : policies_) { + if (policy.second->matches(connection, headers, info)) { + matched = true; + if (effective_policy_id != nullptr) { + *effective_policy_id = policy.first; + } + break; + } + } + + // log if action is LOG and a policy matches + return matched; +} + +bool RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& connection, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const { + static const Http::RequestHeaderMapImpl* empty_header = new Http::RequestHeaderMapImpl(); + return shouldLog(connection, *empty_header, info, effective_policy_id); +} + } // namespace RBAC } // namespace Common } // namespace Filters diff --git a/source/extensions/filters/common/rbac/engine_impl.h b/source/extensions/filters/common/rbac/engine_impl.h index 261b45b0aa133..66439e5f2613e 100644 --- a/source/extensions/filters/common/rbac/engine_impl.h +++ b/source/extensions/filters/common/rbac/engine_impl.h @@ -21,8 +21,15 @@ class RoleBasedAccessControlEngineImpl : public RoleBasedAccessControlEngine, No bool allowed(const Network::Connection& connection, const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const override; + bool shouldLog(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const override; + + bool shouldLog(const Network::Connection& connection, const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const override; + private: const bool allowed_if_matched_; + const bool action_log_; std::map> policies_; diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index 6e1ff3ea33188..e5b51db23a4fa 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -109,6 +109,11 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo const auto engine = config_->engine(callbacks_->route(), Filters::Common::RBAC::EnforcementMode::Enforced); if (engine != nullptr) { + //Set kRbacShouldLog to true if shouldLog; false otherwise + bool log_decision = engine->shouldLog(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr); + callbacks_->streamInfo().filterState()->setData("kRbacShouldLog", std::make_shared(log_decision ? "yes" : "no"), + StreamInfo::FilterState::StateType::Mutable); + if (engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr)) { ENVOY_LOG(debug, "enforced allowed"); config_->stats().allowed_.inc(); diff --git a/source/extensions/filters/http/rbac/rbac_filter.h b/source/extensions/filters/http/rbac/rbac_filter.h index fe7369e34e6be..96eb8198db5cc 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.h +++ b/source/extensions/filters/http/rbac/rbac_filter.h @@ -7,6 +7,11 @@ #include "envoy/stats/scope.h" #include "envoy/stats/stats_macros.h" +//Temporary for key-value setting +#include +#include "envoy/stream_info/filter_state.h" +// + #include "common/common/logger.h" #include "extensions/filters/common/rbac/engine_impl.h" @@ -17,6 +22,20 @@ namespace Extensions { namespace HttpFilters { namespace RBACFilter { +class RBACShouldLogState : public StreamInfo::FilterState::Object { +public: + RBACShouldLogState(std::string value) { + value_ = value; + } + + const std::string& value() const { return value_; } + void setValue(std::string value) { + value_.assign(value); + } +private: + std::string value_{}; +}; + class RoleBasedAccessControlRouteSpecificFilterConfig : public Router::RouteSpecificFilterConfig { public: RoleBasedAccessControlRouteSpecificFilterConfig( diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index 5e2eda5b30e3f..a9d4389b86d0c 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -32,6 +32,14 @@ void checkEngine( EXPECT_EQ(expected, engine.allowed(connection, headers, info, nullptr)); } +//Used for testing shouldLog() function tests +void checkEngineLog(const RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, + const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), + const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl(), + const StreamInfo::StreamInfo& info = NiceMock()) { + EXPECT_EQ(expected, engine.shouldLog(connection, headers, info, nullptr)); +} + TEST(RoleBasedAccessControlEngineImpl, Disabled) { envoy::config::rbac::v3::RBAC rbac; rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); @@ -173,6 +181,29 @@ TEST(RoleBasedAccessControlEngineImpl, DeniedBlacklist) { checkEngine(engine, true, conn, headers, info); } +TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { + envoy::config::rbac::v3::Policy policy; + policy.add_permissions()->set_destination_port(123); + policy.add_principals()->set_any(true); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + (*rbac.mutable_policies())["foo"] = policy; + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + + Envoy::Network::MockConnection conn; + Envoy::Http::TestRequestHeaderMapImpl headers; + NiceMock info; + Envoy::Network::Address::InstanceConstSharedPtr addr = + Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); + // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngine(engine, true, conn, headers, info); + + addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); + // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngine(engine, true, conn, headers, info); +} + TEST(RoleBasedAccessControlEngineImpl, BasicCondition) { envoy::config::rbac::v3::Policy policy; policy.add_permissions()->set_any(true); @@ -358,6 +389,82 @@ TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { checkEngine(engine, false, conn, headers, info); } +//shouldLog() tests +TEST(RoleBasedAccessControlEngineImpl, DisabledLog) { + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + checkEngineLog(RBAC::RoleBasedAccessControlEngineImpl(rbac), false); +} + +TEST(RoleBasedAccessControlEngineImpl, LogIfMatched) { + envoy::config::rbac::v3::Policy policy; + policy.add_permissions()->set_destination_port(123); + policy.add_principals()->set_any(true); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + (*rbac.mutable_policies())["foo"] = policy; + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + + Envoy::Network::MockConnection conn; + Envoy::Http::TestRequestHeaderMapImpl headers; + NiceMock info; + Envoy::Network::Address::InstanceConstSharedPtr addr = + Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); + EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngineLog(engine, true, conn, headers, info); + + addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); + EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngineLog(engine, false, conn, headers, info); +} + +TEST(RoleBasedAccessControlEngineImpl, NeverLogAllow) { + envoy::config::rbac::v3::Policy policy; + policy.add_permissions()->set_destination_port(123); + policy.add_principals()->set_any(true); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); + (*rbac.mutable_policies())["foo"] = policy; + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + + Envoy::Network::MockConnection conn; + Envoy::Http::TestRequestHeaderMapImpl headers; + NiceMock info; + Envoy::Network::Address::InstanceConstSharedPtr addr = + Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); + // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngineLog(engine, false, conn, headers, info); + + addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); + // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngineLog(engine, false, conn, headers, info); +} + +TEST(RoleBasedAccessControlEngineImpl, NeverLogDeny) { + envoy::config::rbac::v3::Policy policy; + policy.add_permissions()->set_destination_port(123); + policy.add_principals()->set_any(true); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); + (*rbac.mutable_policies())["foo"] = policy; + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + + Envoy::Network::MockConnection conn; + Envoy::Http::TestRequestHeaderMapImpl headers; + NiceMock info; + Envoy::Network::Address::InstanceConstSharedPtr addr = + Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); + // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngineLog(engine, false, conn, headers, info); + + addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); + // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngineLog(engine, false, conn, headers, info); +} + } // namespace } // namespace RBAC } // namespace Common diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index d445860f83946..9fe2a6a8b35b9 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -26,7 +26,7 @@ namespace { class RoleBasedAccessControlFilterTest : public testing::Test { public: - RoleBasedAccessControlFilterConfigSharedPtr setupConfig() { + RoleBasedAccessControlFilterConfigSharedPtr setupConfig(envoy::config::rbac::v3::RBAC::Action action) { envoy::extensions::filters::http::rbac::v3::RBAC config; envoy::config::rbac::v3::Policy policy; @@ -36,7 +36,7 @@ class RoleBasedAccessControlFilterTest : public testing::Test { policy_rules->add_rules()->set_destination_port(123); policy_rules->add_rules()->mutable_url_path()->mutable_path()->set_suffix("suffix"); policy.add_principals()->set_any(true); - config.mutable_rules()->set_action(envoy::config::rbac::v3::RBAC::ALLOW); + config.mutable_rules()->set_action(action); (*config.mutable_rules()->mutable_policies())["foo"] = policy; envoy::config::rbac::v3::Policy shadow_policy; @@ -44,18 +44,20 @@ class RoleBasedAccessControlFilterTest : public testing::Test { shadow_policy_rules->add_rules()->mutable_requested_server_name()->set_exact("xyz.cncf.io"); shadow_policy_rules->add_rules()->set_destination_port(456); shadow_policy.add_principals()->set_any(true); - config.mutable_shadow_rules()->set_action(envoy::config::rbac::v3::RBAC::ALLOW); + config.mutable_shadow_rules()->set_action(action); (*config.mutable_shadow_rules()->mutable_policies())["bar"] = shadow_policy; return std::make_shared(config, "test", store_); } - RoleBasedAccessControlFilterTest() : config_(setupConfig()), filter_(config_) {} + RoleBasedAccessControlFilterTest() : config_(setupConfig(envoy::config::rbac::v3::RBAC::ALLOW)), filter_(config_), + log_config_(setupConfig(envoy::config::rbac::v3::RBAC::LOG)), log_filter_(log_config_) {} void SetUp() override { EXPECT_CALL(callbacks_, connection()).WillRepeatedly(Return(&connection_)); EXPECT_CALL(callbacks_, streamInfo()).WillRepeatedly(ReturnRef(req_info_)); filter_.setDecoderFilterCallbacks(callbacks_); + log_filter_.setDecoderFilterCallbacks(callbacks_); } void setDestinationPort(uint16_t port) { @@ -82,8 +84,10 @@ class RoleBasedAccessControlFilterTest : public testing::Test { NiceMock req_info_; Stats::IsolatedStoreImpl store_; RoleBasedAccessControlFilterConfigSharedPtr config_; - RoleBasedAccessControlFilter filter_; + RoleBasedAccessControlFilterConfigSharedPtr log_config_; + RoleBasedAccessControlFilter log_filter_; + Network::Address::InstanceConstSharedPtr address_; std::string requested_server_name_; Http::TestRequestHeaderMapImpl headers_; @@ -170,6 +174,39 @@ TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, true)); } +//Log Tests +TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { + setDestinationPort(123); + + EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); + Http::MetadataMap metadata_map{{"metadata", "metadata"}}; + EXPECT_EQ(Http::FilterMetadataStatus::Continue, log_filter_.decodeMetadata(metadata_map)); + EXPECT_EQ(1U, log_config_->stats().allowed_.value()); + EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); + + Buffer::OwnedImpl data(""); + EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); + EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); + + EXPECT_EQ("yes", req_info_.filterState()->getDataMutable("kRbacShouldLog").value()); +} + +TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { + setDestinationPort(456); + + EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); + Http::MetadataMap metadata_map{{"metadata", "metadata"}}; + EXPECT_EQ(Http::FilterMetadataStatus::Continue, log_filter_.decodeMetadata(metadata_map)); + EXPECT_EQ(1U, log_config_->stats().allowed_.value()); + EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); + + Buffer::OwnedImpl data(""); + EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); + EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); + + EXPECT_EQ("no", req_info_.filterState()->getDataMutable("kRbacShouldLog").value()); +} + } // namespace } // namespace RBACFilter } // namespace HttpFilters diff --git a/tools/api/generate_go_protobuf.py b/tools/api/generate_go_protobuf.py index 746008c82c85f..8cd65cd88c82d 100755 --- a/tools/api/generate_go_protobuf.py +++ b/tools/api/generate_go_protobuf.py @@ -9,13 +9,13 @@ import re TARGETS = '@envoy_api//...' -IMPORT_BASE = 'github.com/envoyproxy/go-control-plane' +IMPORT_BASE = 'github.com/davidraskin/go-control-plane' OUTPUT_BASE = 'build_go' REPO_BASE = 'go-control-plane' BRANCH = 'master' MIRROR_MSG = 'Mirrored from envoyproxy/envoy @ ' -USER_NAME = 'go-control-plane(CircleCI)' -USER_EMAIL = 'go-control-plane@users.noreply.github.com' +USER_NAME = 'davidraskin' +USER_EMAIL = 'draskin@google.com' def generateProtobufs(output): @@ -63,7 +63,7 @@ def git(repo, *args): def cloneGoProtobufs(repo): # Create a local clone of go-control-plane - git(None, 'clone', 'git@github.com:envoyproxy/go-control-plane', repo) + git(None, 'clone', 'git@github.com:davidraskin/go-control-plane', repo) git(repo, 'fetch') git(repo, 'checkout', '-B', BRANCH, 'origin/master') @@ -109,6 +109,7 @@ def publishGoProtobufs(repo, sha): if __name__ == "__main__": + print("=======================================================GENERATING PROTOBUFS=========================================") workspace = check_output(['bazel', 'info', 'workspace']).decode().strip() output = os.path.join(workspace, OUTPUT_BASE) generateProtobufs(output) From 888f35eadb344e7925c052f569bd8548620dac37 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Wed, 17 Jun 2020 03:49:51 +0000 Subject: [PATCH 02/39] Started writing integration test Signed-off-by: davidraskin --- tools/api/generate_go_protobuf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/api/generate_go_protobuf.py b/tools/api/generate_go_protobuf.py index 8cd65cd88c82d..e26083f7dd090 100755 --- a/tools/api/generate_go_protobuf.py +++ b/tools/api/generate_go_protobuf.py @@ -109,7 +109,6 @@ def publishGoProtobufs(repo, sha): if __name__ == "__main__": - print("=======================================================GENERATING PROTOBUFS=========================================") workspace = check_output(['bazel', 'info', 'workspace']).decode().strip() output = os.path.join(workspace, OUTPUT_BASE) generateProtobufs(output) From 83d29ff79452d1f5d40be96f0ba8205e27d924ed Mon Sep 17 00:00:00 2001 From: davidraskin Date: Wed, 17 Jun 2020 03:51:11 +0000 Subject: [PATCH 03/39] Started writing integration test for RBAC Signed-off-by: davidraskin --- .../http/rbac/rbac_filter_integration_test.cc | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc b/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc index 28e4420db014d..d05bf3a7e967e 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc @@ -64,6 +64,20 @@ name: rbac - any: true )EOF"; +// const std::string RBAC_CONFIG_WITH_LOG_ACTION = R"EOF( +// name: rbac +// typed_config: +// "@type": type.googleapis.com/envoy.config.filter.http.rbac.v3.RBAC +// rules: +// action: LOG +// policies: +// foo: +// permissions: +// - header: { name: ":method", exact_match: "GET" } +// principals: +// - any: true +// )EOF"; + using RBACIntegrationTest = HttpProtocolIntegrationTest; INSTANTIATE_TEST_SUITE_P(Protocols, RBACIntegrationTest, @@ -277,5 +291,28 @@ TEST_P(RBACIntegrationTest, PathIgnoreCase) { } } +// TEST_P(RBACIntegrationTest, LogConnectionAllow) { +// config_helper_.addFilter(RBAC_CONFIG_WITH_LOG_ACTION); +// initialize(); + +// codec_client_ = makeHttpConnection(lookupPort("http")); + +// auto response = codec_client_->makeRequestWithBody( +// Http::TestRequestHeaderMapImpl{ +// {":method", "GET"}, +// {":path", "/"}, +// {":scheme", "http"}, +// {":authority", "host"}, +// {"x-forwarded-for", "10.0.0.1"}, +// }, +// 1024); +// response->waitForEndStream(); +// ASSERT_TRUE(response->complete()); +// EXPECT_EQ("200", response->headers().getStatusValue()); +// ASSERT_TRUE(response->headers().ContentLength()); +// EXPECT_NE("0", response->headers().getContentLengthValue()); +// EXPECT_THAT(response->body(), ::testing::IsEmpty()); +// } + } // namespace } // namespace Envoy From b3f63be92adb98ed2e28cf54e835704fce3fb6f3 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Mon, 22 Jun 2020 22:13:49 +0000 Subject: [PATCH 04/39] changed to using dynamic Metadata over filterState Signed-off-by: davidraskin --- .../filters/http/rbac/rbac_filter.cc | 19 +++++++++--------- .../filters/http/rbac/rbac_filter_test.cc | 20 +++++++++++++------ 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index e5b51db23a4fa..72507245bab42 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -73,6 +73,10 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo : "none", headers, callbacks_->streamInfo().dynamicMetadata().DebugString()); + ProtobufWkt::Struct metrics; + auto& fields = *metrics.mutable_fields(); + Http::FilterHeadersStatus result = Http::FilterHeadersStatus::Continue; + std::string effective_policy_id; const auto shadow_engine = config_->engine(callbacks_->route(), Filters::Common::RBAC::EnforcementMode::Shadow); @@ -91,9 +95,7 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().EngineResultDenied; } - ProtobufWkt::Struct metrics; - auto& fields = *metrics.mutable_fields(); if (!effective_policy_id.empty()) { *fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get() .ShadowEffectivePolicyIdField] @@ -102,8 +104,6 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo *fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().ShadowEngineResultField] .mutable_string_value() = shadow_resp_code; - - callbacks_->streamInfo().setDynamicMetadata(HttpFilterNames::get().Rbac, metrics); } const auto engine = @@ -111,24 +111,25 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo if (engine != nullptr) { //Set kRbacShouldLog to true if shouldLog; false otherwise bool log_decision = engine->shouldLog(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr); - callbacks_->streamInfo().filterState()->setData("kRbacShouldLog", std::make_shared(log_decision ? "yes" : "no"), - StreamInfo::FilterState::StateType::Mutable); + // callbacks_->streamInfo().filterState()->setData("envoy.log", std::make_shared(log_decision ? "yes" : "no"), + // StreamInfo::FilterState::StateType::Mutable); + *fields["envoy.log"].mutable_string_value() = log_decision ? "yes": "no"; if (engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr)) { ENVOY_LOG(debug, "enforced allowed"); config_->stats().allowed_.inc(); - return Http::FilterHeadersStatus::Continue; } else { ENVOY_LOG(debug, "enforced denied"); callbacks_->sendLocalReply(Http::Code::Forbidden, "RBAC: access denied", nullptr, absl::nullopt, RcDetails::get().RbacAccessDenied); config_->stats().denied_.inc(); - return Http::FilterHeadersStatus::StopIteration; + result = Http::FilterHeadersStatus::StopIteration; } } + callbacks_->streamInfo().setDynamicMetadata(HttpFilterNames::get().Rbac, metrics); ENVOY_LOG(debug, "no engine, allowed by default"); - return Http::FilterHeadersStatus::Continue; + return result; } } // namespace RBACFilter diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index 9fe2a6a8b35b9..dc17231d73f42 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -133,6 +133,14 @@ TEST_F(RoleBasedAccessControlFilterTest, Path) { {":authority", "host"}, }; EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers, false)); + + headers = Http::TestRequestHeaderMapImpl{ + {":method", "GET"}, + {":path", "prefix/suffix/next"}, + {":scheme", "http"}, + {":authority", "host"}, + }; + EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_.decodeHeaders(headers, false)); } TEST_F(RoleBasedAccessControlFilterTest, Denied) { @@ -177,10 +185,9 @@ TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { //Log Tests TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { setDestinationPort(123); + setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); - Http::MetadataMap metadata_map{{"metadata", "metadata"}}; - EXPECT_EQ(Http::FilterMetadataStatus::Continue, log_filter_.decodeMetadata(metadata_map)); EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); @@ -188,15 +195,15 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); - EXPECT_EQ("yes", req_info_.filterState()->getDataMutable("kRbacShouldLog").value()); + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); + EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); } TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { setDestinationPort(456); + setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); - Http::MetadataMap metadata_map{{"metadata", "metadata"}}; - EXPECT_EQ(Http::FilterMetadataStatus::Continue, log_filter_.decodeMetadata(metadata_map)); EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); @@ -204,7 +211,8 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); - EXPECT_EQ("no", req_info_.filterState()->getDataMutable("kRbacShouldLog").value()); + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); + EXPECT_EQ("no", filter_meta.fields().at("envoy.log").string_value()); } } // namespace From f3185725cb0e7c84efbdbd758159895a27594411 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Wed, 17 Jun 2020 17:36:55 +0000 Subject: [PATCH 05/39] Revert "http1: do not add transfer-encoding: chunked to 1xx/204 responses (#11458)" This reverts commit 353c21673395ba53fad54b4916cda0ad87ddb695. Signed-off-by: davidraskin --- source/common/http/http1/codec_impl.cc | 50 ++--- source/common/http/http1/codec_impl.h | 9 +- source/common/runtime/runtime_features.cc | 3 +- test/common/http/http1/codec_impl_test.cc | 171 +----------------- .../integration/websocket_integration_test.cc | 5 +- 5 files changed, 19 insertions(+), 219 deletions(-) diff --git a/source/common/http/http1/codec_impl.cc b/source/common/http/http1/codec_impl.cc index 7fe0a62590924..f3072449a813a 100644 --- a/source/common/http/http1/codec_impl.cc +++ b/source/common/http/http1/codec_impl.cc @@ -35,8 +35,6 @@ struct Http1ResponseCodeDetailValues { const absl::string_view InvalidUrl = "http1.invalid_url"; const absl::string_view InvalidTransferEncoding = "http1.invalid_transfer_encoding"; const absl::string_view BodyDisallowed = "http1.body_disallowed"; - const absl::string_view TransferEncodingNotAllowed = "http1.transfer_encoding_not_allowed"; - const absl::string_view ContentLengthNotAllowed = "http1.content_length_not_allowed"; }; struct Http1HeaderTypesValues { @@ -71,7 +69,7 @@ StreamEncoderImpl::StreamEncoderImpl(ConnectionImpl& connection, HeaderKeyFormatter* header_key_formatter) : connection_(connection), disable_chunk_encoding_(false), chunk_encoding_(true), processing_100_continue_(false), is_response_to_head_request_(false), - is_response_to_connect_request_(false), is_1xx_(false), is_204_(false), + is_response_to_connect_request_(false), is_content_length_allowed_(true), header_key_formatter_(header_key_formatter) { if (connection_.connection().aboveHighWatermark()) { runHighWatermarkCallbacks(); @@ -161,22 +159,15 @@ void StreamEncoderImpl::encodeHeadersBase(const RequestOrResponseHeaderMap& head // response to a HEAD request. // For 204s and 1xx where content length is disallowed, don't append the content length but // also don't chunk encode. - if (!is_1xx_ && !is_204_) { + if (is_content_length_allowed_) { encodeFormattedHeader(Headers::get().ContentLength.get(), "0"); } chunk_encoding_ = false; } else if (connection_.protocol() == Protocol::Http10) { chunk_encoding_ = false; - } else if (connection_.strict1xxAnd204Headers() && (is_1xx_ || is_204_)) { - // For 1xx and 204 responses, do not send the chunked encoding header or enable chunked - // encoding: https://tools.ietf.org/html/rfc7230#section-3.3.1 - chunk_encoding_ = false; - - // Assert 1xx (may have content) OR 204 and end stream. - ASSERT(is_1xx_ || end_stream); } else { // For responses to connect requests, do not send the chunked encoding header: - // https://tools.ietf.org/html/rfc7231#section-4.3.6. + // https://tools.ietf.org/html/rfc7231#section-4.3.6 if (!is_response_to_connect_request_) { encodeFormattedHeader(Headers::get().TransferEncoding.get(), Headers::get().TransferEncodingValues.Chunked); @@ -361,12 +352,14 @@ void ResponseEncoderImpl::encodeHeaders(const ResponseHeaderMap& headers, bool e connection_.addCharToBuffer('\r'); connection_.addCharToBuffer('\n'); - // Enabling handling of https://tools.ietf.org/html/rfc7230#section-3.3.1 and - // https://tools.ietf.org/html/rfc7230#section-3.3.2. Also resets these flags - // if a 100 Continue is followed by another status. - setIs1xx(numeric_status < 200); - setIs204(numeric_status == 204); - + if (numeric_status == 204 || numeric_status < 200) { + // Per https://tools.ietf.org/html/rfc7230#section-3.3.2 + setIsContentLengthAllowed(false); + } else { + // Make sure that if we encodeHeaders(100) then encodeHeaders(200) that we + // set is_content_length_allowed_ back to true. + setIsContentLengthAllowed(true); + } if (numeric_status >= 300) { // Don't do special CONNECT logic if the CONNECT was rejected. is_response_to_connect_request_ = false; @@ -466,8 +459,6 @@ ConnectionImpl::ConnectionImpl(Network::Connection& connection, CodecStats& stat enable_trailers_(enable_trailers), reject_unsupported_transfer_encodings_(Runtime::runtimeFeatureEnabled( "envoy.reloadable_features.reject_unsupported_transfer_encodings")), - strict_1xx_and_204_headers_(Runtime::runtimeFeatureEnabled( - "envoy.reloadable_features.strict_1xx_and_204_response_headers")), output_buffer_([&]() -> void { this->onBelowLowWatermark(); }, [&]() -> void { this->onAboveHighWatermark(); }, []() -> void { /* TODO(adisuissa): Handle overflow watermark */ }), @@ -1087,25 +1078,6 @@ int ClientConnectionImpl::onHeadersComplete() { } } - if (strict_1xx_and_204_headers_ && (parser_.status_code < 200 || parser_.status_code == 204)) { - if (headers->TransferEncoding()) { - sendProtocolError(Http1ResponseCodeDetails::get().TransferEncodingNotAllowed); - throw CodecProtocolException( - "http/1.1 protocol error: transfer encoding not allowed in 1xx or 204"); - } - - if (headers->ContentLength()) { - // Report a protocol error for non-zero Content-Length, but paper over zero Content-Length. - if (headers->ContentLength()->value().getStringView() != "0") { - sendProtocolError(Http1ResponseCodeDetails::get().ContentLengthNotAllowed); - throw CodecProtocolException( - "http/1.1 protocol error: content length not allowed in 1xx or 204"); - } - - headers->removeContentLength(); - } - } - if (parser_.status_code == 100) { // http-parser treats 100 continue headers as their own complete response. // Swallow the spurious onMessageComplete and continue processing. diff --git a/source/common/http/http1/codec_impl.h b/source/common/http/http1/codec_impl.h index 5ebc73b8363d1..dd731982c6c34 100644 --- a/source/common/http/http1/codec_impl.h +++ b/source/common/http/http1/codec_impl.h @@ -95,8 +95,7 @@ class StreamEncoderImpl : public virtual StreamEncoder, protected: StreamEncoderImpl(ConnectionImpl& connection, HeaderKeyFormatter* header_key_formatter); - void setIs1xx(bool value) { is_1xx_ = value; } - void setIs204(bool value) { is_204_ = value; } + void setIsContentLengthAllowed(bool value) { is_content_length_allowed_ = value; } void encodeHeadersBase(const RequestOrResponseHeaderMap& headers, bool end_stream); void encodeTrailersBase(const HeaderMap& headers); @@ -110,8 +109,7 @@ class StreamEncoderImpl : public virtual StreamEncoder, bool processing_100_continue_ : 1; bool is_response_to_head_request_ : 1; bool is_response_to_connect_request_ : 1; - bool is_1xx_ : 1; - bool is_204_ : 1; + bool is_content_length_allowed_ : 1; private: /** @@ -238,8 +236,6 @@ class ConnectionImpl : public virtual Connection, protected Logger::Loggable decoder; - Http::ResponseEncoder* response_encoder = nullptr; - EXPECT_CALL(callbacks_, newStream(_, _)) - .WillOnce(Invoke([&](ResponseEncoder& encoder, bool) -> RequestDecoder& { - response_encoder = &encoder; - return decoder; - })); - - Buffer::OwnedImpl buffer("GET / HTTP/1.1\r\nConnection: upgrade\r\nUpgrade: foo\r\n\r\n"); - auto status = codec_->dispatch(buffer); - EXPECT_TRUE(status.ok()); - EXPECT_EQ(0U, buffer.length()); - - std::string output; - ON_CALL(connection_, write(_, _)).WillByDefault(AddBufferToString(&output)); - - TestResponseHeaderMapImpl headers{{":status", "101"}}; - response_encoder->encodeHeaders(headers, false); - EXPECT_EQ("HTTP/1.1 101 Switching Protocols\r\n\r\n", output); -} - TEST_F(Http1ServerConnectionImplTest, ConnectRequestNoContentLength) { initialize(); @@ -1981,116 +1956,11 @@ TEST_F(Http1ClientConnectionImplTest, 204Response) { request_encoder.encodeHeaders(headers, true); EXPECT_CALL(response_decoder, decodeHeaders_(_, true)); - Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\n\r\n"); + Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nContent-Length: 20\r\n\r\n"); auto status = codec_->dispatch(response); EXPECT_TRUE(status.ok()); } -// 204 No Content with Content-Length is barred by RFC 7230, Section 3.3.2. -TEST_F(Http1ClientConnectionImplTest, 204ResponseContentLengthNotAllowed) { - // By default, content-length is barred. - { - initialize(); - - NiceMock response_decoder; - Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); - TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; - request_encoder.encodeHeaders(headers, true); - - Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nContent-Length: 20\r\n\r\n"); - auto status = codec_->dispatch(response); - EXPECT_FALSE(status.ok()); - } - - // Test with feature disabled: content-length allowed. - { - TestScopedRuntime scoped_runtime; - Runtime::LoaderSingleton::getExisting()->mergeValues( - {{"envoy.reloadable_features.strict_1xx_and_204_response_headers", "false"}}); - - initialize(); - - NiceMock response_decoder; - Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); - TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; - request_encoder.encodeHeaders(headers, true); - - Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nContent-Length: 20\r\n\r\n"); - auto status = codec_->dispatch(response); - EXPECT_TRUE(status.ok()); - } -} - -// 204 No Content with Content-Length: 0 is technically barred by RFC 7230, Section 3.3.2, but we -// allow it. -TEST_F(Http1ClientConnectionImplTest, 204ResponseWithContentLength0) { - { - initialize(); - - NiceMock response_decoder; - Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); - TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; - request_encoder.encodeHeaders(headers, true); - - EXPECT_CALL(response_decoder, decodeHeaders_(_, true)); - Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nContent-Length: 0\r\n\r\n"); - auto status = codec_->dispatch(response); - EXPECT_TRUE(status.ok()); - } - - // Test with feature disabled: content-length allowed. - { - TestScopedRuntime scoped_runtime; - Runtime::LoaderSingleton::getExisting()->mergeValues( - {{"envoy.reloadable_features.strict_1xx_and_204_response_headers", "false"}}); - - NiceMock response_decoder; - Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); - TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; - request_encoder.encodeHeaders(headers, true); - - EXPECT_CALL(response_decoder, decodeHeaders_(_, true)); - Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nContent-Length: 0\r\n\r\n"); - auto status = codec_->dispatch(response); - EXPECT_TRUE(status.ok()); - } -} - -// 204 No Content with Transfer-Encoding headers is barred by RFC 7230, Section 3.3.1. -TEST_F(Http1ClientConnectionImplTest, 204ResponseTransferEncodingNotAllowed) { - // By default, transfer-encoding is barred. - { - initialize(); - - NiceMock response_decoder; - Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); - TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; - request_encoder.encodeHeaders(headers, true); - - Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); - auto status = codec_->dispatch(response); - EXPECT_FALSE(status.ok()); - } - - // Test with feature disabled: transfer-encoding allowed. - { - TestScopedRuntime scoped_runtime; - Runtime::LoaderSingleton::getExisting()->mergeValues( - {{"envoy.reloadable_features.strict_1xx_and_204_response_headers", "false"}}); - - initialize(); - - NiceMock response_decoder; - Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); - TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; - request_encoder.encodeHeaders(headers, true); - - Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); - auto status = codec_->dispatch(response); - EXPECT_TRUE(status.ok()); - } -} - TEST_F(Http1ClientConnectionImplTest, 100Response) { initialize(); @@ -2106,48 +1976,11 @@ TEST_F(Http1ClientConnectionImplTest, 100Response) { EXPECT_CALL(response_decoder, decodeHeaders_(_, false)); EXPECT_CALL(response_decoder, decodeData(_, _)).Times(0); - Buffer::OwnedImpl response("HTTP/1.1 200 OK\r\n\r\n"); + Buffer::OwnedImpl response("HTTP/1.1 200 OK\r\nContent-Length: 20\r\n\r\n"); status = codec_->dispatch(response); EXPECT_TRUE(status.ok()); } -// 101 Switching Protocol with Transfer-Encoding headers is barred by RFC 7230, Section 3.3.1. -TEST_F(Http1ClientConnectionImplTest, 101ResponseTransferEncodingNotAllowed) { - // By default, transfer-encoding is barred. - { - initialize(); - - NiceMock response_decoder; - Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); - TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; - request_encoder.encodeHeaders(headers, true); - - Buffer::OwnedImpl response( - "HTTP/1.1 101 Switching Protocols\r\nTransfer-Encoding: chunked\r\n\r\n"); - auto status = codec_->dispatch(response); - EXPECT_FALSE(status.ok()); - } - - // Test with feature disabled: transfer-encoding allowed. - { - TestScopedRuntime scoped_runtime; - Runtime::LoaderSingleton::getExisting()->mergeValues( - {{"envoy.reloadable_features.strict_1xx_and_204_response_headers", "false"}}); - - initialize(); - - NiceMock response_decoder; - Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); - TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; - request_encoder.encodeHeaders(headers, true); - - Buffer::OwnedImpl response( - "HTTP/1.1 101 Switching Protocols\r\nTransfer-Encoding: chunked\r\n\r\n"); - auto status = codec_->dispatch(response); - EXPECT_TRUE(status.ok()); - } -} - TEST_F(Http1ClientConnectionImplTest, BadEncodeParams) { initialize(); diff --git a/test/integration/websocket_integration_test.cc b/test/integration/websocket_integration_test.cc index a7e92f4bca6f2..195eb2ce0bdb2 100644 --- a/test/integration/websocket_integration_test.cc +++ b/test/integration/websocket_integration_test.cc @@ -100,8 +100,6 @@ void WebsocketIntegrationTest::validateUpgradeResponseHeaders( proxied_response_headers.removeDate(); proxied_response_headers.removeServer(); - ASSERT_TRUE(proxied_response_headers.TransferEncoding() == nullptr); - commonValidate(proxied_response_headers, original_response_headers); EXPECT_THAT(&proxied_response_headers, HeaderMapEqualIgnoreOrder(&original_response_headers)); @@ -421,6 +419,9 @@ TEST_P(WebsocketIntegrationTest, BidirectionalChunkedData) { if (upstreamProtocol() == FakeHttpConnection::Type::HTTP1) { ASSERT_TRUE(upstream_request_->headers().TransferEncoding() != nullptr); } + if (downstreamProtocol() == Http::CodecClient::Type::HTTP1) { + ASSERT_TRUE(response_->headers().TransferEncoding() != nullptr); + } // Send both a chunked request body and "websocket" payload. std::string request_payload = "3\r\n123\r\n0\r\n\r\nSomeWebsocketRequestPayload"; From 508af807fe5bda3f210a3ebb1242d6690e2b01ed Mon Sep 17 00:00:00 2001 From: davidraskin Date: Fri, 19 Jun 2020 22:29:58 +0000 Subject: [PATCH 06/39] Made proto changes. TODO: Update documentation Signed-off-by: davidraskin --- api/envoy/config/rbac/v3/rbac.proto | 20 ++++++++++++++++---- api/envoy/config/rbac/v4alpha/rbac.proto | 22 +++++++++++++++++----- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/api/envoy/config/rbac/v3/rbac.proto b/api/envoy/config/rbac/v3/rbac.proto index 79d8f7126e5dd..593a8efa70f46 100644 --- a/api/envoy/config/rbac/v3/rbac.proto +++ b/api/envoy/config/rbac/v3/rbac.proto @@ -66,21 +66,33 @@ message RBAC { // Should we do safe-list or block-list style access control? enum Action { - // The policies grant access to principals. The rest is denied. This is safe-list style + // The policies grant access to principals. The rest are denied. This is safe-list style // access control. This is the default type. ALLOW = 0; - // The policies deny access to principals. The rest is allowed. This is block-list style + // The policies deny access to principals. The rest are allowed. This is block-list style // access control. DENY = 1; +<<<<<<< HEAD +======= + // The policies log requests from principals. The rest are not logged. +>>>>>>> ac6f801a2... Made proto changes. TODO: Update documentation LOG = 2; } - // The action to take if a policy matches. The request is allowed if and only if: + // The action to take if a policy matches. + // The request is allowed if and only if: // - // * `action` is "ALLOWED" and at least one policy matches + // * `action` is "ALLOW" and at least one policy matches // * `action` is "DENY" and none of the policies match + // * `action` is "LOG" + // + // The request is logged if and only if: + // + // * `action` is "ALLOW" + // * `action` is "DENY" + // * `action` is "LOG" and at least one policy matches Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. diff --git a/api/envoy/config/rbac/v4alpha/rbac.proto b/api/envoy/config/rbac/v4alpha/rbac.proto index ba9da06908c29..04dc7a26fc765 100644 --- a/api/envoy/config/rbac/v4alpha/rbac.proto +++ b/api/envoy/config/rbac/v4alpha/rbac.proto @@ -66,22 +66,34 @@ message RBAC { // Should we do safe-list or block-list style access control? enum Action { - // The policies grant access to principals. The rest is denied. This is safe-list style + // The policies grant access to principals. The rest are denied. This is safe-list style // access control. This is the default type. ALLOW = 0; - // The policies deny access to principals. The rest is allowed. This is block-list style + // The policies deny access to principals. The rest are allowed. This is block-list style // access control. DENY = 1; +<<<<<<< HEAD +======= + // The policies log requests from principals. The rest are not logged. +>>>>>>> ac6f801a2... Made proto changes. TODO: Update documentation LOG = 2; } - // The action to take if a policy matches. The request is allowed if and only if: + // The action to take if a policy matches. + // The request is allowed if and only if: // - // * `action` is "ALLOWED" and at least one policy matches + // * `action` is "ALLOW" and at least one policy matches // * `action` is "DENY" and none of the policies match - Action action = 1; + // * `action` is "LOG" + // + // The request is logged if and only if: + // + // * `action` is "ALLOW" + // * `action` is "DENY" + // * `action` is "LOG" and at least one policy matches + Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; From df2b5edca236cfd03bc5e714cd35297b7e73c468 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 23 Jun 2020 02:55:27 +0000 Subject: [PATCH 07/39] Updated documentation Signed-off-by: davidraskin --- api/envoy/config/rbac/v3/rbac.proto | 13 ++++--------- .../configuration/http/http_filters/rbac_filter.rst | 1 + .../listeners/network_filters/rbac_filter.rst | 1 + 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/api/envoy/config/rbac/v3/rbac.proto b/api/envoy/config/rbac/v3/rbac.proto index 593a8efa70f46..489e8df4cd0f2 100644 --- a/api/envoy/config/rbac/v3/rbac.proto +++ b/api/envoy/config/rbac/v3/rbac.proto @@ -74,10 +74,7 @@ message RBAC { // access control. DENY = 1; -<<<<<<< HEAD -======= - // The policies log requests from principals. The rest are not logged. ->>>>>>> ac6f801a2... Made proto changes. TODO: Update documentation + // The policies set the "envoy.log" dynamic metadata key based on if requests match LOG = 2; } @@ -87,12 +84,10 @@ message RBAC { // * `action` is "ALLOW" and at least one policy matches // * `action` is "DENY" and none of the policies match // * `action` is "LOG" - // - // The request is logged if and only if: // - // * `action` is "ALLOW" - // * `action` is "DENY" - // * `action` is "LOG" and at least one policy matches + // If the action is "LOG" and at least one policy matches, or if the action is not "LOG", + // the dynamic metadata key `envoy.log` is set to the value "yes". + // Otherwise, it is set to "no". Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. diff --git a/docs/root/configuration/http/http_filters/rbac_filter.rst b/docs/root/configuration/http/http_filters/rbac_filter.rst index d6068bbdcc6c4..599e2c2fe899b 100644 --- a/docs/root/configuration/http/http_filters/rbac_filter.rst +++ b/docs/root/configuration/http/http_filters/rbac_filter.rst @@ -50,3 +50,4 @@ The RBAC filter emits the following dynamic metadata. shadow_effective_policy_id, string, The effective shadow policy ID matching the action (if any). shadow_engine_result, string, The engine result for the shadow rules (i.e. either `allowed` or `denied`). + envoy.log, string, Whether the request should be logged (i.e. either `yes` or `no`). diff --git a/docs/root/configuration/listeners/network_filters/rbac_filter.rst b/docs/root/configuration/listeners/network_filters/rbac_filter.rst index d074174920458..bbefec310985b 100644 --- a/docs/root/configuration/listeners/network_filters/rbac_filter.rst +++ b/docs/root/configuration/listeners/network_filters/rbac_filter.rst @@ -40,3 +40,4 @@ The RBAC filter emits the following dynamic metadata. shadow_effective_policy_id, string, The effective shadow policy ID matching the action (if any). shadow_engine_result, string, The engine result for the shadow rules (i.e. either `allowed` or `denied`). + envoy.log, string, Whether the request should be logged (i.e. either `yes` or `no`). From 43a000b00f3eb51a5bd783d53eee3d3baee5e218 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 23 Jun 2020 03:37:05 +0000 Subject: [PATCH 08/39] Updated v4alpha and api_shadow rbac protos Signed-off-by: davidraskin --- api/envoy/config/rbac/v3/rbac.proto | 4 ++-- api/envoy/config/rbac/v4alpha/rbac.proto | 17 ++++++----------- .../envoy/config/rbac/v3/rbac.proto | 15 +++++++++++---- .../envoy/config/rbac/v4alpha/rbac.proto | 15 +++++++++++---- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/api/envoy/config/rbac/v3/rbac.proto b/api/envoy/config/rbac/v3/rbac.proto index 489e8df4cd0f2..f666ac9c1203d 100644 --- a/api/envoy/config/rbac/v3/rbac.proto +++ b/api/envoy/config/rbac/v3/rbac.proto @@ -78,14 +78,14 @@ message RBAC { LOG = 2; } - // The action to take if a policy matches. + // The action to take if a policy matches. // The request is allowed if and only if: // // * `action` is "ALLOW" and at least one policy matches // * `action` is "DENY" and none of the policies match // * `action` is "LOG" // - // If the action is "LOG" and at least one policy matches, or if the action is not "LOG", + // If the action is "LOG" and at least one policy matches, or if the action is not "LOG", // the dynamic metadata key `envoy.log` is set to the value "yes". // Otherwise, it is set to "no". Action action = 1; diff --git a/api/envoy/config/rbac/v4alpha/rbac.proto b/api/envoy/config/rbac/v4alpha/rbac.proto index 04dc7a26fc765..4e8fc58705566 100644 --- a/api/envoy/config/rbac/v4alpha/rbac.proto +++ b/api/envoy/config/rbac/v4alpha/rbac.proto @@ -74,26 +74,21 @@ message RBAC { // access control. DENY = 1; -<<<<<<< HEAD -======= - // The policies log requests from principals. The rest are not logged. ->>>>>>> ac6f801a2... Made proto changes. TODO: Update documentation + // The policies set the "envoy.log" dynamic metadata key based on if requests match LOG = 2; } - // The action to take if a policy matches. + // The action to take if a policy matches. // The request is allowed if and only if: // // * `action` is "ALLOW" and at least one policy matches // * `action` is "DENY" and none of the policies match // * `action` is "LOG" - // - // The request is logged if and only if: // - // * `action` is "ALLOW" - // * `action` is "DENY" - // * `action` is "LOG" and at least one policy matches - Action action = 1; + // If the action is "LOG" and at least one policy matches, or if the action is not "LOG", + // the dynamic metadata key `envoy.log` is set to the value "yes". + // Otherwise, it is set to "no". + Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; diff --git a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto index 79d8f7126e5dd..f666ac9c1203d 100644 --- a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto @@ -66,21 +66,28 @@ message RBAC { // Should we do safe-list or block-list style access control? enum Action { - // The policies grant access to principals. The rest is denied. This is safe-list style + // The policies grant access to principals. The rest are denied. This is safe-list style // access control. This is the default type. ALLOW = 0; - // The policies deny access to principals. The rest is allowed. This is block-list style + // The policies deny access to principals. The rest are allowed. This is block-list style // access control. DENY = 1; + // The policies set the "envoy.log" dynamic metadata key based on if requests match LOG = 2; } - // The action to take if a policy matches. The request is allowed if and only if: + // The action to take if a policy matches. + // The request is allowed if and only if: // - // * `action` is "ALLOWED" and at least one policy matches + // * `action` is "ALLOW" and at least one policy matches // * `action` is "DENY" and none of the policies match + // * `action` is "LOG" + // + // If the action is "LOG" and at least one policy matches, or if the action is not "LOG", + // the dynamic metadata key `envoy.log` is set to the value "yes". + // Otherwise, it is set to "no". Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. diff --git a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto index a700ef4fd88ce..636c19cbc7911 100644 --- a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto @@ -66,21 +66,28 @@ message RBAC { // Should we do safe-list or block-list style access control? enum Action { - // The policies grant access to principals. The rest is denied. This is safe-list style + // The policies grant access to principals. The rest are denied. This is safe-list style // access control. This is the default type. ALLOW = 0; - // The policies deny access to principals. The rest is allowed. This is block-list style + // The policies deny access to principals. The rest are allowed. This is block-list style // access control. DENY = 1; + // The policies set the "envoy.log" dynamic metadata key based on if requests match LOG = 2; } - // The action to take if a policy matches. The request is allowed if and only if: + // The action to take if a policy matches. + // The request is allowed if and only if: // - // * `action` is "ALLOWED" and at least one policy matches + // * `action` is "ALLOW" and at least one policy matches // * `action` is "DENY" and none of the policies match + // * `action` is "LOG" + // + // If the action is "LOG" and at least one policy matches, or if the action is not "LOG", + // the dynamic metadata key `envoy.log` is set to the value "yes". + // Otherwise, it is set to "no". Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. From ea5f6a5ac0c09089e23c7cddf23afeb7eaa58827 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 23 Jun 2020 03:56:40 +0000 Subject: [PATCH 09/39] Revert "Revert "http1: do not add transfer-encoding: chunked to 1xx/204 responses (#11458)"" This reverts commit c3e9321fa65ce3b2ff52c9040a01cc8e04a796b9. Signed-off-by: davidraskin --- source/common/http/http1/codec_impl.cc | 50 +++-- source/common/http/http1/codec_impl.h | 9 +- source/common/runtime/runtime_features.cc | 3 +- test/common/http/http1/codec_impl_test.cc | 171 +++++++++++++++++- .../integration/websocket_integration_test.cc | 5 +- 5 files changed, 219 insertions(+), 19 deletions(-) diff --git a/source/common/http/http1/codec_impl.cc b/source/common/http/http1/codec_impl.cc index f3072449a813a..7fe0a62590924 100644 --- a/source/common/http/http1/codec_impl.cc +++ b/source/common/http/http1/codec_impl.cc @@ -35,6 +35,8 @@ struct Http1ResponseCodeDetailValues { const absl::string_view InvalidUrl = "http1.invalid_url"; const absl::string_view InvalidTransferEncoding = "http1.invalid_transfer_encoding"; const absl::string_view BodyDisallowed = "http1.body_disallowed"; + const absl::string_view TransferEncodingNotAllowed = "http1.transfer_encoding_not_allowed"; + const absl::string_view ContentLengthNotAllowed = "http1.content_length_not_allowed"; }; struct Http1HeaderTypesValues { @@ -69,7 +71,7 @@ StreamEncoderImpl::StreamEncoderImpl(ConnectionImpl& connection, HeaderKeyFormatter* header_key_formatter) : connection_(connection), disable_chunk_encoding_(false), chunk_encoding_(true), processing_100_continue_(false), is_response_to_head_request_(false), - is_response_to_connect_request_(false), is_content_length_allowed_(true), + is_response_to_connect_request_(false), is_1xx_(false), is_204_(false), header_key_formatter_(header_key_formatter) { if (connection_.connection().aboveHighWatermark()) { runHighWatermarkCallbacks(); @@ -159,15 +161,22 @@ void StreamEncoderImpl::encodeHeadersBase(const RequestOrResponseHeaderMap& head // response to a HEAD request. // For 204s and 1xx where content length is disallowed, don't append the content length but // also don't chunk encode. - if (is_content_length_allowed_) { + if (!is_1xx_ && !is_204_) { encodeFormattedHeader(Headers::get().ContentLength.get(), "0"); } chunk_encoding_ = false; } else if (connection_.protocol() == Protocol::Http10) { chunk_encoding_ = false; + } else if (connection_.strict1xxAnd204Headers() && (is_1xx_ || is_204_)) { + // For 1xx and 204 responses, do not send the chunked encoding header or enable chunked + // encoding: https://tools.ietf.org/html/rfc7230#section-3.3.1 + chunk_encoding_ = false; + + // Assert 1xx (may have content) OR 204 and end stream. + ASSERT(is_1xx_ || end_stream); } else { // For responses to connect requests, do not send the chunked encoding header: - // https://tools.ietf.org/html/rfc7231#section-4.3.6 + // https://tools.ietf.org/html/rfc7231#section-4.3.6. if (!is_response_to_connect_request_) { encodeFormattedHeader(Headers::get().TransferEncoding.get(), Headers::get().TransferEncodingValues.Chunked); @@ -352,14 +361,12 @@ void ResponseEncoderImpl::encodeHeaders(const ResponseHeaderMap& headers, bool e connection_.addCharToBuffer('\r'); connection_.addCharToBuffer('\n'); - if (numeric_status == 204 || numeric_status < 200) { - // Per https://tools.ietf.org/html/rfc7230#section-3.3.2 - setIsContentLengthAllowed(false); - } else { - // Make sure that if we encodeHeaders(100) then encodeHeaders(200) that we - // set is_content_length_allowed_ back to true. - setIsContentLengthAllowed(true); - } + // Enabling handling of https://tools.ietf.org/html/rfc7230#section-3.3.1 and + // https://tools.ietf.org/html/rfc7230#section-3.3.2. Also resets these flags + // if a 100 Continue is followed by another status. + setIs1xx(numeric_status < 200); + setIs204(numeric_status == 204); + if (numeric_status >= 300) { // Don't do special CONNECT logic if the CONNECT was rejected. is_response_to_connect_request_ = false; @@ -459,6 +466,8 @@ ConnectionImpl::ConnectionImpl(Network::Connection& connection, CodecStats& stat enable_trailers_(enable_trailers), reject_unsupported_transfer_encodings_(Runtime::runtimeFeatureEnabled( "envoy.reloadable_features.reject_unsupported_transfer_encodings")), + strict_1xx_and_204_headers_(Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.strict_1xx_and_204_response_headers")), output_buffer_([&]() -> void { this->onBelowLowWatermark(); }, [&]() -> void { this->onAboveHighWatermark(); }, []() -> void { /* TODO(adisuissa): Handle overflow watermark */ }), @@ -1078,6 +1087,25 @@ int ClientConnectionImpl::onHeadersComplete() { } } + if (strict_1xx_and_204_headers_ && (parser_.status_code < 200 || parser_.status_code == 204)) { + if (headers->TransferEncoding()) { + sendProtocolError(Http1ResponseCodeDetails::get().TransferEncodingNotAllowed); + throw CodecProtocolException( + "http/1.1 protocol error: transfer encoding not allowed in 1xx or 204"); + } + + if (headers->ContentLength()) { + // Report a protocol error for non-zero Content-Length, but paper over zero Content-Length. + if (headers->ContentLength()->value().getStringView() != "0") { + sendProtocolError(Http1ResponseCodeDetails::get().ContentLengthNotAllowed); + throw CodecProtocolException( + "http/1.1 protocol error: content length not allowed in 1xx or 204"); + } + + headers->removeContentLength(); + } + } + if (parser_.status_code == 100) { // http-parser treats 100 continue headers as their own complete response. // Swallow the spurious onMessageComplete and continue processing. diff --git a/source/common/http/http1/codec_impl.h b/source/common/http/http1/codec_impl.h index dd731982c6c34..5ebc73b8363d1 100644 --- a/source/common/http/http1/codec_impl.h +++ b/source/common/http/http1/codec_impl.h @@ -95,7 +95,8 @@ class StreamEncoderImpl : public virtual StreamEncoder, protected: StreamEncoderImpl(ConnectionImpl& connection, HeaderKeyFormatter* header_key_formatter); - void setIsContentLengthAllowed(bool value) { is_content_length_allowed_ = value; } + void setIs1xx(bool value) { is_1xx_ = value; } + void setIs204(bool value) { is_204_ = value; } void encodeHeadersBase(const RequestOrResponseHeaderMap& headers, bool end_stream); void encodeTrailersBase(const HeaderMap& headers); @@ -109,7 +110,8 @@ class StreamEncoderImpl : public virtual StreamEncoder, bool processing_100_continue_ : 1; bool is_response_to_head_request_ : 1; bool is_response_to_connect_request_ : 1; - bool is_content_length_allowed_ : 1; + bool is_1xx_ : 1; + bool is_204_ : 1; private: /** @@ -236,6 +238,8 @@ class ConnectionImpl : public virtual Connection, protected Logger::Loggable decoder; + Http::ResponseEncoder* response_encoder = nullptr; + EXPECT_CALL(callbacks_, newStream(_, _)) + .WillOnce(Invoke([&](ResponseEncoder& encoder, bool) -> RequestDecoder& { + response_encoder = &encoder; + return decoder; + })); + + Buffer::OwnedImpl buffer("GET / HTTP/1.1\r\nConnection: upgrade\r\nUpgrade: foo\r\n\r\n"); + auto status = codec_->dispatch(buffer); + EXPECT_TRUE(status.ok()); + EXPECT_EQ(0U, buffer.length()); + + std::string output; + ON_CALL(connection_, write(_, _)).WillByDefault(AddBufferToString(&output)); + + TestResponseHeaderMapImpl headers{{":status", "101"}}; + response_encoder->encodeHeaders(headers, false); + EXPECT_EQ("HTTP/1.1 101 Switching Protocols\r\n\r\n", output); +} + TEST_F(Http1ServerConnectionImplTest, ConnectRequestNoContentLength) { initialize(); @@ -1956,11 +1981,116 @@ TEST_F(Http1ClientConnectionImplTest, 204Response) { request_encoder.encodeHeaders(headers, true); EXPECT_CALL(response_decoder, decodeHeaders_(_, true)); - Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nContent-Length: 20\r\n\r\n"); + Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\n\r\n"); auto status = codec_->dispatch(response); EXPECT_TRUE(status.ok()); } +// 204 No Content with Content-Length is barred by RFC 7230, Section 3.3.2. +TEST_F(Http1ClientConnectionImplTest, 204ResponseContentLengthNotAllowed) { + // By default, content-length is barred. + { + initialize(); + + NiceMock response_decoder; + Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); + TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; + request_encoder.encodeHeaders(headers, true); + + Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nContent-Length: 20\r\n\r\n"); + auto status = codec_->dispatch(response); + EXPECT_FALSE(status.ok()); + } + + // Test with feature disabled: content-length allowed. + { + TestScopedRuntime scoped_runtime; + Runtime::LoaderSingleton::getExisting()->mergeValues( + {{"envoy.reloadable_features.strict_1xx_and_204_response_headers", "false"}}); + + initialize(); + + NiceMock response_decoder; + Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); + TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; + request_encoder.encodeHeaders(headers, true); + + Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nContent-Length: 20\r\n\r\n"); + auto status = codec_->dispatch(response); + EXPECT_TRUE(status.ok()); + } +} + +// 204 No Content with Content-Length: 0 is technically barred by RFC 7230, Section 3.3.2, but we +// allow it. +TEST_F(Http1ClientConnectionImplTest, 204ResponseWithContentLength0) { + { + initialize(); + + NiceMock response_decoder; + Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); + TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; + request_encoder.encodeHeaders(headers, true); + + EXPECT_CALL(response_decoder, decodeHeaders_(_, true)); + Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nContent-Length: 0\r\n\r\n"); + auto status = codec_->dispatch(response); + EXPECT_TRUE(status.ok()); + } + + // Test with feature disabled: content-length allowed. + { + TestScopedRuntime scoped_runtime; + Runtime::LoaderSingleton::getExisting()->mergeValues( + {{"envoy.reloadable_features.strict_1xx_and_204_response_headers", "false"}}); + + NiceMock response_decoder; + Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); + TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; + request_encoder.encodeHeaders(headers, true); + + EXPECT_CALL(response_decoder, decodeHeaders_(_, true)); + Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nContent-Length: 0\r\n\r\n"); + auto status = codec_->dispatch(response); + EXPECT_TRUE(status.ok()); + } +} + +// 204 No Content with Transfer-Encoding headers is barred by RFC 7230, Section 3.3.1. +TEST_F(Http1ClientConnectionImplTest, 204ResponseTransferEncodingNotAllowed) { + // By default, transfer-encoding is barred. + { + initialize(); + + NiceMock response_decoder; + Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); + TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; + request_encoder.encodeHeaders(headers, true); + + Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); + auto status = codec_->dispatch(response); + EXPECT_FALSE(status.ok()); + } + + // Test with feature disabled: transfer-encoding allowed. + { + TestScopedRuntime scoped_runtime; + Runtime::LoaderSingleton::getExisting()->mergeValues( + {{"envoy.reloadable_features.strict_1xx_and_204_response_headers", "false"}}); + + initialize(); + + NiceMock response_decoder; + Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); + TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; + request_encoder.encodeHeaders(headers, true); + + Buffer::OwnedImpl response("HTTP/1.1 204 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); + auto status = codec_->dispatch(response); + EXPECT_TRUE(status.ok()); + } +} + TEST_F(Http1ClientConnectionImplTest, 100Response) { initialize(); @@ -1976,11 +2106,48 @@ TEST_F(Http1ClientConnectionImplTest, 100Response) { EXPECT_CALL(response_decoder, decodeHeaders_(_, false)); EXPECT_CALL(response_decoder, decodeData(_, _)).Times(0); - Buffer::OwnedImpl response("HTTP/1.1 200 OK\r\nContent-Length: 20\r\n\r\n"); + Buffer::OwnedImpl response("HTTP/1.1 200 OK\r\n\r\n"); status = codec_->dispatch(response); EXPECT_TRUE(status.ok()); } +// 101 Switching Protocol with Transfer-Encoding headers is barred by RFC 7230, Section 3.3.1. +TEST_F(Http1ClientConnectionImplTest, 101ResponseTransferEncodingNotAllowed) { + // By default, transfer-encoding is barred. + { + initialize(); + + NiceMock response_decoder; + Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); + TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; + request_encoder.encodeHeaders(headers, true); + + Buffer::OwnedImpl response( + "HTTP/1.1 101 Switching Protocols\r\nTransfer-Encoding: chunked\r\n\r\n"); + auto status = codec_->dispatch(response); + EXPECT_FALSE(status.ok()); + } + + // Test with feature disabled: transfer-encoding allowed. + { + TestScopedRuntime scoped_runtime; + Runtime::LoaderSingleton::getExisting()->mergeValues( + {{"envoy.reloadable_features.strict_1xx_and_204_response_headers", "false"}}); + + initialize(); + + NiceMock response_decoder; + Http::RequestEncoder& request_encoder = codec_->newStream(response_decoder); + TestRequestHeaderMapImpl headers{{":method", "GET"}, {":path", "/"}, {":authority", "host"}}; + request_encoder.encodeHeaders(headers, true); + + Buffer::OwnedImpl response( + "HTTP/1.1 101 Switching Protocols\r\nTransfer-Encoding: chunked\r\n\r\n"); + auto status = codec_->dispatch(response); + EXPECT_TRUE(status.ok()); + } +} + TEST_F(Http1ClientConnectionImplTest, BadEncodeParams) { initialize(); diff --git a/test/integration/websocket_integration_test.cc b/test/integration/websocket_integration_test.cc index 195eb2ce0bdb2..a7e92f4bca6f2 100644 --- a/test/integration/websocket_integration_test.cc +++ b/test/integration/websocket_integration_test.cc @@ -100,6 +100,8 @@ void WebsocketIntegrationTest::validateUpgradeResponseHeaders( proxied_response_headers.removeDate(); proxied_response_headers.removeServer(); + ASSERT_TRUE(proxied_response_headers.TransferEncoding() == nullptr); + commonValidate(proxied_response_headers, original_response_headers); EXPECT_THAT(&proxied_response_headers, HeaderMapEqualIgnoreOrder(&original_response_headers)); @@ -419,9 +421,6 @@ TEST_P(WebsocketIntegrationTest, BidirectionalChunkedData) { if (upstreamProtocol() == FakeHttpConnection::Type::HTTP1) { ASSERT_TRUE(upstream_request_->headers().TransferEncoding() != nullptr); } - if (downstreamProtocol() == Http::CodecClient::Type::HTTP1) { - ASSERT_TRUE(response_->headers().TransferEncoding() != nullptr); - } // Send both a chunked request body and "websocket" payload. std::string request_payload = "3\r\n123\r\n0\r\n\r\nSomeWebsocketRequestPayload"; From 79baea85dfa38b79a5575de53f501bfa393224fc Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 7 Jul 2020 16:42:41 +0000 Subject: [PATCH 10/39] Added documentation for shared dynamic metadata, access_loc_policy Signed-off-by: davidraskin --- api/envoy/config/rbac/v3/rbac.proto | 16 ++++++++++------ .../advanced/well_known_dynamic_metadata.rst | 17 +++++++++++++++++ .../http/http_filters/rbac_filter.rst | 4 +++- .../listeners/network_filters/rbac_filter.rst | 4 +++- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/api/envoy/config/rbac/v3/rbac.proto b/api/envoy/config/rbac/v3/rbac.proto index f666ac9c1203d..b5331c6ed2684 100644 --- a/api/envoy/config/rbac/v3/rbac.proto +++ b/api/envoy/config/rbac/v3/rbac.proto @@ -22,8 +22,13 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Role Based Access Control (RBAC)] // Role Based Access Control (RBAC) provides service-level and method-level access control for a -// service. RBAC policies are additive. The policies are examined in order. A request is allowed -// once a matching policy is found (suppose the `action` is ALLOW). +// service. RBAC policies are additive. The policies are examined in order. Requests are allowed +// or denied based on the `action` and whether a matching policy is found. For instance, if the +// action is ALLOW and a matching policy is found the request should be allowed. +// +// RBAC can also be used to make access logging decisions by communicating with access loggers +// through dynamic metadata. When the action is LOG, and at least one policy matches, the +// `access_log_policy` value is set to `true` indicating the request should be logged. // // Here is an example of RBAC configuration. It has two policies: // @@ -74,7 +79,7 @@ message RBAC { // access control. DENY = 1; - // The policies set the "envoy.log" dynamic metadata key based on if requests match + // The policies set the `access_log_policy` dynamic metadata key based on if requests match LOG = 2; } @@ -85,9 +90,8 @@ message RBAC { // * `action` is "DENY" and none of the policies match // * `action` is "LOG" // - // If the action is "LOG" and at least one policy matches, or if the action is not "LOG", - // the dynamic metadata key `envoy.log` is set to the value "yes". - // Otherwise, it is set to "no". + // If the action is LOG and at least one policy matches, or if the action is not LOG, the + // dynamic metadata key `access_log_policy` is set to the value `true`. Otherwise, it is set to `false`. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. diff --git a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst index 73215617e46db..24be022accebb 100644 --- a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst +++ b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst @@ -18,3 +18,20 @@ The following Envoy filters emit dynamic metadata that other filters can leverag * :ref:`Role Based Access Control (RBAC) Filter ` * :ref:`Role Based Access Control (RBAC) Network Filter ` * :ref:`ZooKeeper Proxy Filter ` + +.. _shared_dynamic_metadata: + +Shared Dynamic Metadata +----------------------- +Dynamic metadata that is set by multiple filters is placed in the common key namespace `envoy.common`. Refer to the corresponding rules when setting this metadata. + +.. csv-table:: + :header: Name, Type, Description, Rules + :widths: 1, 1, 3, 3 + + access_log_policy, boolean, Whether access loggers should log the request., "When this metadata is already set: A `true` value should not be overwritten by a `false` value, while a `false` value can be overwritten by a `true` value." + +The following Envoy filters emit shared dynamic metadata. + +* :ref:`Role Based Access Control (RBAC) Filter ` +* :ref:`Role Based Access Control (RBAC) Network Filter ` \ No newline at end of file diff --git a/docs/root/configuration/http/http_filters/rbac_filter.rst b/docs/root/configuration/http/http_filters/rbac_filter.rst index 599e2c2fe899b..b24e30d059595 100644 --- a/docs/root/configuration/http/http_filters/rbac_filter.rst +++ b/docs/root/configuration/http/http_filters/rbac_filter.rst @@ -36,6 +36,8 @@ owning HTTP connection manager. denied, Counter, Total requests that were denied access shadow_allowed, Counter, Total requests that would be allowed access by the filter's shadow rules shadow_denied, Counter, Total requests that would be denied access by the filter's shadow rules + logged, Counter, Total requests that should be logged + not_logged, Counter, Total requests that should not be logged .. _config_http_filters_rbac_dynamic_metadata: @@ -50,4 +52,4 @@ The RBAC filter emits the following dynamic metadata. shadow_effective_policy_id, string, The effective shadow policy ID matching the action (if any). shadow_engine_result, string, The engine result for the shadow rules (i.e. either `allowed` or `denied`). - envoy.log, string, Whether the request should be logged (i.e. either `yes` or `no`). + access_log_policy, boolean, Whether the request should be logged. This metadata is shared (See :ref:`Shared Dynamic Metadata`). diff --git a/docs/root/configuration/listeners/network_filters/rbac_filter.rst b/docs/root/configuration/listeners/network_filters/rbac_filter.rst index bbefec310985b..d0717d3758934 100644 --- a/docs/root/configuration/listeners/network_filters/rbac_filter.rst +++ b/docs/root/configuration/listeners/network_filters/rbac_filter.rst @@ -26,6 +26,8 @@ The RBAC network filter outputs statistics in the *.rbac.* namespac denied, Counter, Total requests that were denied access shadow_allowed, Counter, Total requests that would be allowed access by the filter's shadow rules shadow_denied, Counter, Total requests that would be denied access by the filter's shadow rules + logged, Counter, Total requests that should be logged + not_logged, Counter, Total requests that should not be logged .. _config_network_filters_rbac_dynamic_metadata: @@ -40,4 +42,4 @@ The RBAC filter emits the following dynamic metadata. shadow_effective_policy_id, string, The effective shadow policy ID matching the action (if any). shadow_engine_result, string, The engine result for the shadow rules (i.e. either `allowed` or `denied`). - envoy.log, string, Whether the request should be logged (i.e. either `yes` or `no`). + access_log_policy, boolean, Whether the request should be logged. This metadata is shared (See :ref:`Shared Dynamic Metadata`). From 3c3457f8340d8d0c3215e777e3df4bd0180c71d9 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 7 Jul 2020 17:15:08 +0000 Subject: [PATCH 11/39] Updated v4alpha and shadow apis Signed-off-by: davidraskin --- api/envoy/config/rbac/v3/rbac.proto | 5 +++-- api/envoy/config/rbac/v4alpha/rbac.proto | 17 +++++++++++------ .../envoy/config/rbac/v3/rbac.proto | 17 +++++++++++------ .../envoy/config/rbac/v4alpha/rbac.proto | 17 +++++++++++------ 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/api/envoy/config/rbac/v3/rbac.proto b/api/envoy/config/rbac/v3/rbac.proto index b5331c6ed2684..2716961e22283 100644 --- a/api/envoy/config/rbac/v3/rbac.proto +++ b/api/envoy/config/rbac/v3/rbac.proto @@ -90,8 +90,9 @@ message RBAC { // * `action` is "DENY" and none of the policies match // * `action` is "LOG" // - // If the action is LOG and at least one policy matches, or if the action is not LOG, the - // dynamic metadata key `access_log_policy` is set to the value `true`. Otherwise, it is set to `false`. + // If the action is LOG and at least one policy matches the dynamic metadata key `access_log_policy` + // is set to the value `true`. If no policies match, it is set to `false`. + // Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. diff --git a/api/envoy/config/rbac/v4alpha/rbac.proto b/api/envoy/config/rbac/v4alpha/rbac.proto index 4e8fc58705566..e9cdc32ef378f 100644 --- a/api/envoy/config/rbac/v4alpha/rbac.proto +++ b/api/envoy/config/rbac/v4alpha/rbac.proto @@ -22,8 +22,13 @@ option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSIO // [#protodoc-title: Role Based Access Control (RBAC)] // Role Based Access Control (RBAC) provides service-level and method-level access control for a -// service. RBAC policies are additive. The policies are examined in order. A request is allowed -// once a matching policy is found (suppose the `action` is ALLOW). +// service. RBAC policies are additive. The policies are examined in order. Requests are allowed +// or denied based on the `action` and whether a matching policy is found. For instance, if the +// action is ALLOW and a matching policy is found the request should be allowed. +// +// RBAC can also be used to make access logging decisions by communicating with access loggers +// through dynamic metadata. When the action is LOG, and at least one policy matches, the +// `access_log_policy` value is set to `true` indicating the request should be logged. // // Here is an example of RBAC configuration. It has two policies: // @@ -74,7 +79,7 @@ message RBAC { // access control. DENY = 1; - // The policies set the "envoy.log" dynamic metadata key based on if requests match + // The policies set the `access_log_policy` dynamic metadata key based on if requests match LOG = 2; } @@ -85,9 +90,9 @@ message RBAC { // * `action` is "DENY" and none of the policies match // * `action` is "LOG" // - // If the action is "LOG" and at least one policy matches, or if the action is not "LOG", - // the dynamic metadata key `envoy.log` is set to the value "yes". - // Otherwise, it is set to "no". + // If the action is LOG and at least one policy matches the dynamic metadata key `access_log_policy` + // is set to the value `true`. If no policies match, it is set to `false`. + // Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. diff --git a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto index f666ac9c1203d..2716961e22283 100644 --- a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto @@ -22,8 +22,13 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Role Based Access Control (RBAC)] // Role Based Access Control (RBAC) provides service-level and method-level access control for a -// service. RBAC policies are additive. The policies are examined in order. A request is allowed -// once a matching policy is found (suppose the `action` is ALLOW). +// service. RBAC policies are additive. The policies are examined in order. Requests are allowed +// or denied based on the `action` and whether a matching policy is found. For instance, if the +// action is ALLOW and a matching policy is found the request should be allowed. +// +// RBAC can also be used to make access logging decisions by communicating with access loggers +// through dynamic metadata. When the action is LOG, and at least one policy matches, the +// `access_log_policy` value is set to `true` indicating the request should be logged. // // Here is an example of RBAC configuration. It has two policies: // @@ -74,7 +79,7 @@ message RBAC { // access control. DENY = 1; - // The policies set the "envoy.log" dynamic metadata key based on if requests match + // The policies set the `access_log_policy` dynamic metadata key based on if requests match LOG = 2; } @@ -85,9 +90,9 @@ message RBAC { // * `action` is "DENY" and none of the policies match // * `action` is "LOG" // - // If the action is "LOG" and at least one policy matches, or if the action is not "LOG", - // the dynamic metadata key `envoy.log` is set to the value "yes". - // Otherwise, it is set to "no". + // If the action is LOG and at least one policy matches the dynamic metadata key `access_log_policy` + // is set to the value `true`. If no policies match, it is set to `false`. + // Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. diff --git a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto index 636c19cbc7911..378ecdff4049d 100644 --- a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto @@ -22,8 +22,13 @@ option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSIO // [#protodoc-title: Role Based Access Control (RBAC)] // Role Based Access Control (RBAC) provides service-level and method-level access control for a -// service. RBAC policies are additive. The policies are examined in order. A request is allowed -// once a matching policy is found (suppose the `action` is ALLOW). +// service. RBAC policies are additive. The policies are examined in order. Requests are allowed +// or denied based on the `action` and whether a matching policy is found. For instance, if the +// action is ALLOW and a matching policy is found the request should be allowed. +// +// RBAC can also be used to make access logging decisions by communicating with access loggers +// through dynamic metadata. When the action is LOG, and at least one policy matches, the +// `access_log_policy` value is set to `true` indicating the request should be logged. // // Here is an example of RBAC configuration. It has two policies: // @@ -74,7 +79,7 @@ message RBAC { // access control. DENY = 1; - // The policies set the "envoy.log" dynamic metadata key based on if requests match + // The policies set the `access_log_policy` dynamic metadata key based on if requests match LOG = 2; } @@ -85,9 +90,9 @@ message RBAC { // * `action` is "DENY" and none of the policies match // * `action` is "LOG" // - // If the action is "LOG" and at least one policy matches, or if the action is not "LOG", - // the dynamic metadata key `envoy.log` is set to the value "yes". - // Otherwise, it is set to "no". + // If the action is LOG and at least one policy matches the dynamic metadata key `access_log_policy` + // is set to the value `true`. If no policies match, it is set to `false`. + // Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. From e5e51695993731532e83b76d4d6322ee4b26990c Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 7 Jul 2020 19:01:38 +0000 Subject: [PATCH 12/39] Added Log Key access log filter Signed-off-by: davidraskin --- api/envoy/config/accesslog/v3/accesslog.proto | 12 +++++++++++- api/envoy/config/accesslog/v4alpha/accesslog.proto | 12 +++++++++++- .../advanced/well_known_dynamic_metadata.rst | 10 +++++++++- .../envoy/config/accesslog/v3/accesslog.proto | 12 +++++++++++- .../envoy/config/accesslog/v4alpha/accesslog.proto | 12 +++++++++++- 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/api/envoy/config/accesslog/v3/accesslog.proto b/api/envoy/config/accesslog/v3/accesslog.proto index 9a2f276b34b40..ebb1fb2f4de98 100644 --- a/api/envoy/config/accesslog/v3/accesslog.proto +++ b/api/envoy/config/accesslog/v3/accesslog.proto @@ -53,7 +53,7 @@ message AccessLog { } } -// [#next-free-field: 12] +// [#next-free-field: 13] message AccessLogFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.accesslog.v2.AccessLogFilter"; @@ -93,6 +93,9 @@ message AccessLogFilter { // Extension filter. ExtensionFilter extension_filter = 11; + + // Log key filter + LogKeyFilter log_key_filter = 12; } } @@ -281,6 +284,13 @@ message GrpcStatusFilter { bool exclude = 2; } +// Filters based on dynamic metadata 'access_log_policy' key. The filter will not log if the key is set to `false`. +// If the key is set to `true` or unset, the request will be logged. +message LogKeyFilter { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.filter.accesslog.v2.LogKeyFilter"; +} + // Extension filter is statically registered at runtime. message ExtensionFilter { option (udpa.annotations.versioning).previous_message_type = diff --git a/api/envoy/config/accesslog/v4alpha/accesslog.proto b/api/envoy/config/accesslog/v4alpha/accesslog.proto index 939d4df95889e..d9262118686aa 100644 --- a/api/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/api/envoy/config/accesslog/v4alpha/accesslog.proto @@ -53,7 +53,7 @@ message AccessLog { } } -// [#next-free-field: 12] +// [#next-free-field: 13] message AccessLogFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.accesslog.v3.AccessLogFilter"; @@ -93,6 +93,9 @@ message AccessLogFilter { // Extension filter. ExtensionFilter extension_filter = 11; + + // Log key filter + LogKeyFilter log_key_filter = 12; } } @@ -280,6 +283,13 @@ message GrpcStatusFilter { bool exclude = 2; } +// Filters based on dynamic metadata 'access_log_policy' key. The filter will not log if the key is set to `false`. +// If the key is set to `true` or unset, the request will be logged. +message LogKeyFilter { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.accesslog.v3.LogKeyFilter"; +} + // Extension filter is statically registered at runtime. message ExtensionFilter { option (udpa.annotations.versioning).previous_message_type = diff --git a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst index 24be022accebb..7977f6a5a901a 100644 --- a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst +++ b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst @@ -34,4 +34,12 @@ Dynamic metadata that is set by multiple filters is placed in the common key nam The following Envoy filters emit shared dynamic metadata. * :ref:`Role Based Access Control (RBAC) Filter ` -* :ref:`Role Based Access Control (RBAC) Network Filter ` \ No newline at end of file +<<<<<<< HEAD +* :ref:`Role Based Access Control (RBAC) Network Filter ` +======= +* :ref:`Role Based Access Control (RBAC) Network Filter ` + +The following filters consume shared dynamic metadata. + +* Log Key Access Log Filter +>>>>>>> 2c3bc0a49... Added Log Key access log filter diff --git a/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto b/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto index 09d691dd36650..c35d7f120f1ee 100644 --- a/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto +++ b/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto @@ -51,7 +51,7 @@ message AccessLog { } } -// [#next-free-field: 12] +// [#next-free-field: 13] message AccessLogFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.accesslog.v2.AccessLogFilter"; @@ -91,6 +91,9 @@ message AccessLogFilter { // Extension filter. ExtensionFilter extension_filter = 11; + + // Log key filter + LogKeyFilter log_key_filter = 12; } } @@ -279,6 +282,13 @@ message GrpcStatusFilter { bool exclude = 2; } +// Filters based on dynamic metadata 'access_log_policy' key. The filter will not log if the key is set to `false`. +// If the key is set to `true` or unset, the request will be logged. +message LogKeyFilter { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.filter.accesslog.v2.LogKeyFilter"; +} + // Extension filter is statically registered at runtime. message ExtensionFilter { option (udpa.annotations.versioning).previous_message_type = diff --git a/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto b/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto index 939d4df95889e..d9262118686aa 100644 --- a/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto @@ -53,7 +53,7 @@ message AccessLog { } } -// [#next-free-field: 12] +// [#next-free-field: 13] message AccessLogFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.accesslog.v3.AccessLogFilter"; @@ -93,6 +93,9 @@ message AccessLogFilter { // Extension filter. ExtensionFilter extension_filter = 11; + + // Log key filter + LogKeyFilter log_key_filter = 12; } } @@ -280,6 +283,13 @@ message GrpcStatusFilter { bool exclude = 2; } +// Filters based on dynamic metadata 'access_log_policy' key. The filter will not log if the key is set to `false`. +// If the key is set to `true` or unset, the request will be logged. +message LogKeyFilter { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.accesslog.v3.LogKeyFilter"; +} + // Extension filter is statically registered at runtime. message ExtensionFilter { option (udpa.annotations.versioning).previous_message_type = From 6593dc30cbd48e778cf1f0f3e88caf7cf3e89600 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Wed, 8 Jul 2020 21:23:40 +0000 Subject: [PATCH 13/39] Changed key name and created Access Log Metadata Filter Signed-off-by: davidraskin --- api/envoy/config/accesslog/v3/BUILD | 1 + api/envoy/config/accesslog/v3/accesslog.proto | 16 ++++++++++------ api/envoy/config/accesslog/v4alpha/BUILD | 1 + .../config/accesslog/v4alpha/accesslog.proto | 16 ++++++++++------ api/envoy/config/rbac/v3/rbac.proto | 13 +++++++------ api/envoy/config/rbac/v4alpha/rbac.proto | 13 +++++++------ .../advanced/well_known_dynamic_metadata.rst | 8 ++------ .../http/http_filters/rbac_filter.rst | 2 +- .../listeners/network_filters/rbac_filter.rst | 2 +- .../envoy/config/accesslog/v3/BUILD | 1 + .../envoy/config/accesslog/v3/accesslog.proto | 16 ++++++++++------ .../envoy/config/accesslog/v4alpha/BUILD | 1 + .../config/accesslog/v4alpha/accesslog.proto | 16 ++++++++++------ .../envoy/config/rbac/v3/rbac.proto | 13 +++++++------ .../envoy/config/rbac/v4alpha/rbac.proto | 13 +++++++------ 15 files changed, 76 insertions(+), 56 deletions(-) diff --git a/api/envoy/config/accesslog/v3/BUILD b/api/envoy/config/accesslog/v3/BUILD index 92e9f39492511..518ca23126cd1 100644 --- a/api/envoy/config/accesslog/v3/BUILD +++ b/api/envoy/config/accesslog/v3/BUILD @@ -9,6 +9,7 @@ api_proto_package( "//envoy/config/core/v3:pkg", "//envoy/config/filter/accesslog/v2:pkg", "//envoy/config/route/v3:pkg", + "//envoy/type/matcher/v3:pkg", "//envoy/type/v3:pkg", "@com_github_cncf_udpa//udpa/annotations:pkg", ], diff --git a/api/envoy/config/accesslog/v3/accesslog.proto b/api/envoy/config/accesslog/v3/accesslog.proto index ebb1fb2f4de98..8ea60dfbc762e 100644 --- a/api/envoy/config/accesslog/v3/accesslog.proto +++ b/api/envoy/config/accesslog/v3/accesslog.proto @@ -4,6 +4,7 @@ package envoy.config.accesslog.v3; import "envoy/config/core/v3/base.proto"; import "envoy/config/route/v3/route_components.proto"; +import "envoy/type/matcher/v3/metadata.proto"; import "envoy/type/v3/percent.proto"; import "google/protobuf/any.proto"; @@ -94,8 +95,8 @@ message AccessLogFilter { // Extension filter. ExtensionFilter extension_filter = 11; - // Log key filter - LogKeyFilter log_key_filter = 12; + // Metadata Filter + MetadataFilter metadata_filter = 12; } } @@ -284,11 +285,14 @@ message GrpcStatusFilter { bool exclude = 2; } -// Filters based on dynamic metadata 'access_log_policy' key. The filter will not log if the key is set to `false`. -// If the key is set to `true` or unset, the request will be logged. -message LogKeyFilter { +// Filters based on matching dynamic metadata. +message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = - "envoy.config.filter.accesslog.v2.LogKeyFilter"; + "envoy.config.filter.accesslog.v2.MetadataFilter"; + + // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata + // set the filter to "envoy.common" and the path to "access_log_hint". + type.matcher.v3.MetadataMatcher matcher = 1; } // Extension filter is statically registered at runtime. diff --git a/api/envoy/config/accesslog/v4alpha/BUILD b/api/envoy/config/accesslog/v4alpha/BUILD index 4ed75a69ea092..e426e922fa726 100644 --- a/api/envoy/config/accesslog/v4alpha/BUILD +++ b/api/envoy/config/accesslog/v4alpha/BUILD @@ -9,6 +9,7 @@ api_proto_package( "//envoy/config/accesslog/v3:pkg", "//envoy/config/core/v4alpha:pkg", "//envoy/config/route/v4alpha:pkg", + "//envoy/type/matcher/v4alpha:pkg", "//envoy/type/v3:pkg", "@com_github_cncf_udpa//udpa/annotations:pkg", ], diff --git a/api/envoy/config/accesslog/v4alpha/accesslog.proto b/api/envoy/config/accesslog/v4alpha/accesslog.proto index d9262118686aa..c890384b48b28 100644 --- a/api/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/api/envoy/config/accesslog/v4alpha/accesslog.proto @@ -4,6 +4,7 @@ package envoy.config.accesslog.v4alpha; import "envoy/config/core/v4alpha/base.proto"; import "envoy/config/route/v4alpha/route_components.proto"; +import "envoy/type/matcher/v4alpha/metadata.proto"; import "envoy/type/v3/percent.proto"; import "google/protobuf/any.proto"; @@ -94,8 +95,8 @@ message AccessLogFilter { // Extension filter. ExtensionFilter extension_filter = 11; - // Log key filter - LogKeyFilter log_key_filter = 12; + // Metadata Filter + MetadataFilter metadata_filter = 12; } } @@ -283,11 +284,14 @@ message GrpcStatusFilter { bool exclude = 2; } -// Filters based on dynamic metadata 'access_log_policy' key. The filter will not log if the key is set to `false`. -// If the key is set to `true` or unset, the request will be logged. -message LogKeyFilter { +// Filters based on matching dynamic metadata. +message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = - "envoy.config.accesslog.v3.LogKeyFilter"; + "envoy.config.accesslog.v3.MetadataFilter"; + + // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata + // set the filter to "envoy.common" and the path to "access_log_hint". + type.matcher.v4alpha.MetadataMatcher matcher = 1; } // Extension filter is statically registered at runtime. diff --git a/api/envoy/config/rbac/v3/rbac.proto b/api/envoy/config/rbac/v3/rbac.proto index 2716961e22283..c13ff55b5faa6 100644 --- a/api/envoy/config/rbac/v3/rbac.proto +++ b/api/envoy/config/rbac/v3/rbac.proto @@ -27,8 +27,9 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // action is ALLOW and a matching policy is found the request should be allowed. // // RBAC can also be used to make access logging decisions by communicating with access loggers -// through dynamic metadata. When the action is LOG, and at least one policy matches, the -// `access_log_policy` value is set to `true` indicating the request should be logged. +// through dynamic metadata. When the action is LOG and at least one policy matches, the +// `access_log_hint` value in the shared key namespace 'envoy.common' is set to `true` indicating +// the request should be logged. // // Here is an example of RBAC configuration. It has two policies: // @@ -79,7 +80,7 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_policy` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match LOG = 2; } @@ -90,9 +91,9 @@ message RBAC { // * `action` is "DENY" and none of the policies match // * `action` is "LOG" // - // If the action is LOG and at least one policy matches the dynamic metadata key `access_log_policy` - // is set to the value `true`. If no policies match, it is set to `false`. - // Other actions do not modify this key. + // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` + // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, + // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. diff --git a/api/envoy/config/rbac/v4alpha/rbac.proto b/api/envoy/config/rbac/v4alpha/rbac.proto index e9cdc32ef378f..25f2545769b73 100644 --- a/api/envoy/config/rbac/v4alpha/rbac.proto +++ b/api/envoy/config/rbac/v4alpha/rbac.proto @@ -27,8 +27,9 @@ option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSIO // action is ALLOW and a matching policy is found the request should be allowed. // // RBAC can also be used to make access logging decisions by communicating with access loggers -// through dynamic metadata. When the action is LOG, and at least one policy matches, the -// `access_log_policy` value is set to `true` indicating the request should be logged. +// through dynamic metadata. When the action is LOG and at least one policy matches, the +// `access_log_hint` value in the shared key namespace 'envoy.common' is set to `true` indicating +// the request should be logged. // // Here is an example of RBAC configuration. It has two policies: // @@ -79,7 +80,7 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_policy` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match LOG = 2; } @@ -90,9 +91,9 @@ message RBAC { // * `action` is "DENY" and none of the policies match // * `action` is "LOG" // - // If the action is LOG and at least one policy matches the dynamic metadata key `access_log_policy` - // is set to the value `true`. If no policies match, it is set to `false`. - // Other actions do not modify this key. + // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` + // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, + // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. diff --git a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst index 7977f6a5a901a..3b16afac99a44 100644 --- a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst +++ b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst @@ -29,17 +29,13 @@ Dynamic metadata that is set by multiple filters is placed in the common key nam :header: Name, Type, Description, Rules :widths: 1, 1, 3, 3 - access_log_policy, boolean, Whether access loggers should log the request., "When this metadata is already set: A `true` value should not be overwritten by a `false` value, while a `false` value can be overwritten by a `true` value." + access_log_hint, boolean, Whether access loggers should log the request., "When this metadata is already set: A `true` value should not be overwritten by a `false` value, while a `false` value can be overwritten by a `true` value." The following Envoy filters emit shared dynamic metadata. * :ref:`Role Based Access Control (RBAC) Filter ` -<<<<<<< HEAD -* :ref:`Role Based Access Control (RBAC) Network Filter ` -======= * :ref:`Role Based Access Control (RBAC) Network Filter ` The following filters consume shared dynamic metadata. -* Log Key Access Log Filter ->>>>>>> 2c3bc0a49... Added Log Key access log filter +* Metadata Access Log Filter diff --git a/docs/root/configuration/http/http_filters/rbac_filter.rst b/docs/root/configuration/http/http_filters/rbac_filter.rst index b24e30d059595..5db112d924eff 100644 --- a/docs/root/configuration/http/http_filters/rbac_filter.rst +++ b/docs/root/configuration/http/http_filters/rbac_filter.rst @@ -52,4 +52,4 @@ The RBAC filter emits the following dynamic metadata. shadow_effective_policy_id, string, The effective shadow policy ID matching the action (if any). shadow_engine_result, string, The engine result for the shadow rules (i.e. either `allowed` or `denied`). - access_log_policy, boolean, Whether the request should be logged. This metadata is shared (See :ref:`Shared Dynamic Metadata`). + access_log_hint, boolean, Whether the request should be logged. This metadata is shared and set under the key namespace 'envoy.common' (See :ref:`Shared Dynamic Metadata`). diff --git a/docs/root/configuration/listeners/network_filters/rbac_filter.rst b/docs/root/configuration/listeners/network_filters/rbac_filter.rst index d0717d3758934..4a01762bc57cc 100644 --- a/docs/root/configuration/listeners/network_filters/rbac_filter.rst +++ b/docs/root/configuration/listeners/network_filters/rbac_filter.rst @@ -42,4 +42,4 @@ The RBAC filter emits the following dynamic metadata. shadow_effective_policy_id, string, The effective shadow policy ID matching the action (if any). shadow_engine_result, string, The engine result for the shadow rules (i.e. either `allowed` or `denied`). - access_log_policy, boolean, Whether the request should be logged. This metadata is shared (See :ref:`Shared Dynamic Metadata`). + access_log_policy, boolean, Whether the request should be logged. This metadata is shared and set under the key namespace 'envoy.common' (See :ref:`Shared Dynamic Metadata`). diff --git a/generated_api_shadow/envoy/config/accesslog/v3/BUILD b/generated_api_shadow/envoy/config/accesslog/v3/BUILD index 92e9f39492511..518ca23126cd1 100644 --- a/generated_api_shadow/envoy/config/accesslog/v3/BUILD +++ b/generated_api_shadow/envoy/config/accesslog/v3/BUILD @@ -9,6 +9,7 @@ api_proto_package( "//envoy/config/core/v3:pkg", "//envoy/config/filter/accesslog/v2:pkg", "//envoy/config/route/v3:pkg", + "//envoy/type/matcher/v3:pkg", "//envoy/type/v3:pkg", "@com_github_cncf_udpa//udpa/annotations:pkg", ], diff --git a/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto b/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto index c35d7f120f1ee..a0da01263e1c9 100644 --- a/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto +++ b/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto @@ -4,6 +4,7 @@ package envoy.config.accesslog.v3; import "envoy/config/core/v3/base.proto"; import "envoy/config/route/v3/route_components.proto"; +import "envoy/type/matcher/v3/metadata.proto"; import "envoy/type/v3/percent.proto"; import "google/protobuf/any.proto"; @@ -92,8 +93,8 @@ message AccessLogFilter { // Extension filter. ExtensionFilter extension_filter = 11; - // Log key filter - LogKeyFilter log_key_filter = 12; + // Metadata Filter + MetadataFilter metadata_filter = 12; } } @@ -282,11 +283,14 @@ message GrpcStatusFilter { bool exclude = 2; } -// Filters based on dynamic metadata 'access_log_policy' key. The filter will not log if the key is set to `false`. -// If the key is set to `true` or unset, the request will be logged. -message LogKeyFilter { +// Filters based on matching dynamic metadata. +message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = - "envoy.config.filter.accesslog.v2.LogKeyFilter"; + "envoy.config.filter.accesslog.v2.MetadataFilter"; + + // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata + // set the filter to "envoy.common" and the path to "access_log_hint". + type.matcher.v3.MetadataMatcher matcher = 1; } // Extension filter is statically registered at runtime. diff --git a/generated_api_shadow/envoy/config/accesslog/v4alpha/BUILD b/generated_api_shadow/envoy/config/accesslog/v4alpha/BUILD index 4ed75a69ea092..e426e922fa726 100644 --- a/generated_api_shadow/envoy/config/accesslog/v4alpha/BUILD +++ b/generated_api_shadow/envoy/config/accesslog/v4alpha/BUILD @@ -9,6 +9,7 @@ api_proto_package( "//envoy/config/accesslog/v3:pkg", "//envoy/config/core/v4alpha:pkg", "//envoy/config/route/v4alpha:pkg", + "//envoy/type/matcher/v4alpha:pkg", "//envoy/type/v3:pkg", "@com_github_cncf_udpa//udpa/annotations:pkg", ], diff --git a/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto b/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto index d9262118686aa..c890384b48b28 100644 --- a/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto @@ -4,6 +4,7 @@ package envoy.config.accesslog.v4alpha; import "envoy/config/core/v4alpha/base.proto"; import "envoy/config/route/v4alpha/route_components.proto"; +import "envoy/type/matcher/v4alpha/metadata.proto"; import "envoy/type/v3/percent.proto"; import "google/protobuf/any.proto"; @@ -94,8 +95,8 @@ message AccessLogFilter { // Extension filter. ExtensionFilter extension_filter = 11; - // Log key filter - LogKeyFilter log_key_filter = 12; + // Metadata Filter + MetadataFilter metadata_filter = 12; } } @@ -283,11 +284,14 @@ message GrpcStatusFilter { bool exclude = 2; } -// Filters based on dynamic metadata 'access_log_policy' key. The filter will not log if the key is set to `false`. -// If the key is set to `true` or unset, the request will be logged. -message LogKeyFilter { +// Filters based on matching dynamic metadata. +message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = - "envoy.config.accesslog.v3.LogKeyFilter"; + "envoy.config.accesslog.v3.MetadataFilter"; + + // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata + // set the filter to "envoy.common" and the path to "access_log_hint". + type.matcher.v4alpha.MetadataMatcher matcher = 1; } // Extension filter is statically registered at runtime. diff --git a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto index 2716961e22283..c13ff55b5faa6 100644 --- a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto @@ -27,8 +27,9 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // action is ALLOW and a matching policy is found the request should be allowed. // // RBAC can also be used to make access logging decisions by communicating with access loggers -// through dynamic metadata. When the action is LOG, and at least one policy matches, the -// `access_log_policy` value is set to `true` indicating the request should be logged. +// through dynamic metadata. When the action is LOG and at least one policy matches, the +// `access_log_hint` value in the shared key namespace 'envoy.common' is set to `true` indicating +// the request should be logged. // // Here is an example of RBAC configuration. It has two policies: // @@ -79,7 +80,7 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_policy` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match LOG = 2; } @@ -90,9 +91,9 @@ message RBAC { // * `action` is "DENY" and none of the policies match // * `action` is "LOG" // - // If the action is LOG and at least one policy matches the dynamic metadata key `access_log_policy` - // is set to the value `true`. If no policies match, it is set to `false`. - // Other actions do not modify this key. + // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` + // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, + // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. diff --git a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto index 378ecdff4049d..1f8a9ed249254 100644 --- a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto @@ -27,8 +27,9 @@ option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSIO // action is ALLOW and a matching policy is found the request should be allowed. // // RBAC can also be used to make access logging decisions by communicating with access loggers -// through dynamic metadata. When the action is LOG, and at least one policy matches, the -// `access_log_policy` value is set to `true` indicating the request should be logged. +// through dynamic metadata. When the action is LOG and at least one policy matches, the +// `access_log_hint` value in the shared key namespace 'envoy.common' is set to `true` indicating +// the request should be logged. // // Here is an example of RBAC configuration. It has two policies: // @@ -79,7 +80,7 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_policy` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match LOG = 2; } @@ -90,9 +91,9 @@ message RBAC { // * `action` is "DENY" and none of the policies match // * `action` is "LOG" // - // If the action is LOG and at least one policy matches the dynamic metadata key `access_log_policy` - // is set to the value `true`. If no policies match, it is set to `false`. - // Other actions do not modify this key. + // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` + // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, + // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. From 9769f5628326231e2024634aa179c784ba097f00 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Sat, 18 Jul 2020 07:32:43 +0000 Subject: [PATCH 14/39] Updated RBAC filter with new key, added metadata access log implementation Signed-off-by: davidraskin --- source/common/access_log/access_log_impl.cc | 11 +++++ source/common/access_log/access_log_impl.h | 18 ++++++++ .../filters/http/rbac/rbac_filter.cc | 28 +++++++------ .../common/access_log/access_log_impl_test.cc | 41 +++++++++++++++++++ .../filters/http/rbac/rbac_filter_test.cc | 33 +++++++++------ 5 files changed, 106 insertions(+), 25 deletions(-) diff --git a/source/common/access_log/access_log_impl.cc b/source/common/access_log/access_log_impl.cc index 9aec83a15fc59..1881680aecaaf 100644 --- a/source/common/access_log/access_log_impl.cc +++ b/source/common/access_log/access_log_impl.cc @@ -76,6 +76,8 @@ FilterPtr FilterFactory::fromProto(const envoy::config::accesslog::v3::AccessLog case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kGrpcStatusFilter: MessageUtil::validate(config, validation_visitor); return FilterPtr{new GrpcStatusFilter(config.grpc_status_filter())}; + case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kMetadataFilter: + return FilterPtr{new MetadataFilter(config.metadata_filter())}; case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kExtensionFilter: MessageUtil::validate(config, validation_visitor); { @@ -255,6 +257,15 @@ Grpc::Status::GrpcStatus GrpcStatusFilter::protoToGrpcStatus( return static_cast(status); } +MetadataFilter::MetadataFilter(const envoy::config::accesslog::v3::MetadataFilter& config) : matcher_(Envoy::Matchers::MetadataMatcher(config.matcher())) {} + +bool MetadataFilter::evaluate(const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap&, + const Http::ResponseHeaderMap&, + const Http::ResponseTrailerMap&) const { + + return matcher_.match(info.dynamicMetadata()); +} + InstanceSharedPtr AccessLogFactory::fromProto(const envoy::config::accesslog::v3::AccessLog& config, Server::Configuration::FactoryContext& context) { FilterPtr filter; diff --git a/source/common/access_log/access_log_impl.h b/source/common/access_log/access_log_impl.h index 518687e779678..2319a18cb46b2 100644 --- a/source/common/access_log/access_log_impl.h +++ b/source/common/access_log/access_log_impl.h @@ -15,6 +15,7 @@ #include "common/grpc/status.h" #include "common/http/header_utility.h" #include "common/protobuf/protobuf.h" +#include "common/common/matchers.h" #include "absl/hash/hash.h" @@ -228,6 +229,23 @@ class GrpcStatusFilter : public Filter { protoToGrpcStatus(envoy::config::accesslog::v3::GrpcStatusFilter::Status status) const; }; +/** + * Filters requests based on dynamic metadata + */ +class MetadataFilter : public Filter { +public: + MetadataFilter(const envoy::config::accesslog::v3::MetadataFilter& config); + + bool evaluate(const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap& request_headers, + const Http::ResponseHeaderMap& response_headers, + const Http::ResponseTrailerMap& response_trailers) const override; + +private: + const Envoy::Matchers::MetadataMatcher matcher_; + + +}; + /** * Extension filter factory that reads from ExtensionFilter proto. */ diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index 72507245bab42..836d189f50718 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -73,15 +73,14 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo : "none", headers, callbacks_->streamInfo().dynamicMetadata().DebugString()); - ProtobufWkt::Struct metrics; - auto& fields = *metrics.mutable_fields(); - Http::FilterHeadersStatus result = Http::FilterHeadersStatus::Continue; - std::string effective_policy_id; const auto shadow_engine = config_->engine(callbacks_->route(), Filters::Common::RBAC::EnforcementMode::Shadow); if (shadow_engine != nullptr) { + ProtobufWkt::Struct metrics; + auto& fields = *metrics.mutable_fields(); + std::string shadow_resp_code = Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().EngineResultAllowed; if (shadow_engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), @@ -95,7 +94,6 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().EngineResultDenied; } - if (!effective_policy_id.empty()) { *fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get() .ShadowEffectivePolicyIdField] @@ -104,32 +102,36 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo *fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().ShadowEngineResultField] .mutable_string_value() = shadow_resp_code; + + callbacks_->streamInfo().setDynamicMetadata(HttpFilterNames::get().Rbac, metrics); } const auto engine = config_->engine(callbacks_->route(), Filters::Common::RBAC::EnforcementMode::Enforced); if (engine != nullptr) { - //Set kRbacShouldLog to true if shouldLog; false otherwise - bool log_decision = engine->shouldLog(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr); - // callbacks_->streamInfo().filterState()->setData("envoy.log", std::make_shared(log_decision ? "yes" : "no"), - // StreamInfo::FilterState::StateType::Mutable); - *fields["envoy.log"].mutable_string_value() = log_decision ? "yes": "no"; + ProtobufWkt::Struct log_metadata; + auto& log_fields = *log_metadata.mutable_fields(); + // Set kRbacShouldLog to true if shouldLog; false otherwise + bool log_decision = + engine->shouldLog(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr); + log_fields["access_log_hint"].set_bool_value(log_decision); + callbacks_->streamInfo().setDynamicMetadata("envoy.common", log_metadata); if (engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr)) { ENVOY_LOG(debug, "enforced allowed"); config_->stats().allowed_.inc(); + return Http::FilterHeadersStatus::Continue; } else { ENVOY_LOG(debug, "enforced denied"); callbacks_->sendLocalReply(Http::Code::Forbidden, "RBAC: access denied", nullptr, absl::nullopt, RcDetails::get().RbacAccessDenied); config_->stats().denied_.inc(); - result = Http::FilterHeadersStatus::StopIteration; + return Http::FilterHeadersStatus::StopIteration; } } - callbacks_->streamInfo().setDynamicMetadata(HttpFilterNames::get().Rbac, metrics); ENVOY_LOG(debug, "no engine, allowed by default"); - return result; + return Http::FilterHeadersStatus::Continue; } } // namespace RBACFilter diff --git a/test/common/access_log/access_log_impl_test.cc b/test/common/access_log/access_log_impl_test.cc index 451c44bf52f88..52a3b4fb9fed4 100644 --- a/test/common/access_log/access_log_impl_test.cc +++ b/test/common/access_log/access_log_impl_test.cc @@ -1264,6 +1264,47 @@ name: accesslog log->log(&request_headers_, &response_headers_, &response_trailers_, stream_info_); } +TEST_F(AccessLogImplTest, MetadataFilter) { + const std::string yaml = R"EOF( +name: accesslog +filter: + metadata_filter: + matcher: + filter: "envoy.common" + path: + - key: "a" + - key: "b" + - key: "c" + value: + bool_match: true + +typed_config: + "@type": type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog + path: /dev/null + )EOF"; + + TestStreamInfo stream_info; + ProtobufWkt::Struct metadata_val; + auto& fields_a = *metadata_val.mutable_fields(); + auto& struct_b = *fields_a["a"].mutable_struct_value(); + auto& fields_b = *struct_b.mutable_fields(); + auto& struct_c = *fields_b["b"].mutable_struct_value(); + auto& fields_c = *struct_c.mutable_fields(); + fields_c["c"].set_bool_value(true); + + stream_info.setDynamicMetadata("envoy.common", metadata_val); + + const InstanceSharedPtr log = + AccessLogFactory::fromProto(parseAccessLogFromV2Yaml(yaml), context_); + + EXPECT_CALL(*file_, write(_)).Times(1); + + log->log(&request_headers_, &response_headers_, &response_trailers_, stream_info); + fields_c["c"].set_bool_value(false); + + EXPECT_CALL(*file_, write(_)).Times(0); +} + class TestHeaderFilterFactory : public ExtensionFilterFactory { public: ~TestHeaderFilterFactory() override = default; diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index dc17231d73f42..33044986c0a3c 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -26,7 +26,8 @@ namespace { class RoleBasedAccessControlFilterTest : public testing::Test { public: - RoleBasedAccessControlFilterConfigSharedPtr setupConfig(envoy::config::rbac::v3::RBAC::Action action) { + RoleBasedAccessControlFilterConfigSharedPtr + setupConfig(envoy::config::rbac::v3::RBAC::Action action) { envoy::extensions::filters::http::rbac::v3::RBAC config; envoy::config::rbac::v3::Policy policy; @@ -50,8 +51,9 @@ class RoleBasedAccessControlFilterTest : public testing::Test { return std::make_shared(config, "test", store_); } - RoleBasedAccessControlFilterTest() : config_(setupConfig(envoy::config::rbac::v3::RBAC::ALLOW)), filter_(config_), - log_config_(setupConfig(envoy::config::rbac::v3::RBAC::LOG)), log_filter_(log_config_) {} + RoleBasedAccessControlFilterTest() + : config_(setupConfig(envoy::config::rbac::v3::RBAC::ALLOW)), filter_(config_), + log_config_(setupConfig(envoy::config::rbac::v3::RBAC::LOG)), log_filter_(log_config_) {} void SetUp() override { EXPECT_CALL(callbacks_, connection()).WillRepeatedly(Return(&connection_)); @@ -77,6 +79,13 @@ class RoleBasedAccessControlFilterTest : public testing::Test { Protobuf::MapPair(HttpFilterNames::get().Rbac, obj)); })); + + ON_CALL(req_info_, setDynamicMetadata("envoy.common", _)) + .WillByDefault(Invoke([this](const std::string&, const ProtobufWkt::Struct& obj) { + req_info_.metadata_.mutable_filter_metadata()->insert( + Protobuf::MapPair("envoy.common", + obj)); + })); } NiceMock callbacks_; @@ -135,10 +144,10 @@ TEST_F(RoleBasedAccessControlFilterTest, Path) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers, false)); headers = Http::TestRequestHeaderMapImpl{ - {":method", "GET"}, - {":path", "prefix/suffix/next"}, - {":scheme", "http"}, - {":authority", "host"}, + {":method", "GET"}, + {":path", "prefix/suffix/next"}, + {":scheme", "http"}, + {":authority", "host"}, }; EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_.decodeHeaders(headers, false)); } @@ -182,7 +191,7 @@ TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, true)); } -//Log Tests +// Log Tests TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { setDestinationPort(123); setMetadata(); @@ -195,8 +204,8 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); - auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); - EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at("envoy.common"); + EXPECT_EQ(true, filter_meta.fields().at("access_log_hint").bool_value()); } TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { @@ -211,8 +220,8 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); - auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); - EXPECT_EQ("no", filter_meta.fields().at("envoy.log").string_value()); + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at("envoy.common"); + EXPECT_EQ(false, filter_meta.fields().at("access_log_hint").bool_value()); } } // namespace From fecd8fb45a59aea7a7a6af861673988a050090b7 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 30 Jun 2020 18:57:27 +0000 Subject: [PATCH 15/39] rbac log action for network filter + log key access log filter Signed-off-by: davidraskin --- .../config/accesslog/v4alpha/accesslog.proto | 12 +++ source/common/access_log/access_log_impl.cc | 24 +++++ source/common/access_log/access_log_impl.h | 9 ++ .../extensions/filters/common/rbac/engine.h | 17 ++-- .../filters/common/rbac/engine_impl.cc | 10 +- .../filters/common/rbac/engine_impl.h | 4 +- .../extensions/filters/common/rbac/utility.h | 4 +- .../filters/http/rbac/rbac_filter.cc | 26 +++++ .../filters/http/rbac/rbac_filter.h | 26 ++--- .../filters/network/rbac/rbac_filter.cc | 20 ++++ .../common/access_log/access_log_impl_test.cc | 28 ++++++ .../filters/common/rbac/engine_impl_test.cc | 99 ++++++++++++------- .../filters/http/rbac/rbac_filter_test.cc | 45 +++++++++ .../filters/network/rbac/filter_test.cc | 81 ++++++++++++++- 14 files changed, 338 insertions(+), 67 deletions(-) diff --git a/api/envoy/config/accesslog/v4alpha/accesslog.proto b/api/envoy/config/accesslog/v4alpha/accesslog.proto index c890384b48b28..f919f11f108f7 100644 --- a/api/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/api/envoy/config/accesslog/v4alpha/accesslog.proto @@ -92,11 +92,17 @@ message AccessLogFilter { // gRPC status filter. GrpcStatusFilter grpc_status_filter = 10; + LogKeyFilter log_key_filter = 11; + // Extension filter. +<<<<<<< HEAD ExtensionFilter extension_filter = 11; // Metadata Filter MetadataFilter metadata_filter = 12; +======= + ExtensionFilter extension_filter = 12; +>>>>>>> c7e38e439... rbac log action for network filter + log key access log filter } } @@ -284,6 +290,7 @@ message GrpcStatusFilter { bool exclude = 2; } +<<<<<<< HEAD // Filters based on matching dynamic metadata. message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = @@ -292,6 +299,11 @@ message MetadataFilter { // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata // set the filter to "envoy.common" and the path to "access_log_hint". type.matcher.v4alpha.MetadataMatcher matcher = 1; +======= +message LogKeyFilter { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.accesslog.v3.LogKeyFilter"; +>>>>>>> c7e38e439... rbac log action for network filter + log key access log filter } // Extension filter is statically registered at runtime. diff --git a/source/common/access_log/access_log_impl.cc b/source/common/access_log/access_log_impl.cc index 1881680aecaaf..cc98ee78a1133 100644 --- a/source/common/access_log/access_log_impl.cc +++ b/source/common/access_log/access_log_impl.cc @@ -76,8 +76,13 @@ FilterPtr FilterFactory::fromProto(const envoy::config::accesslog::v3::AccessLog case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kGrpcStatusFilter: MessageUtil::validate(config, validation_visitor); return FilterPtr{new GrpcStatusFilter(config.grpc_status_filter())}; +<<<<<<< HEAD case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kMetadataFilter: return FilterPtr{new MetadataFilter(config.metadata_filter())}; +======= + case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kLogKeyFilter: + return FilterPtr{new LogKeyFilter()}; +>>>>>>> c7e38e439... rbac log action for network filter + log key access log filter case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kExtensionFilter: MessageUtil::validate(config, validation_visitor); { @@ -257,6 +262,7 @@ Grpc::Status::GrpcStatus GrpcStatusFilter::protoToGrpcStatus( return static_cast(status); } +<<<<<<< HEAD MetadataFilter::MetadataFilter(const envoy::config::accesslog::v3::MetadataFilter& config) : matcher_(Envoy::Matchers::MetadataMatcher(config.matcher())) {} bool MetadataFilter::evaluate(const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap&, @@ -264,6 +270,24 @@ bool MetadataFilter::evaluate(const StreamInfo::StreamInfo& info, const Http::Re const Http::ResponseTrailerMap&) const { return matcher_.match(info.dynamicMetadata()); +======= +bool LogKeyFilter::evaluate(const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap&, + const Http::ResponseHeaderMap&, + const Http::ResponseTrailerMap&) const { + + const auto& metadata = info.dynamicMetadata().filter_metadata(); + const auto& com_metadata = metadata.find("envoy.common"); + if (com_metadata != metadata.end()) { + const auto& key_it = com_metadata->second.fields().find("access_log_policy"); + if (key_it != com_metadata->second.fields().end()) { + std::string access_log_policy = key_it->second.string_value(); + return access_log_policy == "yes"; + } + } + + //If not set, do not filter log. + return true; +>>>>>>> c7e38e439... rbac log action for network filter + log key access log filter } InstanceSharedPtr AccessLogFactory::fromProto(const envoy::config::accesslog::v3::AccessLog& config, diff --git a/source/common/access_log/access_log_impl.h b/source/common/access_log/access_log_impl.h index 2319a18cb46b2..64f3e10809747 100644 --- a/source/common/access_log/access_log_impl.h +++ b/source/common/access_log/access_log_impl.h @@ -230,6 +230,7 @@ class GrpcStatusFilter : public Filter { }; /** +<<<<<<< HEAD * Filters requests based on dynamic metadata */ class MetadataFilter : public Filter { @@ -244,6 +245,14 @@ class MetadataFilter : public Filter { const Envoy::Matchers::MetadataMatcher matcher_; +======= + * Filters requests based on value of 'access_log_policy' key + */ +class LogKeyFilter : public Filter { + bool evaluate(const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap& request_headers, + const Http::ResponseHeaderMap& response_headers, + const Http::ResponseTrailerMap& response_trailers) const override; +>>>>>>> c7e38e439... rbac log action for network filter + log key access log filter }; /** diff --git a/source/extensions/filters/common/rbac/engine.h b/source/extensions/filters/common/rbac/engine.h index 25e7027f1b066..8bf5920cf3d6b 100644 --- a/source/extensions/filters/common/rbac/engine.h +++ b/source/extensions/filters/common/rbac/engine.h @@ -18,6 +18,8 @@ class RoleBasedAccessControlEngine { public: virtual ~RoleBasedAccessControlEngine() = default; + enum class LogDecision { Yes, No, Undecided }; + /** * Returns whether or not the current action is permitted. * @@ -46,7 +48,7 @@ class RoleBasedAccessControlEngine { virtual bool allowed(const Network::Connection& connection, const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const PURE; - /** + /** * Returns whether or not the current action should be logged. * * @param connection the downstream connection used to identify the action/principal. @@ -57,10 +59,10 @@ class RoleBasedAccessControlEngine { * @param effective_policy_id it will be filled by the matching policy's ID, * which is used to identity the source of the allow/deny. */ - virtual bool shouldLog(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const PURE; + virtual LogDecision shouldLog(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const PURE; /** * Returns whether or not the current action should be logged. @@ -71,8 +73,9 @@ class RoleBasedAccessControlEngine { * @param effective_policy_id it will be filled by the matching policy's ID, * which is used to identity the source of the allow/deny. */ - virtual bool shouldLog(const Network::Connection& connection, const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const PURE; + virtual LogDecision shouldLog(const Network::Connection& connection, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const PURE; }; } // namespace RBAC diff --git a/source/extensions/filters/common/rbac/engine_impl.cc b/source/extensions/filters/common/rbac/engine_impl.cc index 70ceec4be70e2..89e4217df83d1 100644 --- a/source/extensions/filters/common/rbac/engine_impl.cc +++ b/source/extensions/filters/common/rbac/engine_impl.cc @@ -10,6 +10,8 @@ namespace Filters { namespace Common { namespace RBAC { +using LogDecision = RoleBasedAccessControlEngine::LogDecision; + RoleBasedAccessControlEngineImpl::RoleBasedAccessControlEngineImpl( const envoy::config::rbac::v3::RBAC& rules) : allowed_if_matched_(rules.action() == envoy::config::rbac::v3::RBAC::ALLOW), action_log_(rules.action() == envoy::config::rbac::v3::RBAC::LOG) { @@ -61,12 +63,12 @@ bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connec return allowed(connection, *empty_header, info, effective_policy_id); } -bool RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& connection, +LogDecision RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const { if(!action_log_) { - return false; + return LogDecision::Undecided; } bool matched = false; @@ -82,10 +84,10 @@ bool RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& conn } // log if action is LOG and a policy matches - return matched; + return matched ? LogDecision::Yes : LogDecision::No; } -bool RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& connection, +LogDecision RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& connection, const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const { static const Http::RequestHeaderMapImpl* empty_header = new Http::RequestHeaderMapImpl(); diff --git a/source/extensions/filters/common/rbac/engine_impl.h b/source/extensions/filters/common/rbac/engine_impl.h index 66439e5f2613e..620fc3f284fa0 100644 --- a/source/extensions/filters/common/rbac/engine_impl.h +++ b/source/extensions/filters/common/rbac/engine_impl.h @@ -21,10 +21,10 @@ class RoleBasedAccessControlEngineImpl : public RoleBasedAccessControlEngine, No bool allowed(const Network::Connection& connection, const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const override; - bool shouldLog(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, + LogDecision shouldLog(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const override; - bool shouldLog(const Network::Connection& connection, const StreamInfo::StreamInfo& info, + LogDecision shouldLog(const Network::Connection& connection, const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const override; private: diff --git a/source/extensions/filters/common/rbac/utility.h b/source/extensions/filters/common/rbac/utility.h index a48efb813234b..48546bf950860 100644 --- a/source/extensions/filters/common/rbac/utility.h +++ b/source/extensions/filters/common/rbac/utility.h @@ -29,7 +29,9 @@ using DynamicMetadataKeysSingleton = ConstSingleton; COUNTER(allowed) \ COUNTER(denied) \ COUNTER(shadow_allowed) \ - COUNTER(shadow_denied) + COUNTER(shadow_denied) \ + COUNTER(logged) \ + COUNTER(not_logged) /** * Wrapper struct for RBAC filter stats. @see stats_macros.h diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index 836d189f50718..ea0498b7abd1d 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -109,6 +109,7 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo const auto engine = config_->engine(callbacks_->route(), Filters::Common::RBAC::EnforcementMode::Enforced); if (engine != nullptr) { +<<<<<<< HEAD ProtobufWkt::Struct log_metadata; auto& log_fields = *log_metadata.mutable_fields(); // Set kRbacShouldLog to true if shouldLog; false otherwise @@ -116,6 +117,24 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo engine->shouldLog(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr); log_fields["access_log_hint"].set_bool_value(log_decision); callbacks_->streamInfo().setDynamicMetadata("envoy.common", log_metadata); +======= + // Set "envoy.log" to true if shouldLog; false otherwise + auto log_dec = + engine->shouldLog(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr); + if (log_dec != Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided) { + bool log_yes = + log_dec == Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision::Yes; + *fields["envoy.log"].mutable_string_value() = log_yes ? "yes" : "no"; + + if (log_yes) { + ENVOY_LOG(debug, "request logged"); + config_->stats().logged_.inc(); + } else { + ENVOY_LOG(debug, "request not logged"); + config_->stats().not_logged_.inc(); + } + } +>>>>>>> c7e38e439... rbac log action for network filter + log key access log filter if (engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr)) { ENVOY_LOG(debug, "enforced allowed"); @@ -130,8 +149,15 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo } } +<<<<<<< HEAD ENVOY_LOG(debug, "no engine, allowed by default"); return Http::FilterHeadersStatus::Continue; +======= + if (!metrics.fields().empty()) + callbacks_->streamInfo().setDynamicMetadata(HttpFilterNames::get().Rbac, metrics); + // ENVOY_LOG(debug, "no engine, allowed by default"); + return result; +>>>>>>> c7e38e439... rbac log action for network filter + log key access log filter } } // namespace RBACFilter diff --git a/source/extensions/filters/http/rbac/rbac_filter.h b/source/extensions/filters/http/rbac/rbac_filter.h index 96eb8198db5cc..4e8407cc52ffb 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.h +++ b/source/extensions/filters/http/rbac/rbac_filter.h @@ -22,19 +22,19 @@ namespace Extensions { namespace HttpFilters { namespace RBACFilter { -class RBACShouldLogState : public StreamInfo::FilterState::Object { -public: - RBACShouldLogState(std::string value) { - value_ = value; - } - - const std::string& value() const { return value_; } - void setValue(std::string value) { - value_.assign(value); - } -private: - std::string value_{}; -}; +// class RBACShouldLogState : public StreamInfo::FilterState::Object { +// public: +// RBACShouldLogState(std::string value) { +// value_ = value; +// } + +// const std::string& value() const { return value_; } +// void setValue(std::string value) { +// value_.assign(value); +// } +// private: +// std::string value_{}; +// }; class RoleBasedAccessControlRouteSpecificFilterConfig : public Router::RouteSpecificFilterConfig { public: diff --git a/source/extensions/filters/network/rbac/rbac_filter.cc b/source/extensions/filters/network/rbac/rbac_filter.cc index 1bc12017b3b6d..7104274e9db40 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.cc +++ b/source/extensions/filters/network/rbac/rbac_filter.cc @@ -8,6 +8,8 @@ #include "absl/strings/str_join.h" +#include + namespace Envoy { namespace Extensions { namespace NetworkFilters { @@ -83,8 +85,26 @@ void RoleBasedAccessControlFilter::setDynamicMetadata(std::string shadow_engine_ EngineResult RoleBasedAccessControlFilter::checkEngine(Filters::Common::RBAC::EnforcementMode mode) { const auto engine = config_->engine(mode); + if (engine != nullptr) { std::string effective_policy_id; + + if (mode == Filters::Common::RBAC::EnforcementMode::Enforced) { + //=====================================LogDecision========================== + ProtobufWkt::Struct metrics; + auto& fields = *metrics.mutable_fields(); + auto log_dec = engine->shouldLog(callbacks_->connection(), + callbacks_->connection().streamInfo(), &effective_policy_id); + if (log_dec != Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided) { + bool log_yes = + log_dec == Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision::Yes; + + *fields["envoy.log"].mutable_string_value() = log_yes ? "yes" : "no"; + } + + callbacks_->connection().streamInfo().setDynamicMetadata("common", metrics); + } + if (engine->allowed(callbacks_->connection(), callbacks_->connection().streamInfo(), &effective_policy_id)) { if (mode == Filters::Common::RBAC::EnforcementMode::Shadow) { diff --git a/test/common/access_log/access_log_impl_test.cc b/test/common/access_log/access_log_impl_test.cc index 52a3b4fb9fed4..3b4aacd6bbf1d 100644 --- a/test/common/access_log/access_log_impl_test.cc +++ b/test/common/access_log/access_log_impl_test.cc @@ -474,6 +474,34 @@ name: accesslog } } +TEST_F(AccessLogImplTest, LogKey) { + + const std::string yaml = R"EOF( +name: accesslog +filter: + log_key_filter: {} +typed_config: + "@type": type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog + path: /dev/null + )EOF"; + + InstanceSharedPtr logger = AccessLogFactory::fromProto(parseAccessLogFromV2Yaml(yaml), context_); + ProtobufWkt::Struct metrics; + auto& fields = *metrics.mutable_fields(); + *fields["access_log_policy"].mutable_string_value() = "no"; + stream_info_.setDynamicMetadata("envoy.common", metrics); + + EXPECT_CALL(*file_, write(_)).Times(0); + logger->log(&request_headers_, &response_headers_, &response_trailers_, stream_info_); + + *fields["access_log_policy"].mutable_string_value() = "yes"; + stream_info_.setDynamicMetadata("envoy.common", metrics); + + EXPECT_CALL(*file_, write(_)); + logger->log(&request_headers_, &response_headers_, &response_trailers_, stream_info_); +} + + TEST(AccessLogImplTestCtor, FiltersMissingInOrAndFilter) { NiceMock context; diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index a9d4389b86d0c..5b5b7adb3f5bc 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -32,8 +32,10 @@ void checkEngine( EXPECT_EQ(expected, engine.allowed(connection, headers, info, nullptr)); } -//Used for testing shouldLog() function tests -void checkEngineLog(const RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, +// Used for testing shouldLog() function tests +void checkEngineLog( + const RBAC::RoleBasedAccessControlEngineImpl& engine, + const RoleBasedAccessControlEngine::LogDecision expected, const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl(), const StreamInfo::StreamInfo& info = NiceMock()) { @@ -181,29 +183,6 @@ TEST(RoleBasedAccessControlEngineImpl, DeniedBlacklist) { checkEngine(engine, true, conn, headers, info); } -TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { - envoy::config::rbac::v3::Policy policy; - policy.add_permissions()->set_destination_port(123); - policy.add_principals()->set_any(true); - - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - (*rbac.mutable_policies())["foo"] = policy; - RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - - Envoy::Network::MockConnection conn; - Envoy::Http::TestRequestHeaderMapImpl headers; - NiceMock info; - Envoy::Network::Address::InstanceConstSharedPtr addr = - Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, true, conn, headers, info); - - addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, true, conn, headers, info); -} - TEST(RoleBasedAccessControlEngineImpl, BasicCondition) { envoy::config::rbac::v3::Policy policy; policy.add_permissions()->set_any(true); @@ -240,6 +219,10 @@ TEST(RoleBasedAccessControlEngineImpl, MalformedCondition) { EXPECT_THROW_WITH_REGEX(RBAC::RoleBasedAccessControlEngineImpl engine(rbac), EnvoyException, "failed to create an expression: .*"); + + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + EXPECT_THROW_WITH_REGEX(RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac), EnvoyException, + "failed to create an expression: .*"); } TEST(RoleBasedAccessControlEngineImpl, MistypedCondition) { @@ -257,6 +240,10 @@ TEST(RoleBasedAccessControlEngineImpl, MistypedCondition) { (*rbac.mutable_policies())["foo"] = policy; RBAC::RoleBasedAccessControlEngineImpl engine(rbac); checkEngine(engine, false); + + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No); } TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { @@ -282,6 +269,10 @@ TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { (*rbac.mutable_policies())["foo"] = policy; RBAC::RoleBasedAccessControlEngineImpl engine(rbac); checkEngine(engine, false, Envoy::Network::MockConnection()); + + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, Envoy::Network::MockConnection()); } TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { @@ -318,6 +309,10 @@ TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { headers.setReference(key, value); checkEngine(engine, true, Envoy::Network::MockConnection(), headers); + + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, Envoy::Network::MockConnection(), headers); } TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { @@ -363,6 +358,10 @@ TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { EXPECT_CALL(Const(info), dynamicMetadata()).WillRepeatedly(ReturnRef(metadata)); checkEngine(engine, true, Envoy::Network::MockConnection(), headers, info); + + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, Envoy::Network::MockConnection(), headers, info); } TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { @@ -385,15 +384,20 @@ TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + EXPECT_CALL(Const(info), downstreamLocalAddress()).Times(2).WillRepeatedly(ReturnRef(addr)); checkEngine(engine, false, conn, headers, info); + + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, conn, headers, info); } -//shouldLog() tests +// Log tests tests TEST(RoleBasedAccessControlEngineImpl, DisabledLog) { envoy::config::rbac::v3::RBAC rbac; rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - checkEngineLog(RBAC::RoleBasedAccessControlEngineImpl(rbac), false); + checkEngineLog(RBAC::RoleBasedAccessControlEngineImpl(rbac), + RBAC::RoleBasedAccessControlEngine::LogDecision::No); } TEST(RoleBasedAccessControlEngineImpl, LogIfMatched) { @@ -412,14 +416,14 @@ TEST(RoleBasedAccessControlEngineImpl, LogIfMatched) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, true, conn, headers, info); + checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::Yes, conn, headers, info); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, false, conn, headers, info); + checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::No, conn, headers, info); } -TEST(RoleBasedAccessControlEngineImpl, NeverLogAllow) { +TEST(RoleBasedAccessControlEngineImpl, LogAllowUndecided) { envoy::config::rbac::v3::Policy policy; policy.add_permissions()->set_destination_port(123); policy.add_principals()->set_any(true); @@ -435,14 +439,14 @@ TEST(RoleBasedAccessControlEngineImpl, NeverLogAllow) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, false, conn, headers, info); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, false, conn, headers, info); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); } -TEST(RoleBasedAccessControlEngineImpl, NeverLogDeny) { +TEST(RoleBasedAccessControlEngineImpl, LogDenyUndecided) { envoy::config::rbac::v3::Policy policy; policy.add_permissions()->set_destination_port(123); policy.add_principals()->set_any(true); @@ -458,11 +462,34 @@ TEST(RoleBasedAccessControlEngineImpl, NeverLogDeny) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, false, conn, headers, info); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); + + addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); + // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); +} + +TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { + envoy::config::rbac::v3::Policy policy; + policy.add_permissions()->set_destination_port(123); + policy.add_principals()->set_any(true); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + (*rbac.mutable_policies())["foo"] = policy; + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + + Envoy::Network::MockConnection conn; + Envoy::Http::TestRequestHeaderMapImpl headers; + NiceMock info; + Envoy::Network::Address::InstanceConstSharedPtr addr = + Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); + // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngine(engine, true, conn, headers, info); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, false, conn, headers, info); + checkEngine(engine, true, conn, headers, info); } } // namespace diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index 33044986c0a3c..1d914e3cc3e50 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -130,6 +130,12 @@ TEST_F(RoleBasedAccessControlFilterTest, RequestedServerName) { Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_.decodeTrailers(trailers_)); + + //Check Log + setMetadata(); + EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); + EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); } TEST_F(RoleBasedAccessControlFilterTest, Path) { @@ -150,6 +156,12 @@ TEST_F(RoleBasedAccessControlFilterTest, Path) { {":authority", "host"}, }; EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_.decodeHeaders(headers, false)); + + //Check Log + setMetadata(); + EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers, false)); + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); + EXPECT_EQ("no", filter_meta.fields().at("envoy.log").string_value()); } TEST_F(RoleBasedAccessControlFilterTest, Denied) { @@ -200,6 +212,9 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); + EXPECT_EQ(1U, log_config_->stats().logged_.value()); + EXPECT_EQ(0U, log_config_->stats().not_logged_.value()); + Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); @@ -216,6 +231,9 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); + EXPECT_EQ(0U, log_config_->stats().logged_.value()); + EXPECT_EQ(1U, log_config_->stats().not_logged_.value()); + Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); @@ -224,6 +242,33 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { EXPECT_EQ(false, filter_meta.fields().at("access_log_hint").bool_value()); } +TEST_F(RoleBasedAccessControlFilterTest, AllowNoChangeLog) { + setDestinationPort(123); + setMetadata(); + + EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); + EXPECT_EQ(0U, config_->stats().logged_.value()); + EXPECT_EQ(0U, config_->stats().not_logged_.value()); + + auto& filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); + // Check that Allow action does not set 'envoy.log' metadata + EXPECT_EQ(filter_meta.fields().end(), filter_meta.fields().find("envoy.log")); + + // setDestinationPort(123); + // setMetadata(); + + // EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); + // filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); + // EXPECT_EQ("yes", req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac).fields().at("envoy.log").string_value()); + + // setDestinationPort(123); + // setMetadata(); + + // filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); + // EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); + // EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); +} + } // namespace } // namespace RBACFilter } // namespace HttpFilters diff --git a/test/extensions/filters/network/rbac/filter_test.cc b/test/extensions/filters/network/rbac/filter_test.cc index 2e8fd2642da33..0be73d361232e 100644 --- a/test/extensions/filters/network/rbac/filter_test.cc +++ b/test/extensions/filters/network/rbac/filter_test.cc @@ -22,8 +22,10 @@ namespace RBACFilter { class RoleBasedAccessControlNetworkFilterTest : public testing::Test { public: - RoleBasedAccessControlFilterConfigSharedPtr setupConfig(bool with_policy = true, - bool continuous = false) { + RoleBasedAccessControlFilterConfigSharedPtr + setupConfig(bool with_policy = true, bool continuous = false, + envoy::config::rbac::v3::RBAC::Action action = envoy::config::rbac::v3::RBAC::ALLOW) { + envoy::extensions::filters::network::rbac::v3::RBAC config; config.set_stat_prefix("tcp."); @@ -34,7 +36,7 @@ class RoleBasedAccessControlNetworkFilterTest : public testing::Test { ".*cncf.io"); policy_rules->add_rules()->set_destination_port(123); policy.add_principals()->set_any(true); - config.mutable_rules()->set_action(envoy::config::rbac::v3::RBAC::ALLOW); + config.mutable_rules()->set_action(action); (*config.mutable_rules()->mutable_policies())["foo"] = policy; envoy::config::rbac::v3::Policy shadow_policy; @@ -42,7 +44,7 @@ class RoleBasedAccessControlNetworkFilterTest : public testing::Test { shadow_policy_rules->add_rules()->mutable_requested_server_name()->set_exact("xyz.cncf.io"); shadow_policy_rules->add_rules()->set_destination_port(456); shadow_policy.add_principals()->set_any(true); - config.mutable_shadow_rules()->set_action(envoy::config::rbac::v3::RBAC::ALLOW); + config.mutable_shadow_rules()->set_action(action); (*config.mutable_shadow_rules()->mutable_policies())["bar"] = shadow_policy; } @@ -79,6 +81,12 @@ class RoleBasedAccessControlNetworkFilterTest : public testing::Test { Protobuf::MapPair(NetworkFilterNames::get().Rbac, obj)); })); + + ON_CALL(stream_info_, setDynamicMetadata("common", _)) + .WillByDefault(Invoke([this](const std::string&, const ProtobufWkt::Struct& obj) { + stream_info_.metadata_.mutable_filter_metadata()->insert( + Protobuf::MapPair("common", obj)); + })); } NiceMock callbacks_; @@ -173,6 +181,71 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, Denied) { EXPECT_EQ("allowed", filter_meta.fields().at("shadow_engine_result").string_value()); } +TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldLog) { + config_ = setupConfig(true, false, envoy::config::rbac::v3::RBAC::LOG); + filter_ = std::make_unique(config_); + filter_->initializeReadFilterCallbacks(callbacks_); + + setDestinationPort(123); + setMetadata(); + + EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(data_, false)); + EXPECT_EQ(1U, config_->stats().allowed_.value()); + EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); + + // Buffer::OwnedImpl data(""); + // EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); + // EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); + + auto filter_meta = stream_info_.dynamicMetadata().filter_metadata().at("common"); + EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); +} + +TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldNotLog) { + config_ = setupConfig(true, false, envoy::config::rbac::v3::RBAC::LOG); + filter_ = std::make_unique(config_); + filter_->initializeReadFilterCallbacks(callbacks_); + + setDestinationPort(456); + setMetadata(); + + EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(data_, false)); + EXPECT_EQ(1U, config_->stats().allowed_.value()); + EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); + + // Buffer::OwnedImpl data(""); + // EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); + // EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); + + auto filter_meta = stream_info_.dynamicMetadata().filter_metadata().at("common"); + EXPECT_EQ("no", filter_meta.fields().at("envoy.log").string_value()); +} + +TEST_F(RoleBasedAccessControlNetworkFilterTest, AllowNoChangeLog) { + setDestinationPort(123); + setMetadata(); + + EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(data_, false)); + + auto filter_meta = stream_info_.dynamicMetadata().filter_metadata().at("common"); + // Check that Allow action does not set 'envoy.log' metadata + EXPECT_EQ(filter_meta.fields().end(), filter_meta.fields().find("envoy.log")); + + // setDestinationPort(123); + // setMetadata(); + + // EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); + // filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); + // EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); + + // setDestinationPort(123); + // setMetadata(); + + // filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); + // EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); + // EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); +} + } // namespace RBACFilter } // namespace NetworkFilters } // namespace Extensions From 73ed999ebffdbe5689acccc4ca909df93cd9cba6 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Wed, 1 Jul 2020 19:51:41 +0000 Subject: [PATCH 16/39] added clarification to proto and previous versioning option Signed-off-by: davidraskin --- api/envoy/config/accesslog/v3/accesslog.proto | 7 +++ .../config/accesslog/v4alpha/accesslog.proto | 11 +--- .../common/access_log/access_log_impl_test.cc | 52 +++++++++---------- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/api/envoy/config/accesslog/v3/accesslog.proto b/api/envoy/config/accesslog/v3/accesslog.proto index 8ea60dfbc762e..cd75323324639 100644 --- a/api/envoy/config/accesslog/v3/accesslog.proto +++ b/api/envoy/config/accesslog/v3/accesslog.proto @@ -285,6 +285,7 @@ message GrpcStatusFilter { bool exclude = 2; } +<<<<<<< HEAD // Filters based on matching dynamic metadata. message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = @@ -293,6 +294,12 @@ message MetadataFilter { // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata // set the filter to "envoy.common" and the path to "access_log_hint". type.matcher.v3.MetadataMatcher matcher = 1; +======= +//Filters based on dynamic metadata log key +message LogKeyFilter { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.filter.accesslog.v2.LogKeyFilter"; +>>>>>>> df71aafb0... added clarification to proto and previous versioning option } // Extension filter is statically registered at runtime. diff --git a/api/envoy/config/accesslog/v4alpha/accesslog.proto b/api/envoy/config/accesslog/v4alpha/accesslog.proto index f919f11f108f7..57d9647fa87a1 100644 --- a/api/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/api/envoy/config/accesslog/v4alpha/accesslog.proto @@ -92,17 +92,14 @@ message AccessLogFilter { // gRPC status filter. GrpcStatusFilter grpc_status_filter = 10; + // Log key filter LogKeyFilter log_key_filter = 11; // Extension filter. -<<<<<<< HEAD ExtensionFilter extension_filter = 11; // Metadata Filter MetadataFilter metadata_filter = 12; -======= - ExtensionFilter extension_filter = 12; ->>>>>>> c7e38e439... rbac log action for network filter + log key access log filter } } @@ -290,7 +287,6 @@ message GrpcStatusFilter { bool exclude = 2; } -<<<<<<< HEAD // Filters based on matching dynamic metadata. message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = @@ -299,11 +295,6 @@ message MetadataFilter { // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata // set the filter to "envoy.common" and the path to "access_log_hint". type.matcher.v4alpha.MetadataMatcher matcher = 1; -======= -message LogKeyFilter { - option (udpa.annotations.versioning).previous_message_type = - "envoy.config.accesslog.v3.LogKeyFilter"; ->>>>>>> c7e38e439... rbac log action for network filter + log key access log filter } // Extension filter is statically registered at runtime. diff --git a/test/common/access_log/access_log_impl_test.cc b/test/common/access_log/access_log_impl_test.cc index 3b4aacd6bbf1d..1130638e31ef9 100644 --- a/test/common/access_log/access_log_impl_test.cc +++ b/test/common/access_log/access_log_impl_test.cc @@ -474,32 +474,32 @@ name: accesslog } } -TEST_F(AccessLogImplTest, LogKey) { - - const std::string yaml = R"EOF( -name: accesslog -filter: - log_key_filter: {} -typed_config: - "@type": type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog - path: /dev/null - )EOF"; - - InstanceSharedPtr logger = AccessLogFactory::fromProto(parseAccessLogFromV2Yaml(yaml), context_); - ProtobufWkt::Struct metrics; - auto& fields = *metrics.mutable_fields(); - *fields["access_log_policy"].mutable_string_value() = "no"; - stream_info_.setDynamicMetadata("envoy.common", metrics); - - EXPECT_CALL(*file_, write(_)).Times(0); - logger->log(&request_headers_, &response_headers_, &response_trailers_, stream_info_); - - *fields["access_log_policy"].mutable_string_value() = "yes"; - stream_info_.setDynamicMetadata("envoy.common", metrics); - - EXPECT_CALL(*file_, write(_)); - logger->log(&request_headers_, &response_headers_, &response_trailers_, stream_info_); -} +// TEST_F(AccessLogImplTest, LogKey) { + +// const std::string yaml = R"EOF( +// name: accesslog +// filter: +// log_key_filter: {} +// typed_config: +// "@type": type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog +// path: /dev/null +// )EOF"; + +// InstanceSharedPtr logger = AccessLogFactory::fromProto(parseAccessLogFromV2Yaml(yaml), context_); +// ProtobufWkt::Struct metrics; +// auto& fields = *metrics.mutable_fields(); +// *fields["access_log_policy"].mutable_string_value() = "no"; +// stream_info_.setDynamicMetadata("envoy.common", metrics); + +// EXPECT_CALL(*file_, write(_)).Times(0); +// logger->log(&request_headers_, &response_headers_, &response_trailers_, stream_info_); + +// *fields["access_log_policy"].mutable_string_value() = "yes"; +// stream_info_.setDynamicMetadata("envoy.common", metrics); + +// EXPECT_CALL(*file_, write(_)); +// logger->log(&request_headers_, &response_headers_, &response_trailers_, stream_info_); +// } TEST(AccessLogImplTestCtor, FiltersMissingInOrAndFilter) { From c2dd767deb001f126acb6ef10fbf1684d1ff10c8 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 7 Jul 2020 17:39:05 +0000 Subject: [PATCH 17/39] Updated documentation for access_log.proto Signed-off-by: davidraskin --- api/envoy/config/accesslog/v3/accesslog.proto | 7 ------- 1 file changed, 7 deletions(-) diff --git a/api/envoy/config/accesslog/v3/accesslog.proto b/api/envoy/config/accesslog/v3/accesslog.proto index cd75323324639..8ea60dfbc762e 100644 --- a/api/envoy/config/accesslog/v3/accesslog.proto +++ b/api/envoy/config/accesslog/v3/accesslog.proto @@ -285,7 +285,6 @@ message GrpcStatusFilter { bool exclude = 2; } -<<<<<<< HEAD // Filters based on matching dynamic metadata. message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = @@ -294,12 +293,6 @@ message MetadataFilter { // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata // set the filter to "envoy.common" and the path to "access_log_hint". type.matcher.v3.MetadataMatcher matcher = 1; -======= -//Filters based on dynamic metadata log key -message LogKeyFilter { - option (udpa.annotations.versioning).previous_message_type = - "envoy.config.filter.accesslog.v2.LogKeyFilter"; ->>>>>>> df71aafb0... added clarification to proto and previous versioning option } // Extension filter is statically registered at runtime. From 5471397d5b91e5762268f94d6e6048a5064f20a4 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Thu, 16 Jul 2020 20:32:18 +0000 Subject: [PATCH 18/39] Implement metadata access log filter Signed-off-by: davidraskin --- .../config/accesslog/v4alpha/accesslog.proto | 3 --- source/common/access_log/access_log_impl.cc | 24 ++++--------------- source/common/access_log/access_log_impl.h | 11 --------- 3 files changed, 5 insertions(+), 33 deletions(-) diff --git a/api/envoy/config/accesslog/v4alpha/accesslog.proto b/api/envoy/config/accesslog/v4alpha/accesslog.proto index 57d9647fa87a1..c890384b48b28 100644 --- a/api/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/api/envoy/config/accesslog/v4alpha/accesslog.proto @@ -92,9 +92,6 @@ message AccessLogFilter { // gRPC status filter. GrpcStatusFilter grpc_status_filter = 10; - // Log key filter - LogKeyFilter log_key_filter = 11; - // Extension filter. ExtensionFilter extension_filter = 11; diff --git a/source/common/access_log/access_log_impl.cc b/source/common/access_log/access_log_impl.cc index cc98ee78a1133..b0134c4142391 100644 --- a/source/common/access_log/access_log_impl.cc +++ b/source/common/access_log/access_log_impl.cc @@ -76,6 +76,7 @@ FilterPtr FilterFactory::fromProto(const envoy::config::accesslog::v3::AccessLog case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kGrpcStatusFilter: MessageUtil::validate(config, validation_visitor); return FilterPtr{new GrpcStatusFilter(config.grpc_status_filter())}; +<<<<<<< HEAD <<<<<<< HEAD case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kMetadataFilter: return FilterPtr{new MetadataFilter(config.metadata_filter())}; @@ -83,6 +84,10 @@ FilterPtr FilterFactory::fromProto(const envoy::config::accesslog::v3::AccessLog case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kLogKeyFilter: return FilterPtr{new LogKeyFilter()}; >>>>>>> c7e38e439... rbac log action for network filter + log key access log filter +======= + case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kMetadataFilter: + return FilterPtr{new MetadataFilter(config.metadata_filter())}; +>>>>>>> cb01b16f4... Implement metadata access log filter case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kExtensionFilter: MessageUtil::validate(config, validation_visitor); { @@ -262,7 +267,6 @@ Grpc::Status::GrpcStatus GrpcStatusFilter::protoToGrpcStatus( return static_cast(status); } -<<<<<<< HEAD MetadataFilter::MetadataFilter(const envoy::config::accesslog::v3::MetadataFilter& config) : matcher_(Envoy::Matchers::MetadataMatcher(config.matcher())) {} bool MetadataFilter::evaluate(const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap&, @@ -270,24 +274,6 @@ bool MetadataFilter::evaluate(const StreamInfo::StreamInfo& info, const Http::Re const Http::ResponseTrailerMap&) const { return matcher_.match(info.dynamicMetadata()); -======= -bool LogKeyFilter::evaluate(const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap&, - const Http::ResponseHeaderMap&, - const Http::ResponseTrailerMap&) const { - - const auto& metadata = info.dynamicMetadata().filter_metadata(); - const auto& com_metadata = metadata.find("envoy.common"); - if (com_metadata != metadata.end()) { - const auto& key_it = com_metadata->second.fields().find("access_log_policy"); - if (key_it != com_metadata->second.fields().end()) { - std::string access_log_policy = key_it->second.string_value(); - return access_log_policy == "yes"; - } - } - - //If not set, do not filter log. - return true; ->>>>>>> c7e38e439... rbac log action for network filter + log key access log filter } InstanceSharedPtr AccessLogFactory::fromProto(const envoy::config::accesslog::v3::AccessLog& config, diff --git a/source/common/access_log/access_log_impl.h b/source/common/access_log/access_log_impl.h index 64f3e10809747..0313b19b9cab9 100644 --- a/source/common/access_log/access_log_impl.h +++ b/source/common/access_log/access_log_impl.h @@ -230,7 +230,6 @@ class GrpcStatusFilter : public Filter { }; /** -<<<<<<< HEAD * Filters requests based on dynamic metadata */ class MetadataFilter : public Filter { @@ -243,16 +242,6 @@ class MetadataFilter : public Filter { private: const Envoy::Matchers::MetadataMatcher matcher_; - - -======= - * Filters requests based on value of 'access_log_policy' key - */ -class LogKeyFilter : public Filter { - bool evaluate(const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap& request_headers, - const Http::ResponseHeaderMap& response_headers, - const Http::ResponseTrailerMap& response_trailers) const override; ->>>>>>> c7e38e439... rbac log action for network filter + log key access log filter }; /** From 30d7fd60b465f05020a8eb456647758b6fe2ff87 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Mon, 20 Jul 2020 18:46:58 +0000 Subject: [PATCH 19/39] Deleted old comments Signed-off-by: davidraskin --- .../filters/http/rbac/rbac_filter.cc | 5 +- .../filters/http/rbac/rbac_filter.h | 19 ------- .../filters/network/rbac/rbac_filter.cc | 2 - .../filters/common/rbac/engine_impl_test.cc | 6 -- .../http/rbac/rbac_filter_integration_test.cc | 56 +++++++++++-------- 5 files changed, 36 insertions(+), 52 deletions(-) diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index ea0498b7abd1d..f231425bbb200 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -78,9 +78,6 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo config_->engine(callbacks_->route(), Filters::Common::RBAC::EnforcementMode::Shadow); if (shadow_engine != nullptr) { - ProtobufWkt::Struct metrics; - auto& fields = *metrics.mutable_fields(); - std::string shadow_resp_code = Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().EngineResultAllowed; if (shadow_engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), @@ -94,6 +91,8 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().EngineResultDenied; } + ProtobufWkt::Struct metrics; + auto& fields = *metrics.mutable_fields(); if (!effective_policy_id.empty()) { *fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get() .ShadowEffectivePolicyIdField] diff --git a/source/extensions/filters/http/rbac/rbac_filter.h b/source/extensions/filters/http/rbac/rbac_filter.h index 4e8407cc52ffb..fe7369e34e6be 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.h +++ b/source/extensions/filters/http/rbac/rbac_filter.h @@ -7,11 +7,6 @@ #include "envoy/stats/scope.h" #include "envoy/stats/stats_macros.h" -//Temporary for key-value setting -#include -#include "envoy/stream_info/filter_state.h" -// - #include "common/common/logger.h" #include "extensions/filters/common/rbac/engine_impl.h" @@ -22,20 +17,6 @@ namespace Extensions { namespace HttpFilters { namespace RBACFilter { -// class RBACShouldLogState : public StreamInfo::FilterState::Object { -// public: -// RBACShouldLogState(std::string value) { -// value_ = value; -// } - -// const std::string& value() const { return value_; } -// void setValue(std::string value) { -// value_.assign(value); -// } -// private: -// std::string value_{}; -// }; - class RoleBasedAccessControlRouteSpecificFilterConfig : public Router::RouteSpecificFilterConfig { public: RoleBasedAccessControlRouteSpecificFilterConfig( diff --git a/source/extensions/filters/network/rbac/rbac_filter.cc b/source/extensions/filters/network/rbac/rbac_filter.cc index 7104274e9db40..3bd8dd13f5e20 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.cc +++ b/source/extensions/filters/network/rbac/rbac_filter.cc @@ -8,8 +8,6 @@ #include "absl/strings/str_join.h" -#include - namespace Envoy { namespace Extensions { namespace NetworkFilters { diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index 5b5b7adb3f5bc..d19f39807d148 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -438,11 +438,9 @@ TEST(RoleBasedAccessControlEngineImpl, LogAllowUndecided) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); } @@ -461,11 +459,9 @@ TEST(RoleBasedAccessControlEngineImpl, LogDenyUndecided) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); } @@ -484,11 +480,9 @@ TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); checkEngine(engine, true, conn, headers, info); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - // EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); checkEngine(engine, true, conn, headers, info); } diff --git a/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc b/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc index d05bf3a7e967e..18f577a9c9e7f 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc @@ -291,28 +291,40 @@ TEST_P(RBACIntegrationTest, PathIgnoreCase) { } } -// TEST_P(RBACIntegrationTest, LogConnectionAllow) { -// config_helper_.addFilter(RBAC_CONFIG_WITH_LOG_ACTION); -// initialize(); - -// codec_client_ = makeHttpConnection(lookupPort("http")); - -// auto response = codec_client_->makeRequestWithBody( -// Http::TestRequestHeaderMapImpl{ -// {":method", "GET"}, -// {":path", "/"}, -// {":scheme", "http"}, -// {":authority", "host"}, -// {"x-forwarded-for", "10.0.0.1"}, -// }, -// 1024); -// response->waitForEndStream(); -// ASSERT_TRUE(response->complete()); -// EXPECT_EQ("200", response->headers().getStatusValue()); -// ASSERT_TRUE(response->headers().ContentLength()); -// EXPECT_NE("0", response->headers().getContentLengthValue()); -// EXPECT_THAT(response->body(), ::testing::IsEmpty()); -// } +std::string getRBACFilterConfig(const std::string& config_str) { + envoy::extensions::filters::http::rbac::v3::RBAC rbac_config; + envoy::extensions::filters::network::http_connection_manager::v3::HttpFilter http_filter; + + TestUtility::loadFromYaml(config_str, rbac_config); + + http_filter.set_name(Extensions::HttpFilters::HttpFilterNames::get().Rbac); + http_filter.mutable_typed_config()->PackFrom(rbac_config); + + return MessageUtil::getJsonStringFromMessage(http_filter); +} + +TEST_P(RBACIntegrationTest, LogConnectionAllow) { + config_helper_.addFilter(getRBACFilterConfig(RBAC_CONFIG_WITH_LOG_ACTION)); + initialize(); + + codec_client_ = makeHttpConnection(lookupPort("http")); + + auto response = codec_client_->makeRequestWithBody( + Http::TestRequestHeaderMapImpl{ + {":method", "POST"}, + {":path", "/"}, + {":scheme", "http"}, + {":authority", "host"}, + {"x-forwarded-for", "10.0.0.1"}, + }, + 1024); + waitForNextUpstreamRequest(); + upstream_request_->encodeHeaders(Http::TestResponseHeaderMapImpl{{":status", "200"}}, true); + + response->waitForEndStream(); + ASSERT_TRUE(response->complete()); + EXPECT_EQ("200", response->headers().getStatusValue()); +} } // namespace } // namespace Envoy From cd90223857078ad895e860cfad78c0b63d5c1d2d Mon Sep 17 00:00:00 2001 From: davidraskin Date: Mon, 20 Jul 2020 19:12:27 +0000 Subject: [PATCH 20/39] Reverted test changes to go proto generator Signed-off-by: davidraskin --- source/common/access_log/access_log_impl.cc | 1 - tools/api/generate_go_protobuf.py | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/source/common/access_log/access_log_impl.cc b/source/common/access_log/access_log_impl.cc index b0134c4142391..b935dbb590d97 100644 --- a/source/common/access_log/access_log_impl.cc +++ b/source/common/access_log/access_log_impl.cc @@ -21,7 +21,6 @@ #include "common/protobuf/utility.h" #include "common/stream_info/utility.h" #include "common/tracing/http_tracer_impl.h" - #include "absl/types/optional.h" namespace Envoy { diff --git a/tools/api/generate_go_protobuf.py b/tools/api/generate_go_protobuf.py index e26083f7dd090..746008c82c85f 100755 --- a/tools/api/generate_go_protobuf.py +++ b/tools/api/generate_go_protobuf.py @@ -9,13 +9,13 @@ import re TARGETS = '@envoy_api//...' -IMPORT_BASE = 'github.com/davidraskin/go-control-plane' +IMPORT_BASE = 'github.com/envoyproxy/go-control-plane' OUTPUT_BASE = 'build_go' REPO_BASE = 'go-control-plane' BRANCH = 'master' MIRROR_MSG = 'Mirrored from envoyproxy/envoy @ ' -USER_NAME = 'davidraskin' -USER_EMAIL = 'draskin@google.com' +USER_NAME = 'go-control-plane(CircleCI)' +USER_EMAIL = 'go-control-plane@users.noreply.github.com' def generateProtobufs(output): @@ -63,7 +63,7 @@ def git(repo, *args): def cloneGoProtobufs(repo): # Create a local clone of go-control-plane - git(None, 'clone', 'git@github.com:davidraskin/go-control-plane', repo) + git(None, 'clone', 'git@github.com:envoyproxy/go-control-plane', repo) git(repo, 'fetch') git(repo, 'checkout', '-B', BRANCH, 'origin/master') From 01f134cfc214cce1bf8f94d07a73ee34b24f9e14 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 21 Jul 2020 17:10:51 +0000 Subject: [PATCH 21/39] Full implementaiton, fix rebase Signed-off-by: davidraskin --- api/envoy/config/accesslog/v3/accesslog.proto | 5 +- .../config/accesslog/v4alpha/accesslog.proto | 5 +- .../envoy/config/accesslog/v3/accesslog.proto | 5 +- .../config/accesslog/v4alpha/accesslog.proto | 5 +- source/common/access_log/access_log_impl.cc | 35 ++++--- source/common/access_log/access_log_impl.h | 5 +- .../extensions/filters/common/rbac/utility.h | 2 + .../filters/http/rbac/rbac_filter.cc | 41 +++----- .../filters/network/rbac/rbac_filter.cc | 35 ++++--- .../common/access_log/access_log_impl_test.cc | 93 +++++++++++++------ .../filters/common/rbac/engine_impl_test.cc | 4 +- .../http/rbac/rbac_filter_integration_test.cc | 23 ++--- .../filters/http/rbac/rbac_filter_test.cc | 54 +++++------ .../filters/network/rbac/filter_test.cc | 56 ++++++----- 14 files changed, 205 insertions(+), 163 deletions(-) diff --git a/api/envoy/config/accesslog/v3/accesslog.proto b/api/envoy/config/accesslog/v3/accesslog.proto index 8ea60dfbc762e..c8a128c5ed2c0 100644 --- a/api/envoy/config/accesslog/v3/accesslog.proto +++ b/api/envoy/config/accesslog/v3/accesslog.proto @@ -290,9 +290,12 @@ message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.accesslog.v2.MetadataFilter"; - // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata + // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata, // set the filter to "envoy.common" and the path to "access_log_hint". type.matcher.v3.MetadataMatcher matcher = 1; + + // Default result if the key does not exist in dynamic metadata: if true, then log; if false, then don't log. + bool no_key_default = 2; } // Extension filter is statically registered at runtime. diff --git a/api/envoy/config/accesslog/v4alpha/accesslog.proto b/api/envoy/config/accesslog/v4alpha/accesslog.proto index c890384b48b28..099945448267e 100644 --- a/api/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/api/envoy/config/accesslog/v4alpha/accesslog.proto @@ -289,9 +289,12 @@ message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.accesslog.v3.MetadataFilter"; - // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata + // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata, // set the filter to "envoy.common" and the path to "access_log_hint". type.matcher.v4alpha.MetadataMatcher matcher = 1; + + // Default result if the key does not exist in dynamic metadata: if true, then log; if false, then don't log. + bool no_key_default = 2; } // Extension filter is statically registered at runtime. diff --git a/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto b/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto index a0da01263e1c9..9eee16c413c28 100644 --- a/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto +++ b/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto @@ -288,9 +288,12 @@ message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.accesslog.v2.MetadataFilter"; - // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata + // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata, // set the filter to "envoy.common" and the path to "access_log_hint". type.matcher.v3.MetadataMatcher matcher = 1; + + // Default result if the key does not exist in dynamic metadata: if true, then log; if false, then don't log. + bool no_key_default = 2; } // Extension filter is statically registered at runtime. diff --git a/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto b/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto index c890384b48b28..099945448267e 100644 --- a/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto @@ -289,9 +289,12 @@ message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.accesslog.v3.MetadataFilter"; - // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata + // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata, // set the filter to "envoy.common" and the path to "access_log_hint". type.matcher.v4alpha.MetadataMatcher matcher = 1; + + // Default result if the key does not exist in dynamic metadata: if true, then log; if false, then don't log. + bool no_key_default = 2; } // Extension filter is statically registered at runtime. diff --git a/source/common/access_log/access_log_impl.cc b/source/common/access_log/access_log_impl.cc index b935dbb590d97..daa50a100e240 100644 --- a/source/common/access_log/access_log_impl.cc +++ b/source/common/access_log/access_log_impl.cc @@ -75,18 +75,8 @@ FilterPtr FilterFactory::fromProto(const envoy::config::accesslog::v3::AccessLog case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kGrpcStatusFilter: MessageUtil::validate(config, validation_visitor); return FilterPtr{new GrpcStatusFilter(config.grpc_status_filter())}; -<<<<<<< HEAD -<<<<<<< HEAD case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kMetadataFilter: return FilterPtr{new MetadataFilter(config.metadata_filter())}; -======= - case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kLogKeyFilter: - return FilterPtr{new LogKeyFilter()}; ->>>>>>> c7e38e439... rbac log action for network filter + log key access log filter -======= - case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kMetadataFilter: - return FilterPtr{new MetadataFilter(config.metadata_filter())}; ->>>>>>> cb01b16f4... Implement metadata access log filter case envoy::config::accesslog::v3::AccessLogFilter::FilterSpecifierCase::kExtensionFilter: MessageUtil::validate(config, validation_visitor); { @@ -266,13 +256,30 @@ Grpc::Status::GrpcStatus GrpcStatusFilter::protoToGrpcStatus( return static_cast(status); } -MetadataFilter::MetadataFilter(const envoy::config::accesslog::v3::MetadataFilter& config) : matcher_(Envoy::Matchers::MetadataMatcher(config.matcher())) {} +MetadataFilter::MetadataFilter(const envoy::config::accesslog::v3::MetadataFilter& filter_config) + : matcher_config_(filter_config.matcher()), default_res_(filter_config.no_key_default()) {} bool MetadataFilter::evaluate(const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap&, - const Http::ResponseHeaderMap&, - const Http::ResponseTrailerMap&) const { + const Http::ResponseHeaderMap&, + const Http::ResponseTrailerMap&) const { + + auto matcher = Matchers::MetadataMatcher(matcher_config_); + + if (matcher.match(info.dynamicMetadata())) { + return true; + } + + auto present_matcher_config = envoy::type::matcher::v3::MetadataMatcher(matcher_config_); + present_matcher_config.mutable_value()->set_present_match(true); + + auto present_matcher = Matchers::MetadataMatcher(present_matcher_config); + + // If the key does not exist, return default_res_ + if(!present_matcher.match(info.dynamicMetadata())) { + return default_res_; + } - return matcher_.match(info.dynamicMetadata()); + return false; } InstanceSharedPtr AccessLogFactory::fromProto(const envoy::config::accesslog::v3::AccessLog& config, diff --git a/source/common/access_log/access_log_impl.h b/source/common/access_log/access_log_impl.h index 0313b19b9cab9..03f32599144ca 100644 --- a/source/common/access_log/access_log_impl.h +++ b/source/common/access_log/access_log_impl.h @@ -234,14 +234,15 @@ class GrpcStatusFilter : public Filter { */ class MetadataFilter : public Filter { public: - MetadataFilter(const envoy::config::accesslog::v3::MetadataFilter& config); + MetadataFilter(const envoy::config::accesslog::v3::MetadataFilter& filter_config); bool evaluate(const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap& request_headers, const Http::ResponseHeaderMap& response_headers, const Http::ResponseTrailerMap& response_trailers) const override; private: - const Envoy::Matchers::MetadataMatcher matcher_; + const envoy::type::matcher::v3::MetadataMatcher matcher_config_; + bool default_res_; }; /** diff --git a/source/extensions/filters/common/rbac/utility.h b/source/extensions/filters/common/rbac/utility.h index 48546bf950860..a3848deb62469 100644 --- a/source/extensions/filters/common/rbac/utility.h +++ b/source/extensions/filters/common/rbac/utility.h @@ -18,6 +18,8 @@ class DynamicMetadataKeys { const std::string ShadowEngineResultField{"shadow_engine_result"}; const std::string EngineResultAllowed{"allowed"}; const std::string EngineResultDenied{"denied"}; + const std::string AccessLogKey{"access_log_hint"}; + const std::string CommonNamespace{"envoy.common"}; }; using DynamicMetadataKeysSingleton = ConstSingleton; diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index f231425bbb200..cfe8b381c6bf3 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -20,6 +20,8 @@ struct RcDetailsValues { }; using RcDetails = ConstSingleton; +using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; + RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::http::rbac::v3::RBAC& proto_config, const std::string& stats_prefix, Stats::Scope& scope) @@ -108,24 +110,18 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo const auto engine = config_->engine(callbacks_->route(), Filters::Common::RBAC::EnforcementMode::Enforced); if (engine != nullptr) { -<<<<<<< HEAD - ProtobufWkt::Struct log_metadata; - auto& log_fields = *log_metadata.mutable_fields(); - // Set kRbacShouldLog to true if shouldLog; false otherwise - bool log_decision = - engine->shouldLog(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr); - log_fields["access_log_hint"].set_bool_value(log_decision); - callbacks_->streamInfo().setDynamicMetadata("envoy.common", log_metadata); -======= - // Set "envoy.log" to true if shouldLog; false otherwise - auto log_dec = + // Check log decision + LogDecision log_dec = engine->shouldLog(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr); - if (log_dec != Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided) { - bool log_yes = - log_dec == Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision::Yes; - *fields["envoy.log"].mutable_string_value() = log_yes ? "yes" : "no"; - - if (log_yes) { + if (log_dec != LogDecision::Undecided) { + ProtobufWkt::Struct log_metadata; + auto& log_fields = *log_metadata.mutable_fields(); + log_fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey] + .set_bool_value(log_dec == LogDecision::Yes); + callbacks_->streamInfo().setDynamicMetadata( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, log_metadata); + + if (log_dec == LogDecision::Yes) { ENVOY_LOG(debug, "request logged"); config_->stats().logged_.inc(); } else { @@ -133,8 +129,8 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo config_->stats().not_logged_.inc(); } } ->>>>>>> c7e38e439... rbac log action for network filter + log key access log filter - + + // Check authorization decision if (engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr)) { ENVOY_LOG(debug, "enforced allowed"); config_->stats().allowed_.inc(); @@ -148,15 +144,8 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo } } -<<<<<<< HEAD ENVOY_LOG(debug, "no engine, allowed by default"); return Http::FilterHeadersStatus::Continue; -======= - if (!metrics.fields().empty()) - callbacks_->streamInfo().setDynamicMetadata(HttpFilterNames::get().Rbac, metrics); - // ENVOY_LOG(debug, "no engine, allowed by default"); - return result; ->>>>>>> c7e38e439... rbac log action for network filter + log key access log filter } } // namespace RBACFilter diff --git a/source/extensions/filters/network/rbac/rbac_filter.cc b/source/extensions/filters/network/rbac/rbac_filter.cc index 3bd8dd13f5e20..6a94212fe15fa 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.cc +++ b/source/extensions/filters/network/rbac/rbac_filter.cc @@ -13,6 +13,8 @@ namespace Extensions { namespace NetworkFilters { namespace RBACFilter { +using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; + RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::network::rbac::v3::RBAC& proto_config, Stats::Scope& scope) : stats_(Filters::Common::RBAC::generateStats(proto_config.stat_prefix(), scope)), @@ -86,23 +88,30 @@ RoleBasedAccessControlFilter::checkEngine(Filters::Common::RBAC::EnforcementMode if (engine != nullptr) { std::string effective_policy_id; - if (mode == Filters::Common::RBAC::EnforcementMode::Enforced) { - //=====================================LogDecision========================== - ProtobufWkt::Struct metrics; - auto& fields = *metrics.mutable_fields(); - auto log_dec = engine->shouldLog(callbacks_->connection(), - callbacks_->connection().streamInfo(), &effective_policy_id); - if (log_dec != Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided) { - bool log_yes = - log_dec == Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision::Yes; - - *fields["envoy.log"].mutable_string_value() = log_yes ? "yes" : "no"; + // Check log decision + LogDecision log_dec = engine->shouldLog( + callbacks_->connection(), callbacks_->connection().streamInfo(), &effective_policy_id); + if (log_dec != LogDecision::Undecided) { + ProtobufWkt::Struct log_metadata; + auto& fields = *log_metadata.mutable_fields(); + fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey] + .set_bool_value(log_dec == LogDecision::Yes); + callbacks_->connection().streamInfo().setDynamicMetadata( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, + log_metadata); + + if (log_dec == LogDecision::Yes) { + ENVOY_LOG(debug, "request logged"); + config_->stats().logged_.inc(); + } else { + ENVOY_LOG(debug, "request not logged"); + config_->stats().not_logged_.inc(); + } } - - callbacks_->connection().streamInfo().setDynamicMetadata("common", metrics); } + // Check authorization decision if (engine->allowed(callbacks_->connection(), callbacks_->connection().streamInfo(), &effective_policy_id)) { if (mode == Filters::Common::RBAC::EnforcementMode::Shadow) { diff --git a/test/common/access_log/access_log_impl_test.cc b/test/common/access_log/access_log_impl_test.cc index 1130638e31ef9..32bc2189ac123 100644 --- a/test/common/access_log/access_log_impl_test.cc +++ b/test/common/access_log/access_log_impl_test.cc @@ -474,34 +474,6 @@ name: accesslog } } -// TEST_F(AccessLogImplTest, LogKey) { - -// const std::string yaml = R"EOF( -// name: accesslog -// filter: -// log_key_filter: {} -// typed_config: -// "@type": type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog -// path: /dev/null -// )EOF"; - -// InstanceSharedPtr logger = AccessLogFactory::fromProto(parseAccessLogFromV2Yaml(yaml), context_); -// ProtobufWkt::Struct metrics; -// auto& fields = *metrics.mutable_fields(); -// *fields["access_log_policy"].mutable_string_value() = "no"; -// stream_info_.setDynamicMetadata("envoy.common", metrics); - -// EXPECT_CALL(*file_, write(_)).Times(0); -// logger->log(&request_headers_, &response_headers_, &response_trailers_, stream_info_); - -// *fields["access_log_policy"].mutable_string_value() = "yes"; -// stream_info_.setDynamicMetadata("envoy.common", metrics); - -// EXPECT_CALL(*file_, write(_)); -// logger->log(&request_headers_, &response_headers_, &response_trailers_, stream_info_); -// } - - TEST(AccessLogImplTestCtor, FiltersMissingInOrAndFilter) { NiceMock context; @@ -1298,7 +1270,7 @@ name: accesslog filter: metadata_filter: matcher: - filter: "envoy.common" + filter: "some.namespace" path: - key: "a" - key: "b" @@ -1320,7 +1292,7 @@ name: accesslog auto& fields_c = *struct_c.mutable_fields(); fields_c["c"].set_bool_value(true); - stream_info.setDynamicMetadata("envoy.common", metadata_val); + stream_info.setDynamicMetadata("some.namespace", metadata_val); const InstanceSharedPtr log = AccessLogFactory::fromProto(parseAccessLogFromV2Yaml(yaml), context_); @@ -1333,6 +1305,67 @@ name: accesslog EXPECT_CALL(*file_, write(_)).Times(0); } +TEST_F(AccessLogImplTest, MetadataFilterNoKey) { + const std::string default_true_yaml = R"EOF( +name: accesslog +filter: + metadata_filter: + matcher: + filter: "some.namespace" + path: + - key: "a" + - key: "b" + - key: "c" + value: + bool_match: true + no_key_default: true + +typed_config: + "@type": type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog + path: /dev/null + )EOF"; + + const std::string default_false_yaml = R"EOF( +name: accesslog +filter: + metadata_filter: + matcher: + filter: "some.namespace" + path: + - key: "a" + - key: "b" + - key: "c" + value: + bool_match: true + no_key_default: false + +typed_config: + "@type": type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog + path: /dev/null + )EOF"; + + TestStreamInfo stream_info; + ProtobufWkt::Struct metadata_val; + auto& fields_a = *metadata_val.mutable_fields(); + auto& struct_b = *fields_a["a"].mutable_struct_value(); + auto& fields_b = *struct_b.mutable_fields(); + fields_b["b"].set_bool_value(true); + + stream_info.setDynamicMetadata("some.namespace", metadata_val); + + const InstanceSharedPtr default_false_log = + AccessLogFactory::fromProto(parseAccessLogFromV2Yaml(default_false_yaml), context_); + EXPECT_CALL(*file_, write(_)).Times(0); + + default_false_log->log(&request_headers_, &response_headers_, &response_trailers_, stream_info); + + const InstanceSharedPtr default_true_log = + AccessLogFactory::fromProto(parseAccessLogFromV2Yaml(default_true_yaml), context_); + EXPECT_CALL(*file_, write(_)).Times(1); + + default_true_log->log(&request_headers_, &response_headers_, &response_trailers_, stream_info); +} + class TestHeaderFilterFactory : public ExtensionFilterFactory { public: ~TestHeaderFilterFactory() override = default; diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index d19f39807d148..1f4194306cfd7 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -137,7 +137,7 @@ TEST(RoleBasedAccessControlEngineImpl, InvalidConfig) { } } -TEST(RoleBasedAccessControlEngineImpl, AllowedWhitelist) { +TEST(RoleBasedAccessControlEngineImpl, AllowedAllowlist) { envoy::config::rbac::v3::Policy policy; policy.add_permissions()->set_destination_port(123); policy.add_principals()->set_any(true); @@ -160,7 +160,7 @@ TEST(RoleBasedAccessControlEngineImpl, AllowedWhitelist) { checkEngine(engine, false, conn, headers, info); } -TEST(RoleBasedAccessControlEngineImpl, DeniedBlacklist) { +TEST(RoleBasedAccessControlEngineImpl, DeniedDenylist) { envoy::config::rbac::v3::Policy policy; policy.add_permissions()->set_destination_port(123); policy.add_principals()->set_any(true); diff --git a/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc b/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc index 18f577a9c9e7f..5e4dab16418ef 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc @@ -64,19 +64,16 @@ name: rbac - any: true )EOF"; -// const std::string RBAC_CONFIG_WITH_LOG_ACTION = R"EOF( -// name: rbac -// typed_config: -// "@type": type.googleapis.com/envoy.config.filter.http.rbac.v3.RBAC -// rules: -// action: LOG -// policies: -// foo: -// permissions: -// - header: { name: ":method", exact_match: "GET" } -// principals: -// - any: true -// )EOF"; +const std::string RBAC_CONFIG_WITH_LOG_ACTION = R"EOF( +rules: + action: LOG + policies: + foo: + permissions: + - header: { name: ":method", exact_match: "GET" } + principals: + - any: true +)EOF"; using RBACIntegrationTest = HttpProtocolIntegrationTest; diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index 1d914e3cc3e50..6a3da375b6768 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -72,6 +72,15 @@ class RoleBasedAccessControlFilterTest : public testing::Test { ON_CALL(connection_, requestedServerName()).WillByDefault(Return(requested_server_name_)); } + void checkAccessLogMetadata(bool expected) { + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); + EXPECT_EQ(expected, + filter_meta.fields() + .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) + .bool_value()); + } + void setMetadata() { ON_CALL(req_info_, setDynamicMetadata(HttpFilterNames::get().Rbac, _)) .WillByDefault(Invoke([this](const std::string&, const ProtobufWkt::Struct& obj) { @@ -80,11 +89,13 @@ class RoleBasedAccessControlFilterTest : public testing::Test { obj)); })); - ON_CALL(req_info_, setDynamicMetadata("envoy.common", _)) + ON_CALL(req_info_, + setDynamicMetadata( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, _)) .WillByDefault(Invoke([this](const std::string&, const ProtobufWkt::Struct& obj) { req_info_.metadata_.mutable_filter_metadata()->insert( - Protobuf::MapPair("envoy.common", - obj)); + Protobuf::MapPair( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, obj)); })); } @@ -131,11 +142,10 @@ TEST_F(RoleBasedAccessControlFilterTest, RequestedServerName) { EXPECT_EQ(Http::FilterDataStatus::Continue, filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_.decodeTrailers(trailers_)); - //Check Log + // Check Log setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); - auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); - EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); + checkAccessLogMetadata(true); } TEST_F(RoleBasedAccessControlFilterTest, Path) { @@ -157,11 +167,10 @@ TEST_F(RoleBasedAccessControlFilterTest, Path) { }; EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_.decodeHeaders(headers, false)); - //Check Log + // Check Log setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers, false)); - auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); - EXPECT_EQ("no", filter_meta.fields().at("envoy.log").string_value()); + checkAccessLogMetadata(false); } TEST_F(RoleBasedAccessControlFilterTest, Denied) { @@ -219,8 +228,7 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); - auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at("envoy.common"); - EXPECT_EQ(true, filter_meta.fields().at("access_log_hint").bool_value()); + checkAccessLogMetadata(true); } TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { @@ -238,8 +246,7 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); - auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at("envoy.common"); - EXPECT_EQ(false, filter_meta.fields().at("access_log_hint").bool_value()); + checkAccessLogMetadata(false); } TEST_F(RoleBasedAccessControlFilterTest, AllowNoChangeLog) { @@ -250,23 +257,10 @@ TEST_F(RoleBasedAccessControlFilterTest, AllowNoChangeLog) { EXPECT_EQ(0U, config_->stats().logged_.value()); EXPECT_EQ(0U, config_->stats().not_logged_.value()); - auto& filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); - // Check that Allow action does not set 'envoy.log' metadata - EXPECT_EQ(filter_meta.fields().end(), filter_meta.fields().find("envoy.log")); - - // setDestinationPort(123); - // setMetadata(); - - // EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); - // filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); - // EXPECT_EQ("yes", req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac).fields().at("envoy.log").string_value()); - - // setDestinationPort(123); - // setMetadata(); - - // filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); - // EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); - // EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); + // Check that Allow action does not set access log metadata + EXPECT_EQ(req_info_.dynamicMetadata().filter_metadata().end(), + req_info_.dynamicMetadata().filter_metadata().find( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace)); } } // namespace diff --git a/test/extensions/filters/network/rbac/filter_test.cc b/test/extensions/filters/network/rbac/filter_test.cc index 0be73d361232e..ae29c1667c089 100644 --- a/test/extensions/filters/network/rbac/filter_test.cc +++ b/test/extensions/filters/network/rbac/filter_test.cc @@ -74,6 +74,15 @@ class RoleBasedAccessControlNetworkFilterTest : public testing::Test { .WillByDefault(Return(requested_server_name_)); } + void checkAccessLogMetadata(bool expected) { + auto filter_meta = stream_info_.dynamicMetadata().filter_metadata().at( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); + EXPECT_EQ(expected, + filter_meta.fields() + .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) + .bool_value()); + } + void setMetadata() { ON_CALL(stream_info_, setDynamicMetadata(NetworkFilterNames::get().Rbac, _)) .WillByDefault(Invoke([this](const std::string&, const ProtobufWkt::Struct& obj) { @@ -82,10 +91,13 @@ class RoleBasedAccessControlNetworkFilterTest : public testing::Test { obj)); })); - ON_CALL(stream_info_, setDynamicMetadata("common", _)) + ON_CALL(stream_info_, + setDynamicMetadata( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, _)) .WillByDefault(Invoke([this](const std::string&, const ProtobufWkt::Struct& obj) { stream_info_.metadata_.mutable_filter_metadata()->insert( - Protobuf::MapPair("common", obj)); + Protobuf::MapPair( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, obj)); })); } @@ -181,6 +193,7 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, Denied) { EXPECT_EQ("allowed", filter_meta.fields().at("shadow_engine_result").string_value()); } +// Log Tests TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldLog) { config_ = setupConfig(true, false, envoy::config::rbac::v3::RBAC::LOG); filter_ = std::make_unique(config_); @@ -193,12 +206,10 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldLog) { EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - // Buffer::OwnedImpl data(""); - // EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); - // EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); + EXPECT_EQ(1U, config_->stats().logged_.value()); + EXPECT_EQ(0U, config_->stats().not_logged_.value()); - auto filter_meta = stream_info_.dynamicMetadata().filter_metadata().at("common"); - EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); + checkAccessLogMetadata(true); } TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldNotLog) { @@ -213,12 +224,10 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldNotLog) { EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - // Buffer::OwnedImpl data(""); - // EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); - // EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); + EXPECT_EQ(0U, config_->stats().logged_.value()); + EXPECT_EQ(1U, config_->stats().not_logged_.value()); - auto filter_meta = stream_info_.dynamicMetadata().filter_metadata().at("common"); - EXPECT_EQ("no", filter_meta.fields().at("envoy.log").string_value()); + checkAccessLogMetadata(false); } TEST_F(RoleBasedAccessControlNetworkFilterTest, AllowNoChangeLog) { @@ -226,24 +235,13 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, AllowNoChangeLog) { setMetadata(); EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(data_, false)); + EXPECT_EQ(0U, config_->stats().logged_.value()); + EXPECT_EQ(0U, config_->stats().not_logged_.value()); - auto filter_meta = stream_info_.dynamicMetadata().filter_metadata().at("common"); - // Check that Allow action does not set 'envoy.log' metadata - EXPECT_EQ(filter_meta.fields().end(), filter_meta.fields().find("envoy.log")); - - // setDestinationPort(123); - // setMetadata(); - - // EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); - // filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); - // EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); - - // setDestinationPort(123); - // setMetadata(); - - // filter_meta = req_info_.dynamicMetadata().filter_metadata().at(HttpFilterNames::get().Rbac); - // EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); - // EXPECT_EQ("yes", filter_meta.fields().at("envoy.log").string_value()); + // Check that Allow action does not set access log metadata + EXPECT_EQ(stream_info_.dynamicMetadata().filter_metadata().end(), + stream_info_.dynamicMetadata().filter_metadata().find( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace)); } } // namespace RBACFilter From 853103fd5f2cc9126453d076665269cd1ff649be Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 21 Jul 2020 21:25:17 +0000 Subject: [PATCH 22/39] Formatting Signed-off-by: davidraskin --- source/common/access_log/access_log_impl.cc | 3 ++- source/common/access_log/access_log_impl.h | 10 ++++---- .../filters/common/rbac/engine_impl.cc | 23 +++++++++--------- .../filters/common/rbac/engine_impl.h | 8 ++++--- .../filters/http/rbac/rbac_filter.cc | 2 +- .../common/access_log/access_log_impl_test.cc | 2 +- .../filters/common/rbac/engine_impl_test.cc | 24 ++++++++++++------- 7 files changed, 42 insertions(+), 30 deletions(-) diff --git a/source/common/access_log/access_log_impl.cc b/source/common/access_log/access_log_impl.cc index e757a4199c422..c33ee3ba39e45 100644 --- a/source/common/access_log/access_log_impl.cc +++ b/source/common/access_log/access_log_impl.cc @@ -21,6 +21,7 @@ #include "common/protobuf/utility.h" #include "common/stream_info/utility.h" #include "common/tracing/http_tracer_impl.h" + #include "absl/types/optional.h" namespace Envoy { @@ -275,7 +276,7 @@ bool MetadataFilter::evaluate(const StreamInfo::StreamInfo& info, const Http::Re auto present_matcher = Matchers::MetadataMatcher(present_matcher_config); // If the key does not exist, return default_res_ - if(!present_matcher.match(info.dynamicMetadata())) { + if (!present_matcher.match(info.dynamicMetadata())) { return default_res_; } diff --git a/source/common/access_log/access_log_impl.h b/source/common/access_log/access_log_impl.h index 2c38954e9d07b..cec4f4b68429f 100644 --- a/source/common/access_log/access_log_impl.h +++ b/source/common/access_log/access_log_impl.h @@ -13,10 +13,10 @@ #include "envoy/server/access_log_config.h" #include "envoy/type/v3/percent.pb.h" +#include "common/common/matchers.h" #include "common/grpc/status.h" #include "common/http/header_utility.h" #include "common/protobuf/protobuf.h" -#include "common/common/matchers.h" #include "absl/hash/hash.h" @@ -230,15 +230,15 @@ class GrpcStatusFilter : public Filter { }; /** - * Filters requests based on dynamic metadata - */ + * Filters requests based on dynamic metadata + */ class MetadataFilter : public Filter { public: MetadataFilter(const envoy::config::accesslog::v3::MetadataFilter& filter_config); bool evaluate(const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap& request_headers, - const Http::ResponseHeaderMap& response_headers, - const Http::ResponseTrailerMap& response_trailers) const override; + const Http::ResponseHeaderMap& response_headers, + const Http::ResponseTrailerMap& response_trailers) const override; private: const envoy::type::matcher::v3::MetadataMatcher matcher_config_; diff --git a/source/extensions/filters/common/rbac/engine_impl.cc b/source/extensions/filters/common/rbac/engine_impl.cc index 182624f43e6cd..fb01e8ccc084b 100644 --- a/source/extensions/filters/common/rbac/engine_impl.cc +++ b/source/extensions/filters/common/rbac/engine_impl.cc @@ -14,7 +14,8 @@ using LogDecision = RoleBasedAccessControlEngine::LogDecision; RoleBasedAccessControlEngineImpl::RoleBasedAccessControlEngineImpl( const envoy::config::rbac::v3::RBAC& rules) - : allowed_if_matched_(rules.action() == envoy::config::rbac::v3::RBAC::ALLOW), action_log_(rules.action() == envoy::config::rbac::v3::RBAC::LOG) { + : allowed_if_matched_(rules.action() == envoy::config::rbac::v3::RBAC::ALLOW), + action_log_(rules.action() == envoy::config::rbac::v3::RBAC::LOG) { // guard expression builder by presence of a condition in policies for (const auto& policy : rules.policies()) { if (policy.second.has_condition()) { @@ -32,8 +33,8 @@ bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connec const Envoy::Http::RequestHeaderMap& headers, const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const { - // Automatically allow if LOG action - if(action_log_) { + // Automatically allow if LOG action + if (action_log_) { return true; } @@ -63,11 +64,10 @@ bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connec effective_policy_id); } -LogDecision RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const { - if(!action_log_) { +LogDecision RoleBasedAccessControlEngineImpl::shouldLog( + const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const { + if (!action_log_) { return LogDecision::Undecided; } @@ -88,9 +88,10 @@ LogDecision RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connectio } LogDecision RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& connection, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const { - return shouldLog(connection, *Http::StaticEmptyHeaders::get().request_headers, info, effective_policy_id); + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const { + return shouldLog(connection, *Http::StaticEmptyHeaders::get().request_headers, info, + effective_policy_id); } } // namespace RBAC diff --git a/source/extensions/filters/common/rbac/engine_impl.h b/source/extensions/filters/common/rbac/engine_impl.h index 620fc3f284fa0..87229a51a4e13 100644 --- a/source/extensions/filters/common/rbac/engine_impl.h +++ b/source/extensions/filters/common/rbac/engine_impl.h @@ -21,11 +21,13 @@ class RoleBasedAccessControlEngineImpl : public RoleBasedAccessControlEngine, No bool allowed(const Network::Connection& connection, const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const override; - LogDecision shouldLog(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const override; + LogDecision shouldLog(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const override; LogDecision shouldLog(const Network::Connection& connection, const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const override; + std::string* effective_policy_id) const override; private: const bool allowed_if_matched_; diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index cfe8b381c6bf3..0c187f5cf541d 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -129,7 +129,7 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo config_->stats().not_logged_.inc(); } } - + // Check authorization decision if (engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr)) { ENVOY_LOG(debug, "enforced allowed"); diff --git a/test/common/access_log/access_log_impl_test.cc b/test/common/access_log/access_log_impl_test.cc index dc9c4c13b2749..8d042cfcc1cdd 100644 --- a/test/common/access_log/access_log_impl_test.cc +++ b/test/common/access_log/access_log_impl_test.cc @@ -1326,7 +1326,7 @@ name: accesslog path: /dev/null )EOF"; - const std::string default_false_yaml = R"EOF( + const std::string default_false_yaml = R"EOF( name: accesslog filter: metadata_filter: diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index 1f4194306cfd7..47b48362a80b4 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -272,7 +272,8 @@ TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, Envoy::Network::MockConnection()); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, + Envoy::Network::MockConnection()); } TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { @@ -312,7 +313,8 @@ TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, Envoy::Network::MockConnection(), headers); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, + Envoy::Network::MockConnection(), headers); } TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { @@ -361,7 +363,8 @@ TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, Envoy::Network::MockConnection(), headers, info); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, + Envoy::Network::MockConnection(), headers, info); } TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { @@ -389,7 +392,8 @@ TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, conn, headers, info); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, conn, headers, + info); } // Log tests tests @@ -438,10 +442,12 @@ TEST(RoleBasedAccessControlEngineImpl, LogAllowUndecided) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, + info); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, + info); } TEST(RoleBasedAccessControlEngineImpl, LogDenyUndecided) { @@ -459,10 +465,12 @@ TEST(RoleBasedAccessControlEngineImpl, LogDenyUndecided) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, + info); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, info); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, + info); } TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { From d479bd676f14ec1f39417bcad52750ab5aa398e9 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Fri, 31 Jul 2020 18:27:44 +0000 Subject: [PATCH 23/39] Fix missed merge conflict Signed-off-by: davidraskin --- api/envoy/config/accesslog/v4alpha/accesslog.proto | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/api/envoy/config/accesslog/v4alpha/accesslog.proto b/api/envoy/config/accesslog/v4alpha/accesslog.proto index c65d68ed0a82f..bd4bcd48c4b4a 100644 --- a/api/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/api/envoy/config/accesslog/v4alpha/accesslog.proto @@ -294,26 +294,15 @@ message GrpcStatusFilter { } // Filters based on matching dynamic metadata. -<<<<<<< HEAD -======= // If the matcher path and key correspond to an existing key in dynamic // metadata, the request is logged only if the matcher value is equal to the // metadata value. If the matcher path and key *do not* correspond to an // existing key in dynamic metadata, the request is logged only if // match_if_key_not_found is "true" or unset. ->>>>>>> upstream/master message MetadataFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.accesslog.v3.MetadataFilter"; -<<<<<<< HEAD - // Matcher to check metadata for specified value. For example, to match on the access_log_hint metadata, - // set the filter to "envoy.common" and the path to "access_log_hint". - type.matcher.v4alpha.MetadataMatcher matcher = 1; - - // Default result if the key does not exist in dynamic metadata: if true, then log; if false, then don't log. - bool no_key_default = 2; -======= // Matcher to check metadata for specified value. For example, to match on the // access_log_hint metadata, set the filter to "envoy.common" and the path to // "access_log_hint", and the value to "true". @@ -322,7 +311,6 @@ message MetadataFilter { // Default result if the key does not exist in dynamic metadata: if unset or // true, then log; if false, then don't log. google.protobuf.BoolValue match_if_key_not_found = 2; ->>>>>>> upstream/master } // Extension filter is statically registered at runtime. From 8bf91f5e25c7c690f96cb1b1f81f8c4c7d750686 Mon Sep 17 00:00:00 2001 From: David Raskin <66272127+davidraskin@users.noreply.github.com> Date: Fri, 31 Jul 2020 17:45:57 -0500 Subject: [PATCH 24/39] Update network_filter rbac_filter.rst Co-authored-by: Matt Klein Signed-off-by: davidraskin --- .../configuration/listeners/network_filters/rbac_filter.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/root/configuration/listeners/network_filters/rbac_filter.rst b/docs/root/configuration/listeners/network_filters/rbac_filter.rst index 4a01762bc57cc..68ae9f2172d46 100644 --- a/docs/root/configuration/listeners/network_filters/rbac_filter.rst +++ b/docs/root/configuration/listeners/network_filters/rbac_filter.rst @@ -42,4 +42,4 @@ The RBAC filter emits the following dynamic metadata. shadow_effective_policy_id, string, The effective shadow policy ID matching the action (if any). shadow_engine_result, string, The engine result for the shadow rules (i.e. either `allowed` or `denied`). - access_log_policy, boolean, Whether the request should be logged. This metadata is shared and set under the key namespace 'envoy.common' (See :ref:`Shared Dynamic Metadata`). + access_log_hint, boolean, Whether the request should be logged. This metadata is shared and set under the key namespace 'envoy.common' (See :ref:`Shared Dynamic Metadata`). From 79b9755d9ac866b5ec4a6536a8b979ad4427e942 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Sat, 1 Aug 2020 19:58:02 +0000 Subject: [PATCH 25/39] Restructure RBAC so engine handles common action operations Signed-off-by: davidraskin --- source/extensions/filters/common/rbac/BUILD | 2 +- .../extensions/filters/common/rbac/engine.h | 50 +--- .../filters/common/rbac/engine_impl.cc | 86 +++--- .../filters/common/rbac/engine_impl.h | 44 ++- .../extensions/filters/common/rbac/utility.h | 42 +-- .../filters/http/rbac/rbac_filter.cc | 33 +-- .../filters/http/rbac/rbac_filter.h | 10 +- .../filters/network/rbac/rbac_filter.cc | 32 +-- .../filters/network/rbac/rbac_filter.h | 2 +- .../filters/common/rbac/engine_impl_test.cc | 250 ++++++++++-------- test/extensions/filters/common/rbac/mocks.h | 5 +- .../filters/http/rbac/rbac_filter_test.cc | 24 +- .../filters/network/rbac/filter_test.cc | 12 +- 13 files changed, 264 insertions(+), 328 deletions(-) diff --git a/source/extensions/filters/common/rbac/BUILD b/source/extensions/filters/common/rbac/BUILD index 9a9bbc1057495..ec1296b13464f 100644 --- a/source/extensions/filters/common/rbac/BUILD +++ b/source/extensions/filters/common/rbac/BUILD @@ -13,7 +13,6 @@ envoy_cc_library( srcs = ["utility.cc"], hdrs = ["utility.h"], deps = [ - ":engine_lib", "//include/envoy/stats:stats_macros", "//source/common/singleton:const_singleton", ], @@ -54,6 +53,7 @@ envoy_cc_library( srcs = ["engine_impl.cc"], hdrs = ["engine_impl.h"], deps = [ + ":utility_lib", "//source/extensions/filters/common/rbac:engine_interface", "//source/extensions/filters/common/rbac:matchers_lib", "@envoy_api//envoy/config/rbac/v3:pkg_cc_proto", diff --git a/source/extensions/filters/common/rbac/engine.h b/source/extensions/filters/common/rbac/engine.h index 8bf5920cf3d6b..04e82c95023d8 100644 --- a/source/extensions/filters/common/rbac/engine.h +++ b/source/extensions/filters/common/rbac/engine.h @@ -18,64 +18,32 @@ class RoleBasedAccessControlEngine { public: virtual ~RoleBasedAccessControlEngine() = default; - enum class LogDecision { Yes, No, Undecided }; - - /** - * Returns whether or not the current action is permitted. - * - * @param connection the downstream connection used to identify the action/principal. - * @param headers the headers of the incoming request used to identify the action/principal. An - * empty map should be used if there are no headers available. - * @param info the per-request or per-connection stream info with additional information - * about the action/principal. - * @param effective_policy_id it will be filled by the matching policy's ID, - * which is used to identity the source of the allow/deny. - */ - virtual bool allowed(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const PURE; - - /** - * Returns whether or not the current action is permitted. - * - * @param connection the downstream connection used to identify the action/principal. - * @param info the per-request or per-connection stream info with additional information - * about the action/principal. - * @param effective_policy_id it will be filled by the matching policy's ID, - * which is used to identity the source of the allow/deny. - */ - virtual bool allowed(const Network::Connection& connection, const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const PURE; - /** - * Returns whether or not the current action should be logged. + * Handles action-specific operations and returns whether or not the request is permitted. * * @param connection the downstream connection used to identify the action/principal. * @param headers the headers of the incoming request used to identify the action/principal. An * empty map should be used if there are no headers available. * @param info the per-request or per-connection stream info with additional information - * about the action/principal. + * about the action/principal. Can be modified by an Action. * @param effective_policy_id it will be filled by the matching policy's ID, * which is used to identity the source of the allow/deny. */ - virtual LogDecision shouldLog(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const PURE; + virtual bool handleAction(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, + StreamInfo::StreamInfo& info, std::string* effective_policy_id) PURE; /** - * Returns whether or not the current action should be logged. + * Handles action-specific operations and returns whether or not the request is permitted. * * @param connection the downstream connection used to identify the action/principal. * @param info the per-request or per-connection stream info with additional information - * about the action/principal. + * about the action/principal. Can be modified by an Action. * @param effective_policy_id it will be filled by the matching policy's ID, * which is used to identity the source of the allow/deny. */ - virtual LogDecision shouldLog(const Network::Connection& connection, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const PURE; + virtual bool handleAction(const Network::Connection& connection, StreamInfo::StreamInfo& info, + std::string* effective_policy_id) PURE; }; } // namespace RBAC diff --git a/source/extensions/filters/common/rbac/engine_impl.cc b/source/extensions/filters/common/rbac/engine_impl.cc index fb01e8ccc084b..ce9493e26896c 100644 --- a/source/extensions/filters/common/rbac/engine_impl.cc +++ b/source/extensions/filters/common/rbac/engine_impl.cc @@ -10,12 +10,9 @@ namespace Filters { namespace Common { namespace RBAC { -using LogDecision = RoleBasedAccessControlEngine::LogDecision; - RoleBasedAccessControlEngineImpl::RoleBasedAccessControlEngineImpl( - const envoy::config::rbac::v3::RBAC& rules) - : allowed_if_matched_(rules.action() == envoy::config::rbac::v3::RBAC::ALLOW), - action_log_(rules.action() == envoy::config::rbac::v3::RBAC::LOG) { + const envoy::config::rbac::v3::RBAC& rules, const EnforcementMode mode) + : action_(rules.action()), mode_(mode) { // guard expression builder by presence of a condition in policies for (const auto& policy : rules.policies()) { if (policy.second.has_condition()) { @@ -29,48 +26,45 @@ RoleBasedAccessControlEngineImpl::RoleBasedAccessControlEngineImpl( } } -bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const { - // Automatically allow if LOG action - if (action_log_) { - return true; - } - - bool matched = false; +bool RoleBasedAccessControlEngineImpl::handleAction(const Network::Connection& connection, + StreamInfo::StreamInfo& info, + std::string* effective_policy_id) { + return handleAction(connection, *Http::StaticEmptyHeaders::get().request_headers, info, + effective_policy_id); +} - for (const auto& policy : policies_) { - if (policy.second->matches(connection, headers, info)) { - matched = true; - if (effective_policy_id != nullptr) { - *effective_policy_id = policy.first; - } - break; +bool RoleBasedAccessControlEngineImpl::handleAction(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, + StreamInfo::StreamInfo& info, + std::string* effective_policy_id) { + bool matched = checkPolicyMatch(connection, info, headers, effective_policy_id); + + switch (action_) { + case envoy::config::rbac::v3::RBAC::ALLOW: + return matched; + case envoy::config::rbac::v3::RBAC::DENY: + return !matched; + case envoy::config::rbac::v3::RBAC::LOG: { + // If not shadow enforcement, set shared log metadata + if (mode_ != EnforcementMode::Shadow) { + ProtobufWkt::Struct log_metadata; + auto& log_fields = *log_metadata.mutable_fields(); + log_fields[DynamicMetadataKeysSingleton::get().AccessLogKey].set_bool_value(matched); + info.setDynamicMetadata(DynamicMetadataKeysSingleton::get().CommonNamespace, log_metadata); } - } - // only allowed if: - // - matched and ALLOW action - // - not matched and DENY action - // - LOG action - return matched == allowed_if_matched_; -} + return true; + } + default: + return true; + } -bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connection, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const { - return allowed(connection, *Http::StaticEmptyHeaders::get().request_headers, info, - effective_policy_id); + return true; } -LogDecision RoleBasedAccessControlEngineImpl::shouldLog( - const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const { - if (!action_log_) { - return LogDecision::Undecided; - } - +bool RoleBasedAccessControlEngineImpl::checkPolicyMatch( + const Network::Connection& connection, const StreamInfo::StreamInfo& info, + const Envoy::Http::RequestHeaderMap& headers, std::string* effective_policy_id) const { bool matched = false; for (const auto& policy : policies_) { @@ -83,15 +77,7 @@ LogDecision RoleBasedAccessControlEngineImpl::shouldLog( } } - // log if action is LOG and a policy matches - return matched ? LogDecision::Yes : LogDecision::No; -} - -LogDecision RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& connection, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const { - return shouldLog(connection, *Http::StaticEmptyHeaders::get().request_headers, info, - effective_policy_id); + return matched; } } // namespace RBAC diff --git a/source/extensions/filters/common/rbac/engine_impl.h b/source/extensions/filters/common/rbac/engine_impl.h index 87229a51a4e13..f24a43a8e9192 100644 --- a/source/extensions/filters/common/rbac/engine_impl.h +++ b/source/extensions/filters/common/rbac/engine_impl.h @@ -4,6 +4,7 @@ #include "extensions/filters/common/rbac/engine.h" #include "extensions/filters/common/rbac/matchers.h" +#include "extensions/filters/common/rbac/utility.h" namespace Envoy { namespace Extensions { @@ -11,27 +12,28 @@ namespace Filters { namespace Common { namespace RBAC { +enum class EnforcementMode { Enforced, Shadow }; + class RoleBasedAccessControlEngineImpl : public RoleBasedAccessControlEngine, NonCopyable { public: - RoleBasedAccessControlEngineImpl(const envoy::config::rbac::v3::RBAC& rules); + RoleBasedAccessControlEngineImpl(const envoy::config::rbac::v3::RBAC& rules, + const EnforcementMode mode = EnforcementMode::Enforced); - bool allowed(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const override; + bool handleAction(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, StreamInfo::StreamInfo& info, + std::string* effective_policy_id) override; - bool allowed(const Network::Connection& connection, const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const override; + bool handleAction(const Network::Connection& connection, StreamInfo::StreamInfo& info, + std::string* effective_policy_id) override; - LogDecision shouldLog(const Network::Connection& connection, +private: + // Checks whether the request matches any policies + bool checkPolicyMatch(const Network::Connection& connection, const StreamInfo::StreamInfo& info, const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const override; + std::string* effective_policy_id) const; - LogDecision shouldLog(const Network::Connection& connection, const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const override; - -private: - const bool allowed_if_matched_; - const bool action_log_; + const envoy::config::rbac::v3::RBAC::Action action_; + const EnforcementMode mode_; std::map> policies_; @@ -39,6 +41,20 @@ class RoleBasedAccessControlEngineImpl : public RoleBasedAccessControlEngine, No Expr::BuilderPtr builder_; }; +template +std::unique_ptr createEngine(const ConfigType& config) { + return config.has_rules() ? std::make_unique( + config.rules(), EnforcementMode::Enforced) + : nullptr; +} + +template +std::unique_ptr createShadowEngine(const ConfigType& config) { + return config.has_shadow_rules() ? std::make_unique( + config.shadow_rules(), EnforcementMode::Shadow) + : nullptr; +} + } // namespace RBAC } // namespace Common } // namespace Filters diff --git a/source/extensions/filters/common/rbac/utility.h b/source/extensions/filters/common/rbac/utility.h index a3848deb62469..317ead0bcac7a 100644 --- a/source/extensions/filters/common/rbac/utility.h +++ b/source/extensions/filters/common/rbac/utility.h @@ -1,29 +1,16 @@ #pragma once +#include "envoy/stats/scope.h" #include "envoy/stats/stats_macros.h" #include "common/singleton/const_singleton.h" -#include "extensions/filters/common/rbac/engine_impl.h" - namespace Envoy { namespace Extensions { namespace Filters { namespace Common { namespace RBAC { -class DynamicMetadataKeys { -public: - const std::string ShadowEffectivePolicyIdField{"shadow_effective_policy_id"}; - const std::string ShadowEngineResultField{"shadow_engine_result"}; - const std::string EngineResultAllowed{"allowed"}; - const std::string EngineResultDenied{"denied"}; - const std::string AccessLogKey{"access_log_hint"}; - const std::string CommonNamespace{"envoy.common"}; -}; - -using DynamicMetadataKeysSingleton = ConstSingleton; - /** * All stats for the RBAC filter. @see stats_macros.h */ @@ -32,8 +19,8 @@ using DynamicMetadataKeysSingleton = ConstSingleton; COUNTER(denied) \ COUNTER(shadow_allowed) \ COUNTER(shadow_denied) \ - COUNTER(logged) \ - COUNTER(not_logged) + // COUNTER(logged) \ + // COUNTER(not_logged) /** * Wrapper struct for RBAC filter stats. @see stats_macros.h @@ -44,20 +31,17 @@ struct RoleBasedAccessControlFilterStats { RoleBasedAccessControlFilterStats generateStats(const std::string& prefix, Stats::Scope& scope); -enum class EnforcementMode { Enforced, Shadow }; - -template -std::unique_ptr createEngine(const ConfigType& config) { - return config.has_rules() ? std::make_unique(config.rules()) - : nullptr; -} +class DynamicMetadataKeys { +public: + const std::string ShadowEffectivePolicyIdField{"shadow_effective_policy_id"}; + const std::string ShadowEngineResultField{"shadow_engine_result"}; + const std::string EngineResultAllowed{"allowed"}; + const std::string EngineResultDenied{"denied"}; + const std::string AccessLogKey{"access_log_hint"}; + const std::string CommonNamespace{"envoy.common"}; +}; -template -std::unique_ptr createShadowEngine(const ConfigType& config) { - return config.has_shadow_rules() - ? std::make_unique(config.shadow_rules()) - : nullptr; -} +using DynamicMetadataKeysSingleton = ConstSingleton; } // namespace RBAC } // namespace Common diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index 0c187f5cf541d..3079664701b91 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -20,7 +20,7 @@ struct RcDetailsValues { }; using RcDetails = ConstSingleton; -using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; +// using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::http::rbac::v3::RBAC& proto_config, @@ -29,7 +29,7 @@ RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( engine_(Filters::Common::RBAC::createEngine(proto_config)), shadow_engine_(Filters::Common::RBAC::createShadowEngine(proto_config)) {} -const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* +Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* RoleBasedAccessControlFilterConfig::engine(const Router::RouteConstSharedPtr route, Filters::Common::RBAC::EnforcementMode mode) const { if (!route || !route->routeEntry()) { @@ -82,8 +82,8 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo if (shadow_engine != nullptr) { std::string shadow_resp_code = Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().EngineResultAllowed; - if (shadow_engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), - &effective_policy_id)) { + if (shadow_engine->handleAction(*callbacks_->connection(), headers, callbacks_->streamInfo(), + &effective_policy_id)) { ENVOY_LOG(debug, "shadow allowed"); config_->stats().shadow_allowed_.inc(); } else { @@ -110,28 +110,9 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo const auto engine = config_->engine(callbacks_->route(), Filters::Common::RBAC::EnforcementMode::Enforced); if (engine != nullptr) { - // Check log decision - LogDecision log_dec = - engine->shouldLog(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr); - if (log_dec != LogDecision::Undecided) { - ProtobufWkt::Struct log_metadata; - auto& log_fields = *log_metadata.mutable_fields(); - log_fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey] - .set_bool_value(log_dec == LogDecision::Yes); - callbacks_->streamInfo().setDynamicMetadata( - Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, log_metadata); - - if (log_dec == LogDecision::Yes) { - ENVOY_LOG(debug, "request logged"); - config_->stats().logged_.inc(); - } else { - ENVOY_LOG(debug, "request not logged"); - config_->stats().not_logged_.inc(); - } - } - - // Check authorization decision - if (engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr)) { + // Check authorization decision and do Action operations + if (engine->handleAction(*callbacks_->connection(), headers, callbacks_->streamInfo(), + nullptr)) { ENVOY_LOG(debug, "enforced allowed"); config_->stats().allowed_.inc(); return Http::FilterHeadersStatus::Continue; diff --git a/source/extensions/filters/http/rbac/rbac_filter.h b/source/extensions/filters/http/rbac/rbac_filter.h index fe7369e34e6be..7434dcd925cd0 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.h +++ b/source/extensions/filters/http/rbac/rbac_filter.h @@ -22,7 +22,7 @@ class RoleBasedAccessControlRouteSpecificFilterConfig : public Router::RouteSpec RoleBasedAccessControlRouteSpecificFilterConfig( const envoy::extensions::filters::http::rbac::v3::RBACPerRoute& per_route_config); - const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); @@ -44,12 +44,12 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats& stats() { return stats_; } - const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(const Router::RouteConstSharedPtr route, Filters::Common::RBAC::EnforcementMode mode) const; private: - const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); @@ -57,8 +57,8 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats stats_; - std::unique_ptr engine_; - std::unique_ptr shadow_engine_; + std::unique_ptr engine_; + std::unique_ptr shadow_engine_; }; using RoleBasedAccessControlFilterConfigSharedPtr = diff --git a/source/extensions/filters/network/rbac/rbac_filter.cc b/source/extensions/filters/network/rbac/rbac_filter.cc index 6a94212fe15fa..5bb07b6aae110 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.cc +++ b/source/extensions/filters/network/rbac/rbac_filter.cc @@ -13,8 +13,6 @@ namespace Extensions { namespace NetworkFilters { namespace RBACFilter { -using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; - RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::network::rbac::v3::RBAC& proto_config, Stats::Scope& scope) : stats_(Filters::Common::RBAC::generateStats(proto_config.stat_prefix(), scope)), @@ -84,36 +82,14 @@ void RoleBasedAccessControlFilter::setDynamicMetadata(std::string shadow_engine_ EngineResult RoleBasedAccessControlFilter::checkEngine(Filters::Common::RBAC::EnforcementMode mode) { - const auto engine = config_->engine(mode); + auto engine = config_->engine(mode); if (engine != nullptr) { std::string effective_policy_id; - if (mode == Filters::Common::RBAC::EnforcementMode::Enforced) { - // Check log decision - LogDecision log_dec = engine->shouldLog( - callbacks_->connection(), callbacks_->connection().streamInfo(), &effective_policy_id); - if (log_dec != LogDecision::Undecided) { - ProtobufWkt::Struct log_metadata; - auto& fields = *log_metadata.mutable_fields(); - fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey] - .set_bool_value(log_dec == LogDecision::Yes); - callbacks_->connection().streamInfo().setDynamicMetadata( - Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, - log_metadata); - - if (log_dec == LogDecision::Yes) { - ENVOY_LOG(debug, "request logged"); - config_->stats().logged_.inc(); - } else { - ENVOY_LOG(debug, "request not logged"); - config_->stats().not_logged_.inc(); - } - } - } - // Check authorization decision - if (engine->allowed(callbacks_->connection(), callbacks_->connection().streamInfo(), - &effective_policy_id)) { + // Check authorization decision and do Action operations + if (engine->handleAction(callbacks_->connection(), callbacks_->connection().streamInfo(), + &effective_policy_id)) { if (mode == Filters::Common::RBAC::EnforcementMode::Shadow) { ENVOY_LOG(debug, "shadow allowed"); config_->stats().shadow_allowed_.inc(); diff --git a/source/extensions/filters/network/rbac/rbac_filter.h b/source/extensions/filters/network/rbac/rbac_filter.h index 19c9360e21342..38530d4e2e600 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.h +++ b/source/extensions/filters/network/rbac/rbac_filter.h @@ -27,7 +27,7 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats& stats() { return stats_; } - const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index 47b48362a80b4..e2ab5468eb45c 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -25,30 +25,42 @@ namespace RBAC { namespace { void checkEngine( - const RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, + RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, StreamInfo::StreamInfo& info, const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), - const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl(), - const StreamInfo::StreamInfo& info = NiceMock()) { - EXPECT_EQ(expected, engine.allowed(connection, headers, info, nullptr)); + const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { + + bool engineRes = engine.handleAction(connection, headers, info, nullptr); + EXPECT_EQ(expected, engineRes); } -// Used for testing shouldLog() function tests -void checkEngineLog( - const RBAC::RoleBasedAccessControlEngineImpl& engine, - const RoleBasedAccessControlEngine::LogDecision expected, +void checkEngine( + RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), - const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl(), - const StreamInfo::StreamInfo& info = NiceMock()) { - EXPECT_EQ(expected, engine.shouldLog(connection, headers, info, nullptr)); + const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { + + NiceMock empty_info; + checkEngine(engine, expected, empty_info, connection, headers); } +// Used for testing shouldLog() function tests +// void checkEngineLog( +// const RBAC::RoleBasedAccessControlEngineImpl& engine, +// const RoleBasedAccessControlEngine::LogDecision expected, +// const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), +// const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl(), +// const StreamInfo::StreamInfo& info = NiceMock()) { +// EXPECT_EQ(expected, engine.handleAction(connection, headers, info, nullptr)); +// } + TEST(RoleBasedAccessControlEngineImpl, Disabled) { envoy::config::rbac::v3::RBAC rbac; rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); - checkEngine(RBAC::RoleBasedAccessControlEngineImpl(rbac), false); + RBAC::RoleBasedAccessControlEngineImpl engine_allow(rbac); + checkEngine(engine_allow, false); rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); - checkEngine(RBAC::RoleBasedAccessControlEngineImpl(rbac), true); + RBAC::RoleBasedAccessControlEngineImpl engine_deny(rbac); + checkEngine(engine_deny, true); } // Test various invalid policies to validate the fix for @@ -153,11 +165,11 @@ TEST(RoleBasedAccessControlEngineImpl, AllowedAllowlist) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, true, conn, headers, info); + checkEngine(engine, true, info, conn, headers); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, false, conn, headers, info); + checkEngine(engine, false, info, conn, headers); } TEST(RoleBasedAccessControlEngineImpl, DeniedDenylist) { @@ -176,11 +188,11 @@ TEST(RoleBasedAccessControlEngineImpl, DeniedDenylist) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, false, conn, headers, info); + checkEngine(engine, false, info, conn, headers); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, true, conn, headers, info); + checkEngine(engine, true, info, conn, headers); } TEST(RoleBasedAccessControlEngineImpl, BasicCondition) { @@ -241,9 +253,9 @@ TEST(RoleBasedAccessControlEngineImpl, MistypedCondition) { RBAC::RoleBasedAccessControlEngineImpl engine(rbac); checkEngine(engine, false); - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No); + // rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + // RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + // checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No); } TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { @@ -270,10 +282,10 @@ TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { RBAC::RoleBasedAccessControlEngineImpl engine(rbac); checkEngine(engine, false, Envoy::Network::MockConnection()); - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, - Envoy::Network::MockConnection()); + // rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + // RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + // checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, + // Envoy::Network::MockConnection()); } TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { @@ -311,10 +323,10 @@ TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { checkEngine(engine, true, Envoy::Network::MockConnection(), headers); - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, - Envoy::Network::MockConnection(), headers); + // rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + // RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + // checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, + // Envoy::Network::MockConnection(), headers); } TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { @@ -359,12 +371,12 @@ TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { Protobuf::MapPair("other", label)); EXPECT_CALL(Const(info), dynamicMetadata()).WillRepeatedly(ReturnRef(metadata)); - checkEngine(engine, true, Envoy::Network::MockConnection(), headers, info); + checkEngine(engine, true, info, Envoy::Network::MockConnection(), headers); - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, - Envoy::Network::MockConnection(), headers, info); + // rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + // RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + // checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, + // Envoy::Network::MockConnection(), headers, info); } TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { @@ -387,91 +399,95 @@ TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - EXPECT_CALL(Const(info), downstreamLocalAddress()).Times(2).WillRepeatedly(ReturnRef(addr)); - checkEngine(engine, false, conn, headers, info); - - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, conn, headers, - info); -} - -// Log tests tests -TEST(RoleBasedAccessControlEngineImpl, DisabledLog) { - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - checkEngineLog(RBAC::RoleBasedAccessControlEngineImpl(rbac), - RBAC::RoleBasedAccessControlEngine::LogDecision::No); -} - -TEST(RoleBasedAccessControlEngineImpl, LogIfMatched) { - envoy::config::rbac::v3::Policy policy; - policy.add_permissions()->set_destination_port(123); - policy.add_principals()->set_any(true); - - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - (*rbac.mutable_policies())["foo"] = policy; - RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - - Envoy::Network::MockConnection conn; - Envoy::Http::TestRequestHeaderMapImpl headers; - NiceMock info; - Envoy::Network::Address::InstanceConstSharedPtr addr = - Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::Yes, conn, headers, info); - - addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::No, conn, headers, info); -} - -TEST(RoleBasedAccessControlEngineImpl, LogAllowUndecided) { - envoy::config::rbac::v3::Policy policy; - policy.add_permissions()->set_destination_port(123); - policy.add_principals()->set_any(true); - - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); - (*rbac.mutable_policies())["foo"] = policy; - RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - - Envoy::Network::MockConnection conn; - Envoy::Http::TestRequestHeaderMapImpl headers; - NiceMock info; - Envoy::Network::Address::InstanceConstSharedPtr addr = - Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, - info); + EXPECT_CALL(Const(info), downstreamLocalAddress()).Times(1).WillRepeatedly(ReturnRef(addr)); + checkEngine(engine, false, info, conn, headers); - addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, - info); + // rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + // RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + // checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, conn, headers, + // info); } -TEST(RoleBasedAccessControlEngineImpl, LogDenyUndecided) { - envoy::config::rbac::v3::Policy policy; - policy.add_permissions()->set_destination_port(123); - policy.add_principals()->set_any(true); - - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); - (*rbac.mutable_policies())["foo"] = policy; - RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - - Envoy::Network::MockConnection conn; - Envoy::Http::TestRequestHeaderMapImpl headers; - NiceMock info; - Envoy::Network::Address::InstanceConstSharedPtr addr = - Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, - info); - - addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, - info); -} +// // Log tests tests +// TEST(RoleBasedAccessControlEngineImpl, DisabledLog) { +// envoy::config::rbac::v3::RBAC rbac; +// rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); +// checkEngineLog(RBAC::RoleBasedAccessControlEngineImpl(rbac), +// RBAC::RoleBasedAccessControlEngine::LogDecision::No); +// } + +// TEST(RoleBasedAccessControlEngineImpl, LogIfMatched) { +// envoy::config::rbac::v3::Policy policy; +// policy.add_permissions()->set_destination_port(123); +// policy.add_principals()->set_any(true); + +// envoy::config::rbac::v3::RBAC rbac; +// rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); +// (*rbac.mutable_policies())["foo"] = policy; +// RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + +// Envoy::Network::MockConnection conn; +// Envoy::Http::TestRequestHeaderMapImpl headers; +// NiceMock info; +// Envoy::Network::Address::InstanceConstSharedPtr addr = +// Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); +// EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); +// checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::Yes, conn, headers, info); + +// addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); +// EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); +// checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::No, conn, headers, info); +// } + +// TEST(RoleBasedAccessControlEngineImpl, LogAllowUndecided) { +// envoy::config::rbac::v3::Policy policy; +// policy.add_permissions()->set_destination_port(123); +// policy.add_principals()->set_any(true); + +// envoy::config::rbac::v3::RBAC rbac; +// rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); +// (*rbac.mutable_policies())["foo"] = policy; +// RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + +// Envoy::Network::MockConnection conn; +// Envoy::Http::TestRequestHeaderMapImpl headers; +// NiceMock info; +// Envoy::Network::Address::InstanceConstSharedPtr addr = +// Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); +// checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, +// headers, +// info); + +// addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); +// checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, +// headers, +// info); +// } + +// TEST(RoleBasedAccessControlEngineImpl, LogDenyUndecided) { +// envoy::config::rbac::v3::Policy policy; +// policy.add_permissions()->set_destination_port(123); +// policy.add_principals()->set_any(true); + +// envoy::config::rbac::v3::RBAC rbac; +// rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); +// (*rbac.mutable_policies())["foo"] = policy; +// RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + +// Envoy::Network::MockConnection conn; +// Envoy::Http::TestRequestHeaderMapImpl headers; +// NiceMock info; +// Envoy::Network::Address::InstanceConstSharedPtr addr = +// Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); +// checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, +// headers, +// info); + +// addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); +// checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, +// headers, +// info); +// } TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { envoy::config::rbac::v3::Policy policy; @@ -488,10 +504,10 @@ TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngine(engine, true, conn, headers, info); + checkEngine(engine, true, info, conn, headers); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngine(engine, true, conn, headers, info); + checkEngine(engine, true, info, conn, headers); } } // namespace diff --git a/test/extensions/filters/common/rbac/mocks.h b/test/extensions/filters/common/rbac/mocks.h index fda95244c8933..936db43752a05 100644 --- a/test/extensions/filters/common/rbac/mocks.h +++ b/test/extensions/filters/common/rbac/mocks.h @@ -14,8 +14,9 @@ namespace RBAC { class MockEngine : public RoleBasedAccessControlEngineImpl { public: - MockEngine(const envoy::config::rbac::v3::RBAC& rules) - : RoleBasedAccessControlEngineImpl(rules){}; + MockEngine(const envoy::config::rbac::v3::RBAC& rules, + const EnforcementMode mode = EnforcementMode::Shadow) + : RoleBasedAccessControlEngineImpl(rules, mode){}; MOCK_METHOD(bool, allowed, (const Envoy::Network::Connection&, const Envoy::Http::RequestHeaderMap&, diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index 6a3da375b6768..dc7f2531ad994 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -145,7 +145,11 @@ TEST_F(RoleBasedAccessControlFilterTest, RequestedServerName) { // Check Log setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); - checkAccessLogMetadata(true); + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); + EXPECT_EQ(true, filter_meta.fields() + .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) + .bool_value()); } TEST_F(RoleBasedAccessControlFilterTest, Path) { @@ -170,7 +174,11 @@ TEST_F(RoleBasedAccessControlFilterTest, Path) { // Check Log setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers, false)); - checkAccessLogMetadata(false); + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); + EXPECT_EQ(false, filter_meta.fields() + .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) + .bool_value()); } TEST_F(RoleBasedAccessControlFilterTest, Denied) { @@ -221,8 +229,8 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); - EXPECT_EQ(1U, log_config_->stats().logged_.value()); - EXPECT_EQ(0U, log_config_->stats().not_logged_.value()); + // EXPECT_EQ(1U, log_config_->stats().logged_.value()); + // EXPECT_EQ(0U, log_config_->stats().not_logged_.value()); Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); @@ -239,8 +247,8 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); - EXPECT_EQ(0U, log_config_->stats().logged_.value()); - EXPECT_EQ(1U, log_config_->stats().not_logged_.value()); + // EXPECT_EQ(0U, log_config_->stats().logged_.value()); + // EXPECT_EQ(1U, log_config_->stats().not_logged_.value()); Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); @@ -254,8 +262,8 @@ TEST_F(RoleBasedAccessControlFilterTest, AllowNoChangeLog) { setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); - EXPECT_EQ(0U, config_->stats().logged_.value()); - EXPECT_EQ(0U, config_->stats().not_logged_.value()); + // EXPECT_EQ(0U, config_->stats().logged_.value()); + // EXPECT_EQ(0U, config_->stats().not_logged_.value()); // Check that Allow action does not set access log metadata EXPECT_EQ(req_info_.dynamicMetadata().filter_metadata().end(), diff --git a/test/extensions/filters/network/rbac/filter_test.cc b/test/extensions/filters/network/rbac/filter_test.cc index ae29c1667c089..dedf4688c8d45 100644 --- a/test/extensions/filters/network/rbac/filter_test.cc +++ b/test/extensions/filters/network/rbac/filter_test.cc @@ -206,8 +206,8 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldLog) { EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - EXPECT_EQ(1U, config_->stats().logged_.value()); - EXPECT_EQ(0U, config_->stats().not_logged_.value()); + // EXPECT_EQ(1U, config_->stats().logged_.value()); + // EXPECT_EQ(0U, config_->stats().not_logged_.value()); checkAccessLogMetadata(true); } @@ -224,8 +224,8 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldNotLog) { EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - EXPECT_EQ(0U, config_->stats().logged_.value()); - EXPECT_EQ(1U, config_->stats().not_logged_.value()); + // EXPECT_EQ(0U, config_->stats().logged_.value()); + // EXPECT_EQ(1U, config_->stats().not_logged_.value()); checkAccessLogMetadata(false); } @@ -235,8 +235,8 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, AllowNoChangeLog) { setMetadata(); EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(data_, false)); - EXPECT_EQ(0U, config_->stats().logged_.value()); - EXPECT_EQ(0U, config_->stats().not_logged_.value()); + // EXPECT_EQ(0U, config_->stats().logged_.value()); + // EXPECT_EQ(0U, config_->stats().not_logged_.value()); // Check that Allow action does not set access log metadata EXPECT_EQ(stream_info_.dynamicMetadata().filter_metadata().end(), From 75a7ae8c732cf1bde14dcd5fe13937c153920365 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Mon, 3 Aug 2020 16:40:08 +0000 Subject: [PATCH 26/39] Updated documentation + deleted comments Signed-off-by: davidraskin --- api/envoy/config/rbac/v3/rbac.proto | 97 ++++++++------- api/envoy/config/rbac/v4alpha/rbac.proto | 97 ++++++++------- .../advanced/well_known_dynamic_metadata.rst | 2 +- docs/root/version_history/current.rst | 1 + .../envoy/config/rbac/v3/rbac.proto | 97 ++++++++------- .../envoy/config/rbac/v4alpha/rbac.proto | 97 ++++++++------- .../extensions/filters/common/rbac/utility.h | 4 +- .../filters/common/rbac/engine_impl_test.cc | 115 ------------------ .../filters/http/rbac/rbac_filter_test.cc | 8 -- .../filters/network/rbac/filter_test.cc | 8 -- 10 files changed, 223 insertions(+), 303 deletions(-) diff --git a/api/envoy/config/rbac/v3/rbac.proto b/api/envoy/config/rbac/v3/rbac.proto index 9b3fd0524868b..278e6857603fe 100644 --- a/api/envoy/config/rbac/v3/rbac.proto +++ b/api/envoy/config/rbac/v3/rbac.proto @@ -82,40 +82,47 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match. + // All requests are allowed. LOG = 2; } - // The action to take if a policy matches. - // The request is allowed if and only if: + // The action to take if a policy matches. Every action either allows or denies a request, + // and can also carry out action-specific operations. // - // * `action` is "ALLOW" and at least one policy matches - // * `action` is "DENY" and none of the policies match - // * `action` is "LOG" + // Actions: + // + // * ALLOW: Allows the request if and only if there is a policy that matches + // the request. + // * DENY: Allows the request if and only if there are no policies that + // match the request. + // * LOG: Allows all requests. If at least one policy matches, the dynamic + // metadata key `access_log_hint` is set to the value `true` under the shared + // key namespace 'envoy.common'. If no policies match, it is set to `false`. + // Other actions do not modify this key. // - // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` - // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, - // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if -// and only if at least one of its permissions match the action taking place AND at least one of its -// principals match the downstream AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. +// A policy matches if and only if at least one of its permissions match the +// action taking place AND at least one of its principals match the downstream +// AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Policy"; - // Required. The set of permissions that define a role. Each permission is matched with OR - // semantics. To match all actions for this policy, a single Permission with the `any` field set - // to true should be used. + // Required. The set of permissions that define a role. Each permission is + // matched with OR semantics. To match all actions for this policy, a single + // Permission with the `any` field set to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on “action”. Each - // principal is matched with OR semantics. To match all downstreams for this policy, a single - // Principal with the `any` field set to true should be used. + // Required. The set of principals that are assigned/denied the role based on + // “action”. Each principal is matched with OR semantics. To match all + // downstreams for this policy, a single Principal with the `any` field set to + // true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; // An optional symbolic expression specifying an access control @@ -176,9 +183,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of `not_rule` would - // match, this permission would not match. Conversely, if the value of `not_rule` would not - // match, this permission would match. + // Negates matching the provided permission. For instance, if the value of + // `not_rule` would match, this permission would not match. Conversely, if + // the value of `not_rule` would not match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -191,7 +198,8 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name `, + // the :ref:`server name + // `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -204,13 +212,14 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream subject. +// Principal defines an identity or a group of identities for a downstream +// subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, - // each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. + // Depending on the context, each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal.Set"; @@ -225,19 +234,21 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the - // certificate, otherwise the subject field is used. If unset, it applies to any user that is - // authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order + // is used from the certificate, otherwise the subject field is used. If + // unset, it applies to any user that is authenticated. type.matcher.v3.StringMatcher principal_name = 2; } oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the downstream. + // A set of identifiers that all must match in order to define the + // downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the downstream. + // A set of identifiers at least one must match in order to define the + // downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -252,21 +263,23 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is inferred - // from for example the x-forwarder-for header, proxy protocol, etc. + // :ref:`remote_ip ` is + // inferred from for example the x-forwarder-for header, proxy protocol, + // etc. core.v3.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip `. - // E.g, if the remote ip is inferred from for example the x-forwarder-for header, - // proxy protocol, etc. + // :ref:`direct_remote_ip + // `. E.g, if the + // remote ip is inferred from for example the x-forwarder-for header, proxy + // protocol, etc. core.v3.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only - // available for HTTP request. - // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` - // field if you want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP + // request. Only available for HTTP request. Note: the pseudo-header :path + // includes the query and fragment string. Use the `url_path` field if you + // want to match the URL path without the query and fragment string. route.v3.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -275,9 +288,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of `not_id` would match, - // this principal would not match. Conversely, if the value of `not_id` would not match, this - // principal would match. + // Negates matching the provided principal. For instance, if the value of + // `not_id` would match, this principal would not match. Conversely, if the + // value of `not_id` would not match, this principal would match. Principal not_id = 8; } } diff --git a/api/envoy/config/rbac/v4alpha/rbac.proto b/api/envoy/config/rbac/v4alpha/rbac.proto index eea66a969f58a..cc9d8933ababc 100644 --- a/api/envoy/config/rbac/v4alpha/rbac.proto +++ b/api/envoy/config/rbac/v4alpha/rbac.proto @@ -81,40 +81,47 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match. + // All requests are allowed. LOG = 2; } - // The action to take if a policy matches. - // The request is allowed if and only if: + // The action to take if a policy matches. Every action either allows or denies a request, + // and can also carry out action-specific operations. // - // * `action` is "ALLOW" and at least one policy matches - // * `action` is "DENY" and none of the policies match - // * `action` is "LOG" + // Actions: + // + // * ALLOW: Allows the request if and only if there is a policy that matches + // the request. + // * DENY: Allows the request if and only if there are no policies that + // match the request. + // * LOG: Allows all requests. If at least one policy matches, the dynamic + // metadata key `access_log_hint` is set to the value `true` under the shared + // key namespace 'envoy.common'. If no policies match, it is set to `false`. + // Other actions do not modify this key. // - // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` - // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, - // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if -// and only if at least one of its permissions match the action taking place AND at least one of its -// principals match the downstream AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. +// A policy matches if and only if at least one of its permissions match the +// action taking place AND at least one of its principals match the downstream +// AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Policy"; - // Required. The set of permissions that define a role. Each permission is matched with OR - // semantics. To match all actions for this policy, a single Permission with the `any` field set - // to true should be used. + // Required. The set of permissions that define a role. Each permission is + // matched with OR semantics. To match all actions for this policy, a single + // Permission with the `any` field set to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on “action”. Each - // principal is matched with OR semantics. To match all downstreams for this policy, a single - // Principal with the `any` field set to true should be used. + // Required. The set of principals that are assigned/denied the role based on + // “action”. Each principal is matched with OR semantics. To match all + // downstreams for this policy, a single Principal with the `any` field set to + // true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; oneof expression_specifier { @@ -175,9 +182,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of `not_rule` would - // match, this permission would not match. Conversely, if the value of `not_rule` would not - // match, this permission would match. + // Negates matching the provided permission. For instance, if the value of + // `not_rule` would match, this permission would not match. Conversely, if + // the value of `not_rule` would not match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -190,7 +197,8 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name `, + // the :ref:`server name + // `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -203,13 +211,14 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream subject. +// Principal defines an identity or a group of identities for a downstream +// subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, - // each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. + // Depending on the context, each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal.Set"; @@ -224,9 +233,9 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the - // certificate, otherwise the subject field is used. If unset, it applies to any user that is - // authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order + // is used from the certificate, otherwise the subject field is used. If + // unset, it applies to any user that is authenticated. type.matcher.v4alpha.StringMatcher principal_name = 2; } @@ -237,10 +246,12 @@ message Principal { oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the downstream. + // A set of identifiers that all must match in order to define the + // downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the downstream. + // A set of identifiers at least one must match in order to define the + // downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -251,21 +262,23 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is inferred - // from for example the x-forwarder-for header, proxy protocol, etc. + // :ref:`remote_ip ` is + // inferred from for example the x-forwarder-for header, proxy protocol, + // etc. core.v4alpha.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip `. - // E.g, if the remote ip is inferred from for example the x-forwarder-for header, - // proxy protocol, etc. + // :ref:`direct_remote_ip + // `. E.g, if the + // remote ip is inferred from for example the x-forwarder-for header, proxy + // protocol, etc. core.v4alpha.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only - // available for HTTP request. - // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` - // field if you want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP + // request. Only available for HTTP request. Note: the pseudo-header :path + // includes the query and fragment string. Use the `url_path` field if you + // want to match the URL path without the query and fragment string. route.v4alpha.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -274,9 +287,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of `not_id` would match, - // this principal would not match. Conversely, if the value of `not_id` would not match, this - // principal would match. + // Negates matching the provided principal. For instance, if the value of + // `not_id` would match, this principal would not match. Conversely, if the + // value of `not_id` would not match, this principal would match. Principal not_id = 8; } } diff --git a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst index 70df6b283415a..4d7f8ed3872c6 100644 --- a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst +++ b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst @@ -47,4 +47,4 @@ The following Envoy filters emit shared dynamic metadata. The following filters consume shared dynamic metadata. -* Metadata Access Log Filter +* :ref:`Metadata Access Log Filter` diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index 01c1f3dd56a0e..4277daa7533cc 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -52,6 +52,7 @@ New Features * load balancer: added a :ref:`configuration` option to specify the active request bias used by the least request load balancer. * lua: added Lua APIs to access :ref:`SSL connection info ` object. * postgres network filter: :ref:`metadata ` is produced based on SQL query. +* rbac filter: added a log action to the :ref:`RBAC filter ` which sets dynamic metadata to inform access loggers whether to log. * router: added new :ref:`envoy-ratelimited` retry policy, which allows retrying envoy's own rate limited responses. diff --git a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto index 9b3fd0524868b..278e6857603fe 100644 --- a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto @@ -82,40 +82,47 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match. + // All requests are allowed. LOG = 2; } - // The action to take if a policy matches. - // The request is allowed if and only if: + // The action to take if a policy matches. Every action either allows or denies a request, + // and can also carry out action-specific operations. // - // * `action` is "ALLOW" and at least one policy matches - // * `action` is "DENY" and none of the policies match - // * `action` is "LOG" + // Actions: + // + // * ALLOW: Allows the request if and only if there is a policy that matches + // the request. + // * DENY: Allows the request if and only if there are no policies that + // match the request. + // * LOG: Allows all requests. If at least one policy matches, the dynamic + // metadata key `access_log_hint` is set to the value `true` under the shared + // key namespace 'envoy.common'. If no policies match, it is set to `false`. + // Other actions do not modify this key. // - // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` - // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, - // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if -// and only if at least one of its permissions match the action taking place AND at least one of its -// principals match the downstream AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. +// A policy matches if and only if at least one of its permissions match the +// action taking place AND at least one of its principals match the downstream +// AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Policy"; - // Required. The set of permissions that define a role. Each permission is matched with OR - // semantics. To match all actions for this policy, a single Permission with the `any` field set - // to true should be used. + // Required. The set of permissions that define a role. Each permission is + // matched with OR semantics. To match all actions for this policy, a single + // Permission with the `any` field set to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on “action”. Each - // principal is matched with OR semantics. To match all downstreams for this policy, a single - // Principal with the `any` field set to true should be used. + // Required. The set of principals that are assigned/denied the role based on + // “action”. Each principal is matched with OR semantics. To match all + // downstreams for this policy, a single Principal with the `any` field set to + // true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; // An optional symbolic expression specifying an access control @@ -176,9 +183,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of `not_rule` would - // match, this permission would not match. Conversely, if the value of `not_rule` would not - // match, this permission would match. + // Negates matching the provided permission. For instance, if the value of + // `not_rule` would match, this permission would not match. Conversely, if + // the value of `not_rule` would not match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -191,7 +198,8 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name `, + // the :ref:`server name + // `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -204,13 +212,14 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream subject. +// Principal defines an identity or a group of identities for a downstream +// subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, - // each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. + // Depending on the context, each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal.Set"; @@ -225,19 +234,21 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the - // certificate, otherwise the subject field is used. If unset, it applies to any user that is - // authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order + // is used from the certificate, otherwise the subject field is used. If + // unset, it applies to any user that is authenticated. type.matcher.v3.StringMatcher principal_name = 2; } oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the downstream. + // A set of identifiers that all must match in order to define the + // downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the downstream. + // A set of identifiers at least one must match in order to define the + // downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -252,21 +263,23 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is inferred - // from for example the x-forwarder-for header, proxy protocol, etc. + // :ref:`remote_ip ` is + // inferred from for example the x-forwarder-for header, proxy protocol, + // etc. core.v3.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip `. - // E.g, if the remote ip is inferred from for example the x-forwarder-for header, - // proxy protocol, etc. + // :ref:`direct_remote_ip + // `. E.g, if the + // remote ip is inferred from for example the x-forwarder-for header, proxy + // protocol, etc. core.v3.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only - // available for HTTP request. - // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` - // field if you want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP + // request. Only available for HTTP request. Note: the pseudo-header :path + // includes the query and fragment string. Use the `url_path` field if you + // want to match the URL path without the query and fragment string. route.v3.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -275,9 +288,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of `not_id` would match, - // this principal would not match. Conversely, if the value of `not_id` would not match, this - // principal would match. + // Negates matching the provided principal. For instance, if the value of + // `not_id` would match, this principal would not match. Conversely, if the + // value of `not_id` would not match, this principal would match. Principal not_id = 8; } } diff --git a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto index 8d2945ee2a757..7139dfaa1485d 100644 --- a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto @@ -81,40 +81,47 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match. + // All requests are allowed. LOG = 2; } - // The action to take if a policy matches. - // The request is allowed if and only if: + // The action to take if a policy matches. Every action either allows or denies a request, + // and can also carry out action-specific operations. // - // * `action` is "ALLOW" and at least one policy matches - // * `action` is "DENY" and none of the policies match - // * `action` is "LOG" + // Actions: + // + // * ALLOW: Allows the request if and only if there is a policy that matches + // the request. + // * DENY: Allows the request if and only if there are no policies that + // match the request. + // * LOG: Allows all requests. If at least one policy matches, the dynamic + // metadata key `access_log_hint` is set to the value `true` under the shared + // key namespace 'envoy.common'. If no policies match, it is set to `false`. + // Other actions do not modify this key. // - // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` - // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, - // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if -// and only if at least one of its permissions match the action taking place AND at least one of its -// principals match the downstream AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. +// A policy matches if and only if at least one of its permissions match the +// action taking place AND at least one of its principals match the downstream +// AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Policy"; - // Required. The set of permissions that define a role. Each permission is matched with OR - // semantics. To match all actions for this policy, a single Permission with the `any` field set - // to true should be used. + // Required. The set of permissions that define a role. Each permission is + // matched with OR semantics. To match all actions for this policy, a single + // Permission with the `any` field set to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on “action”. Each - // principal is matched with OR semantics. To match all downstreams for this policy, a single - // Principal with the `any` field set to true should be used. + // Required. The set of principals that are assigned/denied the role based on + // “action”. Each principal is matched with OR semantics. To match all + // downstreams for this policy, a single Principal with the `any` field set to + // true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; oneof expression_specifier { @@ -175,9 +182,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of `not_rule` would - // match, this permission would not match. Conversely, if the value of `not_rule` would not - // match, this permission would match. + // Negates matching the provided permission. For instance, if the value of + // `not_rule` would match, this permission would not match. Conversely, if + // the value of `not_rule` would not match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -190,7 +197,8 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name `, + // the :ref:`server name + // `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -203,13 +211,14 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream subject. +// Principal defines an identity or a group of identities for a downstream +// subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, - // each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. + // Depending on the context, each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal.Set"; @@ -224,19 +233,21 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the - // certificate, otherwise the subject field is used. If unset, it applies to any user that is - // authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order + // is used from the certificate, otherwise the subject field is used. If + // unset, it applies to any user that is authenticated. type.matcher.v4alpha.StringMatcher principal_name = 2; } oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the downstream. + // A set of identifiers that all must match in order to define the + // downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the downstream. + // A set of identifiers at least one must match in order to define the + // downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -251,21 +262,23 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is inferred - // from for example the x-forwarder-for header, proxy protocol, etc. + // :ref:`remote_ip ` is + // inferred from for example the x-forwarder-for header, proxy protocol, + // etc. core.v4alpha.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip `. - // E.g, if the remote ip is inferred from for example the x-forwarder-for header, - // proxy protocol, etc. + // :ref:`direct_remote_ip + // `. E.g, if the + // remote ip is inferred from for example the x-forwarder-for header, proxy + // protocol, etc. core.v4alpha.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only - // available for HTTP request. - // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` - // field if you want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP + // request. Only available for HTTP request. Note: the pseudo-header :path + // includes the query and fragment string. Use the `url_path` field if you + // want to match the URL path without the query and fragment string. route.v4alpha.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -274,9 +287,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of `not_id` would match, - // this principal would not match. Conversely, if the value of `not_id` would not match, this - // principal would match. + // Negates matching the provided principal. For instance, if the value of + // `not_id` would match, this principal would not match. Conversely, if the + // value of `not_id` would not match, this principal would match. Principal not_id = 8; } } diff --git a/source/extensions/filters/common/rbac/utility.h b/source/extensions/filters/common/rbac/utility.h index 317ead0bcac7a..9fc77c0495e41 100644 --- a/source/extensions/filters/common/rbac/utility.h +++ b/source/extensions/filters/common/rbac/utility.h @@ -18,9 +18,7 @@ namespace RBAC { COUNTER(allowed) \ COUNTER(denied) \ COUNTER(shadow_allowed) \ - COUNTER(shadow_denied) \ - // COUNTER(logged) \ - // COUNTER(not_logged) + COUNTER(shadow_denied) /** * Wrapper struct for RBAC filter stats. @see stats_macros.h diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index e2ab5468eb45c..7a8f192fdb608 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -42,16 +42,6 @@ void checkEngine( checkEngine(engine, expected, empty_info, connection, headers); } -// Used for testing shouldLog() function tests -// void checkEngineLog( -// const RBAC::RoleBasedAccessControlEngineImpl& engine, -// const RoleBasedAccessControlEngine::LogDecision expected, -// const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), -// const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl(), -// const StreamInfo::StreamInfo& info = NiceMock()) { -// EXPECT_EQ(expected, engine.handleAction(connection, headers, info, nullptr)); -// } - TEST(RoleBasedAccessControlEngineImpl, Disabled) { envoy::config::rbac::v3::RBAC rbac; rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); @@ -252,10 +242,6 @@ TEST(RoleBasedAccessControlEngineImpl, MistypedCondition) { (*rbac.mutable_policies())["foo"] = policy; RBAC::RoleBasedAccessControlEngineImpl engine(rbac); checkEngine(engine, false); - - // rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - // RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - // checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No); } TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { @@ -281,11 +267,6 @@ TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { (*rbac.mutable_policies())["foo"] = policy; RBAC::RoleBasedAccessControlEngineImpl engine(rbac); checkEngine(engine, false, Envoy::Network::MockConnection()); - - // rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - // RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - // checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, - // Envoy::Network::MockConnection()); } TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { @@ -322,11 +303,6 @@ TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { headers.setReference(key, value); checkEngine(engine, true, Envoy::Network::MockConnection(), headers); - - // rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - // RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - // checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, - // Envoy::Network::MockConnection(), headers); } TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { @@ -372,11 +348,6 @@ TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { EXPECT_CALL(Const(info), dynamicMetadata()).WillRepeatedly(ReturnRef(metadata)); checkEngine(engine, true, info, Envoy::Network::MockConnection(), headers); - - // rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - // RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - // checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, - // Envoy::Network::MockConnection(), headers, info); } TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { @@ -401,94 +372,8 @@ TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).Times(1).WillRepeatedly(ReturnRef(addr)); checkEngine(engine, false, info, conn, headers); - - // rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - // RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - // checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, conn, headers, - // info); } -// // Log tests tests -// TEST(RoleBasedAccessControlEngineImpl, DisabledLog) { -// envoy::config::rbac::v3::RBAC rbac; -// rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); -// checkEngineLog(RBAC::RoleBasedAccessControlEngineImpl(rbac), -// RBAC::RoleBasedAccessControlEngine::LogDecision::No); -// } - -// TEST(RoleBasedAccessControlEngineImpl, LogIfMatched) { -// envoy::config::rbac::v3::Policy policy; -// policy.add_permissions()->set_destination_port(123); -// policy.add_principals()->set_any(true); - -// envoy::config::rbac::v3::RBAC rbac; -// rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); -// (*rbac.mutable_policies())["foo"] = policy; -// RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - -// Envoy::Network::MockConnection conn; -// Envoy::Http::TestRequestHeaderMapImpl headers; -// NiceMock info; -// Envoy::Network::Address::InstanceConstSharedPtr addr = -// Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); -// EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); -// checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::Yes, conn, headers, info); - -// addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); -// EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); -// checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::No, conn, headers, info); -// } - -// TEST(RoleBasedAccessControlEngineImpl, LogAllowUndecided) { -// envoy::config::rbac::v3::Policy policy; -// policy.add_permissions()->set_destination_port(123); -// policy.add_principals()->set_any(true); - -// envoy::config::rbac::v3::RBAC rbac; -// rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); -// (*rbac.mutable_policies())["foo"] = policy; -// RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - -// Envoy::Network::MockConnection conn; -// Envoy::Http::TestRequestHeaderMapImpl headers; -// NiceMock info; -// Envoy::Network::Address::InstanceConstSharedPtr addr = -// Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); -// checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, -// headers, -// info); - -// addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); -// checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, -// headers, -// info); -// } - -// TEST(RoleBasedAccessControlEngineImpl, LogDenyUndecided) { -// envoy::config::rbac::v3::Policy policy; -// policy.add_permissions()->set_destination_port(123); -// policy.add_principals()->set_any(true); - -// envoy::config::rbac::v3::RBAC rbac; -// rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); -// (*rbac.mutable_policies())["foo"] = policy; -// RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - -// Envoy::Network::MockConnection conn; -// Envoy::Http::TestRequestHeaderMapImpl headers; -// NiceMock info; -// Envoy::Network::Address::InstanceConstSharedPtr addr = -// Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); -// checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, -// headers, -// info); - -// addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); -// checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, -// headers, -// info); -// } - TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { envoy::config::rbac::v3::Policy policy; policy.add_permissions()->set_destination_port(123); diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index dc7f2531ad994..09e3142c706e0 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -229,9 +229,6 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); - // EXPECT_EQ(1U, log_config_->stats().logged_.value()); - // EXPECT_EQ(0U, log_config_->stats().not_logged_.value()); - Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); @@ -247,9 +244,6 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); - // EXPECT_EQ(0U, log_config_->stats().logged_.value()); - // EXPECT_EQ(1U, log_config_->stats().not_logged_.value()); - Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); @@ -262,8 +256,6 @@ TEST_F(RoleBasedAccessControlFilterTest, AllowNoChangeLog) { setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); - // EXPECT_EQ(0U, config_->stats().logged_.value()); - // EXPECT_EQ(0U, config_->stats().not_logged_.value()); // Check that Allow action does not set access log metadata EXPECT_EQ(req_info_.dynamicMetadata().filter_metadata().end(), diff --git a/test/extensions/filters/network/rbac/filter_test.cc b/test/extensions/filters/network/rbac/filter_test.cc index dedf4688c8d45..fe042854baa7a 100644 --- a/test/extensions/filters/network/rbac/filter_test.cc +++ b/test/extensions/filters/network/rbac/filter_test.cc @@ -206,9 +206,6 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldLog) { EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - // EXPECT_EQ(1U, config_->stats().logged_.value()); - // EXPECT_EQ(0U, config_->stats().not_logged_.value()); - checkAccessLogMetadata(true); } @@ -224,9 +221,6 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldNotLog) { EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - // EXPECT_EQ(0U, config_->stats().logged_.value()); - // EXPECT_EQ(1U, config_->stats().not_logged_.value()); - checkAccessLogMetadata(false); } @@ -235,8 +229,6 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, AllowNoChangeLog) { setMetadata(); EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(data_, false)); - // EXPECT_EQ(0U, config_->stats().logged_.value()); - // EXPECT_EQ(0U, config_->stats().not_logged_.value()); // Check that Allow action does not set access log metadata EXPECT_EQ(stream_info_.dynamicMetadata().filter_metadata().end(), From b0688f82e36a11091755499430ca7fd03266113c Mon Sep 17 00:00:00 2001 From: davidraskin Date: Mon, 3 Aug 2020 17:13:48 +0000 Subject: [PATCH 27/39] Format Signed-off-by: davidraskin --- source/extensions/filters/common/rbac/utility.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/extensions/filters/common/rbac/utility.h b/source/extensions/filters/common/rbac/utility.h index 9fc77c0495e41..cc741ee0dc39f 100644 --- a/source/extensions/filters/common/rbac/utility.h +++ b/source/extensions/filters/common/rbac/utility.h @@ -18,7 +18,7 @@ namespace RBAC { COUNTER(allowed) \ COUNTER(denied) \ COUNTER(shadow_allowed) \ - COUNTER(shadow_denied) + COUNTER(shadow_denied) /** * Wrapper struct for RBAC filter stats. @see stats_macros.h From 0635f91bd5e4a49c6b5732da48435d1a57d7569c Mon Sep 17 00:00:00 2001 From: davidraskin Date: Mon, 3 Aug 2020 23:21:54 +0000 Subject: [PATCH 28/39] Attempt to fix potential memory leak Signed-off-by: davidraskin --- bazel.output.txt | 516 ++++++++++++++++++ source/extensions/filters/common/rbac/BUILD | 2 +- .../filters/common/rbac/engine_impl.h | 27 +- .../extensions/filters/common/rbac/utility.h | 26 +- 4 files changed, 543 insertions(+), 28 deletions(-) create mode 100644 bazel.output.txt diff --git a/bazel.output.txt b/bazel.output.txt new file mode 100644 index 0000000000000..f46e9f71acafd --- /dev/null +++ b/bazel.output.txt @@ -0,0 +1,516 @@ +==================== Test output for //test/extensions/filters/http/grpc_http1_reverse_bridge:reverse_bridge_integration_test: +WARNING: Perftools heap leak checker is active -- Performance may suffer +[==========] Running 4 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 4 tests from IpVersions/ReverseBridgeIntegrationTest +[ RUN ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv4 +[ OK ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv4 (860 ms) +[ RUN ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv6 +[2020-08-03 21:22:42.230][35831][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/339/execroot/envoy/_tmp/34b195ec3fd9b4e4f43d020a8e761e79/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address +terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address +[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc224300008bbb +[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): +[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL +[2020-08-03 21:22:42.302][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x41543bc] +[2020-08-03 21:22:42.302][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7fca75ef08a0] +[2020-08-03 21:22:42.372][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x252214e] +[2020-08-03 21:22:42.442][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x2521b89] +[2020-08-03 21:22:42.512][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x2524398] +[2020-08-03 21:22:42.583][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x25242cd] +[2020-08-03 21:22:42.655][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x252427d] +[2020-08-03 21:22:42.724][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x252424d] +[2020-08-03 21:22:42.793][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x252356e] +[2020-08-03 21:22:42.864][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x245e3d5] +[2020-08-03 21:22:42.934][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x245e295] +[2020-08-03 21:22:43.005][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5028a82] +[2020-08-03 21:22:43.075][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x5028a55] +[2020-08-03 21:22:43.075][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7fca75ee56db] +================================================================================ +==================== Test output for //test/server/admin:logs_handler_test: +WARNING: Perftools heap leak checker is active -- Performance may suffer +[==========] Running 2 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 2 tests from IpVersions/AdminInstanceTest +[ RUN ] IpVersions/AdminInstanceTest.ReopenLogs/IPv4 +TestRandomGenerator running with seed 2096517680 +[ OK ] IpVersions/AdminInstanceTest.ReopenLogs/IPv4 (395 ms) +[ RUN ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6 +TestRandomGenerator running with seed 2096517680 +unknown file: Failure +C++ exception with description "cannot bind '[::1]:0': Cannot assign requested address" thrown in the test fixture's constructor. +[ FAILED ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6, where GetParam() = 4-byte object <01-00 00-00> (319 ms) +[----------] 2 tests from IpVersions/AdminInstanceTest (714 ms total) + +[----------] Global test environment tear-down +[==========] 2 tests from 1 test suite ran. (714 ms total) +[ PASSED ] 1 test. +[ FAILED ] 1 test, listed below: +[ FAILED ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6, where GetParam() = 4-byte object <01-00 00-00> + + 1 FAILED TEST +Have memory regions w/o callers: might report false leaks +No leaks found for check "_main_" (but no 100% guarantee that there aren't any): found 17951 reachable heap objects of 2897135 bytes +================================================================================ +==================== Test output for //test/extensions/filters/http/tap:tap_filter_integration_test: +WARNING: Perftools heap leak checker is active -- Performance may suffer +[==========] Running 18 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 18 tests from IpVersions/TapIntegrationTest +[ RUN ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv4 +[ OK ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv4 (943 ms) +[ RUN ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv6 +[2020-08-03 21:28:10.135][41714][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/543/execroot/envoy/_tmp/4ce2d8b1861876b859b107620d7d2ae0/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address +terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address +[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000a2d5 +[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): +[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL +[2020-08-03 21:28:10.206][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x414c97c] +[2020-08-03 21:28:10.207][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7f549b3238a0] +[2020-08-03 21:28:10.277][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x252d4be] +[2020-08-03 21:28:10.347][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x252cef9] +[2020-08-03 21:28:10.416][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x252f708] +[2020-08-03 21:28:10.488][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x252f63d] +[2020-08-03 21:28:10.559][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x252f5ed] +[2020-08-03 21:28:10.629][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x252f5bd] +[2020-08-03 21:28:10.699][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x252e8de] +[2020-08-03 21:28:10.770][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x24694d5] +[2020-08-03 21:28:10.840][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x2469395] +[2020-08-03 21:28:10.909][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5024ee2] +[2020-08-03 21:28:10.980][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x5024eb5] +[2020-08-03 21:28:10.980][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7f549b3186db] +================================================================================ +==================== Test output for //test/extensions/filters/network/postgres_proxy:postgres_integration_test: +WARNING: Perftools heap leak checker is active -- Performance may suffer +[==========] Running 2 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 2 tests from IpVersions/PostgresIntegrationTest +[ RUN ] IpVersions/PostgresIntegrationTest.Login/0 +[ OK ] IpVersions/PostgresIntegrationTest.Login/0 (1510 ms) +[ RUN ] IpVersions/PostgresIntegrationTest.Login/1 +[2020-08-03 21:29:52.988][42506][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/674/execroot/envoy/_tmp/25d60d38146fdfcb74151ad27508c65f/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address +terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address +[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000a5f7 +[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): +[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL +[2020-08-03 21:29:53.037][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x418287c] +[2020-08-03 21:29:53.037][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7fb8f86628a0] +[2020-08-03 21:29:53.086][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x2593dae] +[2020-08-03 21:29:53.136][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x25937e9] +[2020-08-03 21:29:53.185][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x2595ff8] +[2020-08-03 21:29:53.233][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x2595f2d] +[2020-08-03 21:29:53.282][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x2595edd] +[2020-08-03 21:29:53.333][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x2595ead] +[2020-08-03 21:29:53.381][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x25951ce] +[2020-08-03 21:29:53.429][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x24c2305] +[2020-08-03 21:29:53.479][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x24c21c5] +[2020-08-03 21:29:53.529][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5057622] +[2020-08-03 21:29:53.580][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x50575f5] +[2020-08-03 21:29:53.580][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7fb8f86576db] +================================================================================ +[==========] Running 165 tests from 14 test suites. +[----------] Global test environment set-up. +[----------] 79 tests from RouteMatcherTest +[ RUN ] RouteMatcherTest.TestLegacyRoutes +[ OK ] RouteMatcherTest.TestLegacyRoutes (554 ms) +[ RUN ] RouteMatcherTest.TestConnectRoutes +[ OK ] RouteMatcherTest.TestConnectRoutes (175 ms) +[ RUN ] RouteMatcherTest.TestRoutes +[ OK ] RouteMatcherTest.TestRoutes (1526 ms) +[ RUN ] RouteMatcherTest.TestRoutesWithWildcardAndDefaultOnly +[ OK ] RouteMatcherTest.TestRoutesWithWildcardAndDefaultOnly (80 ms) +[ RUN ] RouteMatcherTest.TestRoutesWithInvalidRegexLegacy +[ OK ] RouteMatcherTest.TestRoutesWithInvalidRegexLegacy (67 ms) +[ RUN ] RouteMatcherTest.TestRoutesWithInvalidRegex +[ OK ] RouteMatcherTest.TestRoutesWithInvalidRegex (69 ms) +[ RUN ] RouteMatcherTest.TestRoutesWithInvalidVirtualCluster +[ OK ] RouteMatcherTest.TestRoutesWithInvalidVirtualCluster (51 ms) +[ RUN ] RouteMatcherTest.TestAddRemoveRequestHeaders +[ OK ] RouteMatcherTest.TestAddRemoveRequestHeaders (138 ms) +[ RUN ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalse +[ OK ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalse (117 ms) +[ RUN ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalseMostSpecificWins +[ OK ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalseMostSpecificWins (101 ms) +[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeaders +[ OK ] RouteMatcherTest.TestAddRemoveResponseHeaders (144 ms) +[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendFalse +[ OK ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendFalse (84 ms) +[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendMostSpecificWins +[ OK ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendMostSpecificWins (91 ms) +[ RUN ] RouteMatcherTest.TestAddGlobalResponseHeaderRemoveFromRoute +[ OK ] RouteMatcherTest.TestAddGlobalResponseHeaderRemoveFromRoute (95 ms) +[ RUN ] RouteMatcherTest.TestRequestHeadersToAddNoPseudoHeader +[ OK ] RouteMatcherTest.TestRequestHeadersToAddNoPseudoHeader (140 ms) +[ RUN ] RouteMatcherTest.TestRequestHeadersToRemoveNoPseudoHeader +[ OK ] RouteMatcherTest.TestRequestHeadersToRemoveNoPseudoHeader (152 ms) +[ RUN ] RouteMatcherTest.Priority +[ OK ] RouteMatcherTest.Priority (94 ms) +[ RUN ] RouteMatcherTest.NoHostRewriteAndAutoRewrite +[ OK ] RouteMatcherTest.NoHostRewriteAndAutoRewrite (49 ms) +[ RUN ] RouteMatcherTest.NoHostRewriteAndAutoRewriteHeader +[ OK ] RouteMatcherTest.NoHostRewriteAndAutoRewriteHeader (49 ms) +[ RUN ] RouteMatcherTest.NoAutoRewriteAndAutoRewriteHeader +[ OK ] RouteMatcherTest.NoAutoRewriteAndAutoRewriteHeader (49 ms) +[ RUN ] RouteMatcherTest.HeaderMatchedRouting +[ OK ] RouteMatcherTest.HeaderMatchedRouting (197 ms) +[ RUN ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfigLegacy +[ OK ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfigLegacy (54 ms) +[ RUN ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfig +[ OK ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfig (55 ms) +[ RUN ] RouteMatcherTest.QueryParamMatchedRouting +[ OK ] RouteMatcherTest.QueryParamMatchedRouting (206 ms) +[ RUN ] RouteMatcherTest.InvalidQueryParamMatchedRoutingConfig +[ OK ] RouteMatcherTest.InvalidQueryParamMatchedRoutingConfig (54 ms) +[ RUN ] RouteMatcherTest.ClusterHeader +[ OK ] RouteMatcherTest.ClusterHeader (110 ms) +[ RUN ] RouteMatcherTest.ContentType +[ OK ] RouteMatcherTest.ContentType (95 ms) +[ RUN ] RouteMatcherTest.GrpcTimeoutOffset +[ OK ] RouteMatcherTest.GrpcTimeoutOffset (83 ms) +[ RUN ] RouteMatcherTest.GrpcTimeoutOffsetOfDynamicRoute +[ OK ] RouteMatcherTest.GrpcTimeoutOffsetOfDynamicRoute (99 ms) +[ RUN ] RouteMatcherTest.FractionalRuntime +[ OK ] RouteMatcherTest.FractionalRuntime (81 ms) +[ RUN ] RouteMatcherTest.ShadowClusterNotFound +[ OK ] RouteMatcherTest.ShadowClusterNotFound (50 ms) +[ RUN ] RouteMatcherTest.ClusterNotFound +[ OK ] RouteMatcherTest.ClusterNotFound (51 ms) +[ RUN ] RouteMatcherTest.ClusterNotFoundNotChecking +[ OK ] RouteMatcherTest.ClusterNotFoundNotChecking (50 ms) +[ RUN ] RouteMatcherTest.ClusterNotFoundNotCheckingViaConfig +[ OK ] RouteMatcherTest.ClusterNotFoundNotCheckingViaConfig (51 ms) +[ RUN ] RouteMatcherTest.AttemptCountHeader +[ OK ] RouteMatcherTest.AttemptCountHeader (77 ms) +[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCode +[ OK ] RouteMatcherTest.ClusterNotFoundResponseCode (79 ms) +[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig503 +[ OK ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig503 (79 ms) +[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig404 +[ OK ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig404 (79 ms) +[ RUN ] RouteMatcherTest.Shadow +[ OK ] RouteMatcherTest.Shadow (115 ms) +[ RUN ] RouteMatcherTest.ShadowPolicyAndPolicies +[ OK ] RouteMatcherTest.ShadowPolicyAndPolicies (53 ms) +[ RUN ] RouteMatcherTest.Retry +[ OK ] RouteMatcherTest.Retry (186 ms) +[ RUN ] RouteMatcherTest.RetryVirtualHostLevel +[ OK ] RouteMatcherTest.RetryVirtualHostLevel (215 ms) +[ RUN ] RouteMatcherTest.GrpcRetry +[ OK ] RouteMatcherTest.GrpcRetry (189 ms) +[ RUN ] RouteMatcherTest.RetryBackOffIntervals +[ OK ] RouteMatcherTest.RetryBackOffIntervals (175 ms) +[ RUN ] RouteMatcherTest.InvalidRetryBackOff +[ OK ] RouteMatcherTest.InvalidRetryBackOff (57 ms) +[ RUN ] RouteMatcherTest.HedgeRouteLevel +[ OK ] RouteMatcherTest.HedgeRouteLevel (195 ms) +[ RUN ] RouteMatcherTest.HedgeVirtualHostLevel +[ OK ] RouteMatcherTest.HedgeVirtualHostLevel (199 ms) +[ RUN ] RouteMatcherTest.TestBadDefaultConfig +[ OK ] RouteMatcherTest.TestBadDefaultConfig (71 ms) +[ RUN ] RouteMatcherTest.TestDuplicateDomainConfig +[ OK ] RouteMatcherTest.TestDuplicateDomainConfig (56 ms) +[ RUN ] RouteMatcherTest.TestCaseSensitiveDomainConfig +[ OK ] RouteMatcherTest.TestCaseSensitiveDomainConfig (54 ms) +[ RUN ] RouteMatcherTest.TestDuplicateWildcardDomainConfig +[ OK ] RouteMatcherTest.TestDuplicateWildcardDomainConfig (54 ms) +[ RUN ] RouteMatcherTest.TestDuplicateSuffixWildcardDomainConfig +[ OK ] RouteMatcherTest.TestDuplicateSuffixWildcardDomainConfig (53 ms) +[ RUN ] RouteMatcherTest.TestDuplicatePrefixWildcardDomainConfig +[ OK ] RouteMatcherTest.TestDuplicatePrefixWildcardDomainConfig (53 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInPrefixRewrites +[ OK ] RouteMatcherTest.TestInvalidCharactersInPrefixRewrites (51 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInHostRewrites +[ OK ] RouteMatcherTest.TestInvalidCharactersInHostRewrites (51 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInAutoHostRewrites +[ OK ] RouteMatcherTest.TestInvalidCharactersInAutoHostRewrites (51 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInHostRedirect +[ OK ] RouteMatcherTest.TestInvalidCharactersInHostRedirect (49 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInPathRedirect +[ OK ] RouteMatcherTest.TestInvalidCharactersInPathRedirect (51 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInPrefixRewriteRedirect +[ OK ] RouteMatcherTest.TestInvalidCharactersInPrefixRewriteRedirect (50 ms) +[ RUN ] RouteMatcherTest.TestPrefixAndRegexRewrites +[ OK ] RouteMatcherTest.TestPrefixAndRegexRewrites (51 ms) +[ RUN ] RouteMatcherTest.TestDomainMatchOrderConfig +[ OK ] RouteMatcherTest.TestDomainMatchOrderConfig (157 ms) +[ RUN ] RouteMatcherTest.NoProtocolInHeadersWhenTlsIsRequired +[ OK ] RouteMatcherTest.NoProtocolInHeadersWhenTlsIsRequired (66 ms) +[ RUN ] RouteMatcherTest.RouteName +[ OK ] RouteMatcherTest.RouteName (148 ms) +[ RUN ] RouteMatcherTest.DirectResponse +[ OK ] RouteMatcherTest.DirectResponse (1138 ms) +[ RUN ] RouteMatcherTest.ExclusiveRouteEntryOrDirectResponseEntry +[ OK ] RouteMatcherTest.ExclusiveRouteEntryOrDirectResponseEntry (111 ms) +[ RUN ] RouteMatcherTest.ExclusiveWeightedClustersEntryOrDirectResponseEntry +[ OK ] RouteMatcherTest.ExclusiveWeightedClustersEntryOrDirectResponseEntry (111 ms) +[ RUN ] RouteMatcherTest.WeightedClusters +[ OK ] RouteMatcherTest.WeightedClusters (1129 ms) +[ RUN ] RouteMatcherTest.ExclusiveWeightedClustersOrClusterConfig +[ OK ] RouteMatcherTest.ExclusiveWeightedClustersOrClusterConfig (48 ms) +[ RUN ] RouteMatcherTest.WeightedClustersMissingClusterList +[ OK ] RouteMatcherTest.WeightedClustersMissingClusterList (50 ms) +[ RUN ] RouteMatcherTest.WeightedClustersEmptyClustersList +[ OK ] RouteMatcherTest.WeightedClustersEmptyClustersList (47 ms) +[ RUN ] RouteMatcherTest.WeightedClustersSumOFWeightsNotEqualToMax +[ OK ] RouteMatcherTest.WeightedClustersSumOFWeightsNotEqualToMax (87 ms) +[ RUN ] RouteMatcherTest.TestWeightedClusterWithMissingWeights +[ OK ] RouteMatcherTest.TestWeightedClusterWithMissingWeights (103 ms) +[ RUN ] RouteMatcherTest.TestWeightedClusterInvalidClusterName +[ OK ] RouteMatcherTest.TestWeightedClusterInvalidClusterName (65 ms) +[ RUN ] RouteMatcherTest.TestWeightedClusterHeaderManipulation +[ OK ] RouteMatcherTest.TestWeightedClusterHeaderManipulation (95 ms) +[ RUN ] RouteMatcherTest.TestOpaqueConfig +[ OK ] RouteMatcherTest.TestOpaqueConfig (137 ms) +[ RUN ] RouteMatcherTest.TestOpaqueConfigUsingDeprecatedName +[ OK ] RouteMatcherTest.TestOpaqueConfigUsingDeprecatedName (69 ms) +[ RUN ] RouteMatcherTest.Decorator +[ OK ] RouteMatcherTest.Decorator (83 ms) +[ RUN ] RouteMatcherTest.HeaderMatchedRoutingV2 +[ OK ] RouteMatcherTest.HeaderMatchedRoutingV2 (305 ms) +[ RUN ] RouteMatcherTest.TlsContextMatching +[ OK ] RouteMatcherTest.TlsContextMatching (187 ms) +[----------] 79 tests from RouteMatcherTest (11638 ms total) + +[----------] 10 tests from RouterMatcherHashPolicyTest +[ RUN ] RouterMatcherHashPolicyTest.HashHeaders +[ OK ] RouterMatcherHashPolicyTest.HashHeaders (96 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashHeadersRegexSubstitution +[ OK ] RouterMatcherHashPolicyTest.HashHeadersRegexSubstitution (65 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashIp +[ OK ] RouterMatcherHashPolicyTest.HashIp (124 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashIpNonIpAddress +[ OK ] RouterMatcherHashPolicyTest.HashIpNonIpAddress (73 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashIpv4DifferentAddresses +[ OK ] RouterMatcherHashPolicyTest.HashIpv4DifferentAddresses (82 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashIpv6DifferentAddresses +[ OK ] RouterMatcherHashPolicyTest.HashIpv6DifferentAddresses (81 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashQueryParameters +[ OK ] RouterMatcherHashPolicyTest.HashQueryParameters (94 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashMultiple +[ OK ] RouterMatcherHashPolicyTest.HashMultiple (122 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashTerminal +[ OK ] RouterMatcherHashPolicyTest.HashTerminal (109 ms) +[ RUN ] RouterMatcherHashPolicyTest.InvalidHashPolicies +[ OK ] RouterMatcherHashPolicyTest.InvalidHashPolicies (50 ms) +[----------] 10 tests from RouterMatcherHashPolicyTest (897 ms total) + +[----------] 5 tests from RouterMatcherCookieHashPolicyTest +[ RUN ] RouterMatcherCookieHashPolicyTest.NoTtl +[ OK ] RouterMatcherCookieHashPolicyTest.NoTtl (107 ms) +[ RUN ] RouterMatcherCookieHashPolicyTest.DifferentCookies +[ OK ] RouterMatcherCookieHashPolicyTest.DifferentCookies (80 ms) +[ RUN ] RouterMatcherCookieHashPolicyTest.TtlSet +[ OK ] RouterMatcherCookieHashPolicyTest.TtlSet (141 ms) +[ RUN ] RouterMatcherCookieHashPolicyTest.SetSessionCookie +[ OK ] RouterMatcherCookieHashPolicyTest.SetSessionCookie (66 ms) +[ RUN ] RouterMatcherCookieHashPolicyTest.SetCookiePath +[ OK ] RouterMatcherCookieHashPolicyTest.SetCookiePath (66 ms) +[----------] 5 tests from RouterMatcherCookieHashPolicyTest (460 ms total) + +[----------] 4 tests from RouterMatcherFilterStateHashPolicyTest +[ RUN ] RouterMatcherFilterStateHashPolicyTest.KeyNotFound +[ OK ] RouterMatcherFilterStateHashPolicyTest.KeyNotFound (65 ms) +[ RUN ] RouterMatcherFilterStateHashPolicyTest.NullValue +[ OK ] RouterMatcherFilterStateHashPolicyTest.NullValue (68 ms) +[ RUN ] RouterMatcherFilterStateHashPolicyTest.ValueNonHashable +[ OK ] RouterMatcherFilterStateHashPolicyTest.ValueNonHashable (66 ms) +[ RUN ] RouterMatcherFilterStateHashPolicyTest.Hashable +[ OK ] RouterMatcherFilterStateHashPolicyTest.Hashable (66 ms) +[----------] 4 tests from RouterMatcherFilterStateHashPolicyTest (266 ms total) + +[----------] 24 tests from RouteConfigurationV2 +[ RUN ] RouteConfigurationV2.RequestMirrorPolicy +[ OK ] RouteConfigurationV2.RequestMirrorPolicy (95 ms) +[ RUN ] RouteConfigurationV2.RedirectCode +[ OK ] RouteConfigurationV2.RedirectCode (94 ms) +[ RUN ] RouteConfigurationV2.DirectResponse +[ OK ] RouteConfigurationV2.DirectResponse (63 ms) +[ RUN ] RouteConfigurationV2.DirectResponseTooLarge +[ OK ] RouteConfigurationV2.DirectResponseTooLarge (60 ms) +[ RUN ] RouteConfigurationV2.BrokenTypedMetadata +[ OK ] RouteConfigurationV2.BrokenTypedMetadata (51 ms) +[ RUN ] RouteConfigurationV2.RouteConfigGetters +[ OK ] RouteConfigurationV2.RouteConfigGetters (98 ms) +[ RUN ] RouteConfigurationV2.RouteTracingConfig +[ OK ] RouteConfigurationV2.RouteTracingConfig (104 ms) +[ RUN ] RouteConfigurationV2.RedirectPrefixRewrite +[ OK ] RouteConfigurationV2.RedirectPrefixRewrite (253 ms) +[ RUN ] RouteConfigurationV2.PathRedirectQueryNotPreserved +[ OK ] RouteConfigurationV2.PathRedirectQueryNotPreserved (158 ms) +[ RUN ] RouteConfigurationV2.RedirectStripQuery +[ OK ] RouteConfigurationV2.RedirectStripQuery (196 ms) +[ RUN ] RouteConfigurationV2.RegexPrefixWithNoRewriteWorksWhenPathChanged +[ OK ] RouteConfigurationV2.RegexPrefixWithNoRewriteWorksWhenPathChanged (66 ms) +[ RUN ] RouteConfigurationV2.NoIdleTimeout +[ OK ] RouteConfigurationV2.NoIdleTimeout (61 ms) +[ RUN ] RouteConfigurationV2.ZeroIdleTimeout +[ OK ] RouteConfigurationV2.ZeroIdleTimeout (66 ms) +[ RUN ] RouteConfigurationV2.ExplicitIdleTimeout +[ OK ] RouteConfigurationV2.ExplicitIdleTimeout (63 ms) +[ RUN ] RouteConfigurationV2.RetriableStatusCodes +[ OK ] RouteConfigurationV2.RetriableStatusCodes (60 ms) +[ RUN ] RouteConfigurationV2.RetriableHeaders +[ OK ] RouteConfigurationV2.RetriableHeaders (67 ms) +[ RUN ] RouteConfigurationV2.UpgradeConfigs +[ OK ] RouteConfigurationV2.UpgradeConfigs (66 ms) +[ RUN ] RouteConfigurationV2.DuplicateUpgradeConfigs +[ OK ] RouteConfigurationV2.DuplicateUpgradeConfigs (52 ms) +[ RUN ] RouteConfigurationV2.BadConnectConfig +[ OK ] RouteConfigurationV2.BadConnectConfig (53 ms) +[ RUN ] RouteConfigurationV2.RetryPluginsAreNotReused +[ OK ] RouteConfigurationV2.RetryPluginsAreNotReused (66 ms) +[ RUN ] RouteConfigurationV2.InternalRedirectIsDisabledWhenNotSpecifiedInRouteAction +[ OK ] RouteConfigurationV2.InternalRedirectIsDisabledWhenNotSpecifiedInRouteAction (64 ms) +[ RUN ] RouteConfigurationV2.DefaultInternalRedirectPolicyIsSensible +[ OK ] RouteConfigurationV2.DefaultInternalRedirectPolicyIsSensible (67 ms) +[ RUN ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCode +[ OK ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCode (65 ms) +[ RUN ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCodeCauseEmptySet +[ OK ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCodeCauseEmptySet (67 ms) +[----------] 24 tests from RouteConfigurationV2 (2055 ms total) + +[----------] 1 test from NullConfigImplTest +[ RUN ] NullConfigImplTest.All +[ OK ] NullConfigImplTest.All (11 ms) +[----------] 1 test from NullConfigImplTest (11 ms total) + +[----------] 9 tests from BadHttpRouteConfigurationsTest +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteConfig +[ OK ] BadHttpRouteConfigurationsTest.BadRouteConfig (50 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadVirtualHostConfig +[ OK ] BadHttpRouteConfigurationsTest.BadVirtualHostConfig (51 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfig +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfig (51 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPath +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPath (49 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigMissingPathSpecifier +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigMissingPathSpecifier (49 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndRegex +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndRegex (49 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigNoAction +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigNoAction (49 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPathAndRegex +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPathAndRegex (48 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPathAndRegex +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPathAndRegex (49 ms) +[----------] 9 tests from BadHttpRouteConfigurationsTest (445 ms total) + +[----------] 6 tests from RoutePropertyTest +[ RUN ] RoutePropertyTest.ExcludeVHRateLimits +[ OK ] RoutePropertyTest.ExcludeVHRateLimits (101 ms) +[ RUN ] RoutePropertyTest.TestVHostCorsConfig +[ OK ] RoutePropertyTest.TestVHostCorsConfig (68 ms) +[ RUN ] RoutePropertyTest.TestRouteCorsConfig +[ OK ] RoutePropertyTest.TestRouteCorsConfig (67 ms) +[ RUN ] RoutePropertyTest.TTestVHostCorsLegacyConfig +[ OK ] RoutePropertyTest.TTestVHostCorsLegacyConfig (64 ms) +[ RUN ] RoutePropertyTest.TestRouteCorsLegacyConfig +[ OK ] RoutePropertyTest.TestRouteCorsLegacyConfig (66 ms) +[ RUN ] RoutePropertyTest.TestBadCorsConfig +[ OK ] RoutePropertyTest.TestBadCorsConfig (50 ms) +[----------] 6 tests from RoutePropertyTest (416 ms total) + +[----------] 2 tests from CustomRequestHeadersTest +[ RUN ] CustomRequestHeadersTest.AddNewHeader +[ OK ] CustomRequestHeadersTest.AddNewHeader (80 ms) +[ RUN ] CustomRequestHeadersTest.CustomHeaderWrongFormat +[ OK ] CustomRequestHeadersTest.CustomHeaderWrongFormat (65 ms) +[----------] 2 tests from CustomRequestHeadersTest (1591 ms total) + +[----------] 3 tests from MetadataMatchCriteriaImpl +[ RUN ] MetadataMatchCriteriaImpl.Create +[ OK ] MetadataMatchCriteriaImpl.Create (0 ms) +[ RUN ] MetadataMatchCriteriaImpl.Merge +[ OK ] MetadataMatchCriteriaImpl.Merge (0 ms) +[ RUN ] MetadataMatchCriteriaImpl.Filter +[ OK ] MetadataMatchCriteriaImpl.Filter (0 ms) +[----------] 3 tests from MetadataMatchCriteriaImpl (0 ms total) + +[----------] 1 test from RouteEntryMetadataMatchTest +[ RUN ] RouteEntryMetadataMatchTest.ParsesMetadata +[ OK ] RouteEntryMetadataMatchTest.ParsesMetadata (206 ms) +[----------] 1 test from RouteEntryMetadataMatchTest (206 ms total) + +[----------] 2 tests from ConfigUtilityTest +[ RUN ] ConfigUtilityTest.ParseResponseCode +[ OK ] ConfigUtilityTest.ParseResponseCode (46 ms) +[ RUN ] ConfigUtilityTest.ParseDirectResponseBody +[ OK ] ConfigUtilityTest.ParseDirectResponseBody (46 ms) +[----------] 2 tests from ConfigUtilityTest (92 ms total) + +[----------] 11 tests from PerFilterConfigsTest +[ RUN ] PerFilterConfigsTest.TypedConfigFilterError +[ OK ] PerFilterConfigsTest.TypedConfigFilterError (62 ms) +[ RUN ] PerFilterConfigsTest.UnknownFilterStruct +[ OK ] PerFilterConfigsTest.UnknownFilterStruct (51 ms) +[ RUN ] PerFilterConfigsTest.UnknownFilterAny +[ OK ] PerFilterConfigsTest.UnknownFilterAny (50 ms) +[ RUN ] PerFilterConfigsTest.DefaultFilterImplementationStruct +[ OK ] PerFilterConfigsTest.DefaultFilterImplementationStruct (67 ms) +[ RUN ] PerFilterConfigsTest.DefaultFilterImplementationAny +[ OK ] PerFilterConfigsTest.DefaultFilterImplementationAny (67 ms) +[ RUN ] PerFilterConfigsTest.RouteLocalConfig +[ OK ] PerFilterConfigsTest.RouteLocalConfig (68 ms) +[ RUN ] PerFilterConfigsTest.RouteLocalTypedConfig +[ OK ] PerFilterConfigsTest.RouteLocalTypedConfig (67 ms) +[ RUN ] PerFilterConfigsTest.WeightedClusterConfig +[ OK ] PerFilterConfigsTest.WeightedClusterConfig (68 ms) +[ RUN ] PerFilterConfigsTest.WeightedClusterTypedConfig +[ OK ] PerFilterConfigsTest.WeightedClusterTypedConfig (68 ms) +[ RUN ] PerFilterConfigsTest.WeightedClusterFallthroughConfig +[ OK ] PerFilterConfigsTest.WeightedClusterFallthroughConfig (68 ms) +[ RUN ] PerFilterConfigsTest.WeightedClusterFallthroughTypedConfig +[ OK ] PerFilterConfigsTest.WeightedClusterFallthroughTypedConfig (67 ms) +[----------] 11 tests from PerFilterConfigsTest (704 ms total) + +[----------] 8 tests from RouteMatchOverrideTest +[ RUN ] RouteMatchOverrideTest.VerifyAllMatchableRoutes +[ OK ] RouteMatchOverrideTest.VerifyAllMatchableRoutes (65 ms) +[ RUN ] RouteMatchOverrideTest.VerifyRouteOverrideStops +[ OK ] RouteMatchOverrideTest.VerifyRouteOverrideStops (64 ms) +[ RUN ] RouteMatchOverrideTest.StopWhenNoMoreRoutes +[ OK ] RouteMatchOverrideTest.StopWhenNoMoreRoutes (65 ms) +[ RUN ] RouteMatchOverrideTest.NullRouteOnNoRouteMatch +[ OK ] RouteMatchOverrideTest.NullRouteOnNoRouteMatch (81 ms) +[ RUN ] RouteMatchOverrideTest.NullRouteOnNoHostMatch +[ OK ] RouteMatchOverrideTest.NullRouteOnNoHostMatch (66 ms) +[ RUN ] RouteMatchOverrideTest.NullRouteOnNullXForwardedProto +[ OK ] RouteMatchOverrideTest.NullRouteOnNullXForwardedProto (66 ms) +[ RUN ] RouteMatchOverrideTest.NullRouteOnRequireTlsAll +[ OK ] RouteMatchOverrideTest.NullRouteOnRequireTlsAll (65 ms) +[ RUN ] RouteMatchOverrideTest.NullRouteOnRequireTlsInternal +[ OK ] RouteMatchOverrideTest.NullRouteOnRequireTlsInternal (65 ms) +[----------] 8 tests from RouteMatchOverrideTest (538 ms total) + +[----------] Global test environment tear-down +[==========] 165 tests from 14 test suites ran. (19322 ms total) +[ PASSED ] 165 tests. +==================== Test output for //test/extensions/filters/network/sni_dynamic_forward_proxy:proxy_filter_integration_test: +WARNING: Perftools heap leak checker is active -- Performance may suffer +[==========] Running 4 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 4 tests from IpVersions/SniDynamicProxyFilterIntegrationTest +[ RUN ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv4 +TestRandomGenerator running with seed 205585968 +[ OK ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv4 (765 ms) +[ RUN ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv6 +TestRandomGenerator running with seed 205585968 +[2020-08-03 21:33:40.808][44312][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/898/execroot/envoy/_tmp/282b4d28423b557fc72f2459645621cd/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address +terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address +[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000acdd +[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): +[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL +[2020-08-03 21:33:40.881][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x4267f3c] +[2020-08-03 21:33:40.881][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7f8f0f7748a0] +[2020-08-03 21:33:40.952][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x266b38e] +[2020-08-03 21:33:41.024][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x266adc9] +[2020-08-03 21:33:41.096][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x266d5d8] +[2020-08-03 21:33:41.168][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x266d50d] +[2020-08-03 21:33:41.239][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x266d4bd] +[2020-08-03 21:33:41.311][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x266d48d] +[2020-08-03 21:33:41.382][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x266c7ae] +[2020-08-03 21:33:41.453][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x25b1745] +[2020-08-03 21:33:41.525][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x25b1605] +[2020-08-03 21:33:41.596][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x513dce2] +[2020-08-03 21:33:41.668][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x513dcb5] +[2020-08-03 21:33:41.668][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7f8f0f7696db] +================================================================================ diff --git a/source/extensions/filters/common/rbac/BUILD b/source/extensions/filters/common/rbac/BUILD index ec1296b13464f..9a9bbc1057495 100644 --- a/source/extensions/filters/common/rbac/BUILD +++ b/source/extensions/filters/common/rbac/BUILD @@ -13,6 +13,7 @@ envoy_cc_library( srcs = ["utility.cc"], hdrs = ["utility.h"], deps = [ + ":engine_lib", "//include/envoy/stats:stats_macros", "//source/common/singleton:const_singleton", ], @@ -53,7 +54,6 @@ envoy_cc_library( srcs = ["engine_impl.cc"], hdrs = ["engine_impl.h"], deps = [ - ":utility_lib", "//source/extensions/filters/common/rbac:engine_interface", "//source/extensions/filters/common/rbac:matchers_lib", "@envoy_api//envoy/config/rbac/v3:pkg_cc_proto", diff --git a/source/extensions/filters/common/rbac/engine_impl.h b/source/extensions/filters/common/rbac/engine_impl.h index f24a43a8e9192..4294bc8777547 100644 --- a/source/extensions/filters/common/rbac/engine_impl.h +++ b/source/extensions/filters/common/rbac/engine_impl.h @@ -4,7 +4,6 @@ #include "extensions/filters/common/rbac/engine.h" #include "extensions/filters/common/rbac/matchers.h" -#include "extensions/filters/common/rbac/utility.h" namespace Envoy { namespace Extensions { @@ -12,6 +11,18 @@ namespace Filters { namespace Common { namespace RBAC { +class DynamicMetadataKeys { +public: + const std::string ShadowEffectivePolicyIdField{"shadow_effective_policy_id"}; + const std::string ShadowEngineResultField{"shadow_engine_result"}; + const std::string EngineResultAllowed{"allowed"}; + const std::string EngineResultDenied{"denied"}; + const std::string AccessLogKey{"access_log_hint"}; + const std::string CommonNamespace{"envoy.common"}; +}; + +using DynamicMetadataKeysSingleton = ConstSingleton; + enum class EnforcementMode { Enforced, Shadow }; class RoleBasedAccessControlEngineImpl : public RoleBasedAccessControlEngine, NonCopyable { @@ -41,20 +52,6 @@ class RoleBasedAccessControlEngineImpl : public RoleBasedAccessControlEngine, No Expr::BuilderPtr builder_; }; -template -std::unique_ptr createEngine(const ConfigType& config) { - return config.has_rules() ? std::make_unique( - config.rules(), EnforcementMode::Enforced) - : nullptr; -} - -template -std::unique_ptr createShadowEngine(const ConfigType& config) { - return config.has_shadow_rules() ? std::make_unique( - config.shadow_rules(), EnforcementMode::Shadow) - : nullptr; -} - } // namespace RBAC } // namespace Common } // namespace Filters diff --git a/source/extensions/filters/common/rbac/utility.h b/source/extensions/filters/common/rbac/utility.h index cc741ee0dc39f..8f88ec131a861 100644 --- a/source/extensions/filters/common/rbac/utility.h +++ b/source/extensions/filters/common/rbac/utility.h @@ -1,10 +1,11 @@ #pragma once -#include "envoy/stats/scope.h" #include "envoy/stats/stats_macros.h" #include "common/singleton/const_singleton.h" +#include "extensions/filters/common/rbac/engine_impl.h" + namespace Envoy { namespace Extensions { namespace Filters { @@ -29,17 +30,18 @@ struct RoleBasedAccessControlFilterStats { RoleBasedAccessControlFilterStats generateStats(const std::string& prefix, Stats::Scope& scope); -class DynamicMetadataKeys { -public: - const std::string ShadowEffectivePolicyIdField{"shadow_effective_policy_id"}; - const std::string ShadowEngineResultField{"shadow_engine_result"}; - const std::string EngineResultAllowed{"allowed"}; - const std::string EngineResultDenied{"denied"}; - const std::string AccessLogKey{"access_log_hint"}; - const std::string CommonNamespace{"envoy.common"}; -}; - -using DynamicMetadataKeysSingleton = ConstSingleton; +template +std::unique_ptr createEngine(const ConfigType& config) { + return config.has_rules() ? std::make_unique(config.rules(), EnforcementMode::Enforced) + : nullptr; +} + +template +std::unique_ptr createShadowEngine(const ConfigType& config) { + return config.has_shadow_rules() + ? std::make_unique(config.shadow_rules(), EnforcementMode::Shadow) + : nullptr; +} } // namespace RBAC } // namespace Common From 57e7971ca3f546fb9d14abce4a87a7084711ad36 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Mon, 3 Aug 2020 23:53:29 +0000 Subject: [PATCH 29/39] Forgot to push format fix Signed-off-by: davidraskin --- source/extensions/filters/common/rbac/utility.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source/extensions/filters/common/rbac/utility.h b/source/extensions/filters/common/rbac/utility.h index 8f88ec131a861..04635eb37411e 100644 --- a/source/extensions/filters/common/rbac/utility.h +++ b/source/extensions/filters/common/rbac/utility.h @@ -32,15 +32,16 @@ RoleBasedAccessControlFilterStats generateStats(const std::string& prefix, Stats template std::unique_ptr createEngine(const ConfigType& config) { - return config.has_rules() ? std::make_unique(config.rules(), EnforcementMode::Enforced) + return config.has_rules() ? std::make_unique( + config.rules(), EnforcementMode::Enforced) : nullptr; } template std::unique_ptr createShadowEngine(const ConfigType& config) { - return config.has_shadow_rules() - ? std::make_unique(config.shadow_rules(), EnforcementMode::Shadow) - : nullptr; + return config.has_shadow_rules() ? std::make_unique( + config.shadow_rules(), EnforcementMode::Shadow) + : nullptr; } } // namespace RBAC From 0be2feabba3cc3bef47e2fa7031d0b9150609b2d Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 4 Aug 2020 01:30:55 +0000 Subject: [PATCH 30/39] Attempt to fix mem leak 2 Signed-off-by: davidraskin --- source/extensions/filters/http/rbac/rbac_filter.cc | 14 +++++++++++--- .../extensions/filters/network/rbac/rbac_filter.cc | 14 +++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index 3079664701b91..0c5b96edf3894 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -25,9 +25,17 @@ using RcDetails = ConstSingleton; RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::http::rbac::v3::RBAC& proto_config, const std::string& stats_prefix, Stats::Scope& scope) - : stats_(Filters::Common::RBAC::generateStats(stats_prefix, scope)), - engine_(Filters::Common::RBAC::createEngine(proto_config)), - shadow_engine_(Filters::Common::RBAC::createShadowEngine(proto_config)) {} + : stats_(Filters::Common::RBAC::generateStats(stats_prefix, scope)) { + engine_ = proto_config.has_rules() + ? std::make_unique( + proto_config.rules(), Filters::Common::RBAC::EnforcementMode::Enforced) + : nullptr; + shadow_engine_ = + proto_config.has_shadow_rules() + ? std::make_unique( + proto_config.shadow_rules(), Filters::Common::RBAC::EnforcementMode::Shadow) + : nullptr; +} Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* RoleBasedAccessControlFilterConfig::engine(const Router::RouteConstSharedPtr route, diff --git a/source/extensions/filters/network/rbac/rbac_filter.cc b/source/extensions/filters/network/rbac/rbac_filter.cc index 5bb07b6aae110..db5a8ec075cd3 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.cc +++ b/source/extensions/filters/network/rbac/rbac_filter.cc @@ -16,9 +16,17 @@ namespace RBACFilter { RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::network::rbac::v3::RBAC& proto_config, Stats::Scope& scope) : stats_(Filters::Common::RBAC::generateStats(proto_config.stat_prefix(), scope)), - engine_(Filters::Common::RBAC::createEngine(proto_config)), - shadow_engine_(Filters::Common::RBAC::createShadowEngine(proto_config)), - enforcement_type_(proto_config.enforcement_type()) {} + enforcement_type_(proto_config.enforcement_type()) { + engine_ = proto_config.has_rules() + ? std::make_unique( + proto_config.rules(), Filters::Common::RBAC::EnforcementMode::Enforced) + : nullptr; + shadow_engine_ = + proto_config.has_shadow_rules() + ? std::make_unique( + proto_config.shadow_rules(), Filters::Common::RBAC::EnforcementMode::Shadow) + : nullptr; +} Network::FilterStatus RoleBasedAccessControlFilter::onData(Buffer::Instance&, bool) { ENVOY_LOG(debug, From 4e79f36fc642d8d156b121530c0e42aa67d1759b Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 4 Aug 2020 03:01:27 +0000 Subject: [PATCH 31/39] Fix invalid mock method potentially causing clang_tidy error Signed-off-by: davidraskin --- test/extensions/filters/common/rbac/mocks.h | 18 +++++++------- .../filters/http/rbac/rbac_filter_test.cc | 24 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/test/extensions/filters/common/rbac/mocks.h b/test/extensions/filters/common/rbac/mocks.h index 936db43752a05..c597bbd0ee4b4 100644 --- a/test/extensions/filters/common/rbac/mocks.h +++ b/test/extensions/filters/common/rbac/mocks.h @@ -18,15 +18,15 @@ class MockEngine : public RoleBasedAccessControlEngineImpl { const EnforcementMode mode = EnforcementMode::Shadow) : RoleBasedAccessControlEngineImpl(rules, mode){}; - MOCK_METHOD(bool, allowed, - (const Envoy::Network::Connection&, const Envoy::Http::RequestHeaderMap&, - const StreamInfo::StreamInfo&, std::string* effective_policy_id), - (const)); - - MOCK_METHOD(bool, allowed, - (const Envoy::Network::Connection&, const StreamInfo::StreamInfo&, - std::string* effective_policy_id), - (const)); + // MOCK_METHOD(bool, allowed, + // (const Envoy::Network::Connection&, const Envoy::Http::RequestHeaderMap&, + // const StreamInfo::StreamInfo&, std::string* effective_policy_id), + // (const)); + + // MOCK_METHOD(bool, allowed, + // (const Envoy::Network::Connection&, const StreamInfo::StreamInfo&, + // std::string* effective_policy_id), + // (const)); }; } // namespace RBAC diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index 09e3142c706e0..873121d741001 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -203,22 +203,22 @@ TEST_F(RoleBasedAccessControlFilterTest, Denied) { EXPECT_EQ("rbac_access_denied", callbacks_.details_); } -TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { - setDestinationPort(456); +// TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { +// setDestinationPort(456); - envoy::extensions::filters::http::rbac::v3::RBACPerRoute route_config; - route_config.mutable_rbac()->mutable_rules()->set_action(envoy::config::rbac::v3::RBAC::DENY); - NiceMock engine{route_config.rbac().rules()}; - NiceMock per_route_config_{route_config}; +// envoy::extensions::filters::http::rbac::v3::RBACPerRoute route_config; +// route_config.mutable_rbac()->mutable_rules()->set_action(envoy::config::rbac::v3::RBAC::DENY); +// NiceMock engine{route_config.rbac().rules()}; +// NiceMock per_route_config_{route_config}; - EXPECT_CALL(engine, allowed(_, _, _, _)).WillRepeatedly(Return(true)); - EXPECT_CALL(per_route_config_, engine()).WillRepeatedly(ReturnRef(engine)); +// // EXPECT_CALL(engine, allowed(_, _, _, _)).WillRepeatedly(Return(true)); +// EXPECT_CALL(per_route_config_, engine()).WillRepeatedly(ReturnRef(engine)); - EXPECT_CALL(callbacks_.route_->route_entry_, perFilterConfig(HttpFilterNames::get().Rbac)) - .WillRepeatedly(Return(&per_route_config_)); +// EXPECT_CALL(callbacks_.route_->route_entry_, perFilterConfig(HttpFilterNames::get().Rbac)) +// .WillRepeatedly(Return(&per_route_config_)); - EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, true)); -} +// EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, true)); +// } // Log Tests TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { From a0d58d80b83d113c357b8484ab920d972b58bb69 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 4 Aug 2020 04:24:27 +0000 Subject: [PATCH 32/39] Reverting to last fully working commit Signed-off-by: davidraskin --- api/envoy/config/rbac/v3/rbac.proto | 97 ++-- api/envoy/config/rbac/v4alpha/rbac.proto | 97 ++-- bazel.output.txt | 516 ------------------ .../advanced/well_known_dynamic_metadata.rst | 2 +- .../listeners/network_filters/rbac_filter.rst | 2 +- docs/root/version_history/current.rst | 1 - .../envoy/config/rbac/v3/rbac.proto | 97 ++-- .../envoy/config/rbac/v4alpha/rbac.proto | 97 ++-- .../extensions/filters/common/rbac/engine.h | 50 +- .../filters/common/rbac/engine_impl.cc | 86 +-- .../filters/common/rbac/engine_impl.h | 41 +- .../extensions/filters/common/rbac/utility.h | 27 +- .../filters/http/rbac/rbac_filter.cc | 47 +- .../filters/http/rbac/rbac_filter.h | 10 +- .../filters/network/rbac/rbac_filter.cc | 46 +- .../filters/network/rbac/rbac_filter.h | 2 +- .../filters/common/rbac/engine_impl_test.cc | 147 ++++- test/extensions/filters/common/rbac/mocks.h | 25 +- .../filters/http/rbac/rbac_filter_test.cc | 44 +- .../filters/network/rbac/filter_test.cc | 8 + 20 files changed, 527 insertions(+), 915 deletions(-) delete mode 100644 bazel.output.txt diff --git a/api/envoy/config/rbac/v3/rbac.proto b/api/envoy/config/rbac/v3/rbac.proto index 278e6857603fe..9b3fd0524868b 100644 --- a/api/envoy/config/rbac/v3/rbac.proto +++ b/api/envoy/config/rbac/v3/rbac.proto @@ -82,47 +82,40 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match. - // All requests are allowed. + // The policies set the `access_log_hint` dynamic metadata key based on if requests match LOG = 2; } - // The action to take if a policy matches. Every action either allows or denies a request, - // and can also carry out action-specific operations. + // The action to take if a policy matches. + // The request is allowed if and only if: // - // Actions: - // - // * ALLOW: Allows the request if and only if there is a policy that matches - // the request. - // * DENY: Allows the request if and only if there are no policies that - // match the request. - // * LOG: Allows all requests. If at least one policy matches, the dynamic - // metadata key `access_log_hint` is set to the value `true` under the shared - // key namespace 'envoy.common'. If no policies match, it is set to `false`. - // Other actions do not modify this key. + // * `action` is "ALLOW" and at least one policy matches + // * `action` is "DENY" and none of the policies match + // * `action` is "LOG" // + // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` + // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, + // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. -// A policy matches if and only if at least one of its permissions match the -// action taking place AND at least one of its principals match the downstream -// AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if +// and only if at least one of its permissions match the action taking place AND at least one of its +// principals match the downstream AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Policy"; - // Required. The set of permissions that define a role. Each permission is - // matched with OR semantics. To match all actions for this policy, a single - // Permission with the `any` field set to true should be used. + // Required. The set of permissions that define a role. Each permission is matched with OR + // semantics. To match all actions for this policy, a single Permission with the `any` field set + // to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on - // “action”. Each principal is matched with OR semantics. To match all - // downstreams for this policy, a single Principal with the `any` field set to - // true should be used. + // Required. The set of principals that are assigned/denied the role based on “action”. Each + // principal is matched with OR semantics. To match all downstreams for this policy, a single + // Principal with the `any` field set to true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; // An optional symbolic expression specifying an access control @@ -183,9 +176,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of - // `not_rule` would match, this permission would not match. Conversely, if - // the value of `not_rule` would not match, this permission would match. + // Negates matching the provided permission. For instance, if the value of `not_rule` would + // match, this permission would not match. Conversely, if the value of `not_rule` would not + // match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -198,8 +191,7 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name - // `, + // the :ref:`server name `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -212,14 +204,13 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream -// subject. +// Principal defines an identity or a group of identities for a downstream subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. - // Depending on the context, each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, + // each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal.Set"; @@ -234,21 +225,19 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order - // is used from the certificate, otherwise the subject field is used. If - // unset, it applies to any user that is authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the + // certificate, otherwise the subject field is used. If unset, it applies to any user that is + // authenticated. type.matcher.v3.StringMatcher principal_name = 2; } oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the - // downstream. + // A set of identifiers that all must match in order to define the downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the - // downstream. + // A set of identifiers at least one must match in order to define the downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -263,23 +252,21 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is - // inferred from for example the x-forwarder-for header, proxy protocol, - // etc. + // :ref:`remote_ip ` is inferred + // from for example the x-forwarder-for header, proxy protocol, etc. core.v3.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip - // `. E.g, if the - // remote ip is inferred from for example the x-forwarder-for header, proxy - // protocol, etc. + // :ref:`direct_remote_ip `. + // E.g, if the remote ip is inferred from for example the x-forwarder-for header, + // proxy protocol, etc. core.v3.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP - // request. Only available for HTTP request. Note: the pseudo-header :path - // includes the query and fragment string. Use the `url_path` field if you - // want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only + // available for HTTP request. + // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` + // field if you want to match the URL path without the query and fragment string. route.v3.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -288,9 +275,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of - // `not_id` would match, this principal would not match. Conversely, if the - // value of `not_id` would not match, this principal would match. + // Negates matching the provided principal. For instance, if the value of `not_id` would match, + // this principal would not match. Conversely, if the value of `not_id` would not match, this + // principal would match. Principal not_id = 8; } } diff --git a/api/envoy/config/rbac/v4alpha/rbac.proto b/api/envoy/config/rbac/v4alpha/rbac.proto index cc9d8933ababc..eea66a969f58a 100644 --- a/api/envoy/config/rbac/v4alpha/rbac.proto +++ b/api/envoy/config/rbac/v4alpha/rbac.proto @@ -81,47 +81,40 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match. - // All requests are allowed. + // The policies set the `access_log_hint` dynamic metadata key based on if requests match LOG = 2; } - // The action to take if a policy matches. Every action either allows or denies a request, - // and can also carry out action-specific operations. + // The action to take if a policy matches. + // The request is allowed if and only if: // - // Actions: - // - // * ALLOW: Allows the request if and only if there is a policy that matches - // the request. - // * DENY: Allows the request if and only if there are no policies that - // match the request. - // * LOG: Allows all requests. If at least one policy matches, the dynamic - // metadata key `access_log_hint` is set to the value `true` under the shared - // key namespace 'envoy.common'. If no policies match, it is set to `false`. - // Other actions do not modify this key. + // * `action` is "ALLOW" and at least one policy matches + // * `action` is "DENY" and none of the policies match + // * `action` is "LOG" // + // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` + // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, + // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. -// A policy matches if and only if at least one of its permissions match the -// action taking place AND at least one of its principals match the downstream -// AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if +// and only if at least one of its permissions match the action taking place AND at least one of its +// principals match the downstream AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Policy"; - // Required. The set of permissions that define a role. Each permission is - // matched with OR semantics. To match all actions for this policy, a single - // Permission with the `any` field set to true should be used. + // Required. The set of permissions that define a role. Each permission is matched with OR + // semantics. To match all actions for this policy, a single Permission with the `any` field set + // to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on - // “action”. Each principal is matched with OR semantics. To match all - // downstreams for this policy, a single Principal with the `any` field set to - // true should be used. + // Required. The set of principals that are assigned/denied the role based on “action”. Each + // principal is matched with OR semantics. To match all downstreams for this policy, a single + // Principal with the `any` field set to true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; oneof expression_specifier { @@ -182,9 +175,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of - // `not_rule` would match, this permission would not match. Conversely, if - // the value of `not_rule` would not match, this permission would match. + // Negates matching the provided permission. For instance, if the value of `not_rule` would + // match, this permission would not match. Conversely, if the value of `not_rule` would not + // match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -197,8 +190,7 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name - // `, + // the :ref:`server name `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -211,14 +203,13 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream -// subject. +// Principal defines an identity or a group of identities for a downstream subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. - // Depending on the context, each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, + // each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal.Set"; @@ -233,9 +224,9 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order - // is used from the certificate, otherwise the subject field is used. If - // unset, it applies to any user that is authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the + // certificate, otherwise the subject field is used. If unset, it applies to any user that is + // authenticated. type.matcher.v4alpha.StringMatcher principal_name = 2; } @@ -246,12 +237,10 @@ message Principal { oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the - // downstream. + // A set of identifiers that all must match in order to define the downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the - // downstream. + // A set of identifiers at least one must match in order to define the downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -262,23 +251,21 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is - // inferred from for example the x-forwarder-for header, proxy protocol, - // etc. + // :ref:`remote_ip ` is inferred + // from for example the x-forwarder-for header, proxy protocol, etc. core.v4alpha.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip - // `. E.g, if the - // remote ip is inferred from for example the x-forwarder-for header, proxy - // protocol, etc. + // :ref:`direct_remote_ip `. + // E.g, if the remote ip is inferred from for example the x-forwarder-for header, + // proxy protocol, etc. core.v4alpha.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP - // request. Only available for HTTP request. Note: the pseudo-header :path - // includes the query and fragment string. Use the `url_path` field if you - // want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only + // available for HTTP request. + // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` + // field if you want to match the URL path without the query and fragment string. route.v4alpha.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -287,9 +274,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of - // `not_id` would match, this principal would not match. Conversely, if the - // value of `not_id` would not match, this principal would match. + // Negates matching the provided principal. For instance, if the value of `not_id` would match, + // this principal would not match. Conversely, if the value of `not_id` would not match, this + // principal would match. Principal not_id = 8; } } diff --git a/bazel.output.txt b/bazel.output.txt deleted file mode 100644 index f46e9f71acafd..0000000000000 --- a/bazel.output.txt +++ /dev/null @@ -1,516 +0,0 @@ -==================== Test output for //test/extensions/filters/http/grpc_http1_reverse_bridge:reverse_bridge_integration_test: -WARNING: Perftools heap leak checker is active -- Performance may suffer -[==========] Running 4 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 4 tests from IpVersions/ReverseBridgeIntegrationTest -[ RUN ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv4 -[ OK ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv4 (860 ms) -[ RUN ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv6 -[2020-08-03 21:22:42.230][35831][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/339/execroot/envoy/_tmp/34b195ec3fd9b4e4f43d020a8e761e79/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address -terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address -[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc224300008bbb -[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): -[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL -[2020-08-03 21:22:42.302][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x41543bc] -[2020-08-03 21:22:42.302][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7fca75ef08a0] -[2020-08-03 21:22:42.372][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x252214e] -[2020-08-03 21:22:42.442][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x2521b89] -[2020-08-03 21:22:42.512][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x2524398] -[2020-08-03 21:22:42.583][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x25242cd] -[2020-08-03 21:22:42.655][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x252427d] -[2020-08-03 21:22:42.724][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x252424d] -[2020-08-03 21:22:42.793][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x252356e] -[2020-08-03 21:22:42.864][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x245e3d5] -[2020-08-03 21:22:42.934][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x245e295] -[2020-08-03 21:22:43.005][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5028a82] -[2020-08-03 21:22:43.075][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x5028a55] -[2020-08-03 21:22:43.075][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7fca75ee56db] -================================================================================ -==================== Test output for //test/server/admin:logs_handler_test: -WARNING: Perftools heap leak checker is active -- Performance may suffer -[==========] Running 2 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 2 tests from IpVersions/AdminInstanceTest -[ RUN ] IpVersions/AdminInstanceTest.ReopenLogs/IPv4 -TestRandomGenerator running with seed 2096517680 -[ OK ] IpVersions/AdminInstanceTest.ReopenLogs/IPv4 (395 ms) -[ RUN ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6 -TestRandomGenerator running with seed 2096517680 -unknown file: Failure -C++ exception with description "cannot bind '[::1]:0': Cannot assign requested address" thrown in the test fixture's constructor. -[ FAILED ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6, where GetParam() = 4-byte object <01-00 00-00> (319 ms) -[----------] 2 tests from IpVersions/AdminInstanceTest (714 ms total) - -[----------] Global test environment tear-down -[==========] 2 tests from 1 test suite ran. (714 ms total) -[ PASSED ] 1 test. -[ FAILED ] 1 test, listed below: -[ FAILED ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6, where GetParam() = 4-byte object <01-00 00-00> - - 1 FAILED TEST -Have memory regions w/o callers: might report false leaks -No leaks found for check "_main_" (but no 100% guarantee that there aren't any): found 17951 reachable heap objects of 2897135 bytes -================================================================================ -==================== Test output for //test/extensions/filters/http/tap:tap_filter_integration_test: -WARNING: Perftools heap leak checker is active -- Performance may suffer -[==========] Running 18 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 18 tests from IpVersions/TapIntegrationTest -[ RUN ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv4 -[ OK ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv4 (943 ms) -[ RUN ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv6 -[2020-08-03 21:28:10.135][41714][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/543/execroot/envoy/_tmp/4ce2d8b1861876b859b107620d7d2ae0/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address -terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address -[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000a2d5 -[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): -[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL -[2020-08-03 21:28:10.206][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x414c97c] -[2020-08-03 21:28:10.207][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7f549b3238a0] -[2020-08-03 21:28:10.277][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x252d4be] -[2020-08-03 21:28:10.347][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x252cef9] -[2020-08-03 21:28:10.416][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x252f708] -[2020-08-03 21:28:10.488][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x252f63d] -[2020-08-03 21:28:10.559][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x252f5ed] -[2020-08-03 21:28:10.629][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x252f5bd] -[2020-08-03 21:28:10.699][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x252e8de] -[2020-08-03 21:28:10.770][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x24694d5] -[2020-08-03 21:28:10.840][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x2469395] -[2020-08-03 21:28:10.909][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5024ee2] -[2020-08-03 21:28:10.980][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x5024eb5] -[2020-08-03 21:28:10.980][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7f549b3186db] -================================================================================ -==================== Test output for //test/extensions/filters/network/postgres_proxy:postgres_integration_test: -WARNING: Perftools heap leak checker is active -- Performance may suffer -[==========] Running 2 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 2 tests from IpVersions/PostgresIntegrationTest -[ RUN ] IpVersions/PostgresIntegrationTest.Login/0 -[ OK ] IpVersions/PostgresIntegrationTest.Login/0 (1510 ms) -[ RUN ] IpVersions/PostgresIntegrationTest.Login/1 -[2020-08-03 21:29:52.988][42506][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/674/execroot/envoy/_tmp/25d60d38146fdfcb74151ad27508c65f/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address -terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address -[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000a5f7 -[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): -[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL -[2020-08-03 21:29:53.037][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x418287c] -[2020-08-03 21:29:53.037][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7fb8f86628a0] -[2020-08-03 21:29:53.086][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x2593dae] -[2020-08-03 21:29:53.136][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x25937e9] -[2020-08-03 21:29:53.185][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x2595ff8] -[2020-08-03 21:29:53.233][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x2595f2d] -[2020-08-03 21:29:53.282][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x2595edd] -[2020-08-03 21:29:53.333][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x2595ead] -[2020-08-03 21:29:53.381][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x25951ce] -[2020-08-03 21:29:53.429][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x24c2305] -[2020-08-03 21:29:53.479][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x24c21c5] -[2020-08-03 21:29:53.529][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5057622] -[2020-08-03 21:29:53.580][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x50575f5] -[2020-08-03 21:29:53.580][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7fb8f86576db] -================================================================================ -[==========] Running 165 tests from 14 test suites. -[----------] Global test environment set-up. -[----------] 79 tests from RouteMatcherTest -[ RUN ] RouteMatcherTest.TestLegacyRoutes -[ OK ] RouteMatcherTest.TestLegacyRoutes (554 ms) -[ RUN ] RouteMatcherTest.TestConnectRoutes -[ OK ] RouteMatcherTest.TestConnectRoutes (175 ms) -[ RUN ] RouteMatcherTest.TestRoutes -[ OK ] RouteMatcherTest.TestRoutes (1526 ms) -[ RUN ] RouteMatcherTest.TestRoutesWithWildcardAndDefaultOnly -[ OK ] RouteMatcherTest.TestRoutesWithWildcardAndDefaultOnly (80 ms) -[ RUN ] RouteMatcherTest.TestRoutesWithInvalidRegexLegacy -[ OK ] RouteMatcherTest.TestRoutesWithInvalidRegexLegacy (67 ms) -[ RUN ] RouteMatcherTest.TestRoutesWithInvalidRegex -[ OK ] RouteMatcherTest.TestRoutesWithInvalidRegex (69 ms) -[ RUN ] RouteMatcherTest.TestRoutesWithInvalidVirtualCluster -[ OK ] RouteMatcherTest.TestRoutesWithInvalidVirtualCluster (51 ms) -[ RUN ] RouteMatcherTest.TestAddRemoveRequestHeaders -[ OK ] RouteMatcherTest.TestAddRemoveRequestHeaders (138 ms) -[ RUN ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalse -[ OK ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalse (117 ms) -[ RUN ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalseMostSpecificWins -[ OK ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalseMostSpecificWins (101 ms) -[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeaders -[ OK ] RouteMatcherTest.TestAddRemoveResponseHeaders (144 ms) -[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendFalse -[ OK ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendFalse (84 ms) -[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendMostSpecificWins -[ OK ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendMostSpecificWins (91 ms) -[ RUN ] RouteMatcherTest.TestAddGlobalResponseHeaderRemoveFromRoute -[ OK ] RouteMatcherTest.TestAddGlobalResponseHeaderRemoveFromRoute (95 ms) -[ RUN ] RouteMatcherTest.TestRequestHeadersToAddNoPseudoHeader -[ OK ] RouteMatcherTest.TestRequestHeadersToAddNoPseudoHeader (140 ms) -[ RUN ] RouteMatcherTest.TestRequestHeadersToRemoveNoPseudoHeader -[ OK ] RouteMatcherTest.TestRequestHeadersToRemoveNoPseudoHeader (152 ms) -[ RUN ] RouteMatcherTest.Priority -[ OK ] RouteMatcherTest.Priority (94 ms) -[ RUN ] RouteMatcherTest.NoHostRewriteAndAutoRewrite -[ OK ] RouteMatcherTest.NoHostRewriteAndAutoRewrite (49 ms) -[ RUN ] RouteMatcherTest.NoHostRewriteAndAutoRewriteHeader -[ OK ] RouteMatcherTest.NoHostRewriteAndAutoRewriteHeader (49 ms) -[ RUN ] RouteMatcherTest.NoAutoRewriteAndAutoRewriteHeader -[ OK ] RouteMatcherTest.NoAutoRewriteAndAutoRewriteHeader (49 ms) -[ RUN ] RouteMatcherTest.HeaderMatchedRouting -[ OK ] RouteMatcherTest.HeaderMatchedRouting (197 ms) -[ RUN ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfigLegacy -[ OK ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfigLegacy (54 ms) -[ RUN ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfig -[ OK ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfig (55 ms) -[ RUN ] RouteMatcherTest.QueryParamMatchedRouting -[ OK ] RouteMatcherTest.QueryParamMatchedRouting (206 ms) -[ RUN ] RouteMatcherTest.InvalidQueryParamMatchedRoutingConfig -[ OK ] RouteMatcherTest.InvalidQueryParamMatchedRoutingConfig (54 ms) -[ RUN ] RouteMatcherTest.ClusterHeader -[ OK ] RouteMatcherTest.ClusterHeader (110 ms) -[ RUN ] RouteMatcherTest.ContentType -[ OK ] RouteMatcherTest.ContentType (95 ms) -[ RUN ] RouteMatcherTest.GrpcTimeoutOffset -[ OK ] RouteMatcherTest.GrpcTimeoutOffset (83 ms) -[ RUN ] RouteMatcherTest.GrpcTimeoutOffsetOfDynamicRoute -[ OK ] RouteMatcherTest.GrpcTimeoutOffsetOfDynamicRoute (99 ms) -[ RUN ] RouteMatcherTest.FractionalRuntime -[ OK ] RouteMatcherTest.FractionalRuntime (81 ms) -[ RUN ] RouteMatcherTest.ShadowClusterNotFound -[ OK ] RouteMatcherTest.ShadowClusterNotFound (50 ms) -[ RUN ] RouteMatcherTest.ClusterNotFound -[ OK ] RouteMatcherTest.ClusterNotFound (51 ms) -[ RUN ] RouteMatcherTest.ClusterNotFoundNotChecking -[ OK ] RouteMatcherTest.ClusterNotFoundNotChecking (50 ms) -[ RUN ] RouteMatcherTest.ClusterNotFoundNotCheckingViaConfig -[ OK ] RouteMatcherTest.ClusterNotFoundNotCheckingViaConfig (51 ms) -[ RUN ] RouteMatcherTest.AttemptCountHeader -[ OK ] RouteMatcherTest.AttemptCountHeader (77 ms) -[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCode -[ OK ] RouteMatcherTest.ClusterNotFoundResponseCode (79 ms) -[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig503 -[ OK ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig503 (79 ms) -[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig404 -[ OK ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig404 (79 ms) -[ RUN ] RouteMatcherTest.Shadow -[ OK ] RouteMatcherTest.Shadow (115 ms) -[ RUN ] RouteMatcherTest.ShadowPolicyAndPolicies -[ OK ] RouteMatcherTest.ShadowPolicyAndPolicies (53 ms) -[ RUN ] RouteMatcherTest.Retry -[ OK ] RouteMatcherTest.Retry (186 ms) -[ RUN ] RouteMatcherTest.RetryVirtualHostLevel -[ OK ] RouteMatcherTest.RetryVirtualHostLevel (215 ms) -[ RUN ] RouteMatcherTest.GrpcRetry -[ OK ] RouteMatcherTest.GrpcRetry (189 ms) -[ RUN ] RouteMatcherTest.RetryBackOffIntervals -[ OK ] RouteMatcherTest.RetryBackOffIntervals (175 ms) -[ RUN ] RouteMatcherTest.InvalidRetryBackOff -[ OK ] RouteMatcherTest.InvalidRetryBackOff (57 ms) -[ RUN ] RouteMatcherTest.HedgeRouteLevel -[ OK ] RouteMatcherTest.HedgeRouteLevel (195 ms) -[ RUN ] RouteMatcherTest.HedgeVirtualHostLevel -[ OK ] RouteMatcherTest.HedgeVirtualHostLevel (199 ms) -[ RUN ] RouteMatcherTest.TestBadDefaultConfig -[ OK ] RouteMatcherTest.TestBadDefaultConfig (71 ms) -[ RUN ] RouteMatcherTest.TestDuplicateDomainConfig -[ OK ] RouteMatcherTest.TestDuplicateDomainConfig (56 ms) -[ RUN ] RouteMatcherTest.TestCaseSensitiveDomainConfig -[ OK ] RouteMatcherTest.TestCaseSensitiveDomainConfig (54 ms) -[ RUN ] RouteMatcherTest.TestDuplicateWildcardDomainConfig -[ OK ] RouteMatcherTest.TestDuplicateWildcardDomainConfig (54 ms) -[ RUN ] RouteMatcherTest.TestDuplicateSuffixWildcardDomainConfig -[ OK ] RouteMatcherTest.TestDuplicateSuffixWildcardDomainConfig (53 ms) -[ RUN ] RouteMatcherTest.TestDuplicatePrefixWildcardDomainConfig -[ OK ] RouteMatcherTest.TestDuplicatePrefixWildcardDomainConfig (53 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInPrefixRewrites -[ OK ] RouteMatcherTest.TestInvalidCharactersInPrefixRewrites (51 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInHostRewrites -[ OK ] RouteMatcherTest.TestInvalidCharactersInHostRewrites (51 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInAutoHostRewrites -[ OK ] RouteMatcherTest.TestInvalidCharactersInAutoHostRewrites (51 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInHostRedirect -[ OK ] RouteMatcherTest.TestInvalidCharactersInHostRedirect (49 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInPathRedirect -[ OK ] RouteMatcherTest.TestInvalidCharactersInPathRedirect (51 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInPrefixRewriteRedirect -[ OK ] RouteMatcherTest.TestInvalidCharactersInPrefixRewriteRedirect (50 ms) -[ RUN ] RouteMatcherTest.TestPrefixAndRegexRewrites -[ OK ] RouteMatcherTest.TestPrefixAndRegexRewrites (51 ms) -[ RUN ] RouteMatcherTest.TestDomainMatchOrderConfig -[ OK ] RouteMatcherTest.TestDomainMatchOrderConfig (157 ms) -[ RUN ] RouteMatcherTest.NoProtocolInHeadersWhenTlsIsRequired -[ OK ] RouteMatcherTest.NoProtocolInHeadersWhenTlsIsRequired (66 ms) -[ RUN ] RouteMatcherTest.RouteName -[ OK ] RouteMatcherTest.RouteName (148 ms) -[ RUN ] RouteMatcherTest.DirectResponse -[ OK ] RouteMatcherTest.DirectResponse (1138 ms) -[ RUN ] RouteMatcherTest.ExclusiveRouteEntryOrDirectResponseEntry -[ OK ] RouteMatcherTest.ExclusiveRouteEntryOrDirectResponseEntry (111 ms) -[ RUN ] RouteMatcherTest.ExclusiveWeightedClustersEntryOrDirectResponseEntry -[ OK ] RouteMatcherTest.ExclusiveWeightedClustersEntryOrDirectResponseEntry (111 ms) -[ RUN ] RouteMatcherTest.WeightedClusters -[ OK ] RouteMatcherTest.WeightedClusters (1129 ms) -[ RUN ] RouteMatcherTest.ExclusiveWeightedClustersOrClusterConfig -[ OK ] RouteMatcherTest.ExclusiveWeightedClustersOrClusterConfig (48 ms) -[ RUN ] RouteMatcherTest.WeightedClustersMissingClusterList -[ OK ] RouteMatcherTest.WeightedClustersMissingClusterList (50 ms) -[ RUN ] RouteMatcherTest.WeightedClustersEmptyClustersList -[ OK ] RouteMatcherTest.WeightedClustersEmptyClustersList (47 ms) -[ RUN ] RouteMatcherTest.WeightedClustersSumOFWeightsNotEqualToMax -[ OK ] RouteMatcherTest.WeightedClustersSumOFWeightsNotEqualToMax (87 ms) -[ RUN ] RouteMatcherTest.TestWeightedClusterWithMissingWeights -[ OK ] RouteMatcherTest.TestWeightedClusterWithMissingWeights (103 ms) -[ RUN ] RouteMatcherTest.TestWeightedClusterInvalidClusterName -[ OK ] RouteMatcherTest.TestWeightedClusterInvalidClusterName (65 ms) -[ RUN ] RouteMatcherTest.TestWeightedClusterHeaderManipulation -[ OK ] RouteMatcherTest.TestWeightedClusterHeaderManipulation (95 ms) -[ RUN ] RouteMatcherTest.TestOpaqueConfig -[ OK ] RouteMatcherTest.TestOpaqueConfig (137 ms) -[ RUN ] RouteMatcherTest.TestOpaqueConfigUsingDeprecatedName -[ OK ] RouteMatcherTest.TestOpaqueConfigUsingDeprecatedName (69 ms) -[ RUN ] RouteMatcherTest.Decorator -[ OK ] RouteMatcherTest.Decorator (83 ms) -[ RUN ] RouteMatcherTest.HeaderMatchedRoutingV2 -[ OK ] RouteMatcherTest.HeaderMatchedRoutingV2 (305 ms) -[ RUN ] RouteMatcherTest.TlsContextMatching -[ OK ] RouteMatcherTest.TlsContextMatching (187 ms) -[----------] 79 tests from RouteMatcherTest (11638 ms total) - -[----------] 10 tests from RouterMatcherHashPolicyTest -[ RUN ] RouterMatcherHashPolicyTest.HashHeaders -[ OK ] RouterMatcherHashPolicyTest.HashHeaders (96 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashHeadersRegexSubstitution -[ OK ] RouterMatcherHashPolicyTest.HashHeadersRegexSubstitution (65 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashIp -[ OK ] RouterMatcherHashPolicyTest.HashIp (124 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashIpNonIpAddress -[ OK ] RouterMatcherHashPolicyTest.HashIpNonIpAddress (73 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashIpv4DifferentAddresses -[ OK ] RouterMatcherHashPolicyTest.HashIpv4DifferentAddresses (82 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashIpv6DifferentAddresses -[ OK ] RouterMatcherHashPolicyTest.HashIpv6DifferentAddresses (81 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashQueryParameters -[ OK ] RouterMatcherHashPolicyTest.HashQueryParameters (94 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashMultiple -[ OK ] RouterMatcherHashPolicyTest.HashMultiple (122 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashTerminal -[ OK ] RouterMatcherHashPolicyTest.HashTerminal (109 ms) -[ RUN ] RouterMatcherHashPolicyTest.InvalidHashPolicies -[ OK ] RouterMatcherHashPolicyTest.InvalidHashPolicies (50 ms) -[----------] 10 tests from RouterMatcherHashPolicyTest (897 ms total) - -[----------] 5 tests from RouterMatcherCookieHashPolicyTest -[ RUN ] RouterMatcherCookieHashPolicyTest.NoTtl -[ OK ] RouterMatcherCookieHashPolicyTest.NoTtl (107 ms) -[ RUN ] RouterMatcherCookieHashPolicyTest.DifferentCookies -[ OK ] RouterMatcherCookieHashPolicyTest.DifferentCookies (80 ms) -[ RUN ] RouterMatcherCookieHashPolicyTest.TtlSet -[ OK ] RouterMatcherCookieHashPolicyTest.TtlSet (141 ms) -[ RUN ] RouterMatcherCookieHashPolicyTest.SetSessionCookie -[ OK ] RouterMatcherCookieHashPolicyTest.SetSessionCookie (66 ms) -[ RUN ] RouterMatcherCookieHashPolicyTest.SetCookiePath -[ OK ] RouterMatcherCookieHashPolicyTest.SetCookiePath (66 ms) -[----------] 5 tests from RouterMatcherCookieHashPolicyTest (460 ms total) - -[----------] 4 tests from RouterMatcherFilterStateHashPolicyTest -[ RUN ] RouterMatcherFilterStateHashPolicyTest.KeyNotFound -[ OK ] RouterMatcherFilterStateHashPolicyTest.KeyNotFound (65 ms) -[ RUN ] RouterMatcherFilterStateHashPolicyTest.NullValue -[ OK ] RouterMatcherFilterStateHashPolicyTest.NullValue (68 ms) -[ RUN ] RouterMatcherFilterStateHashPolicyTest.ValueNonHashable -[ OK ] RouterMatcherFilterStateHashPolicyTest.ValueNonHashable (66 ms) -[ RUN ] RouterMatcherFilterStateHashPolicyTest.Hashable -[ OK ] RouterMatcherFilterStateHashPolicyTest.Hashable (66 ms) -[----------] 4 tests from RouterMatcherFilterStateHashPolicyTest (266 ms total) - -[----------] 24 tests from RouteConfigurationV2 -[ RUN ] RouteConfigurationV2.RequestMirrorPolicy -[ OK ] RouteConfigurationV2.RequestMirrorPolicy (95 ms) -[ RUN ] RouteConfigurationV2.RedirectCode -[ OK ] RouteConfigurationV2.RedirectCode (94 ms) -[ RUN ] RouteConfigurationV2.DirectResponse -[ OK ] RouteConfigurationV2.DirectResponse (63 ms) -[ RUN ] RouteConfigurationV2.DirectResponseTooLarge -[ OK ] RouteConfigurationV2.DirectResponseTooLarge (60 ms) -[ RUN ] RouteConfigurationV2.BrokenTypedMetadata -[ OK ] RouteConfigurationV2.BrokenTypedMetadata (51 ms) -[ RUN ] RouteConfigurationV2.RouteConfigGetters -[ OK ] RouteConfigurationV2.RouteConfigGetters (98 ms) -[ RUN ] RouteConfigurationV2.RouteTracingConfig -[ OK ] RouteConfigurationV2.RouteTracingConfig (104 ms) -[ RUN ] RouteConfigurationV2.RedirectPrefixRewrite -[ OK ] RouteConfigurationV2.RedirectPrefixRewrite (253 ms) -[ RUN ] RouteConfigurationV2.PathRedirectQueryNotPreserved -[ OK ] RouteConfigurationV2.PathRedirectQueryNotPreserved (158 ms) -[ RUN ] RouteConfigurationV2.RedirectStripQuery -[ OK ] RouteConfigurationV2.RedirectStripQuery (196 ms) -[ RUN ] RouteConfigurationV2.RegexPrefixWithNoRewriteWorksWhenPathChanged -[ OK ] RouteConfigurationV2.RegexPrefixWithNoRewriteWorksWhenPathChanged (66 ms) -[ RUN ] RouteConfigurationV2.NoIdleTimeout -[ OK ] RouteConfigurationV2.NoIdleTimeout (61 ms) -[ RUN ] RouteConfigurationV2.ZeroIdleTimeout -[ OK ] RouteConfigurationV2.ZeroIdleTimeout (66 ms) -[ RUN ] RouteConfigurationV2.ExplicitIdleTimeout -[ OK ] RouteConfigurationV2.ExplicitIdleTimeout (63 ms) -[ RUN ] RouteConfigurationV2.RetriableStatusCodes -[ OK ] RouteConfigurationV2.RetriableStatusCodes (60 ms) -[ RUN ] RouteConfigurationV2.RetriableHeaders -[ OK ] RouteConfigurationV2.RetriableHeaders (67 ms) -[ RUN ] RouteConfigurationV2.UpgradeConfigs -[ OK ] RouteConfigurationV2.UpgradeConfigs (66 ms) -[ RUN ] RouteConfigurationV2.DuplicateUpgradeConfigs -[ OK ] RouteConfigurationV2.DuplicateUpgradeConfigs (52 ms) -[ RUN ] RouteConfigurationV2.BadConnectConfig -[ OK ] RouteConfigurationV2.BadConnectConfig (53 ms) -[ RUN ] RouteConfigurationV2.RetryPluginsAreNotReused -[ OK ] RouteConfigurationV2.RetryPluginsAreNotReused (66 ms) -[ RUN ] RouteConfigurationV2.InternalRedirectIsDisabledWhenNotSpecifiedInRouteAction -[ OK ] RouteConfigurationV2.InternalRedirectIsDisabledWhenNotSpecifiedInRouteAction (64 ms) -[ RUN ] RouteConfigurationV2.DefaultInternalRedirectPolicyIsSensible -[ OK ] RouteConfigurationV2.DefaultInternalRedirectPolicyIsSensible (67 ms) -[ RUN ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCode -[ OK ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCode (65 ms) -[ RUN ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCodeCauseEmptySet -[ OK ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCodeCauseEmptySet (67 ms) -[----------] 24 tests from RouteConfigurationV2 (2055 ms total) - -[----------] 1 test from NullConfigImplTest -[ RUN ] NullConfigImplTest.All -[ OK ] NullConfigImplTest.All (11 ms) -[----------] 1 test from NullConfigImplTest (11 ms total) - -[----------] 9 tests from BadHttpRouteConfigurationsTest -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteConfig -[ OK ] BadHttpRouteConfigurationsTest.BadRouteConfig (50 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadVirtualHostConfig -[ OK ] BadHttpRouteConfigurationsTest.BadVirtualHostConfig (51 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfig -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfig (51 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPath -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPath (49 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigMissingPathSpecifier -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigMissingPathSpecifier (49 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndRegex -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndRegex (49 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigNoAction -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigNoAction (49 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPathAndRegex -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPathAndRegex (48 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPathAndRegex -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPathAndRegex (49 ms) -[----------] 9 tests from BadHttpRouteConfigurationsTest (445 ms total) - -[----------] 6 tests from RoutePropertyTest -[ RUN ] RoutePropertyTest.ExcludeVHRateLimits -[ OK ] RoutePropertyTest.ExcludeVHRateLimits (101 ms) -[ RUN ] RoutePropertyTest.TestVHostCorsConfig -[ OK ] RoutePropertyTest.TestVHostCorsConfig (68 ms) -[ RUN ] RoutePropertyTest.TestRouteCorsConfig -[ OK ] RoutePropertyTest.TestRouteCorsConfig (67 ms) -[ RUN ] RoutePropertyTest.TTestVHostCorsLegacyConfig -[ OK ] RoutePropertyTest.TTestVHostCorsLegacyConfig (64 ms) -[ RUN ] RoutePropertyTest.TestRouteCorsLegacyConfig -[ OK ] RoutePropertyTest.TestRouteCorsLegacyConfig (66 ms) -[ RUN ] RoutePropertyTest.TestBadCorsConfig -[ OK ] RoutePropertyTest.TestBadCorsConfig (50 ms) -[----------] 6 tests from RoutePropertyTest (416 ms total) - -[----------] 2 tests from CustomRequestHeadersTest -[ RUN ] CustomRequestHeadersTest.AddNewHeader -[ OK ] CustomRequestHeadersTest.AddNewHeader (80 ms) -[ RUN ] CustomRequestHeadersTest.CustomHeaderWrongFormat -[ OK ] CustomRequestHeadersTest.CustomHeaderWrongFormat (65 ms) -[----------] 2 tests from CustomRequestHeadersTest (1591 ms total) - -[----------] 3 tests from MetadataMatchCriteriaImpl -[ RUN ] MetadataMatchCriteriaImpl.Create -[ OK ] MetadataMatchCriteriaImpl.Create (0 ms) -[ RUN ] MetadataMatchCriteriaImpl.Merge -[ OK ] MetadataMatchCriteriaImpl.Merge (0 ms) -[ RUN ] MetadataMatchCriteriaImpl.Filter -[ OK ] MetadataMatchCriteriaImpl.Filter (0 ms) -[----------] 3 tests from MetadataMatchCriteriaImpl (0 ms total) - -[----------] 1 test from RouteEntryMetadataMatchTest -[ RUN ] RouteEntryMetadataMatchTest.ParsesMetadata -[ OK ] RouteEntryMetadataMatchTest.ParsesMetadata (206 ms) -[----------] 1 test from RouteEntryMetadataMatchTest (206 ms total) - -[----------] 2 tests from ConfigUtilityTest -[ RUN ] ConfigUtilityTest.ParseResponseCode -[ OK ] ConfigUtilityTest.ParseResponseCode (46 ms) -[ RUN ] ConfigUtilityTest.ParseDirectResponseBody -[ OK ] ConfigUtilityTest.ParseDirectResponseBody (46 ms) -[----------] 2 tests from ConfigUtilityTest (92 ms total) - -[----------] 11 tests from PerFilterConfigsTest -[ RUN ] PerFilterConfigsTest.TypedConfigFilterError -[ OK ] PerFilterConfigsTest.TypedConfigFilterError (62 ms) -[ RUN ] PerFilterConfigsTest.UnknownFilterStruct -[ OK ] PerFilterConfigsTest.UnknownFilterStruct (51 ms) -[ RUN ] PerFilterConfigsTest.UnknownFilterAny -[ OK ] PerFilterConfigsTest.UnknownFilterAny (50 ms) -[ RUN ] PerFilterConfigsTest.DefaultFilterImplementationStruct -[ OK ] PerFilterConfigsTest.DefaultFilterImplementationStruct (67 ms) -[ RUN ] PerFilterConfigsTest.DefaultFilterImplementationAny -[ OK ] PerFilterConfigsTest.DefaultFilterImplementationAny (67 ms) -[ RUN ] PerFilterConfigsTest.RouteLocalConfig -[ OK ] PerFilterConfigsTest.RouteLocalConfig (68 ms) -[ RUN ] PerFilterConfigsTest.RouteLocalTypedConfig -[ OK ] PerFilterConfigsTest.RouteLocalTypedConfig (67 ms) -[ RUN ] PerFilterConfigsTest.WeightedClusterConfig -[ OK ] PerFilterConfigsTest.WeightedClusterConfig (68 ms) -[ RUN ] PerFilterConfigsTest.WeightedClusterTypedConfig -[ OK ] PerFilterConfigsTest.WeightedClusterTypedConfig (68 ms) -[ RUN ] PerFilterConfigsTest.WeightedClusterFallthroughConfig -[ OK ] PerFilterConfigsTest.WeightedClusterFallthroughConfig (68 ms) -[ RUN ] PerFilterConfigsTest.WeightedClusterFallthroughTypedConfig -[ OK ] PerFilterConfigsTest.WeightedClusterFallthroughTypedConfig (67 ms) -[----------] 11 tests from PerFilterConfigsTest (704 ms total) - -[----------] 8 tests from RouteMatchOverrideTest -[ RUN ] RouteMatchOverrideTest.VerifyAllMatchableRoutes -[ OK ] RouteMatchOverrideTest.VerifyAllMatchableRoutes (65 ms) -[ RUN ] RouteMatchOverrideTest.VerifyRouteOverrideStops -[ OK ] RouteMatchOverrideTest.VerifyRouteOverrideStops (64 ms) -[ RUN ] RouteMatchOverrideTest.StopWhenNoMoreRoutes -[ OK ] RouteMatchOverrideTest.StopWhenNoMoreRoutes (65 ms) -[ RUN ] RouteMatchOverrideTest.NullRouteOnNoRouteMatch -[ OK ] RouteMatchOverrideTest.NullRouteOnNoRouteMatch (81 ms) -[ RUN ] RouteMatchOverrideTest.NullRouteOnNoHostMatch -[ OK ] RouteMatchOverrideTest.NullRouteOnNoHostMatch (66 ms) -[ RUN ] RouteMatchOverrideTest.NullRouteOnNullXForwardedProto -[ OK ] RouteMatchOverrideTest.NullRouteOnNullXForwardedProto (66 ms) -[ RUN ] RouteMatchOverrideTest.NullRouteOnRequireTlsAll -[ OK ] RouteMatchOverrideTest.NullRouteOnRequireTlsAll (65 ms) -[ RUN ] RouteMatchOverrideTest.NullRouteOnRequireTlsInternal -[ OK ] RouteMatchOverrideTest.NullRouteOnRequireTlsInternal (65 ms) -[----------] 8 tests from RouteMatchOverrideTest (538 ms total) - -[----------] Global test environment tear-down -[==========] 165 tests from 14 test suites ran. (19322 ms total) -[ PASSED ] 165 tests. -==================== Test output for //test/extensions/filters/network/sni_dynamic_forward_proxy:proxy_filter_integration_test: -WARNING: Perftools heap leak checker is active -- Performance may suffer -[==========] Running 4 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 4 tests from IpVersions/SniDynamicProxyFilterIntegrationTest -[ RUN ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv4 -TestRandomGenerator running with seed 205585968 -[ OK ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv4 (765 ms) -[ RUN ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv6 -TestRandomGenerator running with seed 205585968 -[2020-08-03 21:33:40.808][44312][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/898/execroot/envoy/_tmp/282b4d28423b557fc72f2459645621cd/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address -terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address -[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000acdd -[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): -[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL -[2020-08-03 21:33:40.881][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x4267f3c] -[2020-08-03 21:33:40.881][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7f8f0f7748a0] -[2020-08-03 21:33:40.952][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x266b38e] -[2020-08-03 21:33:41.024][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x266adc9] -[2020-08-03 21:33:41.096][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x266d5d8] -[2020-08-03 21:33:41.168][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x266d50d] -[2020-08-03 21:33:41.239][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x266d4bd] -[2020-08-03 21:33:41.311][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x266d48d] -[2020-08-03 21:33:41.382][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x266c7ae] -[2020-08-03 21:33:41.453][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x25b1745] -[2020-08-03 21:33:41.525][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x25b1605] -[2020-08-03 21:33:41.596][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x513dce2] -[2020-08-03 21:33:41.668][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x513dcb5] -[2020-08-03 21:33:41.668][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7f8f0f7696db] -================================================================================ diff --git a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst index 4d7f8ed3872c6..70df6b283415a 100644 --- a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst +++ b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst @@ -47,4 +47,4 @@ The following Envoy filters emit shared dynamic metadata. The following filters consume shared dynamic metadata. -* :ref:`Metadata Access Log Filter` +* Metadata Access Log Filter diff --git a/docs/root/configuration/listeners/network_filters/rbac_filter.rst b/docs/root/configuration/listeners/network_filters/rbac_filter.rst index 68ae9f2172d46..4a01762bc57cc 100644 --- a/docs/root/configuration/listeners/network_filters/rbac_filter.rst +++ b/docs/root/configuration/listeners/network_filters/rbac_filter.rst @@ -42,4 +42,4 @@ The RBAC filter emits the following dynamic metadata. shadow_effective_policy_id, string, The effective shadow policy ID matching the action (if any). shadow_engine_result, string, The engine result for the shadow rules (i.e. either `allowed` or `denied`). - access_log_hint, boolean, Whether the request should be logged. This metadata is shared and set under the key namespace 'envoy.common' (See :ref:`Shared Dynamic Metadata`). + access_log_policy, boolean, Whether the request should be logged. This metadata is shared and set under the key namespace 'envoy.common' (See :ref:`Shared Dynamic Metadata`). diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index 4277daa7533cc..01c1f3dd56a0e 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -52,7 +52,6 @@ New Features * load balancer: added a :ref:`configuration` option to specify the active request bias used by the least request load balancer. * lua: added Lua APIs to access :ref:`SSL connection info ` object. * postgres network filter: :ref:`metadata ` is produced based on SQL query. -* rbac filter: added a log action to the :ref:`RBAC filter ` which sets dynamic metadata to inform access loggers whether to log. * router: added new :ref:`envoy-ratelimited` retry policy, which allows retrying envoy's own rate limited responses. diff --git a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto index 278e6857603fe..9b3fd0524868b 100644 --- a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto @@ -82,47 +82,40 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match. - // All requests are allowed. + // The policies set the `access_log_hint` dynamic metadata key based on if requests match LOG = 2; } - // The action to take if a policy matches. Every action either allows or denies a request, - // and can also carry out action-specific operations. + // The action to take if a policy matches. + // The request is allowed if and only if: // - // Actions: - // - // * ALLOW: Allows the request if and only if there is a policy that matches - // the request. - // * DENY: Allows the request if and only if there are no policies that - // match the request. - // * LOG: Allows all requests. If at least one policy matches, the dynamic - // metadata key `access_log_hint` is set to the value `true` under the shared - // key namespace 'envoy.common'. If no policies match, it is set to `false`. - // Other actions do not modify this key. + // * `action` is "ALLOW" and at least one policy matches + // * `action` is "DENY" and none of the policies match + // * `action` is "LOG" // + // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` + // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, + // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. -// A policy matches if and only if at least one of its permissions match the -// action taking place AND at least one of its principals match the downstream -// AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if +// and only if at least one of its permissions match the action taking place AND at least one of its +// principals match the downstream AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Policy"; - // Required. The set of permissions that define a role. Each permission is - // matched with OR semantics. To match all actions for this policy, a single - // Permission with the `any` field set to true should be used. + // Required. The set of permissions that define a role. Each permission is matched with OR + // semantics. To match all actions for this policy, a single Permission with the `any` field set + // to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on - // “action”. Each principal is matched with OR semantics. To match all - // downstreams for this policy, a single Principal with the `any` field set to - // true should be used. + // Required. The set of principals that are assigned/denied the role based on “action”. Each + // principal is matched with OR semantics. To match all downstreams for this policy, a single + // Principal with the `any` field set to true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; // An optional symbolic expression specifying an access control @@ -183,9 +176,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of - // `not_rule` would match, this permission would not match. Conversely, if - // the value of `not_rule` would not match, this permission would match. + // Negates matching the provided permission. For instance, if the value of `not_rule` would + // match, this permission would not match. Conversely, if the value of `not_rule` would not + // match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -198,8 +191,7 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name - // `, + // the :ref:`server name `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -212,14 +204,13 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream -// subject. +// Principal defines an identity or a group of identities for a downstream subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. - // Depending on the context, each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, + // each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal.Set"; @@ -234,21 +225,19 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order - // is used from the certificate, otherwise the subject field is used. If - // unset, it applies to any user that is authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the + // certificate, otherwise the subject field is used. If unset, it applies to any user that is + // authenticated. type.matcher.v3.StringMatcher principal_name = 2; } oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the - // downstream. + // A set of identifiers that all must match in order to define the downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the - // downstream. + // A set of identifiers at least one must match in order to define the downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -263,23 +252,21 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is - // inferred from for example the x-forwarder-for header, proxy protocol, - // etc. + // :ref:`remote_ip ` is inferred + // from for example the x-forwarder-for header, proxy protocol, etc. core.v3.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip - // `. E.g, if the - // remote ip is inferred from for example the x-forwarder-for header, proxy - // protocol, etc. + // :ref:`direct_remote_ip `. + // E.g, if the remote ip is inferred from for example the x-forwarder-for header, + // proxy protocol, etc. core.v3.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP - // request. Only available for HTTP request. Note: the pseudo-header :path - // includes the query and fragment string. Use the `url_path` field if you - // want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only + // available for HTTP request. + // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` + // field if you want to match the URL path without the query and fragment string. route.v3.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -288,9 +275,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of - // `not_id` would match, this principal would not match. Conversely, if the - // value of `not_id` would not match, this principal would match. + // Negates matching the provided principal. For instance, if the value of `not_id` would match, + // this principal would not match. Conversely, if the value of `not_id` would not match, this + // principal would match. Principal not_id = 8; } } diff --git a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto index 7139dfaa1485d..8d2945ee2a757 100644 --- a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto @@ -81,47 +81,40 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match. - // All requests are allowed. + // The policies set the `access_log_hint` dynamic metadata key based on if requests match LOG = 2; } - // The action to take if a policy matches. Every action either allows or denies a request, - // and can also carry out action-specific operations. + // The action to take if a policy matches. + // The request is allowed if and only if: // - // Actions: - // - // * ALLOW: Allows the request if and only if there is a policy that matches - // the request. - // * DENY: Allows the request if and only if there are no policies that - // match the request. - // * LOG: Allows all requests. If at least one policy matches, the dynamic - // metadata key `access_log_hint` is set to the value `true` under the shared - // key namespace 'envoy.common'. If no policies match, it is set to `false`. - // Other actions do not modify this key. + // * `action` is "ALLOW" and at least one policy matches + // * `action` is "DENY" and none of the policies match + // * `action` is "LOG" // + // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` + // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, + // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. -// A policy matches if and only if at least one of its permissions match the -// action taking place AND at least one of its principals match the downstream -// AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if +// and only if at least one of its permissions match the action taking place AND at least one of its +// principals match the downstream AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Policy"; - // Required. The set of permissions that define a role. Each permission is - // matched with OR semantics. To match all actions for this policy, a single - // Permission with the `any` field set to true should be used. + // Required. The set of permissions that define a role. Each permission is matched with OR + // semantics. To match all actions for this policy, a single Permission with the `any` field set + // to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on - // “action”. Each principal is matched with OR semantics. To match all - // downstreams for this policy, a single Principal with the `any` field set to - // true should be used. + // Required. The set of principals that are assigned/denied the role based on “action”. Each + // principal is matched with OR semantics. To match all downstreams for this policy, a single + // Principal with the `any` field set to true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; oneof expression_specifier { @@ -182,9 +175,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of - // `not_rule` would match, this permission would not match. Conversely, if - // the value of `not_rule` would not match, this permission would match. + // Negates matching the provided permission. For instance, if the value of `not_rule` would + // match, this permission would not match. Conversely, if the value of `not_rule` would not + // match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -197,8 +190,7 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name - // `, + // the :ref:`server name `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -211,14 +203,13 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream -// subject. +// Principal defines an identity or a group of identities for a downstream subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. - // Depending on the context, each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, + // each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal.Set"; @@ -233,21 +224,19 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order - // is used from the certificate, otherwise the subject field is used. If - // unset, it applies to any user that is authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the + // certificate, otherwise the subject field is used. If unset, it applies to any user that is + // authenticated. type.matcher.v4alpha.StringMatcher principal_name = 2; } oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the - // downstream. + // A set of identifiers that all must match in order to define the downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the - // downstream. + // A set of identifiers at least one must match in order to define the downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -262,23 +251,21 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is - // inferred from for example the x-forwarder-for header, proxy protocol, - // etc. + // :ref:`remote_ip ` is inferred + // from for example the x-forwarder-for header, proxy protocol, etc. core.v4alpha.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip - // `. E.g, if the - // remote ip is inferred from for example the x-forwarder-for header, proxy - // protocol, etc. + // :ref:`direct_remote_ip `. + // E.g, if the remote ip is inferred from for example the x-forwarder-for header, + // proxy protocol, etc. core.v4alpha.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP - // request. Only available for HTTP request. Note: the pseudo-header :path - // includes the query and fragment string. Use the `url_path` field if you - // want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only + // available for HTTP request. + // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` + // field if you want to match the URL path without the query and fragment string. route.v4alpha.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -287,9 +274,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of - // `not_id` would match, this principal would not match. Conversely, if the - // value of `not_id` would not match, this principal would match. + // Negates matching the provided principal. For instance, if the value of `not_id` would match, + // this principal would not match. Conversely, if the value of `not_id` would not match, this + // principal would match. Principal not_id = 8; } } diff --git a/source/extensions/filters/common/rbac/engine.h b/source/extensions/filters/common/rbac/engine.h index 04e82c95023d8..8bf5920cf3d6b 100644 --- a/source/extensions/filters/common/rbac/engine.h +++ b/source/extensions/filters/common/rbac/engine.h @@ -18,32 +18,64 @@ class RoleBasedAccessControlEngine { public: virtual ~RoleBasedAccessControlEngine() = default; + enum class LogDecision { Yes, No, Undecided }; + + /** + * Returns whether or not the current action is permitted. + * + * @param connection the downstream connection used to identify the action/principal. + * @param headers the headers of the incoming request used to identify the action/principal. An + * empty map should be used if there are no headers available. + * @param info the per-request or per-connection stream info with additional information + * about the action/principal. + * @param effective_policy_id it will be filled by the matching policy's ID, + * which is used to identity the source of the allow/deny. + */ + virtual bool allowed(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const PURE; + + /** + * Returns whether or not the current action is permitted. + * + * @param connection the downstream connection used to identify the action/principal. + * @param info the per-request or per-connection stream info with additional information + * about the action/principal. + * @param effective_policy_id it will be filled by the matching policy's ID, + * which is used to identity the source of the allow/deny. + */ + virtual bool allowed(const Network::Connection& connection, const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const PURE; + /** - * Handles action-specific operations and returns whether or not the request is permitted. + * Returns whether or not the current action should be logged. * * @param connection the downstream connection used to identify the action/principal. * @param headers the headers of the incoming request used to identify the action/principal. An * empty map should be used if there are no headers available. * @param info the per-request or per-connection stream info with additional information - * about the action/principal. Can be modified by an Action. + * about the action/principal. * @param effective_policy_id it will be filled by the matching policy's ID, * which is used to identity the source of the allow/deny. */ - virtual bool handleAction(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, - StreamInfo::StreamInfo& info, std::string* effective_policy_id) PURE; + virtual LogDecision shouldLog(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const PURE; /** - * Handles action-specific operations and returns whether or not the request is permitted. + * Returns whether or not the current action should be logged. * * @param connection the downstream connection used to identify the action/principal. * @param info the per-request or per-connection stream info with additional information - * about the action/principal. Can be modified by an Action. + * about the action/principal. * @param effective_policy_id it will be filled by the matching policy's ID, * which is used to identity the source of the allow/deny. */ - virtual bool handleAction(const Network::Connection& connection, StreamInfo::StreamInfo& info, - std::string* effective_policy_id) PURE; + virtual LogDecision shouldLog(const Network::Connection& connection, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const PURE; }; } // namespace RBAC diff --git a/source/extensions/filters/common/rbac/engine_impl.cc b/source/extensions/filters/common/rbac/engine_impl.cc index ce9493e26896c..fb01e8ccc084b 100644 --- a/source/extensions/filters/common/rbac/engine_impl.cc +++ b/source/extensions/filters/common/rbac/engine_impl.cc @@ -10,9 +10,12 @@ namespace Filters { namespace Common { namespace RBAC { +using LogDecision = RoleBasedAccessControlEngine::LogDecision; + RoleBasedAccessControlEngineImpl::RoleBasedAccessControlEngineImpl( - const envoy::config::rbac::v3::RBAC& rules, const EnforcementMode mode) - : action_(rules.action()), mode_(mode) { + const envoy::config::rbac::v3::RBAC& rules) + : allowed_if_matched_(rules.action() == envoy::config::rbac::v3::RBAC::ALLOW), + action_log_(rules.action() == envoy::config::rbac::v3::RBAC::LOG) { // guard expression builder by presence of a condition in policies for (const auto& policy : rules.policies()) { if (policy.second.has_condition()) { @@ -26,45 +29,48 @@ RoleBasedAccessControlEngineImpl::RoleBasedAccessControlEngineImpl( } } -bool RoleBasedAccessControlEngineImpl::handleAction(const Network::Connection& connection, - StreamInfo::StreamInfo& info, - std::string* effective_policy_id) { - return handleAction(connection, *Http::StaticEmptyHeaders::get().request_headers, info, - effective_policy_id); -} - -bool RoleBasedAccessControlEngineImpl::handleAction(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, - StreamInfo::StreamInfo& info, - std::string* effective_policy_id) { - bool matched = checkPolicyMatch(connection, info, headers, effective_policy_id); - - switch (action_) { - case envoy::config::rbac::v3::RBAC::ALLOW: - return matched; - case envoy::config::rbac::v3::RBAC::DENY: - return !matched; - case envoy::config::rbac::v3::RBAC::LOG: { - // If not shadow enforcement, set shared log metadata - if (mode_ != EnforcementMode::Shadow) { - ProtobufWkt::Struct log_metadata; - auto& log_fields = *log_metadata.mutable_fields(); - log_fields[DynamicMetadataKeysSingleton::get().AccessLogKey].set_bool_value(matched); - info.setDynamicMetadata(DynamicMetadataKeysSingleton::get().CommonNamespace, log_metadata); - } - +bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const { + // Automatically allow if LOG action + if (action_log_) { return true; } - default: - return true; + + bool matched = false; + + for (const auto& policy : policies_) { + if (policy.second->matches(connection, headers, info)) { + matched = true; + if (effective_policy_id != nullptr) { + *effective_policy_id = policy.first; + } + break; + } } - return true; + // only allowed if: + // - matched and ALLOW action + // - not matched and DENY action + // - LOG action + return matched == allowed_if_matched_; } -bool RoleBasedAccessControlEngineImpl::checkPolicyMatch( - const Network::Connection& connection, const StreamInfo::StreamInfo& info, - const Envoy::Http::RequestHeaderMap& headers, std::string* effective_policy_id) const { +bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connection, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const { + return allowed(connection, *Http::StaticEmptyHeaders::get().request_headers, info, + effective_policy_id); +} + +LogDecision RoleBasedAccessControlEngineImpl::shouldLog( + const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const { + if (!action_log_) { + return LogDecision::Undecided; + } + bool matched = false; for (const auto& policy : policies_) { @@ -77,7 +83,15 @@ bool RoleBasedAccessControlEngineImpl::checkPolicyMatch( } } - return matched; + // log if action is LOG and a policy matches + return matched ? LogDecision::Yes : LogDecision::No; +} + +LogDecision RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& connection, + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const { + return shouldLog(connection, *Http::StaticEmptyHeaders::get().request_headers, info, + effective_policy_id); } } // namespace RBAC diff --git a/source/extensions/filters/common/rbac/engine_impl.h b/source/extensions/filters/common/rbac/engine_impl.h index 4294bc8777547..87229a51a4e13 100644 --- a/source/extensions/filters/common/rbac/engine_impl.h +++ b/source/extensions/filters/common/rbac/engine_impl.h @@ -11,40 +11,27 @@ namespace Filters { namespace Common { namespace RBAC { -class DynamicMetadataKeys { -public: - const std::string ShadowEffectivePolicyIdField{"shadow_effective_policy_id"}; - const std::string ShadowEngineResultField{"shadow_engine_result"}; - const std::string EngineResultAllowed{"allowed"}; - const std::string EngineResultDenied{"denied"}; - const std::string AccessLogKey{"access_log_hint"}; - const std::string CommonNamespace{"envoy.common"}; -}; - -using DynamicMetadataKeysSingleton = ConstSingleton; - -enum class EnforcementMode { Enforced, Shadow }; - class RoleBasedAccessControlEngineImpl : public RoleBasedAccessControlEngine, NonCopyable { public: - RoleBasedAccessControlEngineImpl(const envoy::config::rbac::v3::RBAC& rules, - const EnforcementMode mode = EnforcementMode::Enforced); + RoleBasedAccessControlEngineImpl(const envoy::config::rbac::v3::RBAC& rules); - bool handleAction(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, StreamInfo::StreamInfo& info, - std::string* effective_policy_id) override; + bool allowed(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, + const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const override; - bool handleAction(const Network::Connection& connection, StreamInfo::StreamInfo& info, - std::string* effective_policy_id) override; + bool allowed(const Network::Connection& connection, const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const override; -private: - // Checks whether the request matches any policies - bool checkPolicyMatch(const Network::Connection& connection, const StreamInfo::StreamInfo& info, + LogDecision shouldLog(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, - std::string* effective_policy_id) const; + const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const override; - const envoy::config::rbac::v3::RBAC::Action action_; - const EnforcementMode mode_; + LogDecision shouldLog(const Network::Connection& connection, const StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const override; + +private: + const bool allowed_if_matched_; + const bool action_log_; std::map> policies_; diff --git a/source/extensions/filters/common/rbac/utility.h b/source/extensions/filters/common/rbac/utility.h index 04635eb37411e..a3848deb62469 100644 --- a/source/extensions/filters/common/rbac/utility.h +++ b/source/extensions/filters/common/rbac/utility.h @@ -12,6 +12,18 @@ namespace Filters { namespace Common { namespace RBAC { +class DynamicMetadataKeys { +public: + const std::string ShadowEffectivePolicyIdField{"shadow_effective_policy_id"}; + const std::string ShadowEngineResultField{"shadow_engine_result"}; + const std::string EngineResultAllowed{"allowed"}; + const std::string EngineResultDenied{"denied"}; + const std::string AccessLogKey{"access_log_hint"}; + const std::string CommonNamespace{"envoy.common"}; +}; + +using DynamicMetadataKeysSingleton = ConstSingleton; + /** * All stats for the RBAC filter. @see stats_macros.h */ @@ -19,7 +31,9 @@ namespace RBAC { COUNTER(allowed) \ COUNTER(denied) \ COUNTER(shadow_allowed) \ - COUNTER(shadow_denied) + COUNTER(shadow_denied) \ + COUNTER(logged) \ + COUNTER(not_logged) /** * Wrapper struct for RBAC filter stats. @see stats_macros.h @@ -30,18 +44,19 @@ struct RoleBasedAccessControlFilterStats { RoleBasedAccessControlFilterStats generateStats(const std::string& prefix, Stats::Scope& scope); +enum class EnforcementMode { Enforced, Shadow }; + template std::unique_ptr createEngine(const ConfigType& config) { - return config.has_rules() ? std::make_unique( - config.rules(), EnforcementMode::Enforced) + return config.has_rules() ? std::make_unique(config.rules()) : nullptr; } template std::unique_ptr createShadowEngine(const ConfigType& config) { - return config.has_shadow_rules() ? std::make_unique( - config.shadow_rules(), EnforcementMode::Shadow) - : nullptr; + return config.has_shadow_rules() + ? std::make_unique(config.shadow_rules()) + : nullptr; } } // namespace RBAC diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index 0c5b96edf3894..0c187f5cf541d 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -20,24 +20,16 @@ struct RcDetailsValues { }; using RcDetails = ConstSingleton; -// using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; +using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::http::rbac::v3::RBAC& proto_config, const std::string& stats_prefix, Stats::Scope& scope) - : stats_(Filters::Common::RBAC::generateStats(stats_prefix, scope)) { - engine_ = proto_config.has_rules() - ? std::make_unique( - proto_config.rules(), Filters::Common::RBAC::EnforcementMode::Enforced) - : nullptr; - shadow_engine_ = - proto_config.has_shadow_rules() - ? std::make_unique( - proto_config.shadow_rules(), Filters::Common::RBAC::EnforcementMode::Shadow) - : nullptr; -} + : stats_(Filters::Common::RBAC::generateStats(stats_prefix, scope)), + engine_(Filters::Common::RBAC::createEngine(proto_config)), + shadow_engine_(Filters::Common::RBAC::createShadowEngine(proto_config)) {} -Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* +const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* RoleBasedAccessControlFilterConfig::engine(const Router::RouteConstSharedPtr route, Filters::Common::RBAC::EnforcementMode mode) const { if (!route || !route->routeEntry()) { @@ -90,8 +82,8 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo if (shadow_engine != nullptr) { std::string shadow_resp_code = Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().EngineResultAllowed; - if (shadow_engine->handleAction(*callbacks_->connection(), headers, callbacks_->streamInfo(), - &effective_policy_id)) { + if (shadow_engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), + &effective_policy_id)) { ENVOY_LOG(debug, "shadow allowed"); config_->stats().shadow_allowed_.inc(); } else { @@ -118,9 +110,28 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo const auto engine = config_->engine(callbacks_->route(), Filters::Common::RBAC::EnforcementMode::Enforced); if (engine != nullptr) { - // Check authorization decision and do Action operations - if (engine->handleAction(*callbacks_->connection(), headers, callbacks_->streamInfo(), - nullptr)) { + // Check log decision + LogDecision log_dec = + engine->shouldLog(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr); + if (log_dec != LogDecision::Undecided) { + ProtobufWkt::Struct log_metadata; + auto& log_fields = *log_metadata.mutable_fields(); + log_fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey] + .set_bool_value(log_dec == LogDecision::Yes); + callbacks_->streamInfo().setDynamicMetadata( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, log_metadata); + + if (log_dec == LogDecision::Yes) { + ENVOY_LOG(debug, "request logged"); + config_->stats().logged_.inc(); + } else { + ENVOY_LOG(debug, "request not logged"); + config_->stats().not_logged_.inc(); + } + } + + // Check authorization decision + if (engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr)) { ENVOY_LOG(debug, "enforced allowed"); config_->stats().allowed_.inc(); return Http::FilterHeadersStatus::Continue; diff --git a/source/extensions/filters/http/rbac/rbac_filter.h b/source/extensions/filters/http/rbac/rbac_filter.h index 7434dcd925cd0..fe7369e34e6be 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.h +++ b/source/extensions/filters/http/rbac/rbac_filter.h @@ -22,7 +22,7 @@ class RoleBasedAccessControlRouteSpecificFilterConfig : public Router::RouteSpec RoleBasedAccessControlRouteSpecificFilterConfig( const envoy::extensions::filters::http::rbac::v3::RBACPerRoute& per_route_config); - Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); @@ -44,12 +44,12 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats& stats() { return stats_; } - Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(const Router::RouteConstSharedPtr route, Filters::Common::RBAC::EnforcementMode mode) const; private: - Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); @@ -57,8 +57,8 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats stats_; - std::unique_ptr engine_; - std::unique_ptr shadow_engine_; + std::unique_ptr engine_; + std::unique_ptr shadow_engine_; }; using RoleBasedAccessControlFilterConfigSharedPtr = diff --git a/source/extensions/filters/network/rbac/rbac_filter.cc b/source/extensions/filters/network/rbac/rbac_filter.cc index db5a8ec075cd3..6a94212fe15fa 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.cc +++ b/source/extensions/filters/network/rbac/rbac_filter.cc @@ -13,20 +13,14 @@ namespace Extensions { namespace NetworkFilters { namespace RBACFilter { +using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; + RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::network::rbac::v3::RBAC& proto_config, Stats::Scope& scope) : stats_(Filters::Common::RBAC::generateStats(proto_config.stat_prefix(), scope)), - enforcement_type_(proto_config.enforcement_type()) { - engine_ = proto_config.has_rules() - ? std::make_unique( - proto_config.rules(), Filters::Common::RBAC::EnforcementMode::Enforced) - : nullptr; - shadow_engine_ = - proto_config.has_shadow_rules() - ? std::make_unique( - proto_config.shadow_rules(), Filters::Common::RBAC::EnforcementMode::Shadow) - : nullptr; -} + engine_(Filters::Common::RBAC::createEngine(proto_config)), + shadow_engine_(Filters::Common::RBAC::createShadowEngine(proto_config)), + enforcement_type_(proto_config.enforcement_type()) {} Network::FilterStatus RoleBasedAccessControlFilter::onData(Buffer::Instance&, bool) { ENVOY_LOG(debug, @@ -90,14 +84,36 @@ void RoleBasedAccessControlFilter::setDynamicMetadata(std::string shadow_engine_ EngineResult RoleBasedAccessControlFilter::checkEngine(Filters::Common::RBAC::EnforcementMode mode) { - auto engine = config_->engine(mode); + const auto engine = config_->engine(mode); if (engine != nullptr) { std::string effective_policy_id; + if (mode == Filters::Common::RBAC::EnforcementMode::Enforced) { + // Check log decision + LogDecision log_dec = engine->shouldLog( + callbacks_->connection(), callbacks_->connection().streamInfo(), &effective_policy_id); + if (log_dec != LogDecision::Undecided) { + ProtobufWkt::Struct log_metadata; + auto& fields = *log_metadata.mutable_fields(); + fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey] + .set_bool_value(log_dec == LogDecision::Yes); + callbacks_->connection().streamInfo().setDynamicMetadata( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, + log_metadata); + + if (log_dec == LogDecision::Yes) { + ENVOY_LOG(debug, "request logged"); + config_->stats().logged_.inc(); + } else { + ENVOY_LOG(debug, "request not logged"); + config_->stats().not_logged_.inc(); + } + } + } - // Check authorization decision and do Action operations - if (engine->handleAction(callbacks_->connection(), callbacks_->connection().streamInfo(), - &effective_policy_id)) { + // Check authorization decision + if (engine->allowed(callbacks_->connection(), callbacks_->connection().streamInfo(), + &effective_policy_id)) { if (mode == Filters::Common::RBAC::EnforcementMode::Shadow) { ENVOY_LOG(debug, "shadow allowed"); config_->stats().shadow_allowed_.inc(); diff --git a/source/extensions/filters/network/rbac/rbac_filter.h b/source/extensions/filters/network/rbac/rbac_filter.h index 38530d4e2e600..19c9360e21342 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.h +++ b/source/extensions/filters/network/rbac/rbac_filter.h @@ -27,7 +27,7 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats& stats() { return stats_; } - Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index 7a8f192fdb608..47b48362a80b4 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -25,32 +25,30 @@ namespace RBAC { namespace { void checkEngine( - RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, StreamInfo::StreamInfo& info, + const RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), - const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { - - bool engineRes = engine.handleAction(connection, headers, info, nullptr); - EXPECT_EQ(expected, engineRes); + const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl(), + const StreamInfo::StreamInfo& info = NiceMock()) { + EXPECT_EQ(expected, engine.allowed(connection, headers, info, nullptr)); } -void checkEngine( - RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, +// Used for testing shouldLog() function tests +void checkEngineLog( + const RBAC::RoleBasedAccessControlEngineImpl& engine, + const RoleBasedAccessControlEngine::LogDecision expected, const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), - const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { - - NiceMock empty_info; - checkEngine(engine, expected, empty_info, connection, headers); + const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl(), + const StreamInfo::StreamInfo& info = NiceMock()) { + EXPECT_EQ(expected, engine.shouldLog(connection, headers, info, nullptr)); } TEST(RoleBasedAccessControlEngineImpl, Disabled) { envoy::config::rbac::v3::RBAC rbac; rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); - RBAC::RoleBasedAccessControlEngineImpl engine_allow(rbac); - checkEngine(engine_allow, false); + checkEngine(RBAC::RoleBasedAccessControlEngineImpl(rbac), false); rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); - RBAC::RoleBasedAccessControlEngineImpl engine_deny(rbac); - checkEngine(engine_deny, true); + checkEngine(RBAC::RoleBasedAccessControlEngineImpl(rbac), true); } // Test various invalid policies to validate the fix for @@ -155,11 +153,11 @@ TEST(RoleBasedAccessControlEngineImpl, AllowedAllowlist) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, true, info, conn, headers); + checkEngine(engine, true, conn, headers, info); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, false, info, conn, headers); + checkEngine(engine, false, conn, headers, info); } TEST(RoleBasedAccessControlEngineImpl, DeniedDenylist) { @@ -178,11 +176,11 @@ TEST(RoleBasedAccessControlEngineImpl, DeniedDenylist) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, false, info, conn, headers); + checkEngine(engine, false, conn, headers, info); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, true, info, conn, headers); + checkEngine(engine, true, conn, headers, info); } TEST(RoleBasedAccessControlEngineImpl, BasicCondition) { @@ -242,6 +240,10 @@ TEST(RoleBasedAccessControlEngineImpl, MistypedCondition) { (*rbac.mutable_policies())["foo"] = policy; RBAC::RoleBasedAccessControlEngineImpl engine(rbac); checkEngine(engine, false); + + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No); } TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { @@ -267,6 +269,11 @@ TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { (*rbac.mutable_policies())["foo"] = policy; RBAC::RoleBasedAccessControlEngineImpl engine(rbac); checkEngine(engine, false, Envoy::Network::MockConnection()); + + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, + Envoy::Network::MockConnection()); } TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { @@ -303,6 +310,11 @@ TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { headers.setReference(key, value); checkEngine(engine, true, Envoy::Network::MockConnection(), headers); + + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, + Envoy::Network::MockConnection(), headers); } TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { @@ -347,7 +359,12 @@ TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { Protobuf::MapPair("other", label)); EXPECT_CALL(Const(info), dynamicMetadata()).WillRepeatedly(ReturnRef(metadata)); - checkEngine(engine, true, info, Envoy::Network::MockConnection(), headers); + checkEngine(engine, true, Envoy::Network::MockConnection(), headers, info); + + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, + Envoy::Network::MockConnection(), headers, info); } TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { @@ -370,8 +387,90 @@ TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - EXPECT_CALL(Const(info), downstreamLocalAddress()).Times(1).WillRepeatedly(ReturnRef(addr)); - checkEngine(engine, false, info, conn, headers); + EXPECT_CALL(Const(info), downstreamLocalAddress()).Times(2).WillRepeatedly(ReturnRef(addr)); + checkEngine(engine, false, conn, headers, info); + + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); + checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, conn, headers, + info); +} + +// Log tests tests +TEST(RoleBasedAccessControlEngineImpl, DisabledLog) { + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + checkEngineLog(RBAC::RoleBasedAccessControlEngineImpl(rbac), + RBAC::RoleBasedAccessControlEngine::LogDecision::No); +} + +TEST(RoleBasedAccessControlEngineImpl, LogIfMatched) { + envoy::config::rbac::v3::Policy policy; + policy.add_permissions()->set_destination_port(123); + policy.add_principals()->set_any(true); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + (*rbac.mutable_policies())["foo"] = policy; + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + + Envoy::Network::MockConnection conn; + Envoy::Http::TestRequestHeaderMapImpl headers; + NiceMock info; + Envoy::Network::Address::InstanceConstSharedPtr addr = + Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); + EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::Yes, conn, headers, info); + + addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); + EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::No, conn, headers, info); +} + +TEST(RoleBasedAccessControlEngineImpl, LogAllowUndecided) { + envoy::config::rbac::v3::Policy policy; + policy.add_permissions()->set_destination_port(123); + policy.add_principals()->set_any(true); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); + (*rbac.mutable_policies())["foo"] = policy; + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + + Envoy::Network::MockConnection conn; + Envoy::Http::TestRequestHeaderMapImpl headers; + NiceMock info; + Envoy::Network::Address::InstanceConstSharedPtr addr = + Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, + info); + + addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, + info); +} + +TEST(RoleBasedAccessControlEngineImpl, LogDenyUndecided) { + envoy::config::rbac::v3::Policy policy; + policy.add_permissions()->set_destination_port(123); + policy.add_principals()->set_any(true); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); + (*rbac.mutable_policies())["foo"] = policy; + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + + Envoy::Network::MockConnection conn; + Envoy::Http::TestRequestHeaderMapImpl headers; + NiceMock info; + Envoy::Network::Address::InstanceConstSharedPtr addr = + Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, + info); + + addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); + checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, + info); } TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { @@ -389,10 +488,10 @@ TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngine(engine, true, info, conn, headers); + checkEngine(engine, true, conn, headers, info); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngine(engine, true, info, conn, headers); + checkEngine(engine, true, conn, headers, info); } } // namespace diff --git a/test/extensions/filters/common/rbac/mocks.h b/test/extensions/filters/common/rbac/mocks.h index c597bbd0ee4b4..fda95244c8933 100644 --- a/test/extensions/filters/common/rbac/mocks.h +++ b/test/extensions/filters/common/rbac/mocks.h @@ -14,19 +14,18 @@ namespace RBAC { class MockEngine : public RoleBasedAccessControlEngineImpl { public: - MockEngine(const envoy::config::rbac::v3::RBAC& rules, - const EnforcementMode mode = EnforcementMode::Shadow) - : RoleBasedAccessControlEngineImpl(rules, mode){}; - - // MOCK_METHOD(bool, allowed, - // (const Envoy::Network::Connection&, const Envoy::Http::RequestHeaderMap&, - // const StreamInfo::StreamInfo&, std::string* effective_policy_id), - // (const)); - - // MOCK_METHOD(bool, allowed, - // (const Envoy::Network::Connection&, const StreamInfo::StreamInfo&, - // std::string* effective_policy_id), - // (const)); + MockEngine(const envoy::config::rbac::v3::RBAC& rules) + : RoleBasedAccessControlEngineImpl(rules){}; + + MOCK_METHOD(bool, allowed, + (const Envoy::Network::Connection&, const Envoy::Http::RequestHeaderMap&, + const StreamInfo::StreamInfo&, std::string* effective_policy_id), + (const)); + + MOCK_METHOD(bool, allowed, + (const Envoy::Network::Connection&, const StreamInfo::StreamInfo&, + std::string* effective_policy_id), + (const)); }; } // namespace RBAC diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index 873121d741001..6a3da375b6768 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -145,11 +145,7 @@ TEST_F(RoleBasedAccessControlFilterTest, RequestedServerName) { // Check Log setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); - auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at( - Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); - EXPECT_EQ(true, filter_meta.fields() - .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) - .bool_value()); + checkAccessLogMetadata(true); } TEST_F(RoleBasedAccessControlFilterTest, Path) { @@ -174,11 +170,7 @@ TEST_F(RoleBasedAccessControlFilterTest, Path) { // Check Log setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers, false)); - auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at( - Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); - EXPECT_EQ(false, filter_meta.fields() - .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) - .bool_value()); + checkAccessLogMetadata(false); } TEST_F(RoleBasedAccessControlFilterTest, Denied) { @@ -203,22 +195,22 @@ TEST_F(RoleBasedAccessControlFilterTest, Denied) { EXPECT_EQ("rbac_access_denied", callbacks_.details_); } -// TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { -// setDestinationPort(456); +TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { + setDestinationPort(456); -// envoy::extensions::filters::http::rbac::v3::RBACPerRoute route_config; -// route_config.mutable_rbac()->mutable_rules()->set_action(envoy::config::rbac::v3::RBAC::DENY); -// NiceMock engine{route_config.rbac().rules()}; -// NiceMock per_route_config_{route_config}; + envoy::extensions::filters::http::rbac::v3::RBACPerRoute route_config; + route_config.mutable_rbac()->mutable_rules()->set_action(envoy::config::rbac::v3::RBAC::DENY); + NiceMock engine{route_config.rbac().rules()}; + NiceMock per_route_config_{route_config}; -// // EXPECT_CALL(engine, allowed(_, _, _, _)).WillRepeatedly(Return(true)); -// EXPECT_CALL(per_route_config_, engine()).WillRepeatedly(ReturnRef(engine)); + EXPECT_CALL(engine, allowed(_, _, _, _)).WillRepeatedly(Return(true)); + EXPECT_CALL(per_route_config_, engine()).WillRepeatedly(ReturnRef(engine)); -// EXPECT_CALL(callbacks_.route_->route_entry_, perFilterConfig(HttpFilterNames::get().Rbac)) -// .WillRepeatedly(Return(&per_route_config_)); + EXPECT_CALL(callbacks_.route_->route_entry_, perFilterConfig(HttpFilterNames::get().Rbac)) + .WillRepeatedly(Return(&per_route_config_)); -// EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, true)); -// } + EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, true)); +} // Log Tests TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { @@ -229,6 +221,9 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); + EXPECT_EQ(1U, log_config_->stats().logged_.value()); + EXPECT_EQ(0U, log_config_->stats().not_logged_.value()); + Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); @@ -244,6 +239,9 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); + EXPECT_EQ(0U, log_config_->stats().logged_.value()); + EXPECT_EQ(1U, log_config_->stats().not_logged_.value()); + Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); @@ -256,6 +254,8 @@ TEST_F(RoleBasedAccessControlFilterTest, AllowNoChangeLog) { setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); + EXPECT_EQ(0U, config_->stats().logged_.value()); + EXPECT_EQ(0U, config_->stats().not_logged_.value()); // Check that Allow action does not set access log metadata EXPECT_EQ(req_info_.dynamicMetadata().filter_metadata().end(), diff --git a/test/extensions/filters/network/rbac/filter_test.cc b/test/extensions/filters/network/rbac/filter_test.cc index fe042854baa7a..ae29c1667c089 100644 --- a/test/extensions/filters/network/rbac/filter_test.cc +++ b/test/extensions/filters/network/rbac/filter_test.cc @@ -206,6 +206,9 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldLog) { EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); + EXPECT_EQ(1U, config_->stats().logged_.value()); + EXPECT_EQ(0U, config_->stats().not_logged_.value()); + checkAccessLogMetadata(true); } @@ -221,6 +224,9 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldNotLog) { EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); + EXPECT_EQ(0U, config_->stats().logged_.value()); + EXPECT_EQ(1U, config_->stats().not_logged_.value()); + checkAccessLogMetadata(false); } @@ -229,6 +235,8 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, AllowNoChangeLog) { setMetadata(); EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(data_, false)); + EXPECT_EQ(0U, config_->stats().logged_.value()); + EXPECT_EQ(0U, config_->stats().not_logged_.value()); // Check that Allow action does not set access log metadata EXPECT_EQ(stream_info_.dynamicMetadata().filter_metadata().end(), From 883be350a90254e1fe59b8258ec7c8f4898812aa Mon Sep 17 00:00:00 2001 From: davidraskin Date: Tue, 4 Aug 2020 17:28:57 +0000 Subject: [PATCH 33/39] Reverting previous Signed-off-by: davidraskin --- api/envoy/config/rbac/v3/rbac.proto | 97 ++-- api/envoy/config/rbac/v4alpha/rbac.proto | 97 ++-- bazel.output.txt | 516 ++++++++++++++++++ .../advanced/well_known_dynamic_metadata.rst | 2 +- .../listeners/network_filters/rbac_filter.rst | 2 +- docs/root/version_history/current.rst | 1 + .../envoy/config/rbac/v3/rbac.proto | 97 ++-- .../envoy/config/rbac/v4alpha/rbac.proto | 97 ++-- .../extensions/filters/common/rbac/engine.h | 50 +- .../filters/common/rbac/engine_impl.cc | 86 ++- .../filters/common/rbac/engine_impl.h | 41 +- .../extensions/filters/common/rbac/utility.h | 27 +- .../filters/http/rbac/rbac_filter.cc | 47 +- .../filters/http/rbac/rbac_filter.h | 10 +- .../filters/network/rbac/rbac_filter.cc | 46 +- .../filters/network/rbac/rbac_filter.h | 2 +- .../filters/common/rbac/engine_impl_test.cc | 147 +---- test/extensions/filters/common/rbac/mocks.h | 25 +- .../filters/http/rbac/rbac_filter_test.cc | 44 +- .../filters/network/rbac/filter_test.cc | 8 - 20 files changed, 915 insertions(+), 527 deletions(-) create mode 100644 bazel.output.txt diff --git a/api/envoy/config/rbac/v3/rbac.proto b/api/envoy/config/rbac/v3/rbac.proto index 9b3fd0524868b..278e6857603fe 100644 --- a/api/envoy/config/rbac/v3/rbac.proto +++ b/api/envoy/config/rbac/v3/rbac.proto @@ -82,40 +82,47 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match. + // All requests are allowed. LOG = 2; } - // The action to take if a policy matches. - // The request is allowed if and only if: + // The action to take if a policy matches. Every action either allows or denies a request, + // and can also carry out action-specific operations. // - // * `action` is "ALLOW" and at least one policy matches - // * `action` is "DENY" and none of the policies match - // * `action` is "LOG" + // Actions: + // + // * ALLOW: Allows the request if and only if there is a policy that matches + // the request. + // * DENY: Allows the request if and only if there are no policies that + // match the request. + // * LOG: Allows all requests. If at least one policy matches, the dynamic + // metadata key `access_log_hint` is set to the value `true` under the shared + // key namespace 'envoy.common'. If no policies match, it is set to `false`. + // Other actions do not modify this key. // - // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` - // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, - // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if -// and only if at least one of its permissions match the action taking place AND at least one of its -// principals match the downstream AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. +// A policy matches if and only if at least one of its permissions match the +// action taking place AND at least one of its principals match the downstream +// AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Policy"; - // Required. The set of permissions that define a role. Each permission is matched with OR - // semantics. To match all actions for this policy, a single Permission with the `any` field set - // to true should be used. + // Required. The set of permissions that define a role. Each permission is + // matched with OR semantics. To match all actions for this policy, a single + // Permission with the `any` field set to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on “action”. Each - // principal is matched with OR semantics. To match all downstreams for this policy, a single - // Principal with the `any` field set to true should be used. + // Required. The set of principals that are assigned/denied the role based on + // “action”. Each principal is matched with OR semantics. To match all + // downstreams for this policy, a single Principal with the `any` field set to + // true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; // An optional symbolic expression specifying an access control @@ -176,9 +183,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of `not_rule` would - // match, this permission would not match. Conversely, if the value of `not_rule` would not - // match, this permission would match. + // Negates matching the provided permission. For instance, if the value of + // `not_rule` would match, this permission would not match. Conversely, if + // the value of `not_rule` would not match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -191,7 +198,8 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name `, + // the :ref:`server name + // `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -204,13 +212,14 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream subject. +// Principal defines an identity or a group of identities for a downstream +// subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, - // each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. + // Depending on the context, each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal.Set"; @@ -225,19 +234,21 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the - // certificate, otherwise the subject field is used. If unset, it applies to any user that is - // authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order + // is used from the certificate, otherwise the subject field is used. If + // unset, it applies to any user that is authenticated. type.matcher.v3.StringMatcher principal_name = 2; } oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the downstream. + // A set of identifiers that all must match in order to define the + // downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the downstream. + // A set of identifiers at least one must match in order to define the + // downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -252,21 +263,23 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is inferred - // from for example the x-forwarder-for header, proxy protocol, etc. + // :ref:`remote_ip ` is + // inferred from for example the x-forwarder-for header, proxy protocol, + // etc. core.v3.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip `. - // E.g, if the remote ip is inferred from for example the x-forwarder-for header, - // proxy protocol, etc. + // :ref:`direct_remote_ip + // `. E.g, if the + // remote ip is inferred from for example the x-forwarder-for header, proxy + // protocol, etc. core.v3.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only - // available for HTTP request. - // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` - // field if you want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP + // request. Only available for HTTP request. Note: the pseudo-header :path + // includes the query and fragment string. Use the `url_path` field if you + // want to match the URL path without the query and fragment string. route.v3.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -275,9 +288,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of `not_id` would match, - // this principal would not match. Conversely, if the value of `not_id` would not match, this - // principal would match. + // Negates matching the provided principal. For instance, if the value of + // `not_id` would match, this principal would not match. Conversely, if the + // value of `not_id` would not match, this principal would match. Principal not_id = 8; } } diff --git a/api/envoy/config/rbac/v4alpha/rbac.proto b/api/envoy/config/rbac/v4alpha/rbac.proto index eea66a969f58a..cc9d8933ababc 100644 --- a/api/envoy/config/rbac/v4alpha/rbac.proto +++ b/api/envoy/config/rbac/v4alpha/rbac.proto @@ -81,40 +81,47 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match. + // All requests are allowed. LOG = 2; } - // The action to take if a policy matches. - // The request is allowed if and only if: + // The action to take if a policy matches. Every action either allows or denies a request, + // and can also carry out action-specific operations. // - // * `action` is "ALLOW" and at least one policy matches - // * `action` is "DENY" and none of the policies match - // * `action` is "LOG" + // Actions: + // + // * ALLOW: Allows the request if and only if there is a policy that matches + // the request. + // * DENY: Allows the request if and only if there are no policies that + // match the request. + // * LOG: Allows all requests. If at least one policy matches, the dynamic + // metadata key `access_log_hint` is set to the value `true` under the shared + // key namespace 'envoy.common'. If no policies match, it is set to `false`. + // Other actions do not modify this key. // - // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` - // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, - // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if -// and only if at least one of its permissions match the action taking place AND at least one of its -// principals match the downstream AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. +// A policy matches if and only if at least one of its permissions match the +// action taking place AND at least one of its principals match the downstream +// AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Policy"; - // Required. The set of permissions that define a role. Each permission is matched with OR - // semantics. To match all actions for this policy, a single Permission with the `any` field set - // to true should be used. + // Required. The set of permissions that define a role. Each permission is + // matched with OR semantics. To match all actions for this policy, a single + // Permission with the `any` field set to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on “action”. Each - // principal is matched with OR semantics. To match all downstreams for this policy, a single - // Principal with the `any` field set to true should be used. + // Required. The set of principals that are assigned/denied the role based on + // “action”. Each principal is matched with OR semantics. To match all + // downstreams for this policy, a single Principal with the `any` field set to + // true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; oneof expression_specifier { @@ -175,9 +182,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of `not_rule` would - // match, this permission would not match. Conversely, if the value of `not_rule` would not - // match, this permission would match. + // Negates matching the provided permission. For instance, if the value of + // `not_rule` would match, this permission would not match. Conversely, if + // the value of `not_rule` would not match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -190,7 +197,8 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name `, + // the :ref:`server name + // `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -203,13 +211,14 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream subject. +// Principal defines an identity or a group of identities for a downstream +// subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, - // each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. + // Depending on the context, each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal.Set"; @@ -224,9 +233,9 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the - // certificate, otherwise the subject field is used. If unset, it applies to any user that is - // authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order + // is used from the certificate, otherwise the subject field is used. If + // unset, it applies to any user that is authenticated. type.matcher.v4alpha.StringMatcher principal_name = 2; } @@ -237,10 +246,12 @@ message Principal { oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the downstream. + // A set of identifiers that all must match in order to define the + // downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the downstream. + // A set of identifiers at least one must match in order to define the + // downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -251,21 +262,23 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is inferred - // from for example the x-forwarder-for header, proxy protocol, etc. + // :ref:`remote_ip ` is + // inferred from for example the x-forwarder-for header, proxy protocol, + // etc. core.v4alpha.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip `. - // E.g, if the remote ip is inferred from for example the x-forwarder-for header, - // proxy protocol, etc. + // :ref:`direct_remote_ip + // `. E.g, if the + // remote ip is inferred from for example the x-forwarder-for header, proxy + // protocol, etc. core.v4alpha.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only - // available for HTTP request. - // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` - // field if you want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP + // request. Only available for HTTP request. Note: the pseudo-header :path + // includes the query and fragment string. Use the `url_path` field if you + // want to match the URL path without the query and fragment string. route.v4alpha.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -274,9 +287,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of `not_id` would match, - // this principal would not match. Conversely, if the value of `not_id` would not match, this - // principal would match. + // Negates matching the provided principal. For instance, if the value of + // `not_id` would match, this principal would not match. Conversely, if the + // value of `not_id` would not match, this principal would match. Principal not_id = 8; } } diff --git a/bazel.output.txt b/bazel.output.txt new file mode 100644 index 0000000000000..f46e9f71acafd --- /dev/null +++ b/bazel.output.txt @@ -0,0 +1,516 @@ +==================== Test output for //test/extensions/filters/http/grpc_http1_reverse_bridge:reverse_bridge_integration_test: +WARNING: Perftools heap leak checker is active -- Performance may suffer +[==========] Running 4 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 4 tests from IpVersions/ReverseBridgeIntegrationTest +[ RUN ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv4 +[ OK ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv4 (860 ms) +[ RUN ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv6 +[2020-08-03 21:22:42.230][35831][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/339/execroot/envoy/_tmp/34b195ec3fd9b4e4f43d020a8e761e79/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address +terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address +[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc224300008bbb +[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): +[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL +[2020-08-03 21:22:42.302][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x41543bc] +[2020-08-03 21:22:42.302][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7fca75ef08a0] +[2020-08-03 21:22:42.372][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x252214e] +[2020-08-03 21:22:42.442][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x2521b89] +[2020-08-03 21:22:42.512][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x2524398] +[2020-08-03 21:22:42.583][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x25242cd] +[2020-08-03 21:22:42.655][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x252427d] +[2020-08-03 21:22:42.724][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x252424d] +[2020-08-03 21:22:42.793][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x252356e] +[2020-08-03 21:22:42.864][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x245e3d5] +[2020-08-03 21:22:42.934][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x245e295] +[2020-08-03 21:22:43.005][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5028a82] +[2020-08-03 21:22:43.075][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x5028a55] +[2020-08-03 21:22:43.075][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7fca75ee56db] +================================================================================ +==================== Test output for //test/server/admin:logs_handler_test: +WARNING: Perftools heap leak checker is active -- Performance may suffer +[==========] Running 2 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 2 tests from IpVersions/AdminInstanceTest +[ RUN ] IpVersions/AdminInstanceTest.ReopenLogs/IPv4 +TestRandomGenerator running with seed 2096517680 +[ OK ] IpVersions/AdminInstanceTest.ReopenLogs/IPv4 (395 ms) +[ RUN ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6 +TestRandomGenerator running with seed 2096517680 +unknown file: Failure +C++ exception with description "cannot bind '[::1]:0': Cannot assign requested address" thrown in the test fixture's constructor. +[ FAILED ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6, where GetParam() = 4-byte object <01-00 00-00> (319 ms) +[----------] 2 tests from IpVersions/AdminInstanceTest (714 ms total) + +[----------] Global test environment tear-down +[==========] 2 tests from 1 test suite ran. (714 ms total) +[ PASSED ] 1 test. +[ FAILED ] 1 test, listed below: +[ FAILED ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6, where GetParam() = 4-byte object <01-00 00-00> + + 1 FAILED TEST +Have memory regions w/o callers: might report false leaks +No leaks found for check "_main_" (but no 100% guarantee that there aren't any): found 17951 reachable heap objects of 2897135 bytes +================================================================================ +==================== Test output for //test/extensions/filters/http/tap:tap_filter_integration_test: +WARNING: Perftools heap leak checker is active -- Performance may suffer +[==========] Running 18 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 18 tests from IpVersions/TapIntegrationTest +[ RUN ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv4 +[ OK ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv4 (943 ms) +[ RUN ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv6 +[2020-08-03 21:28:10.135][41714][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/543/execroot/envoy/_tmp/4ce2d8b1861876b859b107620d7d2ae0/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address +terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address +[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000a2d5 +[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): +[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL +[2020-08-03 21:28:10.206][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x414c97c] +[2020-08-03 21:28:10.207][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7f549b3238a0] +[2020-08-03 21:28:10.277][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x252d4be] +[2020-08-03 21:28:10.347][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x252cef9] +[2020-08-03 21:28:10.416][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x252f708] +[2020-08-03 21:28:10.488][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x252f63d] +[2020-08-03 21:28:10.559][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x252f5ed] +[2020-08-03 21:28:10.629][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x252f5bd] +[2020-08-03 21:28:10.699][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x252e8de] +[2020-08-03 21:28:10.770][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x24694d5] +[2020-08-03 21:28:10.840][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x2469395] +[2020-08-03 21:28:10.909][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5024ee2] +[2020-08-03 21:28:10.980][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x5024eb5] +[2020-08-03 21:28:10.980][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7f549b3186db] +================================================================================ +==================== Test output for //test/extensions/filters/network/postgres_proxy:postgres_integration_test: +WARNING: Perftools heap leak checker is active -- Performance may suffer +[==========] Running 2 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 2 tests from IpVersions/PostgresIntegrationTest +[ RUN ] IpVersions/PostgresIntegrationTest.Login/0 +[ OK ] IpVersions/PostgresIntegrationTest.Login/0 (1510 ms) +[ RUN ] IpVersions/PostgresIntegrationTest.Login/1 +[2020-08-03 21:29:52.988][42506][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/674/execroot/envoy/_tmp/25d60d38146fdfcb74151ad27508c65f/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address +terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address +[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000a5f7 +[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): +[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL +[2020-08-03 21:29:53.037][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x418287c] +[2020-08-03 21:29:53.037][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7fb8f86628a0] +[2020-08-03 21:29:53.086][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x2593dae] +[2020-08-03 21:29:53.136][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x25937e9] +[2020-08-03 21:29:53.185][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x2595ff8] +[2020-08-03 21:29:53.233][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x2595f2d] +[2020-08-03 21:29:53.282][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x2595edd] +[2020-08-03 21:29:53.333][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x2595ead] +[2020-08-03 21:29:53.381][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x25951ce] +[2020-08-03 21:29:53.429][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x24c2305] +[2020-08-03 21:29:53.479][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x24c21c5] +[2020-08-03 21:29:53.529][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5057622] +[2020-08-03 21:29:53.580][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x50575f5] +[2020-08-03 21:29:53.580][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7fb8f86576db] +================================================================================ +[==========] Running 165 tests from 14 test suites. +[----------] Global test environment set-up. +[----------] 79 tests from RouteMatcherTest +[ RUN ] RouteMatcherTest.TestLegacyRoutes +[ OK ] RouteMatcherTest.TestLegacyRoutes (554 ms) +[ RUN ] RouteMatcherTest.TestConnectRoutes +[ OK ] RouteMatcherTest.TestConnectRoutes (175 ms) +[ RUN ] RouteMatcherTest.TestRoutes +[ OK ] RouteMatcherTest.TestRoutes (1526 ms) +[ RUN ] RouteMatcherTest.TestRoutesWithWildcardAndDefaultOnly +[ OK ] RouteMatcherTest.TestRoutesWithWildcardAndDefaultOnly (80 ms) +[ RUN ] RouteMatcherTest.TestRoutesWithInvalidRegexLegacy +[ OK ] RouteMatcherTest.TestRoutesWithInvalidRegexLegacy (67 ms) +[ RUN ] RouteMatcherTest.TestRoutesWithInvalidRegex +[ OK ] RouteMatcherTest.TestRoutesWithInvalidRegex (69 ms) +[ RUN ] RouteMatcherTest.TestRoutesWithInvalidVirtualCluster +[ OK ] RouteMatcherTest.TestRoutesWithInvalidVirtualCluster (51 ms) +[ RUN ] RouteMatcherTest.TestAddRemoveRequestHeaders +[ OK ] RouteMatcherTest.TestAddRemoveRequestHeaders (138 ms) +[ RUN ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalse +[ OK ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalse (117 ms) +[ RUN ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalseMostSpecificWins +[ OK ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalseMostSpecificWins (101 ms) +[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeaders +[ OK ] RouteMatcherTest.TestAddRemoveResponseHeaders (144 ms) +[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendFalse +[ OK ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendFalse (84 ms) +[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendMostSpecificWins +[ OK ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendMostSpecificWins (91 ms) +[ RUN ] RouteMatcherTest.TestAddGlobalResponseHeaderRemoveFromRoute +[ OK ] RouteMatcherTest.TestAddGlobalResponseHeaderRemoveFromRoute (95 ms) +[ RUN ] RouteMatcherTest.TestRequestHeadersToAddNoPseudoHeader +[ OK ] RouteMatcherTest.TestRequestHeadersToAddNoPseudoHeader (140 ms) +[ RUN ] RouteMatcherTest.TestRequestHeadersToRemoveNoPseudoHeader +[ OK ] RouteMatcherTest.TestRequestHeadersToRemoveNoPseudoHeader (152 ms) +[ RUN ] RouteMatcherTest.Priority +[ OK ] RouteMatcherTest.Priority (94 ms) +[ RUN ] RouteMatcherTest.NoHostRewriteAndAutoRewrite +[ OK ] RouteMatcherTest.NoHostRewriteAndAutoRewrite (49 ms) +[ RUN ] RouteMatcherTest.NoHostRewriteAndAutoRewriteHeader +[ OK ] RouteMatcherTest.NoHostRewriteAndAutoRewriteHeader (49 ms) +[ RUN ] RouteMatcherTest.NoAutoRewriteAndAutoRewriteHeader +[ OK ] RouteMatcherTest.NoAutoRewriteAndAutoRewriteHeader (49 ms) +[ RUN ] RouteMatcherTest.HeaderMatchedRouting +[ OK ] RouteMatcherTest.HeaderMatchedRouting (197 ms) +[ RUN ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfigLegacy +[ OK ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfigLegacy (54 ms) +[ RUN ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfig +[ OK ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfig (55 ms) +[ RUN ] RouteMatcherTest.QueryParamMatchedRouting +[ OK ] RouteMatcherTest.QueryParamMatchedRouting (206 ms) +[ RUN ] RouteMatcherTest.InvalidQueryParamMatchedRoutingConfig +[ OK ] RouteMatcherTest.InvalidQueryParamMatchedRoutingConfig (54 ms) +[ RUN ] RouteMatcherTest.ClusterHeader +[ OK ] RouteMatcherTest.ClusterHeader (110 ms) +[ RUN ] RouteMatcherTest.ContentType +[ OK ] RouteMatcherTest.ContentType (95 ms) +[ RUN ] RouteMatcherTest.GrpcTimeoutOffset +[ OK ] RouteMatcherTest.GrpcTimeoutOffset (83 ms) +[ RUN ] RouteMatcherTest.GrpcTimeoutOffsetOfDynamicRoute +[ OK ] RouteMatcherTest.GrpcTimeoutOffsetOfDynamicRoute (99 ms) +[ RUN ] RouteMatcherTest.FractionalRuntime +[ OK ] RouteMatcherTest.FractionalRuntime (81 ms) +[ RUN ] RouteMatcherTest.ShadowClusterNotFound +[ OK ] RouteMatcherTest.ShadowClusterNotFound (50 ms) +[ RUN ] RouteMatcherTest.ClusterNotFound +[ OK ] RouteMatcherTest.ClusterNotFound (51 ms) +[ RUN ] RouteMatcherTest.ClusterNotFoundNotChecking +[ OK ] RouteMatcherTest.ClusterNotFoundNotChecking (50 ms) +[ RUN ] RouteMatcherTest.ClusterNotFoundNotCheckingViaConfig +[ OK ] RouteMatcherTest.ClusterNotFoundNotCheckingViaConfig (51 ms) +[ RUN ] RouteMatcherTest.AttemptCountHeader +[ OK ] RouteMatcherTest.AttemptCountHeader (77 ms) +[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCode +[ OK ] RouteMatcherTest.ClusterNotFoundResponseCode (79 ms) +[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig503 +[ OK ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig503 (79 ms) +[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig404 +[ OK ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig404 (79 ms) +[ RUN ] RouteMatcherTest.Shadow +[ OK ] RouteMatcherTest.Shadow (115 ms) +[ RUN ] RouteMatcherTest.ShadowPolicyAndPolicies +[ OK ] RouteMatcherTest.ShadowPolicyAndPolicies (53 ms) +[ RUN ] RouteMatcherTest.Retry +[ OK ] RouteMatcherTest.Retry (186 ms) +[ RUN ] RouteMatcherTest.RetryVirtualHostLevel +[ OK ] RouteMatcherTest.RetryVirtualHostLevel (215 ms) +[ RUN ] RouteMatcherTest.GrpcRetry +[ OK ] RouteMatcherTest.GrpcRetry (189 ms) +[ RUN ] RouteMatcherTest.RetryBackOffIntervals +[ OK ] RouteMatcherTest.RetryBackOffIntervals (175 ms) +[ RUN ] RouteMatcherTest.InvalidRetryBackOff +[ OK ] RouteMatcherTest.InvalidRetryBackOff (57 ms) +[ RUN ] RouteMatcherTest.HedgeRouteLevel +[ OK ] RouteMatcherTest.HedgeRouteLevel (195 ms) +[ RUN ] RouteMatcherTest.HedgeVirtualHostLevel +[ OK ] RouteMatcherTest.HedgeVirtualHostLevel (199 ms) +[ RUN ] RouteMatcherTest.TestBadDefaultConfig +[ OK ] RouteMatcherTest.TestBadDefaultConfig (71 ms) +[ RUN ] RouteMatcherTest.TestDuplicateDomainConfig +[ OK ] RouteMatcherTest.TestDuplicateDomainConfig (56 ms) +[ RUN ] RouteMatcherTest.TestCaseSensitiveDomainConfig +[ OK ] RouteMatcherTest.TestCaseSensitiveDomainConfig (54 ms) +[ RUN ] RouteMatcherTest.TestDuplicateWildcardDomainConfig +[ OK ] RouteMatcherTest.TestDuplicateWildcardDomainConfig (54 ms) +[ RUN ] RouteMatcherTest.TestDuplicateSuffixWildcardDomainConfig +[ OK ] RouteMatcherTest.TestDuplicateSuffixWildcardDomainConfig (53 ms) +[ RUN ] RouteMatcherTest.TestDuplicatePrefixWildcardDomainConfig +[ OK ] RouteMatcherTest.TestDuplicatePrefixWildcardDomainConfig (53 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInPrefixRewrites +[ OK ] RouteMatcherTest.TestInvalidCharactersInPrefixRewrites (51 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInHostRewrites +[ OK ] RouteMatcherTest.TestInvalidCharactersInHostRewrites (51 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInAutoHostRewrites +[ OK ] RouteMatcherTest.TestInvalidCharactersInAutoHostRewrites (51 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInHostRedirect +[ OK ] RouteMatcherTest.TestInvalidCharactersInHostRedirect (49 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInPathRedirect +[ OK ] RouteMatcherTest.TestInvalidCharactersInPathRedirect (51 ms) +[ RUN ] RouteMatcherTest.TestInvalidCharactersInPrefixRewriteRedirect +[ OK ] RouteMatcherTest.TestInvalidCharactersInPrefixRewriteRedirect (50 ms) +[ RUN ] RouteMatcherTest.TestPrefixAndRegexRewrites +[ OK ] RouteMatcherTest.TestPrefixAndRegexRewrites (51 ms) +[ RUN ] RouteMatcherTest.TestDomainMatchOrderConfig +[ OK ] RouteMatcherTest.TestDomainMatchOrderConfig (157 ms) +[ RUN ] RouteMatcherTest.NoProtocolInHeadersWhenTlsIsRequired +[ OK ] RouteMatcherTest.NoProtocolInHeadersWhenTlsIsRequired (66 ms) +[ RUN ] RouteMatcherTest.RouteName +[ OK ] RouteMatcherTest.RouteName (148 ms) +[ RUN ] RouteMatcherTest.DirectResponse +[ OK ] RouteMatcherTest.DirectResponse (1138 ms) +[ RUN ] RouteMatcherTest.ExclusiveRouteEntryOrDirectResponseEntry +[ OK ] RouteMatcherTest.ExclusiveRouteEntryOrDirectResponseEntry (111 ms) +[ RUN ] RouteMatcherTest.ExclusiveWeightedClustersEntryOrDirectResponseEntry +[ OK ] RouteMatcherTest.ExclusiveWeightedClustersEntryOrDirectResponseEntry (111 ms) +[ RUN ] RouteMatcherTest.WeightedClusters +[ OK ] RouteMatcherTest.WeightedClusters (1129 ms) +[ RUN ] RouteMatcherTest.ExclusiveWeightedClustersOrClusterConfig +[ OK ] RouteMatcherTest.ExclusiveWeightedClustersOrClusterConfig (48 ms) +[ RUN ] RouteMatcherTest.WeightedClustersMissingClusterList +[ OK ] RouteMatcherTest.WeightedClustersMissingClusterList (50 ms) +[ RUN ] RouteMatcherTest.WeightedClustersEmptyClustersList +[ OK ] RouteMatcherTest.WeightedClustersEmptyClustersList (47 ms) +[ RUN ] RouteMatcherTest.WeightedClustersSumOFWeightsNotEqualToMax +[ OK ] RouteMatcherTest.WeightedClustersSumOFWeightsNotEqualToMax (87 ms) +[ RUN ] RouteMatcherTest.TestWeightedClusterWithMissingWeights +[ OK ] RouteMatcherTest.TestWeightedClusterWithMissingWeights (103 ms) +[ RUN ] RouteMatcherTest.TestWeightedClusterInvalidClusterName +[ OK ] RouteMatcherTest.TestWeightedClusterInvalidClusterName (65 ms) +[ RUN ] RouteMatcherTest.TestWeightedClusterHeaderManipulation +[ OK ] RouteMatcherTest.TestWeightedClusterHeaderManipulation (95 ms) +[ RUN ] RouteMatcherTest.TestOpaqueConfig +[ OK ] RouteMatcherTest.TestOpaqueConfig (137 ms) +[ RUN ] RouteMatcherTest.TestOpaqueConfigUsingDeprecatedName +[ OK ] RouteMatcherTest.TestOpaqueConfigUsingDeprecatedName (69 ms) +[ RUN ] RouteMatcherTest.Decorator +[ OK ] RouteMatcherTest.Decorator (83 ms) +[ RUN ] RouteMatcherTest.HeaderMatchedRoutingV2 +[ OK ] RouteMatcherTest.HeaderMatchedRoutingV2 (305 ms) +[ RUN ] RouteMatcherTest.TlsContextMatching +[ OK ] RouteMatcherTest.TlsContextMatching (187 ms) +[----------] 79 tests from RouteMatcherTest (11638 ms total) + +[----------] 10 tests from RouterMatcherHashPolicyTest +[ RUN ] RouterMatcherHashPolicyTest.HashHeaders +[ OK ] RouterMatcherHashPolicyTest.HashHeaders (96 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashHeadersRegexSubstitution +[ OK ] RouterMatcherHashPolicyTest.HashHeadersRegexSubstitution (65 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashIp +[ OK ] RouterMatcherHashPolicyTest.HashIp (124 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashIpNonIpAddress +[ OK ] RouterMatcherHashPolicyTest.HashIpNonIpAddress (73 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashIpv4DifferentAddresses +[ OK ] RouterMatcherHashPolicyTest.HashIpv4DifferentAddresses (82 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashIpv6DifferentAddresses +[ OK ] RouterMatcherHashPolicyTest.HashIpv6DifferentAddresses (81 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashQueryParameters +[ OK ] RouterMatcherHashPolicyTest.HashQueryParameters (94 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashMultiple +[ OK ] RouterMatcherHashPolicyTest.HashMultiple (122 ms) +[ RUN ] RouterMatcherHashPolicyTest.HashTerminal +[ OK ] RouterMatcherHashPolicyTest.HashTerminal (109 ms) +[ RUN ] RouterMatcherHashPolicyTest.InvalidHashPolicies +[ OK ] RouterMatcherHashPolicyTest.InvalidHashPolicies (50 ms) +[----------] 10 tests from RouterMatcherHashPolicyTest (897 ms total) + +[----------] 5 tests from RouterMatcherCookieHashPolicyTest +[ RUN ] RouterMatcherCookieHashPolicyTest.NoTtl +[ OK ] RouterMatcherCookieHashPolicyTest.NoTtl (107 ms) +[ RUN ] RouterMatcherCookieHashPolicyTest.DifferentCookies +[ OK ] RouterMatcherCookieHashPolicyTest.DifferentCookies (80 ms) +[ RUN ] RouterMatcherCookieHashPolicyTest.TtlSet +[ OK ] RouterMatcherCookieHashPolicyTest.TtlSet (141 ms) +[ RUN ] RouterMatcherCookieHashPolicyTest.SetSessionCookie +[ OK ] RouterMatcherCookieHashPolicyTest.SetSessionCookie (66 ms) +[ RUN ] RouterMatcherCookieHashPolicyTest.SetCookiePath +[ OK ] RouterMatcherCookieHashPolicyTest.SetCookiePath (66 ms) +[----------] 5 tests from RouterMatcherCookieHashPolicyTest (460 ms total) + +[----------] 4 tests from RouterMatcherFilterStateHashPolicyTest +[ RUN ] RouterMatcherFilterStateHashPolicyTest.KeyNotFound +[ OK ] RouterMatcherFilterStateHashPolicyTest.KeyNotFound (65 ms) +[ RUN ] RouterMatcherFilterStateHashPolicyTest.NullValue +[ OK ] RouterMatcherFilterStateHashPolicyTest.NullValue (68 ms) +[ RUN ] RouterMatcherFilterStateHashPolicyTest.ValueNonHashable +[ OK ] RouterMatcherFilterStateHashPolicyTest.ValueNonHashable (66 ms) +[ RUN ] RouterMatcherFilterStateHashPolicyTest.Hashable +[ OK ] RouterMatcherFilterStateHashPolicyTest.Hashable (66 ms) +[----------] 4 tests from RouterMatcherFilterStateHashPolicyTest (266 ms total) + +[----------] 24 tests from RouteConfigurationV2 +[ RUN ] RouteConfigurationV2.RequestMirrorPolicy +[ OK ] RouteConfigurationV2.RequestMirrorPolicy (95 ms) +[ RUN ] RouteConfigurationV2.RedirectCode +[ OK ] RouteConfigurationV2.RedirectCode (94 ms) +[ RUN ] RouteConfigurationV2.DirectResponse +[ OK ] RouteConfigurationV2.DirectResponse (63 ms) +[ RUN ] RouteConfigurationV2.DirectResponseTooLarge +[ OK ] RouteConfigurationV2.DirectResponseTooLarge (60 ms) +[ RUN ] RouteConfigurationV2.BrokenTypedMetadata +[ OK ] RouteConfigurationV2.BrokenTypedMetadata (51 ms) +[ RUN ] RouteConfigurationV2.RouteConfigGetters +[ OK ] RouteConfigurationV2.RouteConfigGetters (98 ms) +[ RUN ] RouteConfigurationV2.RouteTracingConfig +[ OK ] RouteConfigurationV2.RouteTracingConfig (104 ms) +[ RUN ] RouteConfigurationV2.RedirectPrefixRewrite +[ OK ] RouteConfigurationV2.RedirectPrefixRewrite (253 ms) +[ RUN ] RouteConfigurationV2.PathRedirectQueryNotPreserved +[ OK ] RouteConfigurationV2.PathRedirectQueryNotPreserved (158 ms) +[ RUN ] RouteConfigurationV2.RedirectStripQuery +[ OK ] RouteConfigurationV2.RedirectStripQuery (196 ms) +[ RUN ] RouteConfigurationV2.RegexPrefixWithNoRewriteWorksWhenPathChanged +[ OK ] RouteConfigurationV2.RegexPrefixWithNoRewriteWorksWhenPathChanged (66 ms) +[ RUN ] RouteConfigurationV2.NoIdleTimeout +[ OK ] RouteConfigurationV2.NoIdleTimeout (61 ms) +[ RUN ] RouteConfigurationV2.ZeroIdleTimeout +[ OK ] RouteConfigurationV2.ZeroIdleTimeout (66 ms) +[ RUN ] RouteConfigurationV2.ExplicitIdleTimeout +[ OK ] RouteConfigurationV2.ExplicitIdleTimeout (63 ms) +[ RUN ] RouteConfigurationV2.RetriableStatusCodes +[ OK ] RouteConfigurationV2.RetriableStatusCodes (60 ms) +[ RUN ] RouteConfigurationV2.RetriableHeaders +[ OK ] RouteConfigurationV2.RetriableHeaders (67 ms) +[ RUN ] RouteConfigurationV2.UpgradeConfigs +[ OK ] RouteConfigurationV2.UpgradeConfigs (66 ms) +[ RUN ] RouteConfigurationV2.DuplicateUpgradeConfigs +[ OK ] RouteConfigurationV2.DuplicateUpgradeConfigs (52 ms) +[ RUN ] RouteConfigurationV2.BadConnectConfig +[ OK ] RouteConfigurationV2.BadConnectConfig (53 ms) +[ RUN ] RouteConfigurationV2.RetryPluginsAreNotReused +[ OK ] RouteConfigurationV2.RetryPluginsAreNotReused (66 ms) +[ RUN ] RouteConfigurationV2.InternalRedirectIsDisabledWhenNotSpecifiedInRouteAction +[ OK ] RouteConfigurationV2.InternalRedirectIsDisabledWhenNotSpecifiedInRouteAction (64 ms) +[ RUN ] RouteConfigurationV2.DefaultInternalRedirectPolicyIsSensible +[ OK ] RouteConfigurationV2.DefaultInternalRedirectPolicyIsSensible (67 ms) +[ RUN ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCode +[ OK ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCode (65 ms) +[ RUN ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCodeCauseEmptySet +[ OK ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCodeCauseEmptySet (67 ms) +[----------] 24 tests from RouteConfigurationV2 (2055 ms total) + +[----------] 1 test from NullConfigImplTest +[ RUN ] NullConfigImplTest.All +[ OK ] NullConfigImplTest.All (11 ms) +[----------] 1 test from NullConfigImplTest (11 ms total) + +[----------] 9 tests from BadHttpRouteConfigurationsTest +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteConfig +[ OK ] BadHttpRouteConfigurationsTest.BadRouteConfig (50 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadVirtualHostConfig +[ OK ] BadHttpRouteConfigurationsTest.BadVirtualHostConfig (51 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfig +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfig (51 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPath +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPath (49 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigMissingPathSpecifier +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigMissingPathSpecifier (49 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndRegex +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndRegex (49 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigNoAction +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigNoAction (49 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPathAndRegex +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPathAndRegex (48 ms) +[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPathAndRegex +[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPathAndRegex (49 ms) +[----------] 9 tests from BadHttpRouteConfigurationsTest (445 ms total) + +[----------] 6 tests from RoutePropertyTest +[ RUN ] RoutePropertyTest.ExcludeVHRateLimits +[ OK ] RoutePropertyTest.ExcludeVHRateLimits (101 ms) +[ RUN ] RoutePropertyTest.TestVHostCorsConfig +[ OK ] RoutePropertyTest.TestVHostCorsConfig (68 ms) +[ RUN ] RoutePropertyTest.TestRouteCorsConfig +[ OK ] RoutePropertyTest.TestRouteCorsConfig (67 ms) +[ RUN ] RoutePropertyTest.TTestVHostCorsLegacyConfig +[ OK ] RoutePropertyTest.TTestVHostCorsLegacyConfig (64 ms) +[ RUN ] RoutePropertyTest.TestRouteCorsLegacyConfig +[ OK ] RoutePropertyTest.TestRouteCorsLegacyConfig (66 ms) +[ RUN ] RoutePropertyTest.TestBadCorsConfig +[ OK ] RoutePropertyTest.TestBadCorsConfig (50 ms) +[----------] 6 tests from RoutePropertyTest (416 ms total) + +[----------] 2 tests from CustomRequestHeadersTest +[ RUN ] CustomRequestHeadersTest.AddNewHeader +[ OK ] CustomRequestHeadersTest.AddNewHeader (80 ms) +[ RUN ] CustomRequestHeadersTest.CustomHeaderWrongFormat +[ OK ] CustomRequestHeadersTest.CustomHeaderWrongFormat (65 ms) +[----------] 2 tests from CustomRequestHeadersTest (1591 ms total) + +[----------] 3 tests from MetadataMatchCriteriaImpl +[ RUN ] MetadataMatchCriteriaImpl.Create +[ OK ] MetadataMatchCriteriaImpl.Create (0 ms) +[ RUN ] MetadataMatchCriteriaImpl.Merge +[ OK ] MetadataMatchCriteriaImpl.Merge (0 ms) +[ RUN ] MetadataMatchCriteriaImpl.Filter +[ OK ] MetadataMatchCriteriaImpl.Filter (0 ms) +[----------] 3 tests from MetadataMatchCriteriaImpl (0 ms total) + +[----------] 1 test from RouteEntryMetadataMatchTest +[ RUN ] RouteEntryMetadataMatchTest.ParsesMetadata +[ OK ] RouteEntryMetadataMatchTest.ParsesMetadata (206 ms) +[----------] 1 test from RouteEntryMetadataMatchTest (206 ms total) + +[----------] 2 tests from ConfigUtilityTest +[ RUN ] ConfigUtilityTest.ParseResponseCode +[ OK ] ConfigUtilityTest.ParseResponseCode (46 ms) +[ RUN ] ConfigUtilityTest.ParseDirectResponseBody +[ OK ] ConfigUtilityTest.ParseDirectResponseBody (46 ms) +[----------] 2 tests from ConfigUtilityTest (92 ms total) + +[----------] 11 tests from PerFilterConfigsTest +[ RUN ] PerFilterConfigsTest.TypedConfigFilterError +[ OK ] PerFilterConfigsTest.TypedConfigFilterError (62 ms) +[ RUN ] PerFilterConfigsTest.UnknownFilterStruct +[ OK ] PerFilterConfigsTest.UnknownFilterStruct (51 ms) +[ RUN ] PerFilterConfigsTest.UnknownFilterAny +[ OK ] PerFilterConfigsTest.UnknownFilterAny (50 ms) +[ RUN ] PerFilterConfigsTest.DefaultFilterImplementationStruct +[ OK ] PerFilterConfigsTest.DefaultFilterImplementationStruct (67 ms) +[ RUN ] PerFilterConfigsTest.DefaultFilterImplementationAny +[ OK ] PerFilterConfigsTest.DefaultFilterImplementationAny (67 ms) +[ RUN ] PerFilterConfigsTest.RouteLocalConfig +[ OK ] PerFilterConfigsTest.RouteLocalConfig (68 ms) +[ RUN ] PerFilterConfigsTest.RouteLocalTypedConfig +[ OK ] PerFilterConfigsTest.RouteLocalTypedConfig (67 ms) +[ RUN ] PerFilterConfigsTest.WeightedClusterConfig +[ OK ] PerFilterConfigsTest.WeightedClusterConfig (68 ms) +[ RUN ] PerFilterConfigsTest.WeightedClusterTypedConfig +[ OK ] PerFilterConfigsTest.WeightedClusterTypedConfig (68 ms) +[ RUN ] PerFilterConfigsTest.WeightedClusterFallthroughConfig +[ OK ] PerFilterConfigsTest.WeightedClusterFallthroughConfig (68 ms) +[ RUN ] PerFilterConfigsTest.WeightedClusterFallthroughTypedConfig +[ OK ] PerFilterConfigsTest.WeightedClusterFallthroughTypedConfig (67 ms) +[----------] 11 tests from PerFilterConfigsTest (704 ms total) + +[----------] 8 tests from RouteMatchOverrideTest +[ RUN ] RouteMatchOverrideTest.VerifyAllMatchableRoutes +[ OK ] RouteMatchOverrideTest.VerifyAllMatchableRoutes (65 ms) +[ RUN ] RouteMatchOverrideTest.VerifyRouteOverrideStops +[ OK ] RouteMatchOverrideTest.VerifyRouteOverrideStops (64 ms) +[ RUN ] RouteMatchOverrideTest.StopWhenNoMoreRoutes +[ OK ] RouteMatchOverrideTest.StopWhenNoMoreRoutes (65 ms) +[ RUN ] RouteMatchOverrideTest.NullRouteOnNoRouteMatch +[ OK ] RouteMatchOverrideTest.NullRouteOnNoRouteMatch (81 ms) +[ RUN ] RouteMatchOverrideTest.NullRouteOnNoHostMatch +[ OK ] RouteMatchOverrideTest.NullRouteOnNoHostMatch (66 ms) +[ RUN ] RouteMatchOverrideTest.NullRouteOnNullXForwardedProto +[ OK ] RouteMatchOverrideTest.NullRouteOnNullXForwardedProto (66 ms) +[ RUN ] RouteMatchOverrideTest.NullRouteOnRequireTlsAll +[ OK ] RouteMatchOverrideTest.NullRouteOnRequireTlsAll (65 ms) +[ RUN ] RouteMatchOverrideTest.NullRouteOnRequireTlsInternal +[ OK ] RouteMatchOverrideTest.NullRouteOnRequireTlsInternal (65 ms) +[----------] 8 tests from RouteMatchOverrideTest (538 ms total) + +[----------] Global test environment tear-down +[==========] 165 tests from 14 test suites ran. (19322 ms total) +[ PASSED ] 165 tests. +==================== Test output for //test/extensions/filters/network/sni_dynamic_forward_proxy:proxy_filter_integration_test: +WARNING: Perftools heap leak checker is active -- Performance may suffer +[==========] Running 4 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 4 tests from IpVersions/SniDynamicProxyFilterIntegrationTest +[ RUN ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv4 +TestRandomGenerator running with seed 205585968 +[ OK ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv4 (765 ms) +[ RUN ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv6 +TestRandomGenerator running with seed 205585968 +[2020-08-03 21:33:40.808][44312][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/898/execroot/envoy/_tmp/282b4d28423b557fc72f2459645621cd/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address +terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address +[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000acdd +[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): +[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL +[2020-08-03 21:33:40.881][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x4267f3c] +[2020-08-03 21:33:40.881][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7f8f0f7748a0] +[2020-08-03 21:33:40.952][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x266b38e] +[2020-08-03 21:33:41.024][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x266adc9] +[2020-08-03 21:33:41.096][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x266d5d8] +[2020-08-03 21:33:41.168][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x266d50d] +[2020-08-03 21:33:41.239][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x266d4bd] +[2020-08-03 21:33:41.311][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x266d48d] +[2020-08-03 21:33:41.382][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x266c7ae] +[2020-08-03 21:33:41.453][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x25b1745] +[2020-08-03 21:33:41.525][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x25b1605] +[2020-08-03 21:33:41.596][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x513dce2] +[2020-08-03 21:33:41.668][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x513dcb5] +[2020-08-03 21:33:41.668][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7f8f0f7696db] +================================================================================ diff --git a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst index 70df6b283415a..4d7f8ed3872c6 100644 --- a/docs/root/configuration/advanced/well_known_dynamic_metadata.rst +++ b/docs/root/configuration/advanced/well_known_dynamic_metadata.rst @@ -47,4 +47,4 @@ The following Envoy filters emit shared dynamic metadata. The following filters consume shared dynamic metadata. -* Metadata Access Log Filter +* :ref:`Metadata Access Log Filter` diff --git a/docs/root/configuration/listeners/network_filters/rbac_filter.rst b/docs/root/configuration/listeners/network_filters/rbac_filter.rst index 4a01762bc57cc..68ae9f2172d46 100644 --- a/docs/root/configuration/listeners/network_filters/rbac_filter.rst +++ b/docs/root/configuration/listeners/network_filters/rbac_filter.rst @@ -42,4 +42,4 @@ The RBAC filter emits the following dynamic metadata. shadow_effective_policy_id, string, The effective shadow policy ID matching the action (if any). shadow_engine_result, string, The engine result for the shadow rules (i.e. either `allowed` or `denied`). - access_log_policy, boolean, Whether the request should be logged. This metadata is shared and set under the key namespace 'envoy.common' (See :ref:`Shared Dynamic Metadata`). + access_log_hint, boolean, Whether the request should be logged. This metadata is shared and set under the key namespace 'envoy.common' (See :ref:`Shared Dynamic Metadata`). diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index 01c1f3dd56a0e..4277daa7533cc 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -52,6 +52,7 @@ New Features * load balancer: added a :ref:`configuration` option to specify the active request bias used by the least request load balancer. * lua: added Lua APIs to access :ref:`SSL connection info ` object. * postgres network filter: :ref:`metadata ` is produced based on SQL query. +* rbac filter: added a log action to the :ref:`RBAC filter ` which sets dynamic metadata to inform access loggers whether to log. * router: added new :ref:`envoy-ratelimited` retry policy, which allows retrying envoy's own rate limited responses. diff --git a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto index 9b3fd0524868b..278e6857603fe 100644 --- a/generated_api_shadow/envoy/config/rbac/v3/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v3/rbac.proto @@ -82,40 +82,47 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match. + // All requests are allowed. LOG = 2; } - // The action to take if a policy matches. - // The request is allowed if and only if: + // The action to take if a policy matches. Every action either allows or denies a request, + // and can also carry out action-specific operations. // - // * `action` is "ALLOW" and at least one policy matches - // * `action` is "DENY" and none of the policies match - // * `action` is "LOG" + // Actions: + // + // * ALLOW: Allows the request if and only if there is a policy that matches + // the request. + // * DENY: Allows the request if and only if there are no policies that + // match the request. + // * LOG: Allows all requests. If at least one policy matches, the dynamic + // metadata key `access_log_hint` is set to the value `true` under the shared + // key namespace 'envoy.common'. If no policies match, it is set to `false`. + // Other actions do not modify this key. // - // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` - // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, - // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if -// and only if at least one of its permissions match the action taking place AND at least one of its -// principals match the downstream AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. +// A policy matches if and only if at least one of its permissions match the +// action taking place AND at least one of its principals match the downstream +// AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Policy"; - // Required. The set of permissions that define a role. Each permission is matched with OR - // semantics. To match all actions for this policy, a single Permission with the `any` field set - // to true should be used. + // Required. The set of permissions that define a role. Each permission is + // matched with OR semantics. To match all actions for this policy, a single + // Permission with the `any` field set to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on “action”. Each - // principal is matched with OR semantics. To match all downstreams for this policy, a single - // Principal with the `any` field set to true should be used. + // Required. The set of principals that are assigned/denied the role based on + // “action”. Each principal is matched with OR semantics. To match all + // downstreams for this policy, a single Principal with the `any` field set to + // true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; // An optional symbolic expression specifying an access control @@ -176,9 +183,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of `not_rule` would - // match, this permission would not match. Conversely, if the value of `not_rule` would not - // match, this permission would match. + // Negates matching the provided permission. For instance, if the value of + // `not_rule` would match, this permission would not match. Conversely, if + // the value of `not_rule` would not match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -191,7 +198,8 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name `, + // the :ref:`server name + // `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -204,13 +212,14 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream subject. +// Principal defines an identity or a group of identities for a downstream +// subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, - // each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. + // Depending on the context, each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v2.Principal.Set"; @@ -225,19 +234,21 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the - // certificate, otherwise the subject field is used. If unset, it applies to any user that is - // authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order + // is used from the certificate, otherwise the subject field is used. If + // unset, it applies to any user that is authenticated. type.matcher.v3.StringMatcher principal_name = 2; } oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the downstream. + // A set of identifiers that all must match in order to define the + // downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the downstream. + // A set of identifiers at least one must match in order to define the + // downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -252,21 +263,23 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is inferred - // from for example the x-forwarder-for header, proxy protocol, etc. + // :ref:`remote_ip ` is + // inferred from for example the x-forwarder-for header, proxy protocol, + // etc. core.v3.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip `. - // E.g, if the remote ip is inferred from for example the x-forwarder-for header, - // proxy protocol, etc. + // :ref:`direct_remote_ip + // `. E.g, if the + // remote ip is inferred from for example the x-forwarder-for header, proxy + // protocol, etc. core.v3.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only - // available for HTTP request. - // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` - // field if you want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP + // request. Only available for HTTP request. Note: the pseudo-header :path + // includes the query and fragment string. Use the `url_path` field if you + // want to match the URL path without the query and fragment string. route.v3.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -275,9 +288,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v3.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of `not_id` would match, - // this principal would not match. Conversely, if the value of `not_id` would not match, this - // principal would match. + // Negates matching the provided principal. For instance, if the value of + // `not_id` would match, this principal would not match. Conversely, if the + // value of `not_id` would not match, this principal would match. Principal not_id = 8; } } diff --git a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto index 8d2945ee2a757..7139dfaa1485d 100644 --- a/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto +++ b/generated_api_shadow/envoy/config/rbac/v4alpha/rbac.proto @@ -81,40 +81,47 @@ message RBAC { // access control. DENY = 1; - // The policies set the `access_log_hint` dynamic metadata key based on if requests match + // The policies set the `access_log_hint` dynamic metadata key based on if requests match. + // All requests are allowed. LOG = 2; } - // The action to take if a policy matches. - // The request is allowed if and only if: + // The action to take if a policy matches. Every action either allows or denies a request, + // and can also carry out action-specific operations. // - // * `action` is "ALLOW" and at least one policy matches - // * `action` is "DENY" and none of the policies match - // * `action` is "LOG" + // Actions: + // + // * ALLOW: Allows the request if and only if there is a policy that matches + // the request. + // * DENY: Allows the request if and only if there are no policies that + // match the request. + // * LOG: Allows all requests. If at least one policy matches, the dynamic + // metadata key `access_log_hint` is set to the value `true` under the shared + // key namespace 'envoy.common'. If no policies match, it is set to `false`. + // Other actions do not modify this key. // - // If the action is LOG and at least one policy matches, the dynamic metadata key `access_log_hint` - // is set to the value `true` under the shared key namespace 'envoy.common'. If no policies match, - // it is set to `false`. Other actions do not modify this key. Action action = 1; // Maps from policy name to policy. A match occurs when at least one policy matches the request. map policies = 2; } -// Policy specifies a role and the principals that are assigned/denied the role. A policy matches if -// and only if at least one of its permissions match the action taking place AND at least one of its -// principals match the downstream AND the condition is true if specified. +// Policy specifies a role and the principals that are assigned/denied the role. +// A policy matches if and only if at least one of its permissions match the +// action taking place AND at least one of its principals match the downstream +// AND the condition is true if specified. message Policy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Policy"; - // Required. The set of permissions that define a role. Each permission is matched with OR - // semantics. To match all actions for this policy, a single Permission with the `any` field set - // to true should be used. + // Required. The set of permissions that define a role. Each permission is + // matched with OR semantics. To match all actions for this policy, a single + // Permission with the `any` field set to true should be used. repeated Permission permissions = 1 [(validate.rules).repeated = {min_items: 1}]; - // Required. The set of principals that are assigned/denied the role based on “action”. Each - // principal is matched with OR semantics. To match all downstreams for this policy, a single - // Principal with the `any` field set to true should be used. + // Required. The set of principals that are assigned/denied the role based on + // “action”. Each principal is matched with OR semantics. To match all + // downstreams for this policy, a single Principal with the `any` field set to + // true should be used. repeated Principal principals = 2 [(validate.rules).repeated = {min_items: 1}]; oneof expression_specifier { @@ -175,9 +182,9 @@ message Permission { // Metadata that describes additional information about the action. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided permission. For instance, if the value of `not_rule` would - // match, this permission would not match. Conversely, if the value of `not_rule` would not - // match, this permission would match. + // Negates matching the provided permission. For instance, if the value of + // `not_rule` would match, this permission would not match. Conversely, if + // the value of `not_rule` would not match, this permission would match. Permission not_rule = 8; // The request server from the client's connection request. This is @@ -190,7 +197,8 @@ message Permission { // // * If the :ref:`TLS Inspector ` // filter is not added, and if a `FilterChainMatch` is not defined for - // the :ref:`server name `, + // the :ref:`server name + // `, // a TLS connection's requested SNI server name will be treated as if it // wasn't present. // @@ -203,13 +211,14 @@ message Permission { } } -// Principal defines an identity or a group of identities for a downstream subject. +// Principal defines an identity or a group of identities for a downstream +// subject. // [#next-free-field: 12] message Principal { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal"; - // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. Depending on the context, - // each are applied with the associated behavior. + // Used in the `and_ids` and `or_ids` fields in the `identifier` oneof. + // Depending on the context, each are applied with the associated behavior. message Set { option (udpa.annotations.versioning).previous_message_type = "envoy.config.rbac.v3.Principal.Set"; @@ -224,19 +233,21 @@ message Principal { reserved 1; - // The name of the principal. If set, The URI SAN or DNS SAN in that order is used from the - // certificate, otherwise the subject field is used. If unset, it applies to any user that is - // authenticated. + // The name of the principal. If set, The URI SAN or DNS SAN in that order + // is used from the certificate, otherwise the subject field is used. If + // unset, it applies to any user that is authenticated. type.matcher.v4alpha.StringMatcher principal_name = 2; } oneof identifier { option (validate.required) = true; - // A set of identifiers that all must match in order to define the downstream. + // A set of identifiers that all must match in order to define the + // downstream. Set and_ids = 1; - // A set of identifiers at least one must match in order to define the downstream. + // A set of identifiers at least one must match in order to define the + // downstream. Set or_ids = 2; // When any is set, it matches any downstream. @@ -251,21 +262,23 @@ message Principal { // A CIDR block that describes the downstream remote/origin address. // Note: This is always the physical peer even if the - // :ref:`remote_ip ` is inferred - // from for example the x-forwarder-for header, proxy protocol, etc. + // :ref:`remote_ip ` is + // inferred from for example the x-forwarder-for header, proxy protocol, + // etc. core.v4alpha.CidrRange direct_remote_ip = 10; // A CIDR block that describes the downstream remote/origin address. // Note: This may not be the physical peer and could be different from the - // :ref:`direct_remote_ip `. - // E.g, if the remote ip is inferred from for example the x-forwarder-for header, - // proxy protocol, etc. + // :ref:`direct_remote_ip + // `. E.g, if the + // remote ip is inferred from for example the x-forwarder-for header, proxy + // protocol, etc. core.v4alpha.CidrRange remote_ip = 11; - // A header (or pseudo-header such as :path or :method) on the incoming HTTP request. Only - // available for HTTP request. - // Note: the pseudo-header :path includes the query and fragment string. Use the `url_path` - // field if you want to match the URL path without the query and fragment string. + // A header (or pseudo-header such as :path or :method) on the incoming HTTP + // request. Only available for HTTP request. Note: the pseudo-header :path + // includes the query and fragment string. Use the `url_path` field if you + // want to match the URL path without the query and fragment string. route.v4alpha.HeaderMatcher header = 6; // A URL path on the incoming HTTP request. Only available for HTTP. @@ -274,9 +287,9 @@ message Principal { // Metadata that describes additional information about the principal. type.matcher.v4alpha.MetadataMatcher metadata = 7; - // Negates matching the provided principal. For instance, if the value of `not_id` would match, - // this principal would not match. Conversely, if the value of `not_id` would not match, this - // principal would match. + // Negates matching the provided principal. For instance, if the value of + // `not_id` would match, this principal would not match. Conversely, if the + // value of `not_id` would not match, this principal would match. Principal not_id = 8; } } diff --git a/source/extensions/filters/common/rbac/engine.h b/source/extensions/filters/common/rbac/engine.h index 8bf5920cf3d6b..04e82c95023d8 100644 --- a/source/extensions/filters/common/rbac/engine.h +++ b/source/extensions/filters/common/rbac/engine.h @@ -18,64 +18,32 @@ class RoleBasedAccessControlEngine { public: virtual ~RoleBasedAccessControlEngine() = default; - enum class LogDecision { Yes, No, Undecided }; - - /** - * Returns whether or not the current action is permitted. - * - * @param connection the downstream connection used to identify the action/principal. - * @param headers the headers of the incoming request used to identify the action/principal. An - * empty map should be used if there are no headers available. - * @param info the per-request or per-connection stream info with additional information - * about the action/principal. - * @param effective_policy_id it will be filled by the matching policy's ID, - * which is used to identity the source of the allow/deny. - */ - virtual bool allowed(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const PURE; - - /** - * Returns whether or not the current action is permitted. - * - * @param connection the downstream connection used to identify the action/principal. - * @param info the per-request or per-connection stream info with additional information - * about the action/principal. - * @param effective_policy_id it will be filled by the matching policy's ID, - * which is used to identity the source of the allow/deny. - */ - virtual bool allowed(const Network::Connection& connection, const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const PURE; - /** - * Returns whether or not the current action should be logged. + * Handles action-specific operations and returns whether or not the request is permitted. * * @param connection the downstream connection used to identify the action/principal. * @param headers the headers of the incoming request used to identify the action/principal. An * empty map should be used if there are no headers available. * @param info the per-request or per-connection stream info with additional information - * about the action/principal. + * about the action/principal. Can be modified by an Action. * @param effective_policy_id it will be filled by the matching policy's ID, * which is used to identity the source of the allow/deny. */ - virtual LogDecision shouldLog(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const PURE; + virtual bool handleAction(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, + StreamInfo::StreamInfo& info, std::string* effective_policy_id) PURE; /** - * Returns whether or not the current action should be logged. + * Handles action-specific operations and returns whether or not the request is permitted. * * @param connection the downstream connection used to identify the action/principal. * @param info the per-request or per-connection stream info with additional information - * about the action/principal. + * about the action/principal. Can be modified by an Action. * @param effective_policy_id it will be filled by the matching policy's ID, * which is used to identity the source of the allow/deny. */ - virtual LogDecision shouldLog(const Network::Connection& connection, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const PURE; + virtual bool handleAction(const Network::Connection& connection, StreamInfo::StreamInfo& info, + std::string* effective_policy_id) PURE; }; } // namespace RBAC diff --git a/source/extensions/filters/common/rbac/engine_impl.cc b/source/extensions/filters/common/rbac/engine_impl.cc index fb01e8ccc084b..ce9493e26896c 100644 --- a/source/extensions/filters/common/rbac/engine_impl.cc +++ b/source/extensions/filters/common/rbac/engine_impl.cc @@ -10,12 +10,9 @@ namespace Filters { namespace Common { namespace RBAC { -using LogDecision = RoleBasedAccessControlEngine::LogDecision; - RoleBasedAccessControlEngineImpl::RoleBasedAccessControlEngineImpl( - const envoy::config::rbac::v3::RBAC& rules) - : allowed_if_matched_(rules.action() == envoy::config::rbac::v3::RBAC::ALLOW), - action_log_(rules.action() == envoy::config::rbac::v3::RBAC::LOG) { + const envoy::config::rbac::v3::RBAC& rules, const EnforcementMode mode) + : action_(rules.action()), mode_(mode) { // guard expression builder by presence of a condition in policies for (const auto& policy : rules.policies()) { if (policy.second.has_condition()) { @@ -29,48 +26,45 @@ RoleBasedAccessControlEngineImpl::RoleBasedAccessControlEngineImpl( } } -bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const { - // Automatically allow if LOG action - if (action_log_) { - return true; - } - - bool matched = false; +bool RoleBasedAccessControlEngineImpl::handleAction(const Network::Connection& connection, + StreamInfo::StreamInfo& info, + std::string* effective_policy_id) { + return handleAction(connection, *Http::StaticEmptyHeaders::get().request_headers, info, + effective_policy_id); +} - for (const auto& policy : policies_) { - if (policy.second->matches(connection, headers, info)) { - matched = true; - if (effective_policy_id != nullptr) { - *effective_policy_id = policy.first; - } - break; +bool RoleBasedAccessControlEngineImpl::handleAction(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, + StreamInfo::StreamInfo& info, + std::string* effective_policy_id) { + bool matched = checkPolicyMatch(connection, info, headers, effective_policy_id); + + switch (action_) { + case envoy::config::rbac::v3::RBAC::ALLOW: + return matched; + case envoy::config::rbac::v3::RBAC::DENY: + return !matched; + case envoy::config::rbac::v3::RBAC::LOG: { + // If not shadow enforcement, set shared log metadata + if (mode_ != EnforcementMode::Shadow) { + ProtobufWkt::Struct log_metadata; + auto& log_fields = *log_metadata.mutable_fields(); + log_fields[DynamicMetadataKeysSingleton::get().AccessLogKey].set_bool_value(matched); + info.setDynamicMetadata(DynamicMetadataKeysSingleton::get().CommonNamespace, log_metadata); } - } - // only allowed if: - // - matched and ALLOW action - // - not matched and DENY action - // - LOG action - return matched == allowed_if_matched_; -} + return true; + } + default: + return true; + } -bool RoleBasedAccessControlEngineImpl::allowed(const Network::Connection& connection, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const { - return allowed(connection, *Http::StaticEmptyHeaders::get().request_headers, info, - effective_policy_id); + return true; } -LogDecision RoleBasedAccessControlEngineImpl::shouldLog( - const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const { - if (!action_log_) { - return LogDecision::Undecided; - } - +bool RoleBasedAccessControlEngineImpl::checkPolicyMatch( + const Network::Connection& connection, const StreamInfo::StreamInfo& info, + const Envoy::Http::RequestHeaderMap& headers, std::string* effective_policy_id) const { bool matched = false; for (const auto& policy : policies_) { @@ -83,15 +77,7 @@ LogDecision RoleBasedAccessControlEngineImpl::shouldLog( } } - // log if action is LOG and a policy matches - return matched ? LogDecision::Yes : LogDecision::No; -} - -LogDecision RoleBasedAccessControlEngineImpl::shouldLog(const Network::Connection& connection, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const { - return shouldLog(connection, *Http::StaticEmptyHeaders::get().request_headers, info, - effective_policy_id); + return matched; } } // namespace RBAC diff --git a/source/extensions/filters/common/rbac/engine_impl.h b/source/extensions/filters/common/rbac/engine_impl.h index 87229a51a4e13..4294bc8777547 100644 --- a/source/extensions/filters/common/rbac/engine_impl.h +++ b/source/extensions/filters/common/rbac/engine_impl.h @@ -11,27 +11,40 @@ namespace Filters { namespace Common { namespace RBAC { -class RoleBasedAccessControlEngineImpl : public RoleBasedAccessControlEngine, NonCopyable { +class DynamicMetadataKeys { public: - RoleBasedAccessControlEngineImpl(const envoy::config::rbac::v3::RBAC& rules); + const std::string ShadowEffectivePolicyIdField{"shadow_effective_policy_id"}; + const std::string ShadowEngineResultField{"shadow_engine_result"}; + const std::string EngineResultAllowed{"allowed"}; + const std::string EngineResultDenied{"denied"}; + const std::string AccessLogKey{"access_log_hint"}; + const std::string CommonNamespace{"envoy.common"}; +}; - bool allowed(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, std::string* effective_policy_id) const override; +using DynamicMetadataKeysSingleton = ConstSingleton; - bool allowed(const Network::Connection& connection, const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const override; +enum class EnforcementMode { Enforced, Shadow }; - LogDecision shouldLog(const Network::Connection& connection, - const Envoy::Http::RequestHeaderMap& headers, - const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const override; +class RoleBasedAccessControlEngineImpl : public RoleBasedAccessControlEngine, NonCopyable { +public: + RoleBasedAccessControlEngineImpl(const envoy::config::rbac::v3::RBAC& rules, + const EnforcementMode mode = EnforcementMode::Enforced); + + bool handleAction(const Network::Connection& connection, + const Envoy::Http::RequestHeaderMap& headers, StreamInfo::StreamInfo& info, + std::string* effective_policy_id) override; - LogDecision shouldLog(const Network::Connection& connection, const StreamInfo::StreamInfo& info, - std::string* effective_policy_id) const override; + bool handleAction(const Network::Connection& connection, StreamInfo::StreamInfo& info, + std::string* effective_policy_id) override; private: - const bool allowed_if_matched_; - const bool action_log_; + // Checks whether the request matches any policies + bool checkPolicyMatch(const Network::Connection& connection, const StreamInfo::StreamInfo& info, + const Envoy::Http::RequestHeaderMap& headers, + std::string* effective_policy_id) const; + + const envoy::config::rbac::v3::RBAC::Action action_; + const EnforcementMode mode_; std::map> policies_; diff --git a/source/extensions/filters/common/rbac/utility.h b/source/extensions/filters/common/rbac/utility.h index a3848deb62469..04635eb37411e 100644 --- a/source/extensions/filters/common/rbac/utility.h +++ b/source/extensions/filters/common/rbac/utility.h @@ -12,18 +12,6 @@ namespace Filters { namespace Common { namespace RBAC { -class DynamicMetadataKeys { -public: - const std::string ShadowEffectivePolicyIdField{"shadow_effective_policy_id"}; - const std::string ShadowEngineResultField{"shadow_engine_result"}; - const std::string EngineResultAllowed{"allowed"}; - const std::string EngineResultDenied{"denied"}; - const std::string AccessLogKey{"access_log_hint"}; - const std::string CommonNamespace{"envoy.common"}; -}; - -using DynamicMetadataKeysSingleton = ConstSingleton; - /** * All stats for the RBAC filter. @see stats_macros.h */ @@ -31,9 +19,7 @@ using DynamicMetadataKeysSingleton = ConstSingleton; COUNTER(allowed) \ COUNTER(denied) \ COUNTER(shadow_allowed) \ - COUNTER(shadow_denied) \ - COUNTER(logged) \ - COUNTER(not_logged) + COUNTER(shadow_denied) /** * Wrapper struct for RBAC filter stats. @see stats_macros.h @@ -44,19 +30,18 @@ struct RoleBasedAccessControlFilterStats { RoleBasedAccessControlFilterStats generateStats(const std::string& prefix, Stats::Scope& scope); -enum class EnforcementMode { Enforced, Shadow }; - template std::unique_ptr createEngine(const ConfigType& config) { - return config.has_rules() ? std::make_unique(config.rules()) + return config.has_rules() ? std::make_unique( + config.rules(), EnforcementMode::Enforced) : nullptr; } template std::unique_ptr createShadowEngine(const ConfigType& config) { - return config.has_shadow_rules() - ? std::make_unique(config.shadow_rules()) - : nullptr; + return config.has_shadow_rules() ? std::make_unique( + config.shadow_rules(), EnforcementMode::Shadow) + : nullptr; } } // namespace RBAC diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index 0c187f5cf541d..0c5b96edf3894 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -20,16 +20,24 @@ struct RcDetailsValues { }; using RcDetails = ConstSingleton; -using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; +// using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::http::rbac::v3::RBAC& proto_config, const std::string& stats_prefix, Stats::Scope& scope) - : stats_(Filters::Common::RBAC::generateStats(stats_prefix, scope)), - engine_(Filters::Common::RBAC::createEngine(proto_config)), - shadow_engine_(Filters::Common::RBAC::createShadowEngine(proto_config)) {} + : stats_(Filters::Common::RBAC::generateStats(stats_prefix, scope)) { + engine_ = proto_config.has_rules() + ? std::make_unique( + proto_config.rules(), Filters::Common::RBAC::EnforcementMode::Enforced) + : nullptr; + shadow_engine_ = + proto_config.has_shadow_rules() + ? std::make_unique( + proto_config.shadow_rules(), Filters::Common::RBAC::EnforcementMode::Shadow) + : nullptr; +} -const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* +Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* RoleBasedAccessControlFilterConfig::engine(const Router::RouteConstSharedPtr route, Filters::Common::RBAC::EnforcementMode mode) const { if (!route || !route->routeEntry()) { @@ -82,8 +90,8 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo if (shadow_engine != nullptr) { std::string shadow_resp_code = Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().EngineResultAllowed; - if (shadow_engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), - &effective_policy_id)) { + if (shadow_engine->handleAction(*callbacks_->connection(), headers, callbacks_->streamInfo(), + &effective_policy_id)) { ENVOY_LOG(debug, "shadow allowed"); config_->stats().shadow_allowed_.inc(); } else { @@ -110,28 +118,9 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo const auto engine = config_->engine(callbacks_->route(), Filters::Common::RBAC::EnforcementMode::Enforced); if (engine != nullptr) { - // Check log decision - LogDecision log_dec = - engine->shouldLog(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr); - if (log_dec != LogDecision::Undecided) { - ProtobufWkt::Struct log_metadata; - auto& log_fields = *log_metadata.mutable_fields(); - log_fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey] - .set_bool_value(log_dec == LogDecision::Yes); - callbacks_->streamInfo().setDynamicMetadata( - Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, log_metadata); - - if (log_dec == LogDecision::Yes) { - ENVOY_LOG(debug, "request logged"); - config_->stats().logged_.inc(); - } else { - ENVOY_LOG(debug, "request not logged"); - config_->stats().not_logged_.inc(); - } - } - - // Check authorization decision - if (engine->allowed(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr)) { + // Check authorization decision and do Action operations + if (engine->handleAction(*callbacks_->connection(), headers, callbacks_->streamInfo(), + nullptr)) { ENVOY_LOG(debug, "enforced allowed"); config_->stats().allowed_.inc(); return Http::FilterHeadersStatus::Continue; diff --git a/source/extensions/filters/http/rbac/rbac_filter.h b/source/extensions/filters/http/rbac/rbac_filter.h index fe7369e34e6be..7434dcd925cd0 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.h +++ b/source/extensions/filters/http/rbac/rbac_filter.h @@ -22,7 +22,7 @@ class RoleBasedAccessControlRouteSpecificFilterConfig : public Router::RouteSpec RoleBasedAccessControlRouteSpecificFilterConfig( const envoy::extensions::filters::http::rbac::v3::RBACPerRoute& per_route_config); - const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); @@ -44,12 +44,12 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats& stats() { return stats_; } - const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(const Router::RouteConstSharedPtr route, Filters::Common::RBAC::EnforcementMode mode) const; private: - const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); @@ -57,8 +57,8 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats stats_; - std::unique_ptr engine_; - std::unique_ptr shadow_engine_; + std::unique_ptr engine_; + std::unique_ptr shadow_engine_; }; using RoleBasedAccessControlFilterConfigSharedPtr = diff --git a/source/extensions/filters/network/rbac/rbac_filter.cc b/source/extensions/filters/network/rbac/rbac_filter.cc index 6a94212fe15fa..db5a8ec075cd3 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.cc +++ b/source/extensions/filters/network/rbac/rbac_filter.cc @@ -13,14 +13,20 @@ namespace Extensions { namespace NetworkFilters { namespace RBACFilter { -using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; - RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::network::rbac::v3::RBAC& proto_config, Stats::Scope& scope) : stats_(Filters::Common::RBAC::generateStats(proto_config.stat_prefix(), scope)), - engine_(Filters::Common::RBAC::createEngine(proto_config)), - shadow_engine_(Filters::Common::RBAC::createShadowEngine(proto_config)), - enforcement_type_(proto_config.enforcement_type()) {} + enforcement_type_(proto_config.enforcement_type()) { + engine_ = proto_config.has_rules() + ? std::make_unique( + proto_config.rules(), Filters::Common::RBAC::EnforcementMode::Enforced) + : nullptr; + shadow_engine_ = + proto_config.has_shadow_rules() + ? std::make_unique( + proto_config.shadow_rules(), Filters::Common::RBAC::EnforcementMode::Shadow) + : nullptr; +} Network::FilterStatus RoleBasedAccessControlFilter::onData(Buffer::Instance&, bool) { ENVOY_LOG(debug, @@ -84,36 +90,14 @@ void RoleBasedAccessControlFilter::setDynamicMetadata(std::string shadow_engine_ EngineResult RoleBasedAccessControlFilter::checkEngine(Filters::Common::RBAC::EnforcementMode mode) { - const auto engine = config_->engine(mode); + auto engine = config_->engine(mode); if (engine != nullptr) { std::string effective_policy_id; - if (mode == Filters::Common::RBAC::EnforcementMode::Enforced) { - // Check log decision - LogDecision log_dec = engine->shouldLog( - callbacks_->connection(), callbacks_->connection().streamInfo(), &effective_policy_id); - if (log_dec != LogDecision::Undecided) { - ProtobufWkt::Struct log_metadata; - auto& fields = *log_metadata.mutable_fields(); - fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey] - .set_bool_value(log_dec == LogDecision::Yes); - callbacks_->connection().streamInfo().setDynamicMetadata( - Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace, - log_metadata); - - if (log_dec == LogDecision::Yes) { - ENVOY_LOG(debug, "request logged"); - config_->stats().logged_.inc(); - } else { - ENVOY_LOG(debug, "request not logged"); - config_->stats().not_logged_.inc(); - } - } - } - // Check authorization decision - if (engine->allowed(callbacks_->connection(), callbacks_->connection().streamInfo(), - &effective_policy_id)) { + // Check authorization decision and do Action operations + if (engine->handleAction(callbacks_->connection(), callbacks_->connection().streamInfo(), + &effective_policy_id)) { if (mode == Filters::Common::RBAC::EnforcementMode::Shadow) { ENVOY_LOG(debug, "shadow allowed"); config_->stats().shadow_allowed_.inc(); diff --git a/source/extensions/filters/network/rbac/rbac_filter.h b/source/extensions/filters/network/rbac/rbac_filter.h index 19c9360e21342..38530d4e2e600 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.h +++ b/source/extensions/filters/network/rbac/rbac_filter.h @@ -27,7 +27,7 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats& stats() { return stats_; } - const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index 47b48362a80b4..7a8f192fdb608 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -25,30 +25,32 @@ namespace RBAC { namespace { void checkEngine( - const RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, + RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, StreamInfo::StreamInfo& info, const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), - const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl(), - const StreamInfo::StreamInfo& info = NiceMock()) { - EXPECT_EQ(expected, engine.allowed(connection, headers, info, nullptr)); + const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { + + bool engineRes = engine.handleAction(connection, headers, info, nullptr); + EXPECT_EQ(expected, engineRes); } -// Used for testing shouldLog() function tests -void checkEngineLog( - const RBAC::RoleBasedAccessControlEngineImpl& engine, - const RoleBasedAccessControlEngine::LogDecision expected, +void checkEngine( + RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), - const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl(), - const StreamInfo::StreamInfo& info = NiceMock()) { - EXPECT_EQ(expected, engine.shouldLog(connection, headers, info, nullptr)); + const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { + + NiceMock empty_info; + checkEngine(engine, expected, empty_info, connection, headers); } TEST(RoleBasedAccessControlEngineImpl, Disabled) { envoy::config::rbac::v3::RBAC rbac; rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); - checkEngine(RBAC::RoleBasedAccessControlEngineImpl(rbac), false); + RBAC::RoleBasedAccessControlEngineImpl engine_allow(rbac); + checkEngine(engine_allow, false); rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); - checkEngine(RBAC::RoleBasedAccessControlEngineImpl(rbac), true); + RBAC::RoleBasedAccessControlEngineImpl engine_deny(rbac); + checkEngine(engine_deny, true); } // Test various invalid policies to validate the fix for @@ -153,11 +155,11 @@ TEST(RoleBasedAccessControlEngineImpl, AllowedAllowlist) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, true, conn, headers, info); + checkEngine(engine, true, info, conn, headers); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, false, conn, headers, info); + checkEngine(engine, false, info, conn, headers); } TEST(RoleBasedAccessControlEngineImpl, DeniedDenylist) { @@ -176,11 +178,11 @@ TEST(RoleBasedAccessControlEngineImpl, DeniedDenylist) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, false, conn, headers, info); + checkEngine(engine, false, info, conn, headers); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, true, conn, headers, info); + checkEngine(engine, true, info, conn, headers); } TEST(RoleBasedAccessControlEngineImpl, BasicCondition) { @@ -240,10 +242,6 @@ TEST(RoleBasedAccessControlEngineImpl, MistypedCondition) { (*rbac.mutable_policies())["foo"] = policy; RBAC::RoleBasedAccessControlEngineImpl engine(rbac); checkEngine(engine, false); - - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No); } TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { @@ -269,11 +267,6 @@ TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { (*rbac.mutable_policies())["foo"] = policy; RBAC::RoleBasedAccessControlEngineImpl engine(rbac); checkEngine(engine, false, Envoy::Network::MockConnection()); - - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, - Envoy::Network::MockConnection()); } TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { @@ -310,11 +303,6 @@ TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { headers.setReference(key, value); checkEngine(engine, true, Envoy::Network::MockConnection(), headers); - - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, - Envoy::Network::MockConnection(), headers); } TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { @@ -359,12 +347,7 @@ TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { Protobuf::MapPair("other", label)); EXPECT_CALL(Const(info), dynamicMetadata()).WillRepeatedly(ReturnRef(metadata)); - checkEngine(engine, true, Envoy::Network::MockConnection(), headers, info); - - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::Yes, - Envoy::Network::MockConnection(), headers, info); + checkEngine(engine, true, info, Envoy::Network::MockConnection(), headers); } TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { @@ -387,90 +370,8 @@ TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - EXPECT_CALL(Const(info), downstreamLocalAddress()).Times(2).WillRepeatedly(ReturnRef(addr)); - checkEngine(engine, false, conn, headers, info); - - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - RBAC::RoleBasedAccessControlEngineImpl engine_log(rbac); - checkEngineLog(engine_log, RBAC::RoleBasedAccessControlEngine::LogDecision::No, conn, headers, - info); -} - -// Log tests tests -TEST(RoleBasedAccessControlEngineImpl, DisabledLog) { - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - checkEngineLog(RBAC::RoleBasedAccessControlEngineImpl(rbac), - RBAC::RoleBasedAccessControlEngine::LogDecision::No); -} - -TEST(RoleBasedAccessControlEngineImpl, LogIfMatched) { - envoy::config::rbac::v3::Policy policy; - policy.add_permissions()->set_destination_port(123); - policy.add_principals()->set_any(true); - - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - (*rbac.mutable_policies())["foo"] = policy; - RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - - Envoy::Network::MockConnection conn; - Envoy::Http::TestRequestHeaderMapImpl headers; - NiceMock info; - Envoy::Network::Address::InstanceConstSharedPtr addr = - Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::Yes, conn, headers, info); - - addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, RoleBasedAccessControlEngine::LogDecision::No, conn, headers, info); -} - -TEST(RoleBasedAccessControlEngineImpl, LogAllowUndecided) { - envoy::config::rbac::v3::Policy policy; - policy.add_permissions()->set_destination_port(123); - policy.add_principals()->set_any(true); - - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); - (*rbac.mutable_policies())["foo"] = policy; - RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - - Envoy::Network::MockConnection conn; - Envoy::Http::TestRequestHeaderMapImpl headers; - NiceMock info; - Envoy::Network::Address::InstanceConstSharedPtr addr = - Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, - info); - - addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, - info); -} - -TEST(RoleBasedAccessControlEngineImpl, LogDenyUndecided) { - envoy::config::rbac::v3::Policy policy; - policy.add_permissions()->set_destination_port(123); - policy.add_principals()->set_any(true); - - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); - (*rbac.mutable_policies())["foo"] = policy; - RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - - Envoy::Network::MockConnection conn; - Envoy::Http::TestRequestHeaderMapImpl headers; - NiceMock info; - Envoy::Network::Address::InstanceConstSharedPtr addr = - Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, - info); - - addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngineLog(engine, RBAC::RoleBasedAccessControlEngine::LogDecision::Undecided, conn, headers, - info); + EXPECT_CALL(Const(info), downstreamLocalAddress()).Times(1).WillRepeatedly(ReturnRef(addr)); + checkEngine(engine, false, info, conn, headers); } TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { @@ -488,10 +389,10 @@ TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { NiceMock info; Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngine(engine, true, conn, headers, info); + checkEngine(engine, true, info, conn, headers); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngine(engine, true, conn, headers, info); + checkEngine(engine, true, info, conn, headers); } } // namespace diff --git a/test/extensions/filters/common/rbac/mocks.h b/test/extensions/filters/common/rbac/mocks.h index fda95244c8933..c597bbd0ee4b4 100644 --- a/test/extensions/filters/common/rbac/mocks.h +++ b/test/extensions/filters/common/rbac/mocks.h @@ -14,18 +14,19 @@ namespace RBAC { class MockEngine : public RoleBasedAccessControlEngineImpl { public: - MockEngine(const envoy::config::rbac::v3::RBAC& rules) - : RoleBasedAccessControlEngineImpl(rules){}; - - MOCK_METHOD(bool, allowed, - (const Envoy::Network::Connection&, const Envoy::Http::RequestHeaderMap&, - const StreamInfo::StreamInfo&, std::string* effective_policy_id), - (const)); - - MOCK_METHOD(bool, allowed, - (const Envoy::Network::Connection&, const StreamInfo::StreamInfo&, - std::string* effective_policy_id), - (const)); + MockEngine(const envoy::config::rbac::v3::RBAC& rules, + const EnforcementMode mode = EnforcementMode::Shadow) + : RoleBasedAccessControlEngineImpl(rules, mode){}; + + // MOCK_METHOD(bool, allowed, + // (const Envoy::Network::Connection&, const Envoy::Http::RequestHeaderMap&, + // const StreamInfo::StreamInfo&, std::string* effective_policy_id), + // (const)); + + // MOCK_METHOD(bool, allowed, + // (const Envoy::Network::Connection&, const StreamInfo::StreamInfo&, + // std::string* effective_policy_id), + // (const)); }; } // namespace RBAC diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index 6a3da375b6768..873121d741001 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -145,7 +145,11 @@ TEST_F(RoleBasedAccessControlFilterTest, RequestedServerName) { // Check Log setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); - checkAccessLogMetadata(true); + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); + EXPECT_EQ(true, filter_meta.fields() + .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) + .bool_value()); } TEST_F(RoleBasedAccessControlFilterTest, Path) { @@ -170,7 +174,11 @@ TEST_F(RoleBasedAccessControlFilterTest, Path) { // Check Log setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers, false)); - checkAccessLogMetadata(false); + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); + EXPECT_EQ(false, filter_meta.fields() + .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) + .bool_value()); } TEST_F(RoleBasedAccessControlFilterTest, Denied) { @@ -195,22 +203,22 @@ TEST_F(RoleBasedAccessControlFilterTest, Denied) { EXPECT_EQ("rbac_access_denied", callbacks_.details_); } -TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { - setDestinationPort(456); +// TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { +// setDestinationPort(456); - envoy::extensions::filters::http::rbac::v3::RBACPerRoute route_config; - route_config.mutable_rbac()->mutable_rules()->set_action(envoy::config::rbac::v3::RBAC::DENY); - NiceMock engine{route_config.rbac().rules()}; - NiceMock per_route_config_{route_config}; +// envoy::extensions::filters::http::rbac::v3::RBACPerRoute route_config; +// route_config.mutable_rbac()->mutable_rules()->set_action(envoy::config::rbac::v3::RBAC::DENY); +// NiceMock engine{route_config.rbac().rules()}; +// NiceMock per_route_config_{route_config}; - EXPECT_CALL(engine, allowed(_, _, _, _)).WillRepeatedly(Return(true)); - EXPECT_CALL(per_route_config_, engine()).WillRepeatedly(ReturnRef(engine)); +// // EXPECT_CALL(engine, allowed(_, _, _, _)).WillRepeatedly(Return(true)); +// EXPECT_CALL(per_route_config_, engine()).WillRepeatedly(ReturnRef(engine)); - EXPECT_CALL(callbacks_.route_->route_entry_, perFilterConfig(HttpFilterNames::get().Rbac)) - .WillRepeatedly(Return(&per_route_config_)); +// EXPECT_CALL(callbacks_.route_->route_entry_, perFilterConfig(HttpFilterNames::get().Rbac)) +// .WillRepeatedly(Return(&per_route_config_)); - EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, true)); -} +// EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, true)); +// } // Log Tests TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { @@ -221,9 +229,6 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); - EXPECT_EQ(1U, log_config_->stats().logged_.value()); - EXPECT_EQ(0U, log_config_->stats().not_logged_.value()); - Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); @@ -239,9 +244,6 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { EXPECT_EQ(1U, log_config_->stats().allowed_.value()); EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); - EXPECT_EQ(0U, log_config_->stats().logged_.value()); - EXPECT_EQ(1U, log_config_->stats().not_logged_.value()); - Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); @@ -254,8 +256,6 @@ TEST_F(RoleBasedAccessControlFilterTest, AllowNoChangeLog) { setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); - EXPECT_EQ(0U, config_->stats().logged_.value()); - EXPECT_EQ(0U, config_->stats().not_logged_.value()); // Check that Allow action does not set access log metadata EXPECT_EQ(req_info_.dynamicMetadata().filter_metadata().end(), diff --git a/test/extensions/filters/network/rbac/filter_test.cc b/test/extensions/filters/network/rbac/filter_test.cc index ae29c1667c089..fe042854baa7a 100644 --- a/test/extensions/filters/network/rbac/filter_test.cc +++ b/test/extensions/filters/network/rbac/filter_test.cc @@ -206,9 +206,6 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldLog) { EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - EXPECT_EQ(1U, config_->stats().logged_.value()); - EXPECT_EQ(0U, config_->stats().not_logged_.value()); - checkAccessLogMetadata(true); } @@ -224,9 +221,6 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, ShouldNotLog) { EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - EXPECT_EQ(0U, config_->stats().logged_.value()); - EXPECT_EQ(1U, config_->stats().not_logged_.value()); - checkAccessLogMetadata(false); } @@ -235,8 +229,6 @@ TEST_F(RoleBasedAccessControlNetworkFilterTest, AllowNoChangeLog) { setMetadata(); EXPECT_EQ(Network::FilterStatus::Continue, filter_->onData(data_, false)); - EXPECT_EQ(0U, config_->stats().logged_.value()); - EXPECT_EQ(0U, config_->stats().not_logged_.value()); // Check that Allow action does not set access log metadata EXPECT_EQ(stream_info_.dynamicMetadata().filter_metadata().end(), From c74d5bd27e6a31d5ca11965cd3bd9a7d337193bf Mon Sep 17 00:00:00 2001 From: davidraskin Date: Wed, 5 Aug 2020 05:17:41 +0000 Subject: [PATCH 34/39] Add tests to engine + merge Signed-off-by: davidraskin --- bazel.output.txt | 516 ------------------ .../extensions/filters/common/rbac/engine.h | 4 +- .../filters/common/rbac/engine_impl.cc | 4 +- .../filters/common/rbac/engine_impl.h | 4 +- .../filters/http/rbac/rbac_filter.cc | 19 +- .../filters/http/rbac/rbac_filter.h | 10 +- .../filters/network/rbac/rbac_filter.cc | 17 +- .../filters/network/rbac/rbac_filter.h | 2 +- .../filters/common/rbac/engine_impl_test.cc | 112 ++++ test/extensions/filters/common/rbac/mocks.h | 18 +- .../filters/http/rbac/rbac_filter_test.cc | 24 +- 11 files changed, 154 insertions(+), 576 deletions(-) delete mode 100644 bazel.output.txt diff --git a/bazel.output.txt b/bazel.output.txt deleted file mode 100644 index f46e9f71acafd..0000000000000 --- a/bazel.output.txt +++ /dev/null @@ -1,516 +0,0 @@ -==================== Test output for //test/extensions/filters/http/grpc_http1_reverse_bridge:reverse_bridge_integration_test: -WARNING: Perftools heap leak checker is active -- Performance may suffer -[==========] Running 4 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 4 tests from IpVersions/ReverseBridgeIntegrationTest -[ RUN ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv4 -[ OK ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv4 (860 ms) -[ RUN ] IpVersions/ReverseBridgeIntegrationTest.DisabledRoute/IPv6 -[2020-08-03 21:22:42.230][35831][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/339/execroot/envoy/_tmp/34b195ec3fd9b4e4f43d020a8e761e79/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address -terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address -[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc224300008bbb -[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): -[2020-08-03 21:22:42.230][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL -[2020-08-03 21:22:42.302][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x41543bc] -[2020-08-03 21:22:42.302][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7fca75ef08a0] -[2020-08-03 21:22:42.372][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x252214e] -[2020-08-03 21:22:42.442][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x2521b89] -[2020-08-03 21:22:42.512][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x2524398] -[2020-08-03 21:22:42.583][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x25242cd] -[2020-08-03 21:22:42.655][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x252427d] -[2020-08-03 21:22:42.724][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x252424d] -[2020-08-03 21:22:42.793][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x252356e] -[2020-08-03 21:22:42.864][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x245e3d5] -[2020-08-03 21:22:42.934][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x245e295] -[2020-08-03 21:22:43.005][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5028a82] -[2020-08-03 21:22:43.075][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x5028a55] -[2020-08-03 21:22:43.075][35831][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7fca75ee56db] -================================================================================ -==================== Test output for //test/server/admin:logs_handler_test: -WARNING: Perftools heap leak checker is active -- Performance may suffer -[==========] Running 2 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 2 tests from IpVersions/AdminInstanceTest -[ RUN ] IpVersions/AdminInstanceTest.ReopenLogs/IPv4 -TestRandomGenerator running with seed 2096517680 -[ OK ] IpVersions/AdminInstanceTest.ReopenLogs/IPv4 (395 ms) -[ RUN ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6 -TestRandomGenerator running with seed 2096517680 -unknown file: Failure -C++ exception with description "cannot bind '[::1]:0': Cannot assign requested address" thrown in the test fixture's constructor. -[ FAILED ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6, where GetParam() = 4-byte object <01-00 00-00> (319 ms) -[----------] 2 tests from IpVersions/AdminInstanceTest (714 ms total) - -[----------] Global test environment tear-down -[==========] 2 tests from 1 test suite ran. (714 ms total) -[ PASSED ] 1 test. -[ FAILED ] 1 test, listed below: -[ FAILED ] IpVersions/AdminInstanceTest.ReopenLogs/IPv6, where GetParam() = 4-byte object <01-00 00-00> - - 1 FAILED TEST -Have memory regions w/o callers: might report false leaks -No leaks found for check "_main_" (but no 100% guarantee that there aren't any): found 17951 reachable heap objects of 2897135 bytes -================================================================================ -==================== Test output for //test/extensions/filters/http/tap:tap_filter_integration_test: -WARNING: Perftools heap leak checker is active -- Performance may suffer -[==========] Running 18 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 18 tests from IpVersions/TapIntegrationTest -[ RUN ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv4 -[ OK ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv4 (943 ms) -[ RUN ] IpVersions/TapIntegrationTest.StaticFilePerTap/IPv6 -[2020-08-03 21:28:10.135][41714][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/543/execroot/envoy/_tmp/4ce2d8b1861876b859b107620d7d2ae0/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address -terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address -[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000a2d5 -[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): -[2020-08-03 21:28:10.136][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL -[2020-08-03 21:28:10.206][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x414c97c] -[2020-08-03 21:28:10.207][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7f549b3238a0] -[2020-08-03 21:28:10.277][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x252d4be] -[2020-08-03 21:28:10.347][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x252cef9] -[2020-08-03 21:28:10.416][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x252f708] -[2020-08-03 21:28:10.488][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x252f63d] -[2020-08-03 21:28:10.559][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x252f5ed] -[2020-08-03 21:28:10.629][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x252f5bd] -[2020-08-03 21:28:10.699][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x252e8de] -[2020-08-03 21:28:10.770][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x24694d5] -[2020-08-03 21:28:10.840][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x2469395] -[2020-08-03 21:28:10.909][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5024ee2] -[2020-08-03 21:28:10.980][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x5024eb5] -[2020-08-03 21:28:10.980][41714][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7f549b3186db] -================================================================================ -==================== Test output for //test/extensions/filters/network/postgres_proxy:postgres_integration_test: -WARNING: Perftools heap leak checker is active -- Performance may suffer -[==========] Running 2 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 2 tests from IpVersions/PostgresIntegrationTest -[ RUN ] IpVersions/PostgresIntegrationTest.Login/0 -[ OK ] IpVersions/PostgresIntegrationTest.Login/0 (1510 ms) -[ RUN ] IpVersions/PostgresIntegrationTest.Login/1 -[2020-08-03 21:29:52.988][42506][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/674/execroot/envoy/_tmp/25d60d38146fdfcb74151ad27508c65f/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address -terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address -[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000a5f7 -[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): -[2020-08-03 21:29:52.988][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL -[2020-08-03 21:29:53.037][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x418287c] -[2020-08-03 21:29:53.037][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7fb8f86628a0] -[2020-08-03 21:29:53.086][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x2593dae] -[2020-08-03 21:29:53.136][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x25937e9] -[2020-08-03 21:29:53.185][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x2595ff8] -[2020-08-03 21:29:53.233][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x2595f2d] -[2020-08-03 21:29:53.282][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x2595edd] -[2020-08-03 21:29:53.333][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x2595ead] -[2020-08-03 21:29:53.381][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x25951ce] -[2020-08-03 21:29:53.429][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x24c2305] -[2020-08-03 21:29:53.479][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x24c21c5] -[2020-08-03 21:29:53.529][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x5057622] -[2020-08-03 21:29:53.580][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x50575f5] -[2020-08-03 21:29:53.580][42506][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7fb8f86576db] -================================================================================ -[==========] Running 165 tests from 14 test suites. -[----------] Global test environment set-up. -[----------] 79 tests from RouteMatcherTest -[ RUN ] RouteMatcherTest.TestLegacyRoutes -[ OK ] RouteMatcherTest.TestLegacyRoutes (554 ms) -[ RUN ] RouteMatcherTest.TestConnectRoutes -[ OK ] RouteMatcherTest.TestConnectRoutes (175 ms) -[ RUN ] RouteMatcherTest.TestRoutes -[ OK ] RouteMatcherTest.TestRoutes (1526 ms) -[ RUN ] RouteMatcherTest.TestRoutesWithWildcardAndDefaultOnly -[ OK ] RouteMatcherTest.TestRoutesWithWildcardAndDefaultOnly (80 ms) -[ RUN ] RouteMatcherTest.TestRoutesWithInvalidRegexLegacy -[ OK ] RouteMatcherTest.TestRoutesWithInvalidRegexLegacy (67 ms) -[ RUN ] RouteMatcherTest.TestRoutesWithInvalidRegex -[ OK ] RouteMatcherTest.TestRoutesWithInvalidRegex (69 ms) -[ RUN ] RouteMatcherTest.TestRoutesWithInvalidVirtualCluster -[ OK ] RouteMatcherTest.TestRoutesWithInvalidVirtualCluster (51 ms) -[ RUN ] RouteMatcherTest.TestAddRemoveRequestHeaders -[ OK ] RouteMatcherTest.TestAddRemoveRequestHeaders (138 ms) -[ RUN ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalse -[ OK ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalse (117 ms) -[ RUN ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalseMostSpecificWins -[ OK ] RouteMatcherTest.TestRequestHeadersToAddWithAppendFalseMostSpecificWins (101 ms) -[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeaders -[ OK ] RouteMatcherTest.TestAddRemoveResponseHeaders (144 ms) -[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendFalse -[ OK ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendFalse (84 ms) -[ RUN ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendMostSpecificWins -[ OK ] RouteMatcherTest.TestAddRemoveResponseHeadersAppendMostSpecificWins (91 ms) -[ RUN ] RouteMatcherTest.TestAddGlobalResponseHeaderRemoveFromRoute -[ OK ] RouteMatcherTest.TestAddGlobalResponseHeaderRemoveFromRoute (95 ms) -[ RUN ] RouteMatcherTest.TestRequestHeadersToAddNoPseudoHeader -[ OK ] RouteMatcherTest.TestRequestHeadersToAddNoPseudoHeader (140 ms) -[ RUN ] RouteMatcherTest.TestRequestHeadersToRemoveNoPseudoHeader -[ OK ] RouteMatcherTest.TestRequestHeadersToRemoveNoPseudoHeader (152 ms) -[ RUN ] RouteMatcherTest.Priority -[ OK ] RouteMatcherTest.Priority (94 ms) -[ RUN ] RouteMatcherTest.NoHostRewriteAndAutoRewrite -[ OK ] RouteMatcherTest.NoHostRewriteAndAutoRewrite (49 ms) -[ RUN ] RouteMatcherTest.NoHostRewriteAndAutoRewriteHeader -[ OK ] RouteMatcherTest.NoHostRewriteAndAutoRewriteHeader (49 ms) -[ RUN ] RouteMatcherTest.NoAutoRewriteAndAutoRewriteHeader -[ OK ] RouteMatcherTest.NoAutoRewriteAndAutoRewriteHeader (49 ms) -[ RUN ] RouteMatcherTest.HeaderMatchedRouting -[ OK ] RouteMatcherTest.HeaderMatchedRouting (197 ms) -[ RUN ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfigLegacy -[ OK ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfigLegacy (54 ms) -[ RUN ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfig -[ OK ] RouteMatcherTest.InvalidHeaderMatchedRoutingConfig (55 ms) -[ RUN ] RouteMatcherTest.QueryParamMatchedRouting -[ OK ] RouteMatcherTest.QueryParamMatchedRouting (206 ms) -[ RUN ] RouteMatcherTest.InvalidQueryParamMatchedRoutingConfig -[ OK ] RouteMatcherTest.InvalidQueryParamMatchedRoutingConfig (54 ms) -[ RUN ] RouteMatcherTest.ClusterHeader -[ OK ] RouteMatcherTest.ClusterHeader (110 ms) -[ RUN ] RouteMatcherTest.ContentType -[ OK ] RouteMatcherTest.ContentType (95 ms) -[ RUN ] RouteMatcherTest.GrpcTimeoutOffset -[ OK ] RouteMatcherTest.GrpcTimeoutOffset (83 ms) -[ RUN ] RouteMatcherTest.GrpcTimeoutOffsetOfDynamicRoute -[ OK ] RouteMatcherTest.GrpcTimeoutOffsetOfDynamicRoute (99 ms) -[ RUN ] RouteMatcherTest.FractionalRuntime -[ OK ] RouteMatcherTest.FractionalRuntime (81 ms) -[ RUN ] RouteMatcherTest.ShadowClusterNotFound -[ OK ] RouteMatcherTest.ShadowClusterNotFound (50 ms) -[ RUN ] RouteMatcherTest.ClusterNotFound -[ OK ] RouteMatcherTest.ClusterNotFound (51 ms) -[ RUN ] RouteMatcherTest.ClusterNotFoundNotChecking -[ OK ] RouteMatcherTest.ClusterNotFoundNotChecking (50 ms) -[ RUN ] RouteMatcherTest.ClusterNotFoundNotCheckingViaConfig -[ OK ] RouteMatcherTest.ClusterNotFoundNotCheckingViaConfig (51 ms) -[ RUN ] RouteMatcherTest.AttemptCountHeader -[ OK ] RouteMatcherTest.AttemptCountHeader (77 ms) -[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCode -[ OK ] RouteMatcherTest.ClusterNotFoundResponseCode (79 ms) -[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig503 -[ OK ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig503 (79 ms) -[ RUN ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig404 -[ OK ] RouteMatcherTest.ClusterNotFoundResponseCodeConfig404 (79 ms) -[ RUN ] RouteMatcherTest.Shadow -[ OK ] RouteMatcherTest.Shadow (115 ms) -[ RUN ] RouteMatcherTest.ShadowPolicyAndPolicies -[ OK ] RouteMatcherTest.ShadowPolicyAndPolicies (53 ms) -[ RUN ] RouteMatcherTest.Retry -[ OK ] RouteMatcherTest.Retry (186 ms) -[ RUN ] RouteMatcherTest.RetryVirtualHostLevel -[ OK ] RouteMatcherTest.RetryVirtualHostLevel (215 ms) -[ RUN ] RouteMatcherTest.GrpcRetry -[ OK ] RouteMatcherTest.GrpcRetry (189 ms) -[ RUN ] RouteMatcherTest.RetryBackOffIntervals -[ OK ] RouteMatcherTest.RetryBackOffIntervals (175 ms) -[ RUN ] RouteMatcherTest.InvalidRetryBackOff -[ OK ] RouteMatcherTest.InvalidRetryBackOff (57 ms) -[ RUN ] RouteMatcherTest.HedgeRouteLevel -[ OK ] RouteMatcherTest.HedgeRouteLevel (195 ms) -[ RUN ] RouteMatcherTest.HedgeVirtualHostLevel -[ OK ] RouteMatcherTest.HedgeVirtualHostLevel (199 ms) -[ RUN ] RouteMatcherTest.TestBadDefaultConfig -[ OK ] RouteMatcherTest.TestBadDefaultConfig (71 ms) -[ RUN ] RouteMatcherTest.TestDuplicateDomainConfig -[ OK ] RouteMatcherTest.TestDuplicateDomainConfig (56 ms) -[ RUN ] RouteMatcherTest.TestCaseSensitiveDomainConfig -[ OK ] RouteMatcherTest.TestCaseSensitiveDomainConfig (54 ms) -[ RUN ] RouteMatcherTest.TestDuplicateWildcardDomainConfig -[ OK ] RouteMatcherTest.TestDuplicateWildcardDomainConfig (54 ms) -[ RUN ] RouteMatcherTest.TestDuplicateSuffixWildcardDomainConfig -[ OK ] RouteMatcherTest.TestDuplicateSuffixWildcardDomainConfig (53 ms) -[ RUN ] RouteMatcherTest.TestDuplicatePrefixWildcardDomainConfig -[ OK ] RouteMatcherTest.TestDuplicatePrefixWildcardDomainConfig (53 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInPrefixRewrites -[ OK ] RouteMatcherTest.TestInvalidCharactersInPrefixRewrites (51 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInHostRewrites -[ OK ] RouteMatcherTest.TestInvalidCharactersInHostRewrites (51 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInAutoHostRewrites -[ OK ] RouteMatcherTest.TestInvalidCharactersInAutoHostRewrites (51 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInHostRedirect -[ OK ] RouteMatcherTest.TestInvalidCharactersInHostRedirect (49 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInPathRedirect -[ OK ] RouteMatcherTest.TestInvalidCharactersInPathRedirect (51 ms) -[ RUN ] RouteMatcherTest.TestInvalidCharactersInPrefixRewriteRedirect -[ OK ] RouteMatcherTest.TestInvalidCharactersInPrefixRewriteRedirect (50 ms) -[ RUN ] RouteMatcherTest.TestPrefixAndRegexRewrites -[ OK ] RouteMatcherTest.TestPrefixAndRegexRewrites (51 ms) -[ RUN ] RouteMatcherTest.TestDomainMatchOrderConfig -[ OK ] RouteMatcherTest.TestDomainMatchOrderConfig (157 ms) -[ RUN ] RouteMatcherTest.NoProtocolInHeadersWhenTlsIsRequired -[ OK ] RouteMatcherTest.NoProtocolInHeadersWhenTlsIsRequired (66 ms) -[ RUN ] RouteMatcherTest.RouteName -[ OK ] RouteMatcherTest.RouteName (148 ms) -[ RUN ] RouteMatcherTest.DirectResponse -[ OK ] RouteMatcherTest.DirectResponse (1138 ms) -[ RUN ] RouteMatcherTest.ExclusiveRouteEntryOrDirectResponseEntry -[ OK ] RouteMatcherTest.ExclusiveRouteEntryOrDirectResponseEntry (111 ms) -[ RUN ] RouteMatcherTest.ExclusiveWeightedClustersEntryOrDirectResponseEntry -[ OK ] RouteMatcherTest.ExclusiveWeightedClustersEntryOrDirectResponseEntry (111 ms) -[ RUN ] RouteMatcherTest.WeightedClusters -[ OK ] RouteMatcherTest.WeightedClusters (1129 ms) -[ RUN ] RouteMatcherTest.ExclusiveWeightedClustersOrClusterConfig -[ OK ] RouteMatcherTest.ExclusiveWeightedClustersOrClusterConfig (48 ms) -[ RUN ] RouteMatcherTest.WeightedClustersMissingClusterList -[ OK ] RouteMatcherTest.WeightedClustersMissingClusterList (50 ms) -[ RUN ] RouteMatcherTest.WeightedClustersEmptyClustersList -[ OK ] RouteMatcherTest.WeightedClustersEmptyClustersList (47 ms) -[ RUN ] RouteMatcherTest.WeightedClustersSumOFWeightsNotEqualToMax -[ OK ] RouteMatcherTest.WeightedClustersSumOFWeightsNotEqualToMax (87 ms) -[ RUN ] RouteMatcherTest.TestWeightedClusterWithMissingWeights -[ OK ] RouteMatcherTest.TestWeightedClusterWithMissingWeights (103 ms) -[ RUN ] RouteMatcherTest.TestWeightedClusterInvalidClusterName -[ OK ] RouteMatcherTest.TestWeightedClusterInvalidClusterName (65 ms) -[ RUN ] RouteMatcherTest.TestWeightedClusterHeaderManipulation -[ OK ] RouteMatcherTest.TestWeightedClusterHeaderManipulation (95 ms) -[ RUN ] RouteMatcherTest.TestOpaqueConfig -[ OK ] RouteMatcherTest.TestOpaqueConfig (137 ms) -[ RUN ] RouteMatcherTest.TestOpaqueConfigUsingDeprecatedName -[ OK ] RouteMatcherTest.TestOpaqueConfigUsingDeprecatedName (69 ms) -[ RUN ] RouteMatcherTest.Decorator -[ OK ] RouteMatcherTest.Decorator (83 ms) -[ RUN ] RouteMatcherTest.HeaderMatchedRoutingV2 -[ OK ] RouteMatcherTest.HeaderMatchedRoutingV2 (305 ms) -[ RUN ] RouteMatcherTest.TlsContextMatching -[ OK ] RouteMatcherTest.TlsContextMatching (187 ms) -[----------] 79 tests from RouteMatcherTest (11638 ms total) - -[----------] 10 tests from RouterMatcherHashPolicyTest -[ RUN ] RouterMatcherHashPolicyTest.HashHeaders -[ OK ] RouterMatcherHashPolicyTest.HashHeaders (96 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashHeadersRegexSubstitution -[ OK ] RouterMatcherHashPolicyTest.HashHeadersRegexSubstitution (65 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashIp -[ OK ] RouterMatcherHashPolicyTest.HashIp (124 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashIpNonIpAddress -[ OK ] RouterMatcherHashPolicyTest.HashIpNonIpAddress (73 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashIpv4DifferentAddresses -[ OK ] RouterMatcherHashPolicyTest.HashIpv4DifferentAddresses (82 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashIpv6DifferentAddresses -[ OK ] RouterMatcherHashPolicyTest.HashIpv6DifferentAddresses (81 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashQueryParameters -[ OK ] RouterMatcherHashPolicyTest.HashQueryParameters (94 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashMultiple -[ OK ] RouterMatcherHashPolicyTest.HashMultiple (122 ms) -[ RUN ] RouterMatcherHashPolicyTest.HashTerminal -[ OK ] RouterMatcherHashPolicyTest.HashTerminal (109 ms) -[ RUN ] RouterMatcherHashPolicyTest.InvalidHashPolicies -[ OK ] RouterMatcherHashPolicyTest.InvalidHashPolicies (50 ms) -[----------] 10 tests from RouterMatcherHashPolicyTest (897 ms total) - -[----------] 5 tests from RouterMatcherCookieHashPolicyTest -[ RUN ] RouterMatcherCookieHashPolicyTest.NoTtl -[ OK ] RouterMatcherCookieHashPolicyTest.NoTtl (107 ms) -[ RUN ] RouterMatcherCookieHashPolicyTest.DifferentCookies -[ OK ] RouterMatcherCookieHashPolicyTest.DifferentCookies (80 ms) -[ RUN ] RouterMatcherCookieHashPolicyTest.TtlSet -[ OK ] RouterMatcherCookieHashPolicyTest.TtlSet (141 ms) -[ RUN ] RouterMatcherCookieHashPolicyTest.SetSessionCookie -[ OK ] RouterMatcherCookieHashPolicyTest.SetSessionCookie (66 ms) -[ RUN ] RouterMatcherCookieHashPolicyTest.SetCookiePath -[ OK ] RouterMatcherCookieHashPolicyTest.SetCookiePath (66 ms) -[----------] 5 tests from RouterMatcherCookieHashPolicyTest (460 ms total) - -[----------] 4 tests from RouterMatcherFilterStateHashPolicyTest -[ RUN ] RouterMatcherFilterStateHashPolicyTest.KeyNotFound -[ OK ] RouterMatcherFilterStateHashPolicyTest.KeyNotFound (65 ms) -[ RUN ] RouterMatcherFilterStateHashPolicyTest.NullValue -[ OK ] RouterMatcherFilterStateHashPolicyTest.NullValue (68 ms) -[ RUN ] RouterMatcherFilterStateHashPolicyTest.ValueNonHashable -[ OK ] RouterMatcherFilterStateHashPolicyTest.ValueNonHashable (66 ms) -[ RUN ] RouterMatcherFilterStateHashPolicyTest.Hashable -[ OK ] RouterMatcherFilterStateHashPolicyTest.Hashable (66 ms) -[----------] 4 tests from RouterMatcherFilterStateHashPolicyTest (266 ms total) - -[----------] 24 tests from RouteConfigurationV2 -[ RUN ] RouteConfigurationV2.RequestMirrorPolicy -[ OK ] RouteConfigurationV2.RequestMirrorPolicy (95 ms) -[ RUN ] RouteConfigurationV2.RedirectCode -[ OK ] RouteConfigurationV2.RedirectCode (94 ms) -[ RUN ] RouteConfigurationV2.DirectResponse -[ OK ] RouteConfigurationV2.DirectResponse (63 ms) -[ RUN ] RouteConfigurationV2.DirectResponseTooLarge -[ OK ] RouteConfigurationV2.DirectResponseTooLarge (60 ms) -[ RUN ] RouteConfigurationV2.BrokenTypedMetadata -[ OK ] RouteConfigurationV2.BrokenTypedMetadata (51 ms) -[ RUN ] RouteConfigurationV2.RouteConfigGetters -[ OK ] RouteConfigurationV2.RouteConfigGetters (98 ms) -[ RUN ] RouteConfigurationV2.RouteTracingConfig -[ OK ] RouteConfigurationV2.RouteTracingConfig (104 ms) -[ RUN ] RouteConfigurationV2.RedirectPrefixRewrite -[ OK ] RouteConfigurationV2.RedirectPrefixRewrite (253 ms) -[ RUN ] RouteConfigurationV2.PathRedirectQueryNotPreserved -[ OK ] RouteConfigurationV2.PathRedirectQueryNotPreserved (158 ms) -[ RUN ] RouteConfigurationV2.RedirectStripQuery -[ OK ] RouteConfigurationV2.RedirectStripQuery (196 ms) -[ RUN ] RouteConfigurationV2.RegexPrefixWithNoRewriteWorksWhenPathChanged -[ OK ] RouteConfigurationV2.RegexPrefixWithNoRewriteWorksWhenPathChanged (66 ms) -[ RUN ] RouteConfigurationV2.NoIdleTimeout -[ OK ] RouteConfigurationV2.NoIdleTimeout (61 ms) -[ RUN ] RouteConfigurationV2.ZeroIdleTimeout -[ OK ] RouteConfigurationV2.ZeroIdleTimeout (66 ms) -[ RUN ] RouteConfigurationV2.ExplicitIdleTimeout -[ OK ] RouteConfigurationV2.ExplicitIdleTimeout (63 ms) -[ RUN ] RouteConfigurationV2.RetriableStatusCodes -[ OK ] RouteConfigurationV2.RetriableStatusCodes (60 ms) -[ RUN ] RouteConfigurationV2.RetriableHeaders -[ OK ] RouteConfigurationV2.RetriableHeaders (67 ms) -[ RUN ] RouteConfigurationV2.UpgradeConfigs -[ OK ] RouteConfigurationV2.UpgradeConfigs (66 ms) -[ RUN ] RouteConfigurationV2.DuplicateUpgradeConfigs -[ OK ] RouteConfigurationV2.DuplicateUpgradeConfigs (52 ms) -[ RUN ] RouteConfigurationV2.BadConnectConfig -[ OK ] RouteConfigurationV2.BadConnectConfig (53 ms) -[ RUN ] RouteConfigurationV2.RetryPluginsAreNotReused -[ OK ] RouteConfigurationV2.RetryPluginsAreNotReused (66 ms) -[ RUN ] RouteConfigurationV2.InternalRedirectIsDisabledWhenNotSpecifiedInRouteAction -[ OK ] RouteConfigurationV2.InternalRedirectIsDisabledWhenNotSpecifiedInRouteAction (64 ms) -[ RUN ] RouteConfigurationV2.DefaultInternalRedirectPolicyIsSensible -[ OK ] RouteConfigurationV2.DefaultInternalRedirectPolicyIsSensible (67 ms) -[ RUN ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCode -[ OK ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCode (65 ms) -[ RUN ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCodeCauseEmptySet -[ OK ] RouteConfigurationV2.InternalRedirectPolicyDropsInvalidRedirectCodeCauseEmptySet (67 ms) -[----------] 24 tests from RouteConfigurationV2 (2055 ms total) - -[----------] 1 test from NullConfigImplTest -[ RUN ] NullConfigImplTest.All -[ OK ] NullConfigImplTest.All (11 ms) -[----------] 1 test from NullConfigImplTest (11 ms total) - -[----------] 9 tests from BadHttpRouteConfigurationsTest -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteConfig -[ OK ] BadHttpRouteConfigurationsTest.BadRouteConfig (50 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadVirtualHostConfig -[ OK ] BadHttpRouteConfigurationsTest.BadVirtualHostConfig (51 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfig -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfig (51 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPath -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPath (49 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigMissingPathSpecifier -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigMissingPathSpecifier (49 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndRegex -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndRegex (49 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigNoAction -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigNoAction (49 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPathAndRegex -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPathAndRegex (48 ms) -[ RUN ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPathAndRegex -[ OK ] BadHttpRouteConfigurationsTest.BadRouteEntryConfigPrefixAndPathAndRegex (49 ms) -[----------] 9 tests from BadHttpRouteConfigurationsTest (445 ms total) - -[----------] 6 tests from RoutePropertyTest -[ RUN ] RoutePropertyTest.ExcludeVHRateLimits -[ OK ] RoutePropertyTest.ExcludeVHRateLimits (101 ms) -[ RUN ] RoutePropertyTest.TestVHostCorsConfig -[ OK ] RoutePropertyTest.TestVHostCorsConfig (68 ms) -[ RUN ] RoutePropertyTest.TestRouteCorsConfig -[ OK ] RoutePropertyTest.TestRouteCorsConfig (67 ms) -[ RUN ] RoutePropertyTest.TTestVHostCorsLegacyConfig -[ OK ] RoutePropertyTest.TTestVHostCorsLegacyConfig (64 ms) -[ RUN ] RoutePropertyTest.TestRouteCorsLegacyConfig -[ OK ] RoutePropertyTest.TestRouteCorsLegacyConfig (66 ms) -[ RUN ] RoutePropertyTest.TestBadCorsConfig -[ OK ] RoutePropertyTest.TestBadCorsConfig (50 ms) -[----------] 6 tests from RoutePropertyTest (416 ms total) - -[----------] 2 tests from CustomRequestHeadersTest -[ RUN ] CustomRequestHeadersTest.AddNewHeader -[ OK ] CustomRequestHeadersTest.AddNewHeader (80 ms) -[ RUN ] CustomRequestHeadersTest.CustomHeaderWrongFormat -[ OK ] CustomRequestHeadersTest.CustomHeaderWrongFormat (65 ms) -[----------] 2 tests from CustomRequestHeadersTest (1591 ms total) - -[----------] 3 tests from MetadataMatchCriteriaImpl -[ RUN ] MetadataMatchCriteriaImpl.Create -[ OK ] MetadataMatchCriteriaImpl.Create (0 ms) -[ RUN ] MetadataMatchCriteriaImpl.Merge -[ OK ] MetadataMatchCriteriaImpl.Merge (0 ms) -[ RUN ] MetadataMatchCriteriaImpl.Filter -[ OK ] MetadataMatchCriteriaImpl.Filter (0 ms) -[----------] 3 tests from MetadataMatchCriteriaImpl (0 ms total) - -[----------] 1 test from RouteEntryMetadataMatchTest -[ RUN ] RouteEntryMetadataMatchTest.ParsesMetadata -[ OK ] RouteEntryMetadataMatchTest.ParsesMetadata (206 ms) -[----------] 1 test from RouteEntryMetadataMatchTest (206 ms total) - -[----------] 2 tests from ConfigUtilityTest -[ RUN ] ConfigUtilityTest.ParseResponseCode -[ OK ] ConfigUtilityTest.ParseResponseCode (46 ms) -[ RUN ] ConfigUtilityTest.ParseDirectResponseBody -[ OK ] ConfigUtilityTest.ParseDirectResponseBody (46 ms) -[----------] 2 tests from ConfigUtilityTest (92 ms total) - -[----------] 11 tests from PerFilterConfigsTest -[ RUN ] PerFilterConfigsTest.TypedConfigFilterError -[ OK ] PerFilterConfigsTest.TypedConfigFilterError (62 ms) -[ RUN ] PerFilterConfigsTest.UnknownFilterStruct -[ OK ] PerFilterConfigsTest.UnknownFilterStruct (51 ms) -[ RUN ] PerFilterConfigsTest.UnknownFilterAny -[ OK ] PerFilterConfigsTest.UnknownFilterAny (50 ms) -[ RUN ] PerFilterConfigsTest.DefaultFilterImplementationStruct -[ OK ] PerFilterConfigsTest.DefaultFilterImplementationStruct (67 ms) -[ RUN ] PerFilterConfigsTest.DefaultFilterImplementationAny -[ OK ] PerFilterConfigsTest.DefaultFilterImplementationAny (67 ms) -[ RUN ] PerFilterConfigsTest.RouteLocalConfig -[ OK ] PerFilterConfigsTest.RouteLocalConfig (68 ms) -[ RUN ] PerFilterConfigsTest.RouteLocalTypedConfig -[ OK ] PerFilterConfigsTest.RouteLocalTypedConfig (67 ms) -[ RUN ] PerFilterConfigsTest.WeightedClusterConfig -[ OK ] PerFilterConfigsTest.WeightedClusterConfig (68 ms) -[ RUN ] PerFilterConfigsTest.WeightedClusterTypedConfig -[ OK ] PerFilterConfigsTest.WeightedClusterTypedConfig (68 ms) -[ RUN ] PerFilterConfigsTest.WeightedClusterFallthroughConfig -[ OK ] PerFilterConfigsTest.WeightedClusterFallthroughConfig (68 ms) -[ RUN ] PerFilterConfigsTest.WeightedClusterFallthroughTypedConfig -[ OK ] PerFilterConfigsTest.WeightedClusterFallthroughTypedConfig (67 ms) -[----------] 11 tests from PerFilterConfigsTest (704 ms total) - -[----------] 8 tests from RouteMatchOverrideTest -[ RUN ] RouteMatchOverrideTest.VerifyAllMatchableRoutes -[ OK ] RouteMatchOverrideTest.VerifyAllMatchableRoutes (65 ms) -[ RUN ] RouteMatchOverrideTest.VerifyRouteOverrideStops -[ OK ] RouteMatchOverrideTest.VerifyRouteOverrideStops (64 ms) -[ RUN ] RouteMatchOverrideTest.StopWhenNoMoreRoutes -[ OK ] RouteMatchOverrideTest.StopWhenNoMoreRoutes (65 ms) -[ RUN ] RouteMatchOverrideTest.NullRouteOnNoRouteMatch -[ OK ] RouteMatchOverrideTest.NullRouteOnNoRouteMatch (81 ms) -[ RUN ] RouteMatchOverrideTest.NullRouteOnNoHostMatch -[ OK ] RouteMatchOverrideTest.NullRouteOnNoHostMatch (66 ms) -[ RUN ] RouteMatchOverrideTest.NullRouteOnNullXForwardedProto -[ OK ] RouteMatchOverrideTest.NullRouteOnNullXForwardedProto (66 ms) -[ RUN ] RouteMatchOverrideTest.NullRouteOnRequireTlsAll -[ OK ] RouteMatchOverrideTest.NullRouteOnRequireTlsAll (65 ms) -[ RUN ] RouteMatchOverrideTest.NullRouteOnRequireTlsInternal -[ OK ] RouteMatchOverrideTest.NullRouteOnRequireTlsInternal (65 ms) -[----------] 8 tests from RouteMatchOverrideTest (538 ms total) - -[----------] Global test environment tear-down -[==========] 165 tests from 14 test suites ran. (19322 ms total) -[ PASSED ] 165 tests. -==================== Test output for //test/extensions/filters/network/sni_dynamic_forward_proxy:proxy_filter_integration_test: -WARNING: Perftools heap leak checker is active -- Performance may suffer -[==========] Running 4 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 4 tests from IpVersions/SniDynamicProxyFilterIntegrationTest -[ RUN ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv4 -TestRandomGenerator running with seed 205585968 -[ OK ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv4 (765 ms) -[ RUN ] IpVersions/SniDynamicProxyFilterIntegrationTest.UpstreamTls/IPv6 -TestRandomGenerator running with seed 205585968 -[2020-08-03 21:33:40.808][44312][critical][main] [source/server/server.cc:102] error initializing configuration '/build/tmp/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/sandbox/processwrapper-sandbox/898/execroot/envoy/_tmp/282b4d28423b557fc72f2459645621cd/bootstrap.pb': cannot bind '[::1]:0': Cannot assign requested address -terminating with uncaught exception of type Envoy::Network::SocketBindException: cannot bind '[::1]:0': Cannot assign requested address -[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] Caught Aborted, suspect faulting address 0xc22430000acdd -[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:91] Backtrace (use tools/stack_decode.py to get line numbers): -[2020-08-03 21:33:40.809][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:92] Envoy version: 0/1.16.0-dev/test/DEBUG/BoringSSL -[2020-08-03 21:33:40.881][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #0: Envoy::SignalAction::sigHandler() [0x4267f3c] -[2020-08-03 21:33:40.881][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #1: __restore_rt [0x7f8f0f7748a0] -[2020-08-03 21:33:40.952][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #2: Envoy::IntegrationTestServerImpl::createAndRunEnvoyServer() [0x266b38e] -[2020-08-03 21:33:41.024][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #3: Envoy::IntegrationTestServer::threadRoutine() [0x266adc9] -[2020-08-03 21:33:41.096][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #4: Envoy::IntegrationTestServer::start()::$_0::operator()() [0x266d5d8] -[2020-08-03 21:33:41.168][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #5: std::__1::__invoke<>() [0x266d50d] -[2020-08-03 21:33:41.239][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #6: std::__1::__invoke_void_return_wrapper<>::__call<>() [0x266d4bd] -[2020-08-03 21:33:41.311][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #7: std::__1::__function::__alloc_func<>::operator()() [0x266d48d] -[2020-08-03 21:33:41.382][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #8: std::__1::__function::__func<>::operator()() [0x266c7ae] -[2020-08-03 21:33:41.453][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #9: std::__1::__function::__value_func<>::operator()() [0x25b1745] -[2020-08-03 21:33:41.525][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #10: std::__1::function<>::operator()() [0x25b1605] -[2020-08-03 21:33:41.596][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #11: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::operator()() [0x513dce2] -[2020-08-03 21:33:41.668][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #12: Envoy::Thread::ThreadImplPosix::ThreadImplPosix()::{lambda()#1}::__invoke() [0x513dcb5] -[2020-08-03 21:33:41.668][44312][critical][backtrace] [bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:96] #13: start_thread [0x7f8f0f7696db] -================================================================================ diff --git a/source/extensions/filters/common/rbac/engine.h b/source/extensions/filters/common/rbac/engine.h index 04e82c95023d8..777db8ad3783a 100644 --- a/source/extensions/filters/common/rbac/engine.h +++ b/source/extensions/filters/common/rbac/engine.h @@ -31,7 +31,7 @@ class RoleBasedAccessControlEngine { */ virtual bool handleAction(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, - StreamInfo::StreamInfo& info, std::string* effective_policy_id) PURE; + StreamInfo::StreamInfo& info, std::string* effective_policy_id) const PURE; /** * Handles action-specific operations and returns whether or not the request is permitted. @@ -43,7 +43,7 @@ class RoleBasedAccessControlEngine { * which is used to identity the source of the allow/deny. */ virtual bool handleAction(const Network::Connection& connection, StreamInfo::StreamInfo& info, - std::string* effective_policy_id) PURE; + std::string* effective_policy_id) const PURE; }; } // namespace RBAC diff --git a/source/extensions/filters/common/rbac/engine_impl.cc b/source/extensions/filters/common/rbac/engine_impl.cc index ce9493e26896c..d2da2c74c5b63 100644 --- a/source/extensions/filters/common/rbac/engine_impl.cc +++ b/source/extensions/filters/common/rbac/engine_impl.cc @@ -28,7 +28,7 @@ RoleBasedAccessControlEngineImpl::RoleBasedAccessControlEngineImpl( bool RoleBasedAccessControlEngineImpl::handleAction(const Network::Connection& connection, StreamInfo::StreamInfo& info, - std::string* effective_policy_id) { + std::string* effective_policy_id) const { return handleAction(connection, *Http::StaticEmptyHeaders::get().request_headers, info, effective_policy_id); } @@ -36,7 +36,7 @@ bool RoleBasedAccessControlEngineImpl::handleAction(const Network::Connection& c bool RoleBasedAccessControlEngineImpl::handleAction(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, StreamInfo::StreamInfo& info, - std::string* effective_policy_id) { + std::string* effective_policy_id) const { bool matched = checkPolicyMatch(connection, info, headers, effective_policy_id); switch (action_) { diff --git a/source/extensions/filters/common/rbac/engine_impl.h b/source/extensions/filters/common/rbac/engine_impl.h index 4294bc8777547..0aacfb41f8e15 100644 --- a/source/extensions/filters/common/rbac/engine_impl.h +++ b/source/extensions/filters/common/rbac/engine_impl.h @@ -32,10 +32,10 @@ class RoleBasedAccessControlEngineImpl : public RoleBasedAccessControlEngine, No bool handleAction(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, StreamInfo::StreamInfo& info, - std::string* effective_policy_id) override; + std::string* effective_policy_id) const override; bool handleAction(const Network::Connection& connection, StreamInfo::StreamInfo& info, - std::string* effective_policy_id) override; + std::string* effective_policy_id) const override; private: // Checks whether the request matches any policies diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index 0c5b96edf3894..e52cfb4281974 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -20,24 +20,14 @@ struct RcDetailsValues { }; using RcDetails = ConstSingleton; -// using LogDecision = Filters::Common::RBAC::RoleBasedAccessControlEngine::LogDecision; - RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::http::rbac::v3::RBAC& proto_config, const std::string& stats_prefix, Stats::Scope& scope) - : stats_(Filters::Common::RBAC::generateStats(stats_prefix, scope)) { - engine_ = proto_config.has_rules() - ? std::make_unique( - proto_config.rules(), Filters::Common::RBAC::EnforcementMode::Enforced) - : nullptr; - shadow_engine_ = - proto_config.has_shadow_rules() - ? std::make_unique( - proto_config.shadow_rules(), Filters::Common::RBAC::EnforcementMode::Shadow) - : nullptr; -} + : stats_(Filters::Common::RBAC::generateStats(stats_prefix, scope)), + engine_(Filters::Common::RBAC::createEngine(proto_config)), + shadow_engine_(Filters::Common::RBAC::createShadowEngine(proto_config)) {} -Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* +const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* RoleBasedAccessControlFilterConfig::engine(const Router::RouteConstSharedPtr route, Filters::Common::RBAC::EnforcementMode mode) const { if (!route || !route->routeEntry()) { @@ -102,6 +92,7 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo } ProtobufWkt::Struct metrics; + auto& fields = *metrics.mutable_fields(); if (!effective_policy_id.empty()) { *fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get() diff --git a/source/extensions/filters/http/rbac/rbac_filter.h b/source/extensions/filters/http/rbac/rbac_filter.h index 7434dcd925cd0..fe7369e34e6be 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.h +++ b/source/extensions/filters/http/rbac/rbac_filter.h @@ -22,7 +22,7 @@ class RoleBasedAccessControlRouteSpecificFilterConfig : public Router::RouteSpec RoleBasedAccessControlRouteSpecificFilterConfig( const envoy::extensions::filters::http::rbac::v3::RBACPerRoute& per_route_config); - Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); @@ -44,12 +44,12 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats& stats() { return stats_; } - Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(const Router::RouteConstSharedPtr route, Filters::Common::RBAC::EnforcementMode mode) const; private: - Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); @@ -57,8 +57,8 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats stats_; - std::unique_ptr engine_; - std::unique_ptr shadow_engine_; + std::unique_ptr engine_; + std::unique_ptr shadow_engine_; }; using RoleBasedAccessControlFilterConfigSharedPtr = diff --git a/source/extensions/filters/network/rbac/rbac_filter.cc b/source/extensions/filters/network/rbac/rbac_filter.cc index db5a8ec075cd3..3b328ed2815f9 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.cc +++ b/source/extensions/filters/network/rbac/rbac_filter.cc @@ -16,17 +16,9 @@ namespace RBACFilter { RoleBasedAccessControlFilterConfig::RoleBasedAccessControlFilterConfig( const envoy::extensions::filters::network::rbac::v3::RBAC& proto_config, Stats::Scope& scope) : stats_(Filters::Common::RBAC::generateStats(proto_config.stat_prefix(), scope)), - enforcement_type_(proto_config.enforcement_type()) { - engine_ = proto_config.has_rules() - ? std::make_unique( - proto_config.rules(), Filters::Common::RBAC::EnforcementMode::Enforced) - : nullptr; - shadow_engine_ = - proto_config.has_shadow_rules() - ? std::make_unique( - proto_config.shadow_rules(), Filters::Common::RBAC::EnforcementMode::Shadow) - : nullptr; -} + engine_(Filters::Common::RBAC::createEngine(proto_config)), + shadow_engine_(Filters::Common::RBAC::createShadowEngine(proto_config)), + enforcement_type_(proto_config.enforcement_type()) {} Network::FilterStatus RoleBasedAccessControlFilter::onData(Buffer::Instance&, bool) { ENVOY_LOG(debug, @@ -90,8 +82,7 @@ void RoleBasedAccessControlFilter::setDynamicMetadata(std::string shadow_engine_ EngineResult RoleBasedAccessControlFilter::checkEngine(Filters::Common::RBAC::EnforcementMode mode) { - auto engine = config_->engine(mode); - + const auto engine = config_->engine(mode); if (engine != nullptr) { std::string effective_policy_id; diff --git a/source/extensions/filters/network/rbac/rbac_filter.h b/source/extensions/filters/network/rbac/rbac_filter.h index 38530d4e2e600..19c9360e21342 100644 --- a/source/extensions/filters/network/rbac/rbac_filter.h +++ b/source/extensions/filters/network/rbac/rbac_filter.h @@ -27,7 +27,7 @@ class RoleBasedAccessControlFilterConfig { Filters::Common::RBAC::RoleBasedAccessControlFilterStats& stats() { return stats_; } - Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* + const Filters::Common::RBAC::RoleBasedAccessControlEngineImpl* engine(Filters::Common::RBAC::EnforcementMode mode) const { return mode == Filters::Common::RBAC::EnforcementMode::Enforced ? engine_.get() : shadow_engine_.get(); diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index 7a8f192fdb608..0b791b6acad08 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -24,6 +24,8 @@ namespace Common { namespace RBAC { namespace { +enum class LogResult { Yes, No, Undecided }; + void checkEngine( RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, StreamInfo::StreamInfo& info, const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), @@ -42,6 +44,34 @@ void checkEngine( checkEngine(engine, expected, empty_info, connection, headers); } +void checkEngineLog( + RBAC::RoleBasedAccessControlEngineImpl& engine, LogResult expected, + NiceMock& info, + const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), + const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { + engine.handleAction(connection, headers, info, nullptr); + + if (expected != LogResult::Undecided) { + auto filter_meta = info.dynamicMetadata().filter_metadata().at( + RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); + EXPECT_EQ(expected == LogResult::Yes, + filter_meta.fields() + .at(RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) + .bool_value()); + } else { + EXPECT_EQ(info.dynamicMetadata().filter_metadata().end(), + info.dynamicMetadata().filter_metadata().find( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace)); + } +} + +void onMetadata(NiceMock& info) { + ON_CALL(info, setDynamicMetadata("envoy.common", _)) + .WillByDefault(Invoke([&info](const std::string&, const ProtobufWkt::Struct& obj) { + (*info.metadata_.mutable_filter_metadata())["envoy.common"] = obj; + })); +} + TEST(RoleBasedAccessControlEngineImpl, Disabled) { envoy::config::rbac::v3::RBAC rbac; rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); @@ -374,6 +404,88 @@ TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { checkEngine(engine, false, info, conn, headers); } +// Log tests +TEST(RoleBasedAccessControlEngineImpl, DisabledLog) { + NiceMock info; + onMetadata(info); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + checkEngineLog(engine, RBAC::LogResult::No, info); +} + +TEST(RoleBasedAccessControlEngineImpl, LogIfMatched) { + envoy::config::rbac::v3::Policy policy; + policy.add_permissions()->set_destination_port(123); + policy.add_principals()->set_any(true); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); + (*rbac.mutable_policies())["foo"] = policy; + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + + Envoy::Network::MockConnection conn; + Envoy::Http::TestRequestHeaderMapImpl headers; + NiceMock info; + onMetadata(info); + + Envoy::Network::Address::InstanceConstSharedPtr addr = + Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); + EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngineLog(engine, RBAC::LogResult::Yes, info, conn, headers); + + addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); + EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); + checkEngineLog(engine, RBAC::LogResult::No, info, conn, headers); +} + +TEST(RoleBasedAccessControlEngineImpl, LogAllowUndecided) { + envoy::config::rbac::v3::Policy policy; + policy.add_permissions()->set_destination_port(123); + policy.add_principals()->set_any(true); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); + (*rbac.mutable_policies())["foo"] = policy; + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + + Envoy::Network::MockConnection conn; + Envoy::Http::TestRequestHeaderMapImpl headers; + NiceMock info; + onMetadata(info); + + Envoy::Network::Address::InstanceConstSharedPtr addr = + Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); + checkEngineLog(engine, RBAC::LogResult::Undecided, info, conn, headers); + + addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); + checkEngineLog(engine, RBAC::LogResult::Undecided, info, conn, headers); +} + +TEST(RoleBasedAccessControlEngineImpl, LogDenyUndecided) { + envoy::config::rbac::v3::Policy policy; + policy.add_permissions()->set_destination_port(123); + policy.add_principals()->set_any(true); + + envoy::config::rbac::v3::RBAC rbac; + rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); + (*rbac.mutable_policies())["foo"] = policy; + RBAC::RoleBasedAccessControlEngineImpl engine(rbac); + + Envoy::Network::MockConnection conn; + Envoy::Http::TestRequestHeaderMapImpl headers; + NiceMock info; + onMetadata(info); + + Envoy::Network::Address::InstanceConstSharedPtr addr = + Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); + checkEngineLog(engine, RBAC::LogResult::Undecided, info, conn, headers); + + addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); + checkEngineLog(engine, RBAC::LogResult::Undecided, info, conn, headers); +} + TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { envoy::config::rbac::v3::Policy policy; policy.add_permissions()->set_destination_port(123); diff --git a/test/extensions/filters/common/rbac/mocks.h b/test/extensions/filters/common/rbac/mocks.h index c597bbd0ee4b4..5ed798aacdb16 100644 --- a/test/extensions/filters/common/rbac/mocks.h +++ b/test/extensions/filters/common/rbac/mocks.h @@ -18,15 +18,15 @@ class MockEngine : public RoleBasedAccessControlEngineImpl { const EnforcementMode mode = EnforcementMode::Shadow) : RoleBasedAccessControlEngineImpl(rules, mode){}; - // MOCK_METHOD(bool, allowed, - // (const Envoy::Network::Connection&, const Envoy::Http::RequestHeaderMap&, - // const StreamInfo::StreamInfo&, std::string* effective_policy_id), - // (const)); - - // MOCK_METHOD(bool, allowed, - // (const Envoy::Network::Connection&, const StreamInfo::StreamInfo&, - // std::string* effective_policy_id), - // (const)); + MOCK_METHOD(bool, handleAction, + (const Envoy::Network::Connection&, const Envoy::Http::RequestHeaderMap&, + StreamInfo::StreamInfo&, std::string* effective_policy_id), + (const)); + + MOCK_METHOD(bool, handleAction, + (const Envoy::Network::Connection&, StreamInfo::StreamInfo&, + std::string* effective_policy_id), + (const)); }; } // namespace RBAC diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index 873121d741001..68aa94daebe24 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -203,22 +203,22 @@ TEST_F(RoleBasedAccessControlFilterTest, Denied) { EXPECT_EQ("rbac_access_denied", callbacks_.details_); } -// TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { -// setDestinationPort(456); +TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { + setDestinationPort(456); -// envoy::extensions::filters::http::rbac::v3::RBACPerRoute route_config; -// route_config.mutable_rbac()->mutable_rules()->set_action(envoy::config::rbac::v3::RBAC::DENY); -// NiceMock engine{route_config.rbac().rules()}; -// NiceMock per_route_config_{route_config}; + envoy::extensions::filters::http::rbac::v3::RBACPerRoute route_config; + route_config.mutable_rbac()->mutable_rules()->set_action(envoy::config::rbac::v3::RBAC::DENY); + NiceMock engine{route_config.rbac().rules()}; + NiceMock per_route_config_{route_config}; -// // EXPECT_CALL(engine, allowed(_, _, _, _)).WillRepeatedly(Return(true)); -// EXPECT_CALL(per_route_config_, engine()).WillRepeatedly(ReturnRef(engine)); + EXPECT_CALL(engine, handleAction(_, _, _, _)).WillRepeatedly(Return(true)); + EXPECT_CALL(per_route_config_, engine()).WillRepeatedly(ReturnRef(engine)); -// EXPECT_CALL(callbacks_.route_->route_entry_, perFilterConfig(HttpFilterNames::get().Rbac)) -// .WillRepeatedly(Return(&per_route_config_)); + EXPECT_CALL(callbacks_.route_->route_entry_, perFilterConfig(HttpFilterNames::get().Rbac)) + .WillRepeatedly(Return(&per_route_config_)); -// EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, true)); -// } + EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, true)); +} // Log Tests TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { From 31d5e600fb69f4f796190a25d99adcdcf0f943fd Mon Sep 17 00:00:00 2001 From: davidraskin Date: Wed, 5 Aug 2020 06:36:12 +0000 Subject: [PATCH 35/39] fix format Signed-off-by: davidraskin --- docs/root/version_history/current.rst | 2 +- source/extensions/filters/common/rbac/engine.h | 3 ++- source/extensions/filters/http/rbac/rbac_filter.cc | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index bf0478eab166c..7df592b5f8387 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -59,8 +59,8 @@ New Features * load balancer: added a :ref:`configuration` option to specify the active request bias used by the least request load balancer. * lua: added Lua APIs to access :ref:`SSL connection info ` object. * postgres network filter: :ref:`metadata ` is produced based on SQL query. -* rbac filter: added a log action to the :ref:`RBAC filter ` which sets dynamic metadata to inform access loggers whether to log. * ratelimit: added :ref:`enable_x_ratelimit_headers ` option to enable `X-RateLimit-*` headers as defined in `draft RFC `_. +* rbac filter: added a log action to the :ref:`RBAC filter ` which sets dynamic metadata to inform access loggers whether to log. * router: added new :ref:`envoy-ratelimited` retry policy, which allows retrying envoy's own rate limited responses. diff --git a/source/extensions/filters/common/rbac/engine.h b/source/extensions/filters/common/rbac/engine.h index 777db8ad3783a..0e0dc9b6c968f 100644 --- a/source/extensions/filters/common/rbac/engine.h +++ b/source/extensions/filters/common/rbac/engine.h @@ -31,7 +31,8 @@ class RoleBasedAccessControlEngine { */ virtual bool handleAction(const Network::Connection& connection, const Envoy::Http::RequestHeaderMap& headers, - StreamInfo::StreamInfo& info, std::string* effective_policy_id) const PURE; + StreamInfo::StreamInfo& info, + std::string* effective_policy_id) const PURE; /** * Handles action-specific operations and returns whether or not the request is permitted. diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index e52cfb4281974..86dac66020530 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -92,7 +92,7 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo } ProtobufWkt::Struct metrics; - + auto& fields = *metrics.mutable_fields(); if (!effective_policy_id.empty()) { *fields[Filters::Common::RBAC::DynamicMetadataKeysSingleton::get() From b2881d290b7c3b5f1803484980a8cbc7ebbf01a0 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Thu, 6 Aug 2020 16:03:33 +0000 Subject: [PATCH 36/39] Update test logic Signed-off-by: davidraskin --- .../extensions/filters/common/rbac/engine.h | 4 +- .../filters/common/rbac/engine_impl.cc | 2 +- .../filters/http/rbac/rbac_filter.cc | 1 - .../filters/common/rbac/engine_impl_test.cc | 130 ++++-------------- test/extensions/filters/common/rbac/mocks.h | 2 +- .../http/rbac/rbac_filter_integration_test.cc | 33 ++--- .../filters/http/rbac/rbac_filter_test.cc | 107 +++++++------- 7 files changed, 90 insertions(+), 189 deletions(-) diff --git a/source/extensions/filters/common/rbac/engine.h b/source/extensions/filters/common/rbac/engine.h index 0e0dc9b6c968f..7174d4edb8607 100644 --- a/source/extensions/filters/common/rbac/engine.h +++ b/source/extensions/filters/common/rbac/engine.h @@ -25,7 +25,7 @@ class RoleBasedAccessControlEngine { * @param headers the headers of the incoming request used to identify the action/principal. An * empty map should be used if there are no headers available. * @param info the per-request or per-connection stream info with additional information - * about the action/principal. Can be modified by an Action. + * about the action/principal. Can be modified by the LOG Action. * @param effective_policy_id it will be filled by the matching policy's ID, * which is used to identity the source of the allow/deny. */ @@ -39,7 +39,7 @@ class RoleBasedAccessControlEngine { * * @param connection the downstream connection used to identify the action/principal. * @param info the per-request or per-connection stream info with additional information - * about the action/principal. Can be modified by an Action. + * about the action/principal. Can be modified by the LOG Action. * @param effective_policy_id it will be filled by the matching policy's ID, * which is used to identity the source of the allow/deny. */ diff --git a/source/extensions/filters/common/rbac/engine_impl.cc b/source/extensions/filters/common/rbac/engine_impl.cc index d2da2c74c5b63..339bd82669b0d 100644 --- a/source/extensions/filters/common/rbac/engine_impl.cc +++ b/source/extensions/filters/common/rbac/engine_impl.cc @@ -56,7 +56,7 @@ bool RoleBasedAccessControlEngineImpl::handleAction(const Network::Connection& c return true; } default: - return true; + NOT_REACHED_GCOVR_EXCL_LINE; } return true; diff --git a/source/extensions/filters/http/rbac/rbac_filter.cc b/source/extensions/filters/http/rbac/rbac_filter.cc index 86dac66020530..d396db7f52bcd 100644 --- a/source/extensions/filters/http/rbac/rbac_filter.cc +++ b/source/extensions/filters/http/rbac/rbac_filter.cc @@ -109,7 +109,6 @@ RoleBasedAccessControlFilter::decodeHeaders(Http::RequestHeaderMap& headers, boo const auto engine = config_->engine(callbacks_->route(), Filters::Common::RBAC::EnforcementMode::Enforced); if (engine != nullptr) { - // Check authorization decision and do Action operations if (engine->handleAction(*callbacks_->connection(), headers, callbacks_->streamInfo(), nullptr)) { ENVOY_LOG(debug, "enforced allowed"); diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index 0b791b6acad08..6a7741d0e2117 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -27,34 +27,18 @@ namespace { enum class LogResult { Yes, No, Undecided }; void checkEngine( - RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, StreamInfo::StreamInfo& info, + RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, LogResult expectedLog, + StreamInfo::StreamInfo& info, const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { bool engineRes = engine.handleAction(connection, headers, info, nullptr); EXPECT_EQ(expected, engineRes); -} - -void checkEngine( - RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, - const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), - const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { - NiceMock empty_info; - checkEngine(engine, expected, empty_info, connection, headers); -} - -void checkEngineLog( - RBAC::RoleBasedAccessControlEngineImpl& engine, LogResult expected, - NiceMock& info, - const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), - const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { - engine.handleAction(connection, headers, info, nullptr); - - if (expected != LogResult::Undecided) { + if (expectedLog != LogResult::Undecided) { auto filter_meta = info.dynamicMetadata().filter_metadata().at( RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); - EXPECT_EQ(expected == LogResult::Yes, + EXPECT_EQ(expectedLog == LogResult::Yes, filter_meta.fields() .at(RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) .bool_value()); @@ -65,6 +49,15 @@ void checkEngineLog( } } +void checkEngine( + RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, LogResult expectedLog, + const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), + const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { + + NiceMock empty_info; + checkEngine(engine, expected, expectedLog, empty_info, connection, headers); +} + void onMetadata(NiceMock& info) { ON_CALL(info, setDynamicMetadata("envoy.common", _)) .WillByDefault(Invoke([&info](const std::string&, const ProtobufWkt::Struct& obj) { @@ -76,11 +69,11 @@ TEST(RoleBasedAccessControlEngineImpl, Disabled) { envoy::config::rbac::v3::RBAC rbac; rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); RBAC::RoleBasedAccessControlEngineImpl engine_allow(rbac); - checkEngine(engine_allow, false); + checkEngine(engine_allow, false, LogResult::Undecided); rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); RBAC::RoleBasedAccessControlEngineImpl engine_deny(rbac); - checkEngine(engine_deny, true); + checkEngine(engine_deny, true, LogResult::Undecided); } // Test various invalid policies to validate the fix for @@ -185,11 +178,11 @@ TEST(RoleBasedAccessControlEngineImpl, AllowedAllowlist) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, true, info, conn, headers); + checkEngine(engine, true, LogResult::Undecided, info, conn, headers); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, false, info, conn, headers); + checkEngine(engine, false, LogResult::Undecided, info, conn, headers); } TEST(RoleBasedAccessControlEngineImpl, DeniedDenylist) { @@ -208,11 +201,11 @@ TEST(RoleBasedAccessControlEngineImpl, DeniedDenylist) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, false, info, conn, headers); + checkEngine(engine, false, LogResult::Undecided, info, conn, headers); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngine(engine, true, info, conn, headers); + checkEngine(engine, true, LogResult::Undecided, info, conn, headers); } TEST(RoleBasedAccessControlEngineImpl, BasicCondition) { @@ -229,7 +222,7 @@ TEST(RoleBasedAccessControlEngineImpl, BasicCondition) { rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); (*rbac.mutable_policies())["foo"] = policy; RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - checkEngine(engine, false); + checkEngine(engine, false, LogResult::Undecided); } TEST(RoleBasedAccessControlEngineImpl, MalformedCondition) { @@ -271,7 +264,7 @@ TEST(RoleBasedAccessControlEngineImpl, MistypedCondition) { rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); (*rbac.mutable_policies())["foo"] = policy; RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - checkEngine(engine, false); + checkEngine(engine, false, LogResult::Undecided); } TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { @@ -296,7 +289,7 @@ TEST(RoleBasedAccessControlEngineImpl, ErrorCondition) { rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); (*rbac.mutable_policies())["foo"] = policy; RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - checkEngine(engine, false, Envoy::Network::MockConnection()); + checkEngine(engine, false, LogResult::Undecided, Envoy::Network::MockConnection()); } TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { @@ -332,7 +325,7 @@ TEST(RoleBasedAccessControlEngineImpl, HeaderCondition) { std::string value = "bar"; headers.setReference(key, value); - checkEngine(engine, true, Envoy::Network::MockConnection(), headers); + checkEngine(engine, true, LogResult::Undecided, Envoy::Network::MockConnection(), headers); } TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { @@ -377,7 +370,7 @@ TEST(RoleBasedAccessControlEngineImpl, MetadataCondition) { Protobuf::MapPair("other", label)); EXPECT_CALL(Const(info), dynamicMetadata()).WillRepeatedly(ReturnRef(metadata)); - checkEngine(engine, true, info, Envoy::Network::MockConnection(), headers); + checkEngine(engine, true, LogResult::Undecided, info, Envoy::Network::MockConnection(), headers); } TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { @@ -401,7 +394,7 @@ TEST(RoleBasedAccessControlEngineImpl, ConjunctiveCondition) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).Times(1).WillRepeatedly(ReturnRef(addr)); - checkEngine(engine, false, info, conn, headers); + checkEngine(engine, false, LogResult::Undecided, info, conn, headers); } // Log tests @@ -412,7 +405,7 @@ TEST(RoleBasedAccessControlEngineImpl, DisabledLog) { envoy::config::rbac::v3::RBAC rbac; rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - checkEngineLog(engine, RBAC::LogResult::No, info); + checkEngine(engine, true, RBAC::LogResult::No, info); } TEST(RoleBasedAccessControlEngineImpl, LogIfMatched) { @@ -433,78 +426,11 @@ TEST(RoleBasedAccessControlEngineImpl, LogIfMatched) { Envoy::Network::Address::InstanceConstSharedPtr addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, RBAC::LogResult::Yes, info, conn, headers); + checkEngine(engine, true, RBAC::LogResult::Yes, info, conn, headers); addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); EXPECT_CALL(Const(info), downstreamLocalAddress()).WillOnce(ReturnRef(addr)); - checkEngineLog(engine, RBAC::LogResult::No, info, conn, headers); -} - -TEST(RoleBasedAccessControlEngineImpl, LogAllowUndecided) { - envoy::config::rbac::v3::Policy policy; - policy.add_permissions()->set_destination_port(123); - policy.add_principals()->set_any(true); - - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::ALLOW); - (*rbac.mutable_policies())["foo"] = policy; - RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - - Envoy::Network::MockConnection conn; - Envoy::Http::TestRequestHeaderMapImpl headers; - NiceMock info; - onMetadata(info); - - Envoy::Network::Address::InstanceConstSharedPtr addr = - Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngineLog(engine, RBAC::LogResult::Undecided, info, conn, headers); - - addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngineLog(engine, RBAC::LogResult::Undecided, info, conn, headers); -} - -TEST(RoleBasedAccessControlEngineImpl, LogDenyUndecided) { - envoy::config::rbac::v3::Policy policy; - policy.add_permissions()->set_destination_port(123); - policy.add_principals()->set_any(true); - - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::DENY); - (*rbac.mutable_policies())["foo"] = policy; - RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - - Envoy::Network::MockConnection conn; - Envoy::Http::TestRequestHeaderMapImpl headers; - NiceMock info; - onMetadata(info); - - Envoy::Network::Address::InstanceConstSharedPtr addr = - Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngineLog(engine, RBAC::LogResult::Undecided, info, conn, headers); - - addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngineLog(engine, RBAC::LogResult::Undecided, info, conn, headers); -} - -TEST(RoleBasedAccessControlEngineImpl, LogAllowAll) { - envoy::config::rbac::v3::Policy policy; - policy.add_permissions()->set_destination_port(123); - policy.add_principals()->set_any(true); - - envoy::config::rbac::v3::RBAC rbac; - rbac.set_action(envoy::config::rbac::v3::RBAC::LOG); - (*rbac.mutable_policies())["foo"] = policy; - RBAC::RoleBasedAccessControlEngineImpl engine(rbac); - - Envoy::Network::MockConnection conn; - Envoy::Http::TestRequestHeaderMapImpl headers; - NiceMock info; - Envoy::Network::Address::InstanceConstSharedPtr addr = - Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 123, false); - checkEngine(engine, true, info, conn, headers); - - addr = Envoy::Network::Utility::parseInternetAddress("1.2.3.4", 456, false); - checkEngine(engine, true, info, conn, headers); + checkEngine(engine, true, RBAC::LogResult::No, info, conn, headers); } } // namespace diff --git a/test/extensions/filters/common/rbac/mocks.h b/test/extensions/filters/common/rbac/mocks.h index 5ed798aacdb16..a99e97aa9ea69 100644 --- a/test/extensions/filters/common/rbac/mocks.h +++ b/test/extensions/filters/common/rbac/mocks.h @@ -15,7 +15,7 @@ namespace RBAC { class MockEngine : public RoleBasedAccessControlEngineImpl { public: MockEngine(const envoy::config::rbac::v3::RBAC& rules, - const EnforcementMode mode = EnforcementMode::Shadow) + const EnforcementMode mode = EnforcementMode::Enforced) : RoleBasedAccessControlEngineImpl(rules, mode){}; MOCK_METHOD(bool, handleAction, diff --git a/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc b/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc index 5e4dab16418ef..b7fcd3ebcbb78 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_integration_test.cc @@ -65,14 +65,17 @@ name: rbac )EOF"; const std::string RBAC_CONFIG_WITH_LOG_ACTION = R"EOF( -rules: - action: LOG - policies: - foo: - permissions: - - header: { name: ":method", exact_match: "GET" } - principals: - - any: true +name: rbac +typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC + rules: + action: LOG + policies: + foo: + permissions: + - header: { name: ":method", exact_match: "GET" } + principals: + - any: true )EOF"; using RBACIntegrationTest = HttpProtocolIntegrationTest; @@ -288,20 +291,8 @@ TEST_P(RBACIntegrationTest, PathIgnoreCase) { } } -std::string getRBACFilterConfig(const std::string& config_str) { - envoy::extensions::filters::http::rbac::v3::RBAC rbac_config; - envoy::extensions::filters::network::http_connection_manager::v3::HttpFilter http_filter; - - TestUtility::loadFromYaml(config_str, rbac_config); - - http_filter.set_name(Extensions::HttpFilters::HttpFilterNames::get().Rbac); - http_filter.mutable_typed_config()->PackFrom(rbac_config); - - return MessageUtil::getJsonStringFromMessage(http_filter); -} - TEST_P(RBACIntegrationTest, LogConnectionAllow) { - config_helper_.addFilter(getRBACFilterConfig(RBAC_CONFIG_WITH_LOG_ACTION)); + config_helper_.addFilter(RBAC_CONFIG_WITH_LOG_ACTION); initialize(); codec_client_ = makeHttpConnection(lookupPort("http")); diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index 68aa94daebe24..519a49126bbb7 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -24,6 +24,8 @@ namespace HttpFilters { namespace RBACFilter { namespace { +enum class LogResult { Yes, No, Undecided }; + class RoleBasedAccessControlFilterTest : public testing::Test { public: RoleBasedAccessControlFilterConfigSharedPtr @@ -52,14 +54,12 @@ class RoleBasedAccessControlFilterTest : public testing::Test { } RoleBasedAccessControlFilterTest() - : config_(setupConfig(envoy::config::rbac::v3::RBAC::ALLOW)), filter_(config_), - log_config_(setupConfig(envoy::config::rbac::v3::RBAC::LOG)), log_filter_(log_config_) {} + : config_(setupConfig(envoy::config::rbac::v3::RBAC::ALLOW)), filter_(config_) {} void SetUp() override { EXPECT_CALL(callbacks_, connection()).WillRepeatedly(Return(&connection_)); EXPECT_CALL(callbacks_, streamInfo()).WillRepeatedly(ReturnRef(req_info_)); filter_.setDecoderFilterCallbacks(callbacks_); - log_filter_.setDecoderFilterCallbacks(callbacks_); } void setDestinationPort(uint16_t port) { @@ -72,13 +72,19 @@ class RoleBasedAccessControlFilterTest : public testing::Test { ON_CALL(connection_, requestedServerName()).WillByDefault(Return(requested_server_name_)); } - void checkAccessLogMetadata(bool expected) { - auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at( - Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); - EXPECT_EQ(expected, - filter_meta.fields() - .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) - .bool_value()); + void checkAccessLogMetadata(LogResult expected) { + if (expected != LogResult::Undecided) { + auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); + EXPECT_EQ(expected == LogResult::Yes, + filter_meta.fields() + .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) + .bool_value()); + } else { + EXPECT_EQ(req_info_.dynamicMetadata().filter_metadata().end(), + req_info_.dynamicMetadata().filter_metadata().find( + Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace)); + } } void setMetadata() { @@ -105,8 +111,6 @@ class RoleBasedAccessControlFilterTest : public testing::Test { Stats::IsolatedStoreImpl store_; RoleBasedAccessControlFilterConfigSharedPtr config_; RoleBasedAccessControlFilter filter_; - RoleBasedAccessControlFilterConfigSharedPtr log_config_; - RoleBasedAccessControlFilter log_filter_; Network::Address::InstanceConstSharedPtr address_; std::string requested_server_name_; @@ -116,6 +120,7 @@ class RoleBasedAccessControlFilterTest : public testing::Test { TEST_F(RoleBasedAccessControlFilterTest, Allowed) { setDestinationPort(123); + setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); Http::MetadataMap metadata_map{{"metadata", "metadata"}}; @@ -126,11 +131,14 @@ TEST_F(RoleBasedAccessControlFilterTest, Allowed) { Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_.decodeTrailers(trailers_)); + + checkAccessLogMetadata(LogResult::Undecided); } TEST_F(RoleBasedAccessControlFilterTest, RequestedServerName) { setDestinationPort(999); setRequestedServerName("www.cncf.io"); + setMetadata(); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); EXPECT_EQ(1U, config_->stats().allowed_.value()); @@ -142,18 +150,12 @@ TEST_F(RoleBasedAccessControlFilterTest, RequestedServerName) { EXPECT_EQ(Http::FilterDataStatus::Continue, filter_.decodeData(data, false)); EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_.decodeTrailers(trailers_)); - // Check Log - setMetadata(); - EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); - auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at( - Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); - EXPECT_EQ(true, filter_meta.fields() - .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) - .bool_value()); + checkAccessLogMetadata(LogResult::Undecided); } TEST_F(RoleBasedAccessControlFilterTest, Path) { setDestinationPort(999); + setMetadata(); auto headers = Http::TestRequestHeaderMapImpl{ {":method", "GET"}, @@ -162,23 +164,7 @@ TEST_F(RoleBasedAccessControlFilterTest, Path) { {":authority", "host"}, }; EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers, false)); - - headers = Http::TestRequestHeaderMapImpl{ - {":method", "GET"}, - {":path", "prefix/suffix/next"}, - {":scheme", "http"}, - {":authority", "host"}, - }; - EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_.decodeHeaders(headers, false)); - - // Check Log - setMetadata(); - EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers, false)); - auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at( - Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); - EXPECT_EQ(false, filter_meta.fields() - .at(Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) - .bool_value()); + checkAccessLogMetadata(LogResult::Undecided); } TEST_F(RoleBasedAccessControlFilterTest, Denied) { @@ -201,10 +187,12 @@ TEST_F(RoleBasedAccessControlFilterTest, Denied) { EXPECT_EQ("allowed", filter_meta.fields().at("shadow_engine_result").string_value()); EXPECT_EQ("bar", filter_meta.fields().at("shadow_effective_policy_id").string_value()); EXPECT_EQ("rbac_access_denied", callbacks_.details_); + checkAccessLogMetadata(LogResult::Undecided); } TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { setDestinationPort(456); + setMetadata(); envoy::extensions::filters::http::rbac::v3::RBACPerRoute route_config; route_config.mutable_rbac()->mutable_rules()->set_action(envoy::config::rbac::v3::RBAC::DENY); @@ -218,49 +206,46 @@ TEST_F(RoleBasedAccessControlFilterTest, RouteLocalOverride) { .WillRepeatedly(Return(&per_route_config_)); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, true)); + checkAccessLogMetadata(LogResult::Undecided); } // Log Tests TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { + config_ = setupConfig(envoy::config::rbac::v3::RBAC::LOG); + filter_ = RoleBasedAccessControlFilter(config_); + filter_.setDecoderFilterCallbacks(callbacks_); + setDestinationPort(123); setMetadata(); - EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); - EXPECT_EQ(1U, log_config_->stats().allowed_.value()); - EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); + EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); + EXPECT_EQ(1U, config_->stats().allowed_.value()); + EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); Buffer::OwnedImpl data(""); - EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); - EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); + EXPECT_EQ(Http::FilterDataStatus::Continue, filter_.decodeData(data, false)); + EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_.decodeTrailers(trailers_)); - checkAccessLogMetadata(true); + checkAccessLogMetadata(LogResult::Yes); } TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { + config_ = setupConfig(envoy::config::rbac::v3::RBAC::LOG); + filter_ = RoleBasedAccessControlFilter(config_); + filter_.setDecoderFilterCallbacks(callbacks_); + setDestinationPort(456); setMetadata(); - EXPECT_EQ(Http::FilterHeadersStatus::Continue, log_filter_.decodeHeaders(headers_, false)); - EXPECT_EQ(1U, log_config_->stats().allowed_.value()); - EXPECT_EQ(0U, log_config_->stats().shadow_denied_.value()); + EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); + EXPECT_EQ(1U, config_->stats().allowed_.value()); + EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); Buffer::OwnedImpl data(""); - EXPECT_EQ(Http::FilterDataStatus::Continue, log_filter_.decodeData(data, false)); - EXPECT_EQ(Http::FilterTrailersStatus::Continue, log_filter_.decodeTrailers(trailers_)); - - checkAccessLogMetadata(false); -} - -TEST_F(RoleBasedAccessControlFilterTest, AllowNoChangeLog) { - setDestinationPort(123); - setMetadata(); - - EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(headers_, false)); + EXPECT_EQ(Http::FilterDataStatus::Continue, filter_.decodeData(data, false)); + EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_.decodeTrailers(trailers_)); - // Check that Allow action does not set access log metadata - EXPECT_EQ(req_info_.dynamicMetadata().filter_metadata().end(), - req_info_.dynamicMetadata().filter_metadata().find( - Filters::Common::RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace)); + checkAccessLogMetadata(LogResult::No); } } // namespace From 6c11ca550ccc1e62e4d20ff33de2eba9ae059df5 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Thu, 6 Aug 2020 17:57:16 +0000 Subject: [PATCH 37/39] clang-tidy fix Signed-off-by: davidraskin --- .../extensions/filters/common/rbac/engine_impl_test.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index 6a7741d0e2117..b9d8608a92083 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -27,7 +27,7 @@ namespace { enum class LogResult { Yes, No, Undecided }; void checkEngine( - RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, LogResult expectedLog, + RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, LogResult expected_log, StreamInfo::StreamInfo& info, const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { @@ -35,10 +35,10 @@ void checkEngine( bool engineRes = engine.handleAction(connection, headers, info, nullptr); EXPECT_EQ(expected, engineRes); - if (expectedLog != LogResult::Undecided) { + if (expected_log != LogResult::Undecided) { auto filter_meta = info.dynamicMetadata().filter_metadata().at( RBAC::DynamicMetadataKeysSingleton::get().CommonNamespace); - EXPECT_EQ(expectedLog == LogResult::Yes, + EXPECT_EQ(expected_log == LogResult::Yes, filter_meta.fields() .at(RBAC::DynamicMetadataKeysSingleton::get().AccessLogKey) .bool_value()); @@ -50,12 +50,12 @@ void checkEngine( } void checkEngine( - RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, LogResult expectedLog, + RBAC::RoleBasedAccessControlEngineImpl& engine, bool expected, LogResult expected_log, const Envoy::Network::Connection& connection = Envoy::Network::MockConnection(), const Envoy::Http::RequestHeaderMap& headers = Envoy::Http::TestRequestHeaderMapImpl()) { NiceMock empty_info; - checkEngine(engine, expected, expectedLog, empty_info, connection, headers); + checkEngine(engine, expected, expected_log, empty_info, connection, headers); } void onMetadata(NiceMock& info) { From 879729cd9bafcf134ffbb0e004a8413946f5c522 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Thu, 6 Aug 2020 19:54:10 +0000 Subject: [PATCH 38/39] Remove unneeded return Signed-off-by: davidraskin --- source/extensions/filters/common/rbac/engine_impl.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/extensions/filters/common/rbac/engine_impl.cc b/source/extensions/filters/common/rbac/engine_impl.cc index 339bd82669b0d..dc2a6ba79222a 100644 --- a/source/extensions/filters/common/rbac/engine_impl.cc +++ b/source/extensions/filters/common/rbac/engine_impl.cc @@ -58,8 +58,6 @@ bool RoleBasedAccessControlEngineImpl::handleAction(const Network::Connection& c default: NOT_REACHED_GCOVR_EXCL_LINE; } - - return true; } bool RoleBasedAccessControlEngineImpl::checkPolicyMatch( From 37b7425fba49d5fc71de8556cba2c483b30a0af1 Mon Sep 17 00:00:00 2001 From: davidraskin Date: Mon, 10 Aug 2020 22:33:48 +0000 Subject: [PATCH 39/39] Hopefully fixed merge issue Signed-off-by: davidraskin --- docs/root/version_history/current.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index fbc8b0e69b79f..4a6ac04a2576d 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -59,7 +59,7 @@ New Features * load balancer: added a :ref:`configuration` option to specify the active request bias used by the least request load balancer. * lua: added Lua APIs to access :ref:`SSL connection info ` object. * postgres network filter: :ref:`metadata ` is produced based on SQL query. -* ratelimit: added :ref:`enable_x_ratelimit_headers ` option to enable `X-RateLimit-*` headers as defined in `draft RFC `_. +* ratelimit: added :ref:`enable_x_ratelimit_headers ` option to enable `X-RateLimit-*` headers as defined in `draft RFC `_. * rbac filter: added a log action to the :ref:`RBAC filter ` which sets dynamic metadata to inform access loggers whether to log. * router: added new :ref:`envoy-ratelimited`