/proc/self/cwd/source/extensions/filters/common/ext_authz/ext_authz_grpc_impl.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "source/extensions/filters/common/ext_authz/ext_authz_grpc_impl.h" |
2 | | |
3 | | #include "envoy/config/core/v3/base.pb.h" |
4 | | #include "envoy/service/auth/v3/external_auth.pb.h" |
5 | | |
6 | | #include "source/common/common/assert.h" |
7 | | #include "source/common/grpc/async_client_impl.h" |
8 | | #include "source/common/http/headers.h" |
9 | | #include "source/common/http/utility.h" |
10 | | #include "source/common/network/utility.h" |
11 | | #include "source/common/protobuf/protobuf.h" |
12 | | |
13 | | namespace Envoy { |
14 | | namespace Extensions { |
15 | | namespace Filters { |
16 | | namespace Common { |
17 | | namespace ExtAuthz { |
18 | | |
19 | | GrpcClientImpl::GrpcClientImpl(const Grpc::RawAsyncClientSharedPtr& async_client, |
20 | | const absl::optional<std::chrono::milliseconds>& timeout) |
21 | | : async_client_(async_client), timeout_(timeout), |
22 | | service_method_(*Protobuf::DescriptorPool::generated_pool()->FindMethodByName( |
23 | 5 | "envoy.service.auth.v3.Authorization.Check")) {} |
24 | | |
25 | 5 | GrpcClientImpl::~GrpcClientImpl() { ASSERT(!callbacks_); } |
26 | | |
27 | 3 | void GrpcClientImpl::cancel() { |
28 | 3 | ASSERT(callbacks_ != nullptr); |
29 | 3 | request_->cancel(); |
30 | 3 | callbacks_ = nullptr; |
31 | 3 | } |
32 | | |
33 | | void GrpcClientImpl::check(RequestCallbacks& callbacks, |
34 | | const envoy::service::auth::v3::CheckRequest& request, |
35 | 3 | Tracing::Span& parent_span, const StreamInfo::StreamInfo& stream_info) { |
36 | 3 | ASSERT(callbacks_ == nullptr); |
37 | 3 | callbacks_ = &callbacks; |
38 | 3 | Http::AsyncClient::RequestOptions options; |
39 | 3 | options.setTimeout(timeout_); |
40 | 3 | options.setParentContext(Http::AsyncClient::ParentContext{&stream_info}); |
41 | | |
42 | 3 | ENVOY_LOG(trace, "Sending CheckRequest: {}", request.DebugString()); |
43 | 3 | request_ = async_client_->send(service_method_, request, *this, parent_span, options); |
44 | 3 | } |
45 | | |
46 | | void GrpcClientImpl::onSuccess(std::unique_ptr<envoy::service::auth::v3::CheckResponse>&& response, |
47 | 0 | Tracing::Span& span) { |
48 | 0 | ENVOY_LOG(trace, "Received CheckResponse: {}", response->DebugString()); |
49 | 0 | ResponsePtr authz_response = std::make_unique<Response>(Response{}); |
50 | 0 | if (response->status().code() == Grpc::Status::WellKnownGrpcStatus::Ok) { |
51 | 0 | span.setTag(TracingConstants::get().TraceStatus, TracingConstants::get().TraceOk); |
52 | 0 | authz_response->status = CheckStatus::OK; |
53 | 0 | if (response->has_ok_response()) { |
54 | 0 | toAuthzResponseHeader(authz_response, response->ok_response().headers()); |
55 | 0 | if (response->ok_response().headers_to_remove_size() > 0) { |
56 | 0 | for (const auto& header : response->ok_response().headers_to_remove()) { |
57 | 0 | authz_response->headers_to_remove.push_back(Http::LowerCaseString(header)); |
58 | 0 | } |
59 | 0 | } |
60 | 0 | if (response->ok_response().query_parameters_to_set_size() > 0) { |
61 | 0 | for (const auto& query_parameter : response->ok_response().query_parameters_to_set()) { |
62 | 0 | authz_response->query_parameters_to_set.push_back( |
63 | 0 | std::pair(query_parameter.key(), query_parameter.value())); |
64 | 0 | } |
65 | 0 | } |
66 | 0 | if (response->ok_response().query_parameters_to_remove_size() > 0) { |
67 | 0 | for (const auto& key : response->ok_response().query_parameters_to_remove()) { |
68 | 0 | authz_response->query_parameters_to_remove.push_back(key); |
69 | 0 | } |
70 | 0 | } |
71 | | // These two vectors hold header overrides of encoded response headers. |
72 | 0 | if (response->ok_response().response_headers_to_add_size() > 0) { |
73 | 0 | for (const auto& header : response->ok_response().response_headers_to_add()) { |
74 | 0 | if (header.append().value()) { |
75 | 0 | authz_response->response_headers_to_add.emplace_back( |
76 | 0 | Http::LowerCaseString(header.header().key()), header.header().value()); |
77 | 0 | } else { |
78 | 0 | authz_response->response_headers_to_set.emplace_back( |
79 | 0 | Http::LowerCaseString(header.header().key()), header.header().value()); |
80 | 0 | } |
81 | 0 | } |
82 | 0 | } |
83 | 0 | } |
84 | 0 | } else { |
85 | 0 | span.setTag(TracingConstants::get().TraceStatus, TracingConstants::get().TraceUnauthz); |
86 | 0 | authz_response->status = CheckStatus::Denied; |
87 | | |
88 | | // The default HTTP status code for denied response is 403 Forbidden. |
89 | 0 | authz_response->status_code = Http::Code::Forbidden; |
90 | 0 | if (response->has_denied_response()) { |
91 | 0 | toAuthzResponseHeader(authz_response, response->denied_response().headers()); |
92 | |
|
93 | 0 | const uint32_t status_code = response->denied_response().status().code(); |
94 | 0 | if (status_code > 0) { |
95 | 0 | authz_response->status_code = static_cast<Http::Code>(status_code); |
96 | 0 | } |
97 | 0 | authz_response->body = response->denied_response().body(); |
98 | 0 | } |
99 | 0 | } |
100 | | |
101 | | // OkHttpResponse.dynamic_metadata is deprecated. Until OkHttpResponse.dynamic_metadata is |
102 | | // removed, it overrides dynamic_metadata field of the outer check response. |
103 | 0 | if (response->has_ok_response() && response->ok_response().has_dynamic_metadata()) { |
104 | 0 | authz_response->dynamic_metadata = response->ok_response().dynamic_metadata(); |
105 | 0 | } else { |
106 | 0 | authz_response->dynamic_metadata = response->dynamic_metadata(); |
107 | 0 | } |
108 | |
|
109 | 0 | callbacks_->onComplete(std::move(authz_response)); |
110 | 0 | callbacks_ = nullptr; |
111 | 0 | } |
112 | | |
113 | | void GrpcClientImpl::onFailure(Grpc::Status::GrpcStatus status, const std::string&, |
114 | 0 | Tracing::Span&) { |
115 | 0 | ENVOY_LOG(trace, "CheckRequest call failed with status: {}", |
116 | 0 | Grpc::Utility::grpcStatusToString(status)); |
117 | 0 | ASSERT(status != Grpc::Status::WellKnownGrpcStatus::Ok); |
118 | 0 | Response response{}; |
119 | 0 | response.status = CheckStatus::Error; |
120 | 0 | response.status_code = Http::Code::Forbidden; |
121 | 0 | callbacks_->onComplete(std::make_unique<Response>(response)); |
122 | 0 | callbacks_ = nullptr; |
123 | 0 | } |
124 | | |
125 | | void GrpcClientImpl::toAuthzResponseHeader( |
126 | | ResponsePtr& response, |
127 | 0 | const Protobuf::RepeatedPtrField<envoy::config::core::v3::HeaderValueOption>& headers) { |
128 | 0 | for (const auto& header : headers) { |
129 | 0 | if (header.append().value()) { |
130 | 0 | response->headers_to_append.emplace_back(Http::LowerCaseString(header.header().key()), |
131 | 0 | header.header().value()); |
132 | 0 | } else { |
133 | 0 | response->headers_to_set.emplace_back(Http::LowerCaseString(header.header().key()), |
134 | 0 | header.header().value()); |
135 | 0 | } |
136 | 0 | } |
137 | 0 | } |
138 | | |
139 | | } // namespace ExtAuthz |
140 | | } // namespace Common |
141 | | } // namespace Filters |
142 | | } // namespace Extensions |
143 | | } // namespace Envoy |