/proc/self/cwd/source/extensions/filters/network/ext_authz/ext_authz.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "source/extensions/filters/network/ext_authz/ext_authz.h" |
2 | | |
3 | | #include <chrono> |
4 | | #include <cstdint> |
5 | | #include <string> |
6 | | |
7 | | #include "envoy/stats/scope.h" |
8 | | |
9 | | #include "source/common/common/assert.h" |
10 | | #include "source/common/tracing/http_tracer_impl.h" |
11 | | #include "source/extensions/filters/network/well_known_names.h" |
12 | | |
13 | | namespace Envoy { |
14 | | namespace Extensions { |
15 | | namespace NetworkFilters { |
16 | | namespace ExtAuthz { |
17 | | |
18 | 9 | InstanceStats Config::generateStats(const std::string& name, Stats::Scope& scope) { |
19 | 9 | const std::string final_prefix = fmt::format("ext_authz.{}.", name); |
20 | 9 | return {ALL_TCP_EXT_AUTHZ_STATS(POOL_COUNTER_PREFIX(scope, final_prefix), |
21 | 9 | POOL_GAUGE_PREFIX(scope, final_prefix))}; |
22 | 9 | } |
23 | | |
24 | 3 | void Filter::callCheck() { |
25 | 3 | Filters::Common::ExtAuthz::CheckRequestUtils::createTcpCheck(filter_callbacks_, check_request_, |
26 | 3 | config_->includePeerCertificate(), |
27 | 3 | config_->destinationLabels()); |
28 | | // Store start time of ext_authz filter call |
29 | 3 | start_time_ = filter_callbacks_->connection().dispatcher().timeSource().monotonicTime(); |
30 | 3 | status_ = Status::Calling; |
31 | 3 | config_->stats().active_.inc(); |
32 | 3 | config_->stats().total_.inc(); |
33 | | |
34 | 3 | calling_check_ = true; |
35 | 3 | client_->check(*this, check_request_, Tracing::NullSpan::instance(), |
36 | 3 | filter_callbacks_->connection().streamInfo()); |
37 | 3 | calling_check_ = false; |
38 | 3 | } |
39 | | |
40 | 243 | Network::FilterStatus Filter::onData(Buffer::Instance&, bool /* end_stream */) { |
41 | 243 | if (!filterEnabled(filter_callbacks_->connection().streamInfo().dynamicMetadata())) { |
42 | 63 | config_->stats().disabled_.inc(); |
43 | 63 | return Network::FilterStatus::Continue; |
44 | 63 | } |
45 | | |
46 | 180 | if (status_ == Status::NotStarted) { |
47 | | // By waiting to invoke the check at onData() the call to authorization service will have |
48 | | // sufficient information to fill out the checkRequest_. |
49 | 3 | callCheck(); |
50 | 3 | } |
51 | 180 | return filter_return_ == FilterReturn::Stop ? Network::FilterStatus::StopIteration |
52 | 180 | : Network::FilterStatus::Continue; |
53 | 243 | } |
54 | | |
55 | 359 | Network::FilterStatus Filter::onNewConnection() { |
56 | | // Wait till onData() happens. |
57 | 359 | return Network::FilterStatus::Continue; |
58 | 359 | } |
59 | | |
60 | 5 | void Filter::onEvent(Network::ConnectionEvent event) { |
61 | 5 | if (event == Network::ConnectionEvent::RemoteClose || |
62 | 5 | event == Network::ConnectionEvent::LocalClose) { |
63 | 5 | if (status_ == Status::Calling) { |
64 | | // Make sure that any pending request in the client is cancelled. This will be NOP if the |
65 | | // request already completed. |
66 | 3 | client_->cancel(); |
67 | 3 | config_->stats().active_.dec(); |
68 | 3 | } |
69 | 5 | } |
70 | 5 | } |
71 | | |
72 | 0 | void Filter::onComplete(Filters::Common::ExtAuthz::ResponsePtr&& response) { |
73 | 0 | status_ = Status::Complete; |
74 | 0 | config_->stats().active_.dec(); |
75 | |
|
76 | 0 | switch (response->status) { |
77 | 0 | case Filters::Common::ExtAuthz::CheckStatus::OK: |
78 | 0 | config_->stats().ok_.inc(); |
79 | | // Add duration of call to dynamic metadata if applicable |
80 | 0 | if (start_time_.has_value()) { |
81 | 0 | ProtobufWkt::Value ext_authz_duration_value; |
82 | 0 | auto duration = filter_callbacks_->connection().dispatcher().timeSource().monotonicTime() - |
83 | 0 | start_time_.value(); |
84 | 0 | ext_authz_duration_value.set_number_value( |
85 | 0 | std::chrono::duration_cast<std::chrono::milliseconds>(duration).count()); |
86 | 0 | (*response->dynamic_metadata.mutable_fields())["ext_authz_duration"] = |
87 | 0 | ext_authz_duration_value; |
88 | 0 | } |
89 | 0 | break; |
90 | 0 | case Filters::Common::ExtAuthz::CheckStatus::Error: |
91 | 0 | config_->stats().error_.inc(); |
92 | 0 | break; |
93 | 0 | case Filters::Common::ExtAuthz::CheckStatus::Denied: |
94 | 0 | config_->stats().denied_.inc(); |
95 | 0 | break; |
96 | 0 | } |
97 | | |
98 | 0 | if (!response->dynamic_metadata.fields().empty()) { |
99 | |
|
100 | 0 | filter_callbacks_->connection().streamInfo().setDynamicMetadata( |
101 | 0 | NetworkFilterNames::get().ExtAuthorization, response->dynamic_metadata); |
102 | 0 | } |
103 | | |
104 | | // Fail open only if configured to do so and if the check status was a error. |
105 | 0 | if (response->status == Filters::Common::ExtAuthz::CheckStatus::Denied || |
106 | 0 | (response->status == Filters::Common::ExtAuthz::CheckStatus::Error && |
107 | 0 | !config_->failureModeAllow())) { |
108 | 0 | config_->stats().cx_closed_.inc(); |
109 | 0 | filter_callbacks_->connection().close(Network::ConnectionCloseType::NoFlush, "ext_authz_close"); |
110 | 0 | filter_callbacks_->connection().streamInfo().setResponseFlag( |
111 | 0 | StreamInfo::ResponseFlag::UnauthorizedExternalService); |
112 | 0 | filter_callbacks_->connection().streamInfo().setResponseCodeDetails( |
113 | 0 | response->status == Filters::Common::ExtAuthz::CheckStatus::Denied |
114 | 0 | ? Filters::Common::ExtAuthz::ResponseCodeDetails::get().AuthzDenied |
115 | 0 | : Filters::Common::ExtAuthz::ResponseCodeDetails::get().AuthzError); |
116 | 0 | } else { |
117 | | // Let the filter chain continue. |
118 | 0 | filter_return_ = FilterReturn::Continue; |
119 | 0 | if (config_->failureModeAllow() && |
120 | 0 | response->status == Filters::Common::ExtAuthz::CheckStatus::Error) { |
121 | | // Status is Error and yet we are configured to allow traffic. Click a counter. |
122 | 0 | config_->stats().failure_mode_allowed_.inc(); |
123 | 0 | } |
124 | | |
125 | | // We can get completion inline, so only call continue if that isn't happening. |
126 | 0 | if (!calling_check_) { |
127 | 0 | filter_callbacks_->continueReading(); |
128 | 0 | } |
129 | 0 | } |
130 | 0 | } |
131 | | |
132 | | } // namespace ExtAuthz |
133 | | } // namespace NetworkFilters |
134 | | } // namespace Extensions |
135 | | } // namespace Envoy |