From 16b9c3ad5f0525b08593b2d6202933313bd47bf3 Mon Sep 17 00:00:00 2001 From: Pengyuan Bian Date: Mon, 4 Nov 2019 17:05:13 -0800 Subject: [PATCH] Add response flags into cel expression context (#8827) Description: Add response flags into expression context Risk Level: low Testing: unit test Docs Changes: Release Notes: Signed-off-by: Pengyuan Bian --- docs/root/intro/arch_overview/security/rbac_filter.rst | 1 + include/envoy/stream_info/stream_info.h | 5 +++++ source/common/stream_info/stream_info_impl.h | 2 ++ source/extensions/filters/common/expr/BUILD | 1 + source/extensions/filters/common/expr/context.cc | 2 ++ source/extensions/filters/common/expr/context.h | 1 + test/common/stream_info/stream_info_impl_test.cc | 1 + test/common/stream_info/test_util.h | 1 + test/extensions/filters/common/expr/context_test.cc | 7 +++++++ test/mocks/stream_info/mocks.h | 1 + 10 files changed, 22 insertions(+) diff --git a/docs/root/intro/arch_overview/security/rbac_filter.rst b/docs/root/intro/arch_overview/security/rbac_filter.rst index f69a00f986ae..96685df1ac07 100644 --- a/docs/root/intro/arch_overview/security/rbac_filter.rst +++ b/docs/root/intro/arch_overview/security/rbac_filter.rst @@ -81,6 +81,7 @@ The following attributes are exposed to the language runtime: response.headers, string map, All response headers response.trailers, string map, All response trailers response.size, int, Size of the response body + response.flags, int, Additional details about the response beyond the standard response code source.address, string, Downstream connection remote address source.port, int, Downstream connection remote port destination.address, string, Downstream connection local address diff --git a/include/envoy/stream_info/stream_info.h b/include/envoy/stream_info/stream_info.h index 196d2fb50f2e..49b46080257e 100644 --- a/include/envoy/stream_info/stream_info.h +++ b/include/envoy/stream_info/stream_info.h @@ -357,6 +357,11 @@ class StreamInfo { */ virtual bool hasAnyResponseFlag() const PURE; + /** + * @return response flags encoded as an integer. + */ + virtual uint64_t responseFlags() const PURE; + /** * @return upstream host description. */ diff --git a/source/common/stream_info/stream_info_impl.h b/source/common/stream_info/stream_info_impl.h index cd9f0db4a381..99cc23e980bd 100644 --- a/source/common/stream_info/stream_info_impl.h +++ b/source/common/stream_info/stream_info_impl.h @@ -123,6 +123,8 @@ struct StreamInfoImpl : public StreamInfo { bool hasAnyResponseFlag() const override { return response_flags_ != 0; } + uint64_t responseFlags() const override { return response_flags_; } + void onUpstreamHostSelected(Upstream::HostDescriptionConstSharedPtr host) override { upstream_host_ = host; } diff --git a/source/extensions/filters/common/expr/BUILD b/source/extensions/filters/common/expr/BUILD index 7b2a6f140792..01906b7d2b33 100644 --- a/source/extensions/filters/common/expr/BUILD +++ b/source/extensions/filters/common/expr/BUILD @@ -29,6 +29,7 @@ envoy_cc_library( hdrs = ["context.h"], deps = [ "//source/common/http:utility_lib", + "//source/common/stream_info:utility_lib", "@com_google_cel_cpp//eval/public:cel_value", ], ) diff --git a/source/extensions/filters/common/expr/context.cc b/source/extensions/filters/common/expr/context.cc index b9f1f699e904..a6eaf8a459ca 100644 --- a/source/extensions/filters/common/expr/context.cc +++ b/source/extensions/filters/common/expr/context.cc @@ -129,6 +129,8 @@ absl::optional ResponseWrapper::operator[](CelValue key) const { return CelValue::CreateMap(&headers_); } else if (value == Trailers) { return CelValue::CreateMap(&trailers_); + } else if (value == Flags) { + return CelValue::CreateInt64(info_.responseFlags()); } return {}; } diff --git a/source/extensions/filters/common/expr/context.h b/source/extensions/filters/common/expr/context.h index 1b6c4e07e6ab..0f79f197e677 100644 --- a/source/extensions/filters/common/expr/context.h +++ b/source/extensions/filters/common/expr/context.h @@ -34,6 +34,7 @@ constexpr absl::string_view Duration = "duration"; constexpr absl::string_view Response = "response"; constexpr absl::string_view Code = "code"; constexpr absl::string_view Trailers = "trailers"; +constexpr absl::string_view Flags = "flags"; // Per-request or per-connection metadata constexpr absl::string_view Metadata = "metadata"; diff --git a/test/common/stream_info/stream_info_impl_test.cc b/test/common/stream_info/stream_info_impl_test.cc index 380f60ffcebb..a57d4eaae3e4 100644 --- a/test/common/stream_info/stream_info_impl_test.cc +++ b/test/common/stream_info/stream_info_impl_test.cc @@ -121,6 +121,7 @@ TEST_F(StreamInfoImplTest, ResponseFlagTest) { << fmt::format("Flag: {} was expected to be set", flag); } EXPECT_TRUE(stream_info.hasAnyResponseFlag()); + EXPECT_EQ(0xFFF, stream_info.responseFlags()); StreamInfoImpl stream_info2(Http::Protocol::Http2, test_time_.timeSystem()); stream_info2.setResponseFlag(FailedLocalHealthCheck); diff --git a/test/common/stream_info/test_util.h b/test/common/stream_info/test_util.h index 83627789c3dc..670d981db84e 100644 --- a/test/common/stream_info/test_util.h +++ b/test/common/stream_info/test_util.h @@ -49,6 +49,7 @@ class TestStreamInfo : public StreamInfo::StreamInfo { void setResponseFlag(Envoy::StreamInfo::ResponseFlag response_flag) override { response_flags_ |= response_flag; } + uint64_t responseFlags() const override { return response_flags_; } void onUpstreamHostSelected(Upstream::HostDescriptionConstSharedPtr host) override { upstream_host_ = host; } diff --git a/test/extensions/filters/common/expr/context_test.cc b/test/extensions/filters/common/expr/context_test.cc index a3b52cc89d1b..ce4217cc58fb 100644 --- a/test/extensions/filters/common/expr/context_test.cc +++ b/test/extensions/filters/common/expr/context_test.cc @@ -195,6 +195,7 @@ TEST(Context, ResponseAttributes) { EXPECT_CALL(info, responseCode()).WillRepeatedly(Return(404)); EXPECT_CALL(info, bytesSent()).WillRepeatedly(Return(123)); + EXPECT_CALL(info, responseFlags()).WillRepeatedly(Return(0x1)); { auto value = response[CelValue::CreateString(Undefined)]; @@ -250,6 +251,12 @@ TEST(Context, ResponseAttributes) { ASSERT_TRUE(header.value().IsString()); EXPECT_EQ("b", header.value().StringOrDie().value()); } + { + auto value = response[CelValue::CreateString(Flags)]; + EXPECT_TRUE(value.has_value()); + ASSERT_TRUE(value.value().IsInt64()); + EXPECT_EQ(0x1, value.value().Int64OrDie()); + } } TEST(Context, ConnectionAttributes) { diff --git a/test/mocks/stream_info/mocks.h b/test/mocks/stream_info/mocks.h index 648cafe20a5c..ba3a7af0c536 100644 --- a/test/mocks/stream_info/mocks.h +++ b/test/mocks/stream_info/mocks.h @@ -52,6 +52,7 @@ class MockStreamInfo : public StreamInfo { MOCK_CONST_METHOD0(bytesSent, uint64_t()); MOCK_CONST_METHOD1(hasResponseFlag, bool(ResponseFlag)); MOCK_CONST_METHOD0(hasAnyResponseFlag, bool()); + MOCK_CONST_METHOD0(responseFlags, uint64_t()); MOCK_CONST_METHOD0(upstreamHost, Upstream::HostDescriptionConstSharedPtr()); MOCK_METHOD1(setUpstreamLocalAddress, void(const Network::Address::InstanceConstSharedPtr&)); MOCK_CONST_METHOD0(upstreamLocalAddress, const Network::Address::InstanceConstSharedPtr&());