Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/extensions/filters/common/expr/context.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/extensions/filters/common/expr/context.h"
2
3
#include "source/common/grpc/common.h"
4
#include "source/common/http/header_map_impl.h"
5
#include "source/common/http/utility.h"
6
#include "source/extensions/filters/common/expr/cel_state.h"
7
8
#include "absl/strings/numbers.h"
9
#include "absl/time/time.h"
10
11
namespace Envoy {
12
namespace Extensions {
13
namespace Filters {
14
namespace Common {
15
namespace Expr {
16
17
Http::RegisterCustomInlineHeader<Http::CustomInlineHeaderRegistry::Type::RequestHeaders>
18
    referer_handle(Http::CustomHeaders::get().Referer);
19
20
936
absl::optional<CelValue> convertHeaderEntry(const Http::HeaderEntry* header) {
21
936
  if (header == nullptr) {
22
912
    return {};
23
912
  }
24
24
  return CelValue::CreateStringView(header->value().getStringView());
25
936
}
26
27
absl::optional<CelValue>
28
convertHeaderEntry(Protobuf::Arena& arena,
29
131k
                   Http::HeaderUtility::GetAllOfHeaderAsStringResult&& result) {
30
131k
  if (!result.result().has_value()) {
31
510
    return {};
32
130k
  } else if (!result.backingString().empty()) {
33
40.1k
    return CelValue::CreateString(
34
40.1k
        Protobuf::Arena::Create<std::string>(&arena, result.backingString()));
35
90.7k
  } else {
36
90.7k
    return CelValue::CreateStringView(result.result().value());
37
90.7k
  }
38
131k
}
39
40
namespace {
41
42
absl::optional<CelValue> extractSslInfo(const Ssl::ConnectionInfo& ssl_info,
43
2.39k
                                        absl::string_view value) {
44
2.39k
  if (value == TLSVersion) {
45
19
    return CelValue::CreateString(&ssl_info.tlsVersion());
46
2.37k
  } else if (value == SubjectLocalCertificate) {
47
23
    return CelValue::CreateString(&ssl_info.subjectLocalCertificate());
48
2.35k
  } else if (value == SubjectPeerCertificate) {
49
59
    return CelValue::CreateString(&ssl_info.subjectPeerCertificate());
50
2.29k
  } else if (value == URISanLocalCertificate) {
51
62
    if (!ssl_info.uriSanLocalCertificate().empty()) {
52
0
      return CelValue::CreateString(&ssl_info.uriSanLocalCertificate()[0]);
53
0
    }
54
2.23k
  } else if (value == URISanPeerCertificate) {
55
66
    if (!ssl_info.uriSanPeerCertificate().empty()) {
56
0
      return CelValue::CreateString(&ssl_info.uriSanPeerCertificate()[0]);
57
0
    }
58
2.16k
  } else if (value == DNSSanLocalCertificate) {
59
48
    if (!ssl_info.dnsSansLocalCertificate().empty()) {
60
0
      return CelValue::CreateString(&ssl_info.dnsSansLocalCertificate()[0]);
61
0
    }
62
2.11k
  } else if (value == DNSSanPeerCertificate) {
63
61
    if (!ssl_info.dnsSansPeerCertificate().empty()) {
64
0
      return CelValue::CreateString(&ssl_info.dnsSansPeerCertificate()[0]);
65
0
    }
66
2.05k
  } else if (value == SHA256PeerCertificateDigest) {
67
505
    if (!ssl_info.sha256PeerCertificateDigest().empty()) {
68
0
      return CelValue::CreateString(&ssl_info.sha256PeerCertificateDigest());
69
0
    }
70
505
  }
71
2.29k
  return {};
72
2.39k
}
73
74
} // namespace
75
76
8.05k
absl::optional<CelValue> RequestWrapper::operator[](CelValue key) const {
77
8.05k
  if (!key.IsString()) {
78
102
    return {};
79
102
  }
80
7.95k
  auto value = key.StringOrDie().value();
81
82
7.95k
  if (value == Headers) {
83
3.14k
    return CelValue::CreateMap(&headers_);
84
4.81k
  } else if (value == Time) {
85
16
    return CelValue::CreateTimestamp(absl::FromChrono(info_.startTime()));
86
4.79k
  } else if (value == Size) {
87
    // it is important to make a choice whether to rely on content-length vs stream info
88
    // (which is not available at the time of the request headers)
89
384
    if (headers_.value_ != nullptr && headers_.value_->ContentLength() != nullptr) {
90
298
      int64_t length;
91
298
      if (absl::SimpleAtoi(headers_.value_->getContentLengthValue(), &length)) {
92
48
        return CelValue::CreateInt64(length);
93
48
      }
94
298
    } else {
95
86
      return CelValue::CreateInt64(info_.bytesReceived());
96
86
    }
97
4.41k
  } else if (value == TotalSize) {
98
50
    return CelValue::CreateInt64(info_.bytesReceived() +
99
50
                                 (headers_.value_ ? headers_.value_->byteSize() : 0));
100
4.36k
  } else if (value == Duration) {
101
51
    auto duration = info_.requestComplete();
102
51
    if (duration.has_value()) {
103
51
      return CelValue::CreateDuration(absl::FromChrono(duration.value()));
104
51
    }
105
4.31k
  } else if (value == Protocol) {
106
180
    if (info_.protocol().has_value()) {
107
0
      return CelValue::CreateString(&Http::Utility::getProtocolString(info_.protocol().value()));
108
180
    } else {
109
180
      return {};
110
180
    }
111
180
  }
112
113
4.38k
  if (headers_.value_ != nullptr) {
114
4.38k
    if (value == Path) {
115
48
      return convertHeaderEntry(headers_.value_->Path());
116
4.33k
    } else if (value == UrlPath) {
117
589
      absl::string_view path = headers_.value_->getPathValue();
118
589
      size_t query_offset = path.find('?');
119
589
      if (query_offset == absl::string_view::npos) {
120
413
        return CelValue::CreateStringView(path);
121
413
      }
122
176
      return CelValue::CreateStringView(path.substr(0, query_offset));
123
3.74k
    } else if (value == Host) {
124
56
      return convertHeaderEntry(headers_.value_->Host());
125
3.69k
    } else if (value == Scheme) {
126
48
      return convertHeaderEntry(headers_.value_->Scheme());
127
3.64k
    } else if (value == Method) {
128
49
      return convertHeaderEntry(headers_.value_->Method());
129
3.59k
    } else if (value == Referer) {
130
72
      return convertHeaderEntry(headers_.value_->getInline(referer_handle.handle()));
131
3.52k
    } else if (value == ID) {
132
0
      return convertHeaderEntry(headers_.value_->RequestId());
133
3.52k
    } else if (value == UserAgent) {
134
663
      return convertHeaderEntry(headers_.value_->UserAgent());
135
2.85k
    } else if (value == Query) {
136
856
      absl::string_view path = headers_.value_->getPathValue();
137
856
      auto query_offset = path.find('?');
138
856
      if (query_offset == absl::string_view::npos) {
139
740
        return CelValue::CreateStringView(absl::string_view());
140
740
      }
141
116
      path = path.substr(query_offset + 1);
142
116
      auto fragment_offset = path.find('#');
143
116
      return CelValue::CreateStringView(path.substr(0, fragment_offset));
144
856
    }
145
4.38k
  }
146
2.00k
  return {};
147
4.38k
}
148
149
6.97k
absl::optional<CelValue> ResponseWrapper::operator[](CelValue key) const {
150
6.97k
  if (!key.IsString()) {
151
153
    return {};
152
153
  }
153
6.82k
  auto value = key.StringOrDie().value();
154
6.82k
  if (value == Code) {
155
321
    auto code = info_.responseCode();
156
321
    if (code.has_value()) {
157
51
      return CelValue::CreateInt64(code.value());
158
51
    }
159
270
    return {};
160
6.50k
  } else if (value == Size) {
161
111
    return CelValue::CreateInt64(info_.bytesSent());
162
6.39k
  } else if (value == Headers) {
163
1.90k
    return CelValue::CreateMap(&headers_);
164
4.48k
  } else if (value == Trailers) {
165
1.59k
    return CelValue::CreateMap(&trailers_);
166
2.88k
  } else if (value == Flags) {
167
48
    return CelValue::CreateInt64(info_.responseFlags());
168
2.83k
  } else if (value == GrpcStatus) {
169
1.18k
    auto const& optional_status = Grpc::Common::getGrpcStatus(
170
1.18k
        trailers_.value_ ? *trailers_.value_ : *Http::StaticEmptyHeaders::get().response_trailers,
171
1.18k
        headers_.value_ ? *headers_.value_ : *Http::StaticEmptyHeaders::get().response_headers,
172
1.18k
        info_);
173
1.18k
    if (optional_status.has_value()) {
174
993
      return CelValue::CreateInt64(optional_status.value());
175
993
    }
176
190
    return {};
177
1.65k
  } else if (value == TotalSize) {
178
251
    return CelValue::CreateInt64(info_.bytesSent() +
179
251
                                 (headers_.value_ ? headers_.value_->byteSize() : 0) +
180
251
                                 (trailers_.value_ ? trailers_.value_->byteSize() : 0));
181
1.40k
  } else if (value == CodeDetails) {
182
56
    const absl::optional<std::string>& details = info_.responseCodeDetails();
183
56
    if (details.has_value()) {
184
0
      return CelValue::CreateString(&details.value());
185
0
    }
186
56
    return {};
187
56
  }
188
1.34k
  return {};
189
6.82k
}
190
191
3.67k
absl::optional<CelValue> ConnectionWrapper::operator[](CelValue key) const {
192
3.67k
  if (!key.IsString()) {
193
500
    return {};
194
500
  }
195
3.17k
  auto value = key.StringOrDie().value();
196
3.17k
  if (value == MTLS) {
197
0
    return CelValue::CreateBool(
198
0
        info_.downstreamAddressProvider().sslConnection() != nullptr &&
199
0
        info_.downstreamAddressProvider().sslConnection()->peerCertificatePresented());
200
3.17k
  } else if (value == RequestedServerName) {
201
68
    return CelValue::CreateStringView(info_.downstreamAddressProvider().requestedServerName());
202
3.11k
  } else if (value == ID) {
203
609
    auto id = info_.downstreamAddressProvider().connectionID();
204
609
    if (id.has_value()) {
205
212
      return CelValue::CreateUint64(id.value());
206
212
    }
207
397
    return {};
208
2.50k
  } else if (value == ConnectionTerminationDetails) {
209
56
    if (info_.connectionTerminationDetails().has_value()) {
210
0
      return CelValue::CreateString(&info_.connectionTerminationDetails().value());
211
0
    }
212
56
    return {};
213
56
  }
214
215
2.44k
  auto ssl_info = info_.downstreamAddressProvider().sslConnection();
216
2.44k
  if (ssl_info != nullptr) {
217
2.39k
    return extractSslInfo(*ssl_info, value);
218
2.39k
  }
219
220
49
  return {};
221
2.44k
}
222
223
4.23k
absl::optional<CelValue> UpstreamWrapper::operator[](CelValue key) const {
224
4.23k
  if (!key.IsString() || !info_.upstreamInfo().has_value()) {
225
34
    return {};
226
34
  }
227
4.20k
  auto value = key.StringOrDie().value();
228
4.20k
  if (value == Address) {
229
16
    auto upstream_host = info_.upstreamInfo().value().get().upstreamHost();
230
16
    if (upstream_host != nullptr && upstream_host->address() != nullptr) {
231
16
      return CelValue::CreateStringView(upstream_host->address()->asStringView());
232
16
    }
233
4.18k
  } else if (value == Port) {
234
56
    auto upstream_host = info_.upstreamInfo().value().get().upstreamHost();
235
56
    if (upstream_host != nullptr && upstream_host->address() != nullptr &&
236
56
        upstream_host->address()->ip() != nullptr) {
237
56
      return CelValue::CreateInt64(upstream_host->address()->ip()->port());
238
56
    }
239
4.12k
  } else if (value == UpstreamLocalAddress) {
240
187
    auto upstream_local_address = info_.upstreamInfo().value().get().upstreamLocalAddress();
241
187
    if (upstream_local_address != nullptr) {
242
187
      return CelValue::CreateStringView(upstream_local_address->asStringView());
243
187
    }
244
3.94k
  } else if (value == UpstreamTransportFailureReason) {
245
49
    return CelValue::CreateStringView(
246
49
        info_.upstreamInfo().value().get().upstreamTransportFailureReason());
247
49
  }
248
249
3.89k
  auto ssl_info = info_.upstreamInfo().value().get().upstreamSslConnection();
250
3.89k
  if (ssl_info != nullptr) {
251
0
    return extractSslInfo(*ssl_info, value);
252
0
  }
253
254
3.89k
  return {};
255
3.89k
}
256
257
1.34k
absl::optional<CelValue> PeerWrapper::operator[](CelValue key) const {
258
1.34k
  if (!key.IsString()) {
259
426
    return {};
260
426
  }
261
921
  auto value = key.StringOrDie().value();
262
921
  if (value == Address) {
263
112
    if (local_) {
264
48
      return CelValue::CreateStringView(
265
48
          info_.downstreamAddressProvider().localAddress()->asStringView());
266
64
    } else {
267
64
      return CelValue::CreateStringView(
268
64
          info_.downstreamAddressProvider().remoteAddress()->asStringView());
269
64
    }
270
809
  } else if (value == Port) {
271
652
    if (local_) {
272
225
      if (info_.downstreamAddressProvider().localAddress()->ip() != nullptr) {
273
142
        return CelValue::CreateInt64(
274
142
            info_.downstreamAddressProvider().localAddress()->ip()->port());
275
142
      }
276
427
    } else {
277
427
      if (info_.downstreamAddressProvider().remoteAddress()->ip() != nullptr) {
278
358
        return CelValue::CreateInt64(
279
358
            info_.downstreamAddressProvider().remoteAddress()->ip()->port());
280
358
      }
281
427
    }
282
652
  }
283
284
309
  return {};
285
921
}
286
287
class FilterStateObjectWrapper : public google::api::expr::runtime::CelMap {
288
public:
289
  FilterStateObjectWrapper(const StreamInfo::FilterState::ObjectReflection* reflection)
290
0
      : reflection_(reflection) {}
291
0
  absl::optional<CelValue> operator[](CelValue key) const override {
292
0
    if (reflection_ == nullptr || !key.IsString()) {
293
0
      return {};
294
0
    }
295
0
    auto field_value = reflection_->getField(key.StringOrDie().value());
296
0
    return absl::visit(Visitor{}, field_value);
297
0
  }
298
  // Default stubs.
299
0
  int size() const override { return 0; }
300
0
  bool empty() const override { return true; }
301
0
  absl::StatusOr<const google::api::expr::runtime::CelList*> ListKeys() const override {
302
0
    return &WrapperFields::get().Empty;
303
0
  }
304
305
private:
306
  struct Visitor {
307
0
    absl::optional<CelValue> operator()(int64_t val) { return CelValue::CreateInt64(val); }
308
0
    absl::optional<CelValue> operator()(absl::string_view val) {
309
0
      return CelValue::CreateStringView(val);
310
0
    }
311
0
    absl::optional<CelValue> operator()(absl::monostate) { return {}; }
312
  };
313
  const StreamInfo::FilterState::ObjectReflection* reflection_;
314
};
315
316
1.03k
absl::optional<CelValue> FilterStateWrapper::operator[](CelValue key) const {
317
1.03k
  if (!key.IsString()) {
318
456
    return {};
319
456
  }
320
576
  auto value = key.StringOrDie().value();
321
576
  if (const StreamInfo::FilterState::Object* object = filter_state_.getDataReadOnlyGeneric(value);
322
576
      object != nullptr) {
323
0
    const CelState* cel_state = dynamic_cast<const CelState*>(object);
324
0
    if (cel_state) {
325
0
      return cel_state->exprValue(&arena_, false);
326
0
    } else if (object != nullptr) {
327
      // Attempt to find the reflection object.
328
0
      auto factory =
329
0
          Registry::FactoryRegistry<StreamInfo::FilterState::ObjectFactory>::getFactory(value);
330
0
      if (factory) {
331
0
        auto reflection = factory->reflect(object);
332
0
        if (reflection) {
333
0
          auto* raw_reflection = reflection.release();
334
0
          arena_.Own(raw_reflection);
335
0
          return CelValue::CreateMap(
336
0
              ProtobufWkt::Arena::Create<FilterStateObjectWrapper>(&arena_, raw_reflection));
337
0
        }
338
0
      }
339
0
      absl::optional<std::string> serialized = object->serializeAsString();
340
0
      if (serialized.has_value()) {
341
0
        std::string* out = ProtobufWkt::Arena::Create<std::string>(&arena_, serialized.value());
342
0
        return CelValue::CreateBytes(out);
343
0
      }
344
0
    }
345
0
  }
346
576
  return {};
347
576
}
348
349
2.09k
absl::optional<CelValue> XDSWrapper::operator[](CelValue key) const {
350
2.09k
  if (!key.IsString()) {
351
129
    return {};
352
129
  }
353
1.96k
  auto value = key.StringOrDie().value();
354
1.96k
  if (value == ClusterName) {
355
94
    const auto cluster_info = info_.upstreamClusterInfo();
356
94
    if (cluster_info && cluster_info.value()) {
357
0
      return CelValue::CreateString(&cluster_info.value()->name());
358
0
    }
359
1.87k
  } else if (value == ClusterMetadata) {
360
53
    const auto cluster_info = info_.upstreamClusterInfo();
361
53
    if (cluster_info && cluster_info.value()) {
362
0
      return CelProtoWrapper::CreateMessage(&cluster_info.value()->metadata(), &arena_);
363
0
    }
364
1.81k
  } else if (value == RouteName) {
365
48
    if (info_.route()) {
366
0
      return CelValue::CreateString(&info_.route()->routeName());
367
0
    }
368
1.77k
  } else if (value == RouteMetadata) {
369
48
    if (info_.route()) {
370
0
      return CelProtoWrapper::CreateMessage(&info_.route()->metadata(), &arena_);
371
0
    }
372
1.72k
  } else if (value == UpstreamHostMetadata) {
373
35
    const auto upstream_info = info_.upstreamInfo();
374
35
    if (upstream_info && upstream_info->upstreamHost()) {
375
35
      return CelProtoWrapper::CreateMessage(upstream_info->upstreamHost()->metadata().get(),
376
35
                                            &arena_);
377
35
    }
378
1.68k
  } else if (value == FilterChainName) {
379
62
    const auto filter_chain_info = info_.downstreamAddressProvider().filterChainInfo();
380
62
    const absl::string_view filter_chain_name =
381
62
        filter_chain_info.has_value() ? filter_chain_info->name() : absl::string_view{};
382
62
    return CelValue::CreateStringView(filter_chain_name);
383
62
  }
384
1.86k
  return {};
385
1.96k
}
386
387
} // namespace Expr
388
} // namespace Common
389
} // namespace Filters
390
} // namespace Extensions
391
} // namespace Envoy