1
#include "source/common/config/metadata.h"
2
#include "source/common/http/header_utility.h"
3
#include "source/common/http/utility.h"
4
#include "source/common/protobuf/protobuf.h"
5
#include "source/common/stats/utility.h"
6
#include "source/extensions/access_loggers/dynamic_modules/access_log.h"
7
#include "source/extensions/access_loggers/dynamic_modules/access_log_config.h"
8
#include "source/extensions/dynamic_modules/abi/abi.h"
9

            
10
#include "absl/strings/str_split.h"
11
#include "access_log.h"
12

            
13
namespace Envoy {
14
namespace Extensions {
15
namespace AccessLoggers {
16
namespace DynamicModules {
17

            
18
namespace {
19

            
20
using HeadersMapOptConstRef = OptRef<const Http::HeaderMap>;
21

            
22
HeadersMapOptConstRef getHeaderMapByType(ThreadLocalLogger* logger,
23
37
                                         envoy_dynamic_module_type_http_header_type header_type) {
24
37
  switch (header_type) {
25
17
  case envoy_dynamic_module_type_http_header_type_RequestHeader:
26
17
    return logger->log_context_->requestHeaders();
27
11
  case envoy_dynamic_module_type_http_header_type_ResponseHeader:
28
11
    return logger->log_context_->responseHeaders();
29
9
  case envoy_dynamic_module_type_http_header_type_ResponseTrailer:
30
9
    return logger->log_context_->responseTrailers();
31
  default:
32
    return {};
33
37
  }
34
37
}
35

            
36
bool getHeaderValueImpl(HeadersMapOptConstRef map, envoy_dynamic_module_type_module_buffer key,
37
                        envoy_dynamic_module_type_envoy_buffer* result, size_t index,
38
11
                        size_t* optional_size) {
39
11
  if (!map.has_value()) {
40
5
    *result = {.ptr = nullptr, .length = 0};
41
5
    if (optional_size != nullptr) {
42
      *optional_size = 0;
43
    }
44
5
    return false;
45
5
  }
46
6
  absl::string_view key_view(key.ptr, key.length);
47

            
48
  // Note: We convert to LowerCaseString which may involve copying. This could be optimized if
49
  // callers guarantee lowercase keys.
50
6
  const auto values = map->get(Envoy::Http::LowerCaseString(key_view));
51
6
  if (optional_size != nullptr) {
52
5
    *optional_size = values.size();
53
5
  }
54

            
55
6
  if (index >= values.size()) {
56
2
    *result = {.ptr = nullptr, .length = 0};
57
2
    return false;
58
2
  }
59

            
60
4
  const auto value = values[index]->value().getStringView();
61
4
  *result = {.ptr = const_cast<char*>(value.data()), .length = value.size()};
62
4
  return true;
63
6
}
64

            
65
bool getHeadersImpl(HeadersMapOptConstRef map,
66
10
                    envoy_dynamic_module_type_envoy_http_header* result_headers) {
67
10
  if (!map) {
68
1
    return false;
69
1
  }
70
9
  size_t i = 0;
71
46
  map->iterate([&i, &result_headers](const Http::HeaderEntry& header) -> Http::HeaderMap::Iterate {
72
46
    auto& key = header.key();
73
46
    result_headers[i].key_ptr = const_cast<char*>(key.getStringView().data());
74
46
    result_headers[i].key_length = key.size();
75
46
    auto& value = header.value();
76
46
    result_headers[i].value_ptr = const_cast<char*>(value.getStringView().data());
77
46
    result_headers[i].value_length = value.size();
78
46
    i++;
79
46
    return Http::HeaderMap::Iterate::Continue;
80
46
  });
81
9
  return true;
82
10
}
83

            
84
// Helper to convert MonotonicTime to nanoseconds duration from start time.
85
int64_t monotonicTimeToNanos(const absl::optional<MonotonicTime>& time,
86
36
                             const MonotonicTime& start_time) {
87
36
  if (!time.has_value()) {
88
6
    return -1;
89
6
  }
90
30
  return std::chrono::duration_cast<std::chrono::nanoseconds>(time.value() - start_time).count();
91
36
}
92

            
93
} // namespace
94

            
95
extern "C" {
96

            
97
// -----------------------------------------------------------------------------
98
// Access Logger Callbacks - Headers
99
// -----------------------------------------------------------------------------
100

            
101
size_t envoy_dynamic_module_callback_access_logger_get_headers_size(
102
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
103
16
    envoy_dynamic_module_type_http_header_type header_type) {
104
16
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
105
16
  HeadersMapOptConstRef map = getHeaderMapByType(logger, header_type);
106
16
  return map.has_value() ? map->size() : 0;
107
16
}
108

            
109
bool envoy_dynamic_module_callback_access_logger_get_headers(
110
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
111
    envoy_dynamic_module_type_http_header_type header_type,
112
10
    envoy_dynamic_module_type_envoy_http_header* result_headers) {
113
10
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
114
10
  return getHeadersImpl(getHeaderMapByType(logger, header_type), result_headers);
115
10
}
116

            
117
bool envoy_dynamic_module_callback_access_logger_get_header_value(
118
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
119
    envoy_dynamic_module_type_http_header_type header_type,
120
    envoy_dynamic_module_type_module_buffer key, envoy_dynamic_module_type_envoy_buffer* result,
121
11
    size_t index, size_t* total_count_out) {
122
11
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
123
11
  return getHeaderValueImpl(getHeaderMapByType(logger, header_type), key, result, index,
124
11
                            total_count_out);
125
11
}
126

            
127
// -----------------------------------------------------------------------------
128
// Access Logger Callbacks - Stream Info Basic
129
// -----------------------------------------------------------------------------
130

            
131
uint32_t envoy_dynamic_module_callback_access_logger_get_response_code(
132
6
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
133
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
134
6
  return logger->stream_info_->responseCode().value_or(0);
135
6
}
136

            
137
bool envoy_dynamic_module_callback_access_logger_get_response_code_details(
138
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
139
2
    envoy_dynamic_module_type_envoy_buffer* result) {
140
2
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
141
2
  if (!logger->stream_info_->responseCodeDetails().has_value()) {
142
1
    return false;
143
1
  }
144
1
  const auto& details = logger->stream_info_->responseCodeDetails().value();
145
1
  *result = {const_cast<char*>(details.data()), details.size()};
146
1
  return true;
147
2
}
148

            
149
bool envoy_dynamic_module_callback_access_logger_has_response_flag(
150
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
151
7
    envoy_dynamic_module_type_response_flag flag) {
152
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
153
  // Convert ABI flag to Envoy flag. The enum values are expected to match CoreResponseFlag.
154
7
  return logger->stream_info_->hasResponseFlag(
155
7
      StreamInfo::ResponseFlag(static_cast<StreamInfo::CoreResponseFlag>(flag)));
156
7
}
157

            
158
uint64_t envoy_dynamic_module_callback_access_logger_get_response_flags(
159
5
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
160
5
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
161
5
  return logger->stream_info_->legacyResponseFlags();
162
5
}
163

            
164
bool envoy_dynamic_module_callback_access_logger_get_protocol(
165
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
166
7
    envoy_dynamic_module_type_envoy_buffer* result) {
167
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
168
7
  if (!logger->stream_info_->protocol().has_value()) {
169
1
    return false;
170
1
  }
171
6
  const auto& protocol_str =
172
6
      Http::Utility::getProtocolString(logger->stream_info_->protocol().value());
173
6
  *result = {const_cast<char*>(protocol_str.data()), protocol_str.size()};
174
6
  return true;
175
7
}
176

            
177
void envoy_dynamic_module_callback_access_logger_get_timing_info(
178
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
179
7
    envoy_dynamic_module_type_timing_info* timing_out) {
180
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
181
7
  const auto& info = *logger->stream_info_;
182
7
  const MonotonicTime start_time = info.startTimeMonotonic();
183

            
184
7
  timing_out->start_time_unix_ns =
185
7
      std::chrono::duration_cast<std::chrono::nanoseconds>(info.startTime().time_since_epoch())
186
7
          .count();
187

            
188
7
  auto duration = info.requestComplete();
189
7
  timing_out->request_complete_duration_ns = duration.has_value() ? duration->count() : -1;
190

            
191
  // Downstream timing.
192
7
  const auto downstream = info.downstreamTiming();
193
7
  if (downstream.has_value()) {
194
6
    timing_out->first_downstream_tx_byte_sent_ns =
195
6
        monotonicTimeToNanos(downstream->firstDownstreamTxByteSent(), start_time);
196
6
    timing_out->last_downstream_tx_byte_sent_ns =
197
6
        monotonicTimeToNanos(downstream->lastDownstreamTxByteSent(), start_time);
198
6
  } else {
199
1
    timing_out->first_downstream_tx_byte_sent_ns = -1;
200
1
    timing_out->last_downstream_tx_byte_sent_ns = -1;
201
1
  }
202

            
203
  // Upstream timing.
204
7
  const auto upstream = info.upstreamInfo();
205
7
  if (upstream.has_value()) {
206
6
    const auto& upstream_timing = upstream->upstreamTiming();
207
6
    timing_out->first_upstream_tx_byte_sent_ns =
208
6
        monotonicTimeToNanos(upstream_timing.first_upstream_tx_byte_sent_, start_time);
209
6
    timing_out->last_upstream_tx_byte_sent_ns =
210
6
        monotonicTimeToNanos(upstream_timing.last_upstream_tx_byte_sent_, start_time);
211
6
    timing_out->first_upstream_rx_byte_received_ns =
212
6
        monotonicTimeToNanos(upstream_timing.first_upstream_rx_byte_received_, start_time);
213
6
    timing_out->last_upstream_rx_byte_received_ns =
214
6
        monotonicTimeToNanos(upstream_timing.last_upstream_rx_byte_received_, start_time);
215
6
  } else {
216
1
    timing_out->first_upstream_tx_byte_sent_ns = -1;
217
1
    timing_out->last_upstream_tx_byte_sent_ns = -1;
218
1
    timing_out->first_upstream_rx_byte_received_ns = -1;
219
1
    timing_out->last_upstream_rx_byte_received_ns = -1;
220
1
  }
221
7
}
222

            
223
void envoy_dynamic_module_callback_access_logger_get_bytes_info(
224
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
225
6
    envoy_dynamic_module_type_bytes_info* bytes_out) {
226
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
227
6
  const auto& info = *logger->stream_info_;
228
6
  bytes_out->bytes_received = info.bytesReceived();
229
6
  bytes_out->bytes_sent = info.bytesSent();
230

            
231
6
  const auto& upstream = info.getUpstreamBytesMeter();
232
6
  if (upstream) {
233
5
    bytes_out->wire_bytes_received = upstream->wireBytesReceived();
234
5
    bytes_out->wire_bytes_sent = upstream->wireBytesSent();
235
5
  } else {
236
1
    bytes_out->wire_bytes_received = 0;
237
1
    bytes_out->wire_bytes_sent = 0;
238
1
  }
239
6
}
240

            
241
bool envoy_dynamic_module_callback_access_logger_get_route_name(
242
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
243
6
    envoy_dynamic_module_type_envoy_buffer* result) {
244
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
245
6
  const auto& name = logger->stream_info_->getRouteName();
246
6
  if (name.empty()) {
247
5
    return false;
248
5
  }
249
1
  *result = {const_cast<char*>(name.data()), name.size()};
250
1
  return true;
251
6
}
252

            
253
bool envoy_dynamic_module_callback_access_logger_get_virtual_cluster_name(
254
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
255
3
    envoy_dynamic_module_type_envoy_buffer* result) {
256
3
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
257
3
  const auto& name = logger->stream_info_->virtualClusterName();
258
3
  if (!name.has_value() || name->empty()) {
259
2
    return false;
260
2
  }
261
1
  *result = {const_cast<char*>(name->data()), name->size()};
262
1
  return true;
263
3
}
264

            
265
bool envoy_dynamic_module_callback_access_logger_is_health_check(
266
6
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
267
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
268
6
  return logger->stream_info_->healthCheck();
269
6
}
270

            
271
uint32_t envoy_dynamic_module_callback_access_logger_get_attempt_count(
272
6
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
273
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
274
6
  return logger->stream_info_->attemptCount().value_or(0);
275
6
}
276

            
277
bool envoy_dynamic_module_callback_access_logger_get_connection_termination_details(
278
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
279
7
    envoy_dynamic_module_type_envoy_buffer* result) {
280
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
281
7
  const auto& details = logger->stream_info_->connectionTerminationDetails();
282
7
  if (!details.has_value() || details->empty()) {
283
6
    return false;
284
6
  }
285
1
  *result = {const_cast<char*>(details->data()), details->size()};
286
1
  return true;
287
7
}
288

            
289
// -----------------------------------------------------------------------------
290
// Access Logger Callbacks - Address Information
291
// -----------------------------------------------------------------------------
292

            
293
bool envoy_dynamic_module_callback_access_logger_get_downstream_remote_address(
294
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
295
6
    envoy_dynamic_module_type_envoy_buffer* address_out, uint32_t* port_out) {
296
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
297
6
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
298
6
  if (!provider.remoteAddress() || provider.remoteAddress()->type() != Network::Address::Type::Ip) {
299
1
    return false;
300
1
  }
301

            
302
5
  const auto& ip = provider.remoteAddress()->ip();
303
5
  const std::string& addr_str = ip->addressAsString();
304
5
  *address_out = {const_cast<char*>(addr_str.data()), addr_str.size()};
305
5
  *port_out = ip->port();
306
5
  return true;
307
6
}
308

            
309
bool envoy_dynamic_module_callback_access_logger_get_downstream_local_address(
310
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
311
6
    envoy_dynamic_module_type_envoy_buffer* address_out, uint32_t* port_out) {
312
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
313
6
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
314
6
  if (!provider.localAddress() || provider.localAddress()->type() != Network::Address::Type::Ip) {
315
1
    return false;
316
1
  }
317

            
318
5
  const auto& ip = provider.localAddress()->ip();
319
5
  const std::string& addr_str = ip->addressAsString();
320
5
  *address_out = {const_cast<char*>(addr_str.data()), addr_str.size()};
321
5
  *port_out = ip->port();
322
5
  return true;
323
6
}
324

            
325
bool envoy_dynamic_module_callback_access_logger_get_downstream_direct_remote_address(
326
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
327
6
    envoy_dynamic_module_type_envoy_buffer* address_out, uint32_t* port_out) {
328
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
329
6
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
330
6
  if (!provider.directRemoteAddress() ||
331
6
      provider.directRemoteAddress()->type() != Network::Address::Type::Ip) {
332
1
    return false;
333
1
  }
334

            
335
5
  const auto& ip = provider.directRemoteAddress()->ip();
336
5
  const std::string& addr_str = ip->addressAsString();
337
5
  *address_out = {const_cast<char*>(addr_str.data()), addr_str.size()};
338
5
  *port_out = ip->port();
339
5
  return true;
340
6
}
341

            
342
bool envoy_dynamic_module_callback_access_logger_get_downstream_direct_local_address(
343
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
344
6
    envoy_dynamic_module_type_envoy_buffer* address_out, uint32_t* port_out) {
345
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
346
6
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
347
6
  if (!provider.directLocalAddress() ||
348
6
      provider.directLocalAddress()->type() != Network::Address::Type::Ip) {
349
1
    return false;
350
1
  }
351

            
352
5
  const auto& ip = provider.directLocalAddress()->ip();
353
5
  const std::string& addr_str = ip->addressAsString();
354
5
  *address_out = {const_cast<char*>(addr_str.data()), addr_str.size()};
355
5
  *port_out = ip->port();
356
5
  return true;
357
6
}
358

            
359
bool envoy_dynamic_module_callback_access_logger_get_upstream_remote_address(
360
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
361
7
    envoy_dynamic_module_type_envoy_buffer* address_out, uint32_t* port_out) {
362
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
363
7
  const auto upstream = logger->stream_info_->upstreamInfo();
364
7
  if (!upstream.has_value() || !upstream->upstreamHost() || !upstream->upstreamHost()->address()) {
365
1
    return false;
366
1
  }
367

            
368
6
  const auto& address = upstream->upstreamHost()->address();
369
6
  if (address->type() != Network::Address::Type::Ip) {
370
1
    return false;
371
1
  }
372

            
373
5
  const auto& ip = address->ip();
374
5
  const std::string& addr_str = ip->addressAsString();
375
5
  *address_out = {const_cast<char*>(addr_str.data()), addr_str.size()};
376
5
  *port_out = ip->port();
377
5
  return true;
378
6
}
379

            
380
bool envoy_dynamic_module_callback_access_logger_get_upstream_local_address(
381
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
382
7
    envoy_dynamic_module_type_envoy_buffer* address_out, uint32_t* port_out) {
383
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
384
7
  const auto upstream = logger->stream_info_->upstreamInfo();
385
7
  if (!upstream.has_value() || !upstream->upstreamLocalAddress()) {
386
1
    return false;
387
1
  }
388

            
389
6
  const auto& address = upstream->upstreamLocalAddress();
390
6
  if (address->type() != Network::Address::Type::Ip) {
391
1
    return false;
392
1
  }
393

            
394
5
  const auto& ip = address->ip();
395
5
  const std::string& addr_str = ip->addressAsString();
396
5
  *address_out = {const_cast<char*>(addr_str.data()), addr_str.size()};
397
5
  *port_out = ip->port();
398
5
  return true;
399
6
}
400

            
401
// -----------------------------------------------------------------------------
402
// Access Logger Callbacks - Upstream Info
403
// -----------------------------------------------------------------------------
404

            
405
bool envoy_dynamic_module_callback_access_logger_get_upstream_cluster(
406
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
407
3
    envoy_dynamic_module_type_envoy_buffer* result) {
408
3
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
409
  // upstreamClusterInfo is on StreamInfo, not UpstreamInfo.
410
3
  const auto cluster_info = logger->stream_info_->upstreamClusterInfo();
411
3
  if (!cluster_info.has_value() || cluster_info.value() == nullptr) {
412
1
    return false;
413
1
  }
414

            
415
2
  const auto& name = cluster_info.value()->name();
416
2
  *result = {const_cast<char*>(name.data()), name.size()};
417
2
  return true;
418
3
}
419

            
420
bool envoy_dynamic_module_callback_access_logger_get_upstream_host(
421
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
422
3
    envoy_dynamic_module_type_envoy_buffer* result) {
423
3
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
424
3
  const auto upstream = logger->stream_info_->upstreamInfo();
425
3
  if (!upstream.has_value() || !upstream->upstreamHost()) {
426
1
    return false;
427
1
  }
428

            
429
2
  const auto& hostname = upstream->upstreamHost()->hostname();
430
2
  *result = {const_cast<char*>(hostname.data()), hostname.size()};
431
2
  return true;
432
3
}
433

            
434
bool envoy_dynamic_module_callback_access_logger_get_upstream_transport_failure_reason(
435
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
436
7
    envoy_dynamic_module_type_envoy_buffer* result) {
437
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
438
7
  const auto upstream = logger->stream_info_->upstreamInfo();
439
7
  if (!upstream.has_value() || upstream->upstreamTransportFailureReason().empty()) {
440
5
    return false;
441
5
  }
442

            
443
2
  const auto& reason = upstream->upstreamTransportFailureReason();
444
2
  *result = {const_cast<char*>(reason.data()), reason.size()};
445
2
  return true;
446
7
}
447

            
448
uint64_t envoy_dynamic_module_callback_access_logger_get_upstream_connection_id(
449
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
450
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
451
7
  const auto upstream = logger->stream_info_->upstreamInfo();
452
7
  if (!upstream.has_value() || !upstream->upstreamConnectionId().has_value()) {
453
2
    return 0;
454
2
  }
455
5
  return upstream->upstreamConnectionId().value();
456
7
}
457

            
458
bool envoy_dynamic_module_callback_access_logger_get_upstream_tls_version(
459
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
460
8
    envoy_dynamic_module_type_envoy_buffer* result) {
461
8
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
462
8
  const auto upstream = logger->stream_info_->upstreamInfo();
463
8
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
464
6
    return false;
465
6
  }
466

            
467
2
  const std::string& version = upstream->upstreamSslConnection()->tlsVersion();
468
2
  if (version.empty()) {
469
1
    return false;
470
1
  }
471
1
  *result = {const_cast<char*>(version.data()), version.size()};
472
1
  return true;
473
2
}
474

            
475
bool envoy_dynamic_module_callback_access_logger_get_upstream_tls_cipher(
476
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
477
8
    envoy_dynamic_module_type_envoy_buffer* result) {
478
  // ciphersuiteString() returns std::string by value, so we use thread-local storage.
479
8
  static thread_local std::string tls_cipher_str;
480
8
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
481
8
  const auto upstream = logger->stream_info_->upstreamInfo();
482
8
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
483
6
    return false;
484
6
  }
485

            
486
2
  tls_cipher_str = upstream->upstreamSslConnection()->ciphersuiteString();
487
2
  if (tls_cipher_str.empty()) {
488
1
    return false;
489
1
  }
490
1
  *result = {const_cast<char*>(tls_cipher_str.data()), tls_cipher_str.size()};
491
1
  return true;
492
2
}
493

            
494
bool envoy_dynamic_module_callback_access_logger_get_upstream_tls_session_id(
495
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
496
8
    envoy_dynamic_module_type_envoy_buffer* result) {
497
8
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
498
8
  const auto upstream = logger->stream_info_->upstreamInfo();
499
8
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
500
6
    return false;
501
6
  }
502

            
503
2
  const std::string& session_id = upstream->upstreamSslConnection()->sessionId();
504
2
  if (session_id.empty()) {
505
1
    return false;
506
1
  }
507
1
  *result = {const_cast<char*>(session_id.data()), session_id.size()};
508
1
  return true;
509
2
}
510

            
511
bool envoy_dynamic_module_callback_access_logger_get_upstream_peer_subject(
512
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
513
8
    envoy_dynamic_module_type_envoy_buffer* result) {
514
8
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
515
8
  const auto upstream = logger->stream_info_->upstreamInfo();
516
8
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
517
6
    return false;
518
6
  }
519

            
520
2
  const std::string& subject = upstream->upstreamSslConnection()->subjectPeerCertificate();
521
2
  if (subject.empty()) {
522
1
    return false;
523
1
  }
524
1
  *result = {const_cast<char*>(subject.data()), subject.size()};
525
1
  return true;
526
2
}
527

            
528
bool envoy_dynamic_module_callback_access_logger_get_upstream_peer_issuer(
529
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
530
8
    envoy_dynamic_module_type_envoy_buffer* result) {
531
8
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
532
8
  const auto upstream = logger->stream_info_->upstreamInfo();
533
8
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
534
6
    return false;
535
6
  }
536

            
537
2
  const std::string& issuer = upstream->upstreamSslConnection()->issuerPeerCertificate();
538
2
  if (issuer.empty()) {
539
1
    return false;
540
1
  }
541
1
  *result = {const_cast<char*>(issuer.data()), issuer.size()};
542
1
  return true;
543
2
}
544

            
545
bool envoy_dynamic_module_callback_access_logger_get_upstream_local_subject(
546
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
547
7
    envoy_dynamic_module_type_envoy_buffer* result) {
548
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
549
7
  const auto upstream = logger->stream_info_->upstreamInfo();
550
7
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
551
5
    return false;
552
5
  }
553

            
554
2
  const std::string& subject = upstream->upstreamSslConnection()->subjectLocalCertificate();
555
2
  if (subject.empty()) {
556
1
    return false;
557
1
  }
558
1
  *result = {const_cast<char*>(subject.data()), subject.size()};
559
1
  return true;
560
2
}
561

            
562
bool envoy_dynamic_module_callback_access_logger_get_upstream_peer_cert_digest(
563
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
564
7
    envoy_dynamic_module_type_envoy_buffer* result) {
565
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
566
7
  const auto upstream = logger->stream_info_->upstreamInfo();
567
7
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
568
5
    return false;
569
5
  }
570

            
571
2
  const std::string& digest = upstream->upstreamSslConnection()->sha256PeerCertificateDigest();
572
2
  if (digest.empty()) {
573
1
    return false;
574
1
  }
575
1
  *result = {const_cast<char*>(digest.data()), digest.size()};
576
1
  return true;
577
2
}
578

            
579
int64_t envoy_dynamic_module_callback_access_logger_get_upstream_peer_cert_v_start(
580
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
581
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
582
7
  const auto upstream = logger->stream_info_->upstreamInfo();
583
7
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
584
5
    return 0;
585
5
  }
586
2
  const auto valid_from = upstream->upstreamSslConnection()->validFromPeerCertificate();
587
2
  if (!valid_from.has_value()) {
588
1
    return 0;
589
1
  }
590
1
  return std::chrono::duration_cast<std::chrono::seconds>(valid_from->time_since_epoch()).count();
591
2
}
592

            
593
int64_t envoy_dynamic_module_callback_access_logger_get_upstream_peer_cert_v_end(
594
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
595
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
596
7
  const auto upstream = logger->stream_info_->upstreamInfo();
597
7
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
598
5
    return 0;
599
5
  }
600
2
  const auto expiration = upstream->upstreamSslConnection()->expirationPeerCertificate();
601
2
  if (!expiration.has_value()) {
602
1
    return 0;
603
1
  }
604
1
  return std::chrono::duration_cast<std::chrono::seconds>(expiration->time_since_epoch()).count();
605
2
}
606

            
607
size_t envoy_dynamic_module_callback_access_logger_get_upstream_peer_uri_san_size(
608
6
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
609
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
610
6
  const auto upstream = logger->stream_info_->upstreamInfo();
611
6
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
612
5
    return 0;
613
5
  }
614
1
  return upstream->upstreamSslConnection()->uriSanPeerCertificate().size();
615
6
}
616

            
617
bool envoy_dynamic_module_callback_access_logger_get_upstream_peer_uri_san(
618
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
619
2
    envoy_dynamic_module_type_envoy_buffer* sans_out) {
620
2
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
621
2
  const auto upstream = logger->stream_info_->upstreamInfo();
622
2
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
623
1
    return false;
624
1
  }
625
1
  const auto& sans = upstream->upstreamSslConnection()->uriSanPeerCertificate();
626
2
  for (size_t i = 0; i < sans.size(); ++i) {
627
1
    sans_out[i].ptr = const_cast<char*>(sans[i].data());
628
1
    sans_out[i].length = sans[i].size();
629
1
  }
630
1
  return true;
631
2
}
632

            
633
size_t envoy_dynamic_module_callback_access_logger_get_upstream_local_uri_san_size(
634
6
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
635
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
636
6
  const auto upstream = logger->stream_info_->upstreamInfo();
637
6
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
638
5
    return 0;
639
5
  }
640
1
  return upstream->upstreamSslConnection()->uriSanLocalCertificate().size();
641
6
}
642

            
643
bool envoy_dynamic_module_callback_access_logger_get_upstream_local_uri_san(
644
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
645
2
    envoy_dynamic_module_type_envoy_buffer* sans_out) {
646
2
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
647
2
  const auto upstream = logger->stream_info_->upstreamInfo();
648
2
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
649
1
    return false;
650
1
  }
651
1
  const auto& sans = upstream->upstreamSslConnection()->uriSanLocalCertificate();
652
2
  for (size_t i = 0; i < sans.size(); ++i) {
653
1
    sans_out[i].ptr = const_cast<char*>(sans[i].data());
654
1
    sans_out[i].length = sans[i].size();
655
1
  }
656
1
  return true;
657
2
}
658

            
659
size_t envoy_dynamic_module_callback_access_logger_get_upstream_peer_dns_san_size(
660
6
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
661
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
662
6
  const auto upstream = logger->stream_info_->upstreamInfo();
663
6
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
664
5
    return 0;
665
5
  }
666
1
  return upstream->upstreamSslConnection()->dnsSansPeerCertificate().size();
667
6
}
668

            
669
bool envoy_dynamic_module_callback_access_logger_get_upstream_peer_dns_san(
670
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
671
2
    envoy_dynamic_module_type_envoy_buffer* sans_out) {
672
2
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
673
2
  const auto upstream = logger->stream_info_->upstreamInfo();
674
2
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
675
1
    return false;
676
1
  }
677
1
  const auto& sans = upstream->upstreamSslConnection()->dnsSansPeerCertificate();
678
2
  for (size_t i = 0; i < sans.size(); ++i) {
679
1
    sans_out[i].ptr = const_cast<char*>(sans[i].data());
680
1
    sans_out[i].length = sans[i].size();
681
1
  }
682
1
  return true;
683
2
}
684

            
685
size_t envoy_dynamic_module_callback_access_logger_get_upstream_local_dns_san_size(
686
6
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
687
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
688
6
  const auto upstream = logger->stream_info_->upstreamInfo();
689
6
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
690
5
    return 0;
691
5
  }
692
1
  return upstream->upstreamSslConnection()->dnsSansLocalCertificate().size();
693
6
}
694

            
695
bool envoy_dynamic_module_callback_access_logger_get_upstream_local_dns_san(
696
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
697
2
    envoy_dynamic_module_type_envoy_buffer* sans_out) {
698
2
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
699
2
  const auto upstream = logger->stream_info_->upstreamInfo();
700
2
  if (!upstream.has_value() || !upstream->upstreamSslConnection()) {
701
1
    return false;
702
1
  }
703
1
  const auto& sans = upstream->upstreamSslConnection()->dnsSansLocalCertificate();
704
2
  for (size_t i = 0; i < sans.size(); ++i) {
705
1
    sans_out[i].ptr = const_cast<char*>(sans[i].data());
706
1
    sans_out[i].length = sans[i].size();
707
1
  }
708
1
  return true;
709
2
}
710

            
711
// -----------------------------------------------------------------------------
712
// Access Logger Callbacks - Connection/TLS Info
713
// -----------------------------------------------------------------------------
714

            
715
uint64_t envoy_dynamic_module_callback_access_logger_get_connection_id(
716
3
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
717
3
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
718
3
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
719
3
  if (!provider.connectionID().has_value()) {
720
1
    return 0;
721
1
  }
722
2
  return provider.connectionID().value();
723
3
}
724

            
725
bool envoy_dynamic_module_callback_access_logger_is_mtls(
726
3
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
727
3
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
728
3
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
729
3
  if (!provider.sslConnection()) {
730
1
    return false;
731
1
  }
732
2
  return provider.sslConnection()->peerCertificateValidated();
733
3
}
734

            
735
bool envoy_dynamic_module_callback_access_logger_get_requested_server_name(
736
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
737
4
    envoy_dynamic_module_type_envoy_buffer* result) {
738
4
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
739
4
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
740
4
  const auto& sni = provider.requestedServerName();
741
4
  if (sni.empty()) {
742
2
    return false;
743
2
  }
744
2
  *result = {const_cast<char*>(sni.data()), sni.size()};
745
2
  return true;
746
4
}
747

            
748
bool envoy_dynamic_module_callback_access_logger_get_downstream_tls_version(
749
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
750
8
    envoy_dynamic_module_type_envoy_buffer* result) {
751
8
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
752
8
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
753
8
  if (!provider.sslConnection()) {
754
5
    return false;
755
5
  }
756

            
757
3
  const std::string& version = provider.sslConnection()->tlsVersion();
758
3
  *result = {const_cast<char*>(version.data()), version.size()};
759
3
  return true;
760
8
}
761

            
762
bool envoy_dynamic_module_callback_access_logger_get_downstream_peer_subject(
763
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
764
8
    envoy_dynamic_module_type_envoy_buffer* result) {
765
8
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
766
8
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
767
8
  if (!provider.sslConnection()) {
768
5
    return false;
769
5
  }
770

            
771
3
  const std::string& subject = provider.sslConnection()->subjectPeerCertificate();
772
3
  if (subject.empty()) {
773
1
    return false;
774
1
  }
775
2
  *result = {const_cast<char*>(subject.data()), subject.size()};
776
2
  return true;
777
3
}
778

            
779
bool envoy_dynamic_module_callback_access_logger_get_downstream_peer_cert_digest(
780
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
781
8
    envoy_dynamic_module_type_envoy_buffer* result) {
782
8
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
783
8
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
784
8
  if (!provider.sslConnection()) {
785
5
    return false;
786
5
  }
787

            
788
3
  const std::string& digest = provider.sslConnection()->sha256PeerCertificateDigest();
789
3
  if (digest.empty()) {
790
1
    return false;
791
1
  }
792
2
  *result = {const_cast<char*>(digest.data()), digest.size()};
793
2
  return true;
794
3
}
795

            
796
bool envoy_dynamic_module_callback_access_logger_get_downstream_tls_cipher(
797
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
798
7
    envoy_dynamic_module_type_envoy_buffer* result) {
799
  // ciphersuiteString() returns std::string by value, so we use thread-local storage.
800
7
  static thread_local std::string tls_cipher_str;
801
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
802
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
803
7
  if (!provider.sslConnection()) {
804
5
    return false;
805
5
  }
806

            
807
2
  tls_cipher_str = provider.sslConnection()->ciphersuiteString();
808
2
  if (tls_cipher_str.empty()) {
809
1
    return false;
810
1
  }
811
1
  *result = {const_cast<char*>(tls_cipher_str.data()), tls_cipher_str.size()};
812
1
  return true;
813
2
}
814

            
815
bool envoy_dynamic_module_callback_access_logger_get_downstream_tls_session_id(
816
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
817
7
    envoy_dynamic_module_type_envoy_buffer* result) {
818
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
819
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
820
7
  if (!provider.sslConnection()) {
821
5
    return false;
822
5
  }
823

            
824
2
  const std::string& session_id = provider.sslConnection()->sessionId();
825
2
  if (session_id.empty()) {
826
1
    return false;
827
1
  }
828
1
  *result = {const_cast<char*>(session_id.data()), session_id.size()};
829
1
  return true;
830
2
}
831

            
832
bool envoy_dynamic_module_callback_access_logger_get_downstream_peer_issuer(
833
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
834
7
    envoy_dynamic_module_type_envoy_buffer* result) {
835
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
836
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
837
7
  if (!provider.sslConnection()) {
838
5
    return false;
839
5
  }
840

            
841
2
  const std::string& issuer = provider.sslConnection()->issuerPeerCertificate();
842
2
  if (issuer.empty()) {
843
1
    return false;
844
1
  }
845
1
  *result = {const_cast<char*>(issuer.data()), issuer.size()};
846
1
  return true;
847
2
}
848

            
849
bool envoy_dynamic_module_callback_access_logger_get_downstream_peer_serial(
850
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
851
7
    envoy_dynamic_module_type_envoy_buffer* result) {
852
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
853
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
854
7
  if (!provider.sslConnection()) {
855
5
    return false;
856
5
  }
857

            
858
2
  const std::string& serial = provider.sslConnection()->serialNumberPeerCertificate();
859
2
  if (serial.empty()) {
860
1
    return false;
861
1
  }
862
1
  *result = {const_cast<char*>(serial.data()), serial.size()};
863
1
  return true;
864
2
}
865

            
866
bool envoy_dynamic_module_callback_access_logger_get_downstream_peer_fingerprint_1(
867
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
868
7
    envoy_dynamic_module_type_envoy_buffer* result) {
869
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
870
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
871
7
  if (!provider.sslConnection()) {
872
5
    return false;
873
5
  }
874

            
875
2
  const std::string& digest = provider.sslConnection()->sha1PeerCertificateDigest();
876
2
  if (digest.empty()) {
877
1
    return false;
878
1
  }
879
1
  *result = {const_cast<char*>(digest.data()), digest.size()};
880
1
  return true;
881
2
}
882

            
883
bool envoy_dynamic_module_callback_access_logger_get_downstream_local_subject(
884
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
885
7
    envoy_dynamic_module_type_envoy_buffer* result) {
886
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
887
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
888
7
  if (!provider.sslConnection()) {
889
5
    return false;
890
5
  }
891

            
892
2
  const std::string& subject = provider.sslConnection()->subjectLocalCertificate();
893
2
  if (subject.empty()) {
894
1
    return false;
895
1
  }
896
1
  *result = {const_cast<char*>(subject.data()), subject.size()};
897
1
  return true;
898
2
}
899

            
900
bool envoy_dynamic_module_callback_access_logger_get_downstream_peer_cert_presented(
901
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
902
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
903
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
904
7
  if (!provider.sslConnection()) {
905
5
    return false;
906
5
  }
907
2
  return provider.sslConnection()->peerCertificatePresented();
908
7
}
909

            
910
bool envoy_dynamic_module_callback_access_logger_get_downstream_peer_cert_validated(
911
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
912
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
913
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
914
7
  if (!provider.sslConnection()) {
915
5
    return false;
916
5
  }
917
2
  return provider.sslConnection()->peerCertificateValidated();
918
7
}
919

            
920
int64_t envoy_dynamic_module_callback_access_logger_get_downstream_peer_cert_v_start(
921
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
922
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
923
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
924
7
  if (!provider.sslConnection()) {
925
5
    return 0;
926
5
  }
927
2
  const auto valid_from = provider.sslConnection()->validFromPeerCertificate();
928
2
  if (!valid_from.has_value()) {
929
1
    return 0;
930
1
  }
931
1
  return std::chrono::duration_cast<std::chrono::seconds>(valid_from->time_since_epoch()).count();
932
2
}
933

            
934
int64_t envoy_dynamic_module_callback_access_logger_get_downstream_peer_cert_v_end(
935
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
936
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
937
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
938
7
  if (!provider.sslConnection()) {
939
5
    return 0;
940
5
  }
941
2
  const auto expiration = provider.sslConnection()->expirationPeerCertificate();
942
2
  if (!expiration.has_value()) {
943
1
    return 0;
944
1
  }
945
1
  return std::chrono::duration_cast<std::chrono::seconds>(expiration->time_since_epoch()).count();
946
2
}
947

            
948
size_t envoy_dynamic_module_callback_access_logger_get_downstream_peer_uri_san_size(
949
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
950
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
951
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
952
7
  if (!provider.sslConnection()) {
953
5
    return 0;
954
5
  }
955
2
  return provider.sslConnection()->uriSanPeerCertificate().size();
956
7
}
957

            
958
bool envoy_dynamic_module_callback_access_logger_get_downstream_peer_uri_san(
959
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
960
2
    envoy_dynamic_module_type_envoy_buffer* sans_out) {
961
2
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
962
2
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
963
2
  if (!provider.sslConnection()) {
964
1
    return false;
965
1
  }
966
1
  const auto& sans = provider.sslConnection()->uriSanPeerCertificate();
967
3
  for (size_t i = 0; i < sans.size(); ++i) {
968
2
    sans_out[i].ptr = const_cast<char*>(sans[i].data());
969
2
    sans_out[i].length = sans[i].size();
970
2
  }
971
1
  return true;
972
2
}
973

            
974
size_t envoy_dynamic_module_callback_access_logger_get_downstream_local_uri_san_size(
975
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
976
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
977
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
978
7
  if (!provider.sslConnection()) {
979
5
    return 0;
980
5
  }
981
2
  return provider.sslConnection()->uriSanLocalCertificate().size();
982
7
}
983

            
984
bool envoy_dynamic_module_callback_access_logger_get_downstream_local_uri_san(
985
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
986
2
    envoy_dynamic_module_type_envoy_buffer* sans_out) {
987
2
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
988
2
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
989
2
  if (!provider.sslConnection()) {
990
1
    return false;
991
1
  }
992
1
  const auto& sans = provider.sslConnection()->uriSanLocalCertificate();
993
2
  for (size_t i = 0; i < sans.size(); ++i) {
994
1
    sans_out[i].ptr = const_cast<char*>(sans[i].data());
995
1
    sans_out[i].length = sans[i].size();
996
1
  }
997
1
  return true;
998
2
}
999

            
size_t envoy_dynamic_module_callback_access_logger_get_downstream_peer_dns_san_size(
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
7
  if (!provider.sslConnection()) {
5
    return 0;
5
  }
2
  return provider.sslConnection()->dnsSansPeerCertificate().size();
7
}
bool envoy_dynamic_module_callback_access_logger_get_downstream_peer_dns_san(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
2
    envoy_dynamic_module_type_envoy_buffer* sans_out) {
2
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
2
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
2
  if (!provider.sslConnection()) {
1
    return false;
1
  }
1
  const auto& sans = provider.sslConnection()->dnsSansPeerCertificate();
3
  for (size_t i = 0; i < sans.size(); ++i) {
2
    sans_out[i].ptr = const_cast<char*>(sans[i].data());
2
    sans_out[i].length = sans[i].size();
2
  }
1
  return true;
2
}
size_t envoy_dynamic_module_callback_access_logger_get_downstream_local_dns_san_size(
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
7
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
7
  if (!provider.sslConnection()) {
5
    return 0;
5
  }
2
  return provider.sslConnection()->dnsSansLocalCertificate().size();
7
}
bool envoy_dynamic_module_callback_access_logger_get_downstream_local_dns_san(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
2
    envoy_dynamic_module_type_envoy_buffer* sans_out) {
2
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
2
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
2
  if (!provider.sslConnection()) {
1
    return false;
1
  }
1
  const auto& sans = provider.sslConnection()->dnsSansLocalCertificate();
2
  for (size_t i = 0; i < sans.size(); ++i) {
1
    sans_out[i].ptr = const_cast<char*>(sans[i].data());
1
    sans_out[i].length = sans[i].size();
1
  }
1
  return true;
2
}
// -----------------------------------------------------------------------------
// Access Logger Callbacks - Metadata and Dynamic State
// -----------------------------------------------------------------------------
bool envoy_dynamic_module_callback_access_logger_get_dynamic_metadata(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
    envoy_dynamic_module_type_module_buffer filter_name,
3
    envoy_dynamic_module_type_module_buffer path, envoy_dynamic_module_type_envoy_buffer* result) {
3
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
3
  std::string filter_name_str(filter_name.ptr, filter_name.length);
3
  std::string path_str(path.ptr, path.length);
3
  std::vector<std::string> path_parts = absl::StrSplit(path_str, '.');
3
  const auto& metadata = logger->stream_info_->dynamicMetadata();
3
  const auto& value =
3
      Envoy::Config::Metadata::metadataValue(&metadata, filter_name_str, path_parts);
3
  if (value.kind_case() == Protobuf::Value::KIND_NOT_SET) {
1
    return false;
1
  }
  // Note: Currently only string values are supported. Complex types would require serialization
  // to a buffer, but the ABI uses zero-copy pointers to Envoy memory.
2
  if (value.kind_case() == Protobuf::Value::kStringValue) {
1
    const auto& str = value.string_value();
1
    *result = {const_cast<char*>(str.data()), str.size()};
1
    return true;
1
  }
1
  return false;
2
}
bool envoy_dynamic_module_callback_access_logger_get_filter_state(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
5
    envoy_dynamic_module_type_module_buffer key, envoy_dynamic_module_type_envoy_buffer* result) {
  // Note: FilterState access is not currently supported. FilterState serialization requires
  // allocation, but the ABI uses zero-copy pointers.
5
  UNREFERENCED_PARAMETER(logger_envoy_ptr);
5
  UNREFERENCED_PARAMETER(key);
5
  UNREFERENCED_PARAMETER(result);
5
  return false;
5
}
bool envoy_dynamic_module_callback_access_logger_get_request_id(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
6
    envoy_dynamic_module_type_envoy_buffer* result) {
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
6
  const auto provider = logger->stream_info_->getStreamIdProvider();
6
  if (provider.has_value() && provider->toStringView().has_value()) {
5
    absl::string_view view = provider->toStringView().value();
5
    *result = {const_cast<char*>(view.data()), view.size()};
5
    return true;
5
  }
1
  return false;
6
}
bool envoy_dynamic_module_callback_access_logger_get_local_reply_body(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
2
    envoy_dynamic_module_type_envoy_buffer* result) {
2
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
2
  absl::string_view body = logger->log_context_->localReplyBody();
2
  if (body.empty()) {
1
    return false;
1
  }
1
  *result = {const_cast<char*>(body.data()), body.size()};
1
  return true;
2
}
// -----------------------------------------------------------------------------
// Access Logger Callbacks - Tracing
// -----------------------------------------------------------------------------
bool envoy_dynamic_module_callback_access_logger_get_trace_id(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
5
    envoy_dynamic_module_type_envoy_buffer* result) {
  // Note: Tracing span access is not currently supported. The Span interface doesn't expose
  // trace/span IDs in a way that allows zero-copy access.
5
  UNREFERENCED_PARAMETER(logger_envoy_ptr);
5
  UNREFERENCED_PARAMETER(result);
5
  return false;
5
}
bool envoy_dynamic_module_callback_access_logger_get_span_id(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
5
    envoy_dynamic_module_type_envoy_buffer* result) {
  // Note: Tracing span access is not currently supported. The Span interface doesn't expose
  // trace/span IDs in a way that allows zero-copy access.
5
  UNREFERENCED_PARAMETER(logger_envoy_ptr);
5
  UNREFERENCED_PARAMETER(result);
5
  return false;
5
}
bool envoy_dynamic_module_callback_access_logger_is_trace_sampled(
2
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
2
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
  // Note: The Span interface doesn't expose a sampled() method. We check trace reason instead.
2
  return logger->stream_info_->traceReason() != Tracing::Reason::NotTraceable;
2
}
// -----------------------------------------------------------------------------
// Access Logger Callbacks - Additional Stream Info
// -----------------------------------------------------------------------------
bool envoy_dynamic_module_callback_access_logger_get_ja3_hash(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
6
    envoy_dynamic_module_type_envoy_buffer* result) {
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
6
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
6
  const auto& hash = provider.ja3Hash();
6
  if (hash.empty()) {
5
    return false;
5
  }
1
  *result = {const_cast<char*>(hash.data()), hash.size()};
1
  return true;
6
}
bool envoy_dynamic_module_callback_access_logger_get_ja4_hash(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
6
    envoy_dynamic_module_type_envoy_buffer* result) {
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
6
  const auto& provider = logger->stream_info_->downstreamAddressProvider();
6
  const auto& hash = provider.ja4Hash();
6
  if (hash.empty()) {
5
    return false;
5
  }
1
  *result = {const_cast<char*>(hash.data()), hash.size()};
1
  return true;
6
}
bool envoy_dynamic_module_callback_access_logger_get_downstream_transport_failure_reason(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
6
    envoy_dynamic_module_type_envoy_buffer* result) {
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
6
  const auto& reason = logger->stream_info_->downstreamTransportFailureReason();
6
  if (reason.empty()) {
5
    return false;
5
  }
1
  *result = {const_cast<char*>(reason.data()), reason.size()};
1
  return true;
6
}
uint64_t envoy_dynamic_module_callback_access_logger_get_request_headers_bytes(
6
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
6
  const auto& headers = logger->log_context_->requestHeaders();
6
  return headers.has_value() ? headers->byteSize() : 0;
6
}
uint64_t envoy_dynamic_module_callback_access_logger_get_response_headers_bytes(
6
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
6
  const auto& headers = logger->log_context_->responseHeaders();
6
  return headers.has_value() ? headers->byteSize() : 0;
6
}
uint64_t envoy_dynamic_module_callback_access_logger_get_response_trailers_bytes(
6
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
6
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
6
  const auto& trailers = logger->log_context_->responseTrailers();
6
  return trailers.has_value() ? trailers->byteSize() : 0;
6
}
bool envoy_dynamic_module_callback_access_logger_get_upstream_protocol(
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr,
8
    envoy_dynamic_module_type_envoy_buffer* result) {
8
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
8
  const auto upstream = logger->stream_info_->upstreamInfo();
8
  if (!upstream.has_value() || !upstream->upstreamProtocol().has_value()) {
2
    return false;
2
  }
6
  const auto& protocol_str = Http::Utility::getProtocolString(upstream->upstreamProtocol().value());
6
  *result = {const_cast<char*>(protocol_str.data()), protocol_str.size()};
6
  return true;
8
}
int64_t envoy_dynamic_module_callback_access_logger_get_upstream_pool_ready_duration_ns(
7
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
7
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
7
  const auto upstream = logger->stream_info_->upstreamInfo();
7
  if (!upstream.has_value()) {
1
    return -1;
1
  }
6
  const auto& latency = upstream->upstreamTiming().connectionPoolCallbackLatency();
6
  if (!latency.has_value()) {
1
    return -1;
1
  }
5
  return std::chrono::duration_cast<std::chrono::nanoseconds>(latency.value()).count();
6
}
// -----------------------------------------------------------------------------
// Metrics Callbacks
// -----------------------------------------------------------------------------
envoy_dynamic_module_type_metrics_result
envoy_dynamic_module_callback_access_logger_config_define_counter(
    envoy_dynamic_module_type_access_logger_config_envoy_ptr config_envoy_ptr,
3
    envoy_dynamic_module_type_module_buffer name, size_t* counter_id_ptr) {
3
  auto* config = static_cast<DynamicModuleAccessLogConfig*>(config_envoy_ptr);
3
  Stats::StatName main_stat_name =
3
      config->stat_name_pool_.add(absl::string_view(name.ptr, name.length));
3
  Stats::Counter& c = Stats::Utility::counterFromStatNames(*config->stats_scope_, {main_stat_name});
3
  *counter_id_ptr = config->addCounter({c});
3
  return envoy_dynamic_module_type_metrics_result_Success;
3
}
envoy_dynamic_module_type_metrics_result
envoy_dynamic_module_callback_access_logger_increment_counter(
    envoy_dynamic_module_type_access_logger_config_envoy_ptr config_envoy_ptr, size_t id,
6
    uint64_t value) {
6
  auto* config = static_cast<DynamicModuleAccessLogConfig*>(config_envoy_ptr);
6
  auto counter = config->getCounterById(id);
6
  if (!counter.has_value()) {
1
    return envoy_dynamic_module_type_metrics_result_MetricNotFound;
1
  }
5
  counter->add(value);
5
  return envoy_dynamic_module_type_metrics_result_Success;
6
}
envoy_dynamic_module_type_metrics_result
envoy_dynamic_module_callback_access_logger_config_define_gauge(
    envoy_dynamic_module_type_access_logger_config_envoy_ptr config_envoy_ptr,
1
    envoy_dynamic_module_type_module_buffer name, size_t* gauge_id_ptr) {
1
  auto* config = static_cast<DynamicModuleAccessLogConfig*>(config_envoy_ptr);
1
  Stats::StatName main_stat_name =
1
      config->stat_name_pool_.add(absl::string_view(name.ptr, name.length));
1
  Stats::Gauge& g = Stats::Utility::gaugeFromStatNames(*config->stats_scope_, {main_stat_name},
1
                                                       Stats::Gauge::ImportMode::Accumulate);
1
  *gauge_id_ptr = config->addGauge({g});
1
  return envoy_dynamic_module_type_metrics_result_Success;
1
}
envoy_dynamic_module_type_metrics_result envoy_dynamic_module_callback_access_logger_set_gauge(
    envoy_dynamic_module_type_access_logger_config_envoy_ptr config_envoy_ptr, size_t id,
2
    uint64_t value) {
2
  auto* config = static_cast<DynamicModuleAccessLogConfig*>(config_envoy_ptr);
2
  auto gauge = config->getGaugeById(id);
2
  if (!gauge.has_value()) {
1
    return envoy_dynamic_module_type_metrics_result_MetricNotFound;
1
  }
1
  gauge->set(value);
1
  return envoy_dynamic_module_type_metrics_result_Success;
2
}
envoy_dynamic_module_type_metrics_result
envoy_dynamic_module_callback_access_logger_increment_gauge(
    envoy_dynamic_module_type_access_logger_config_envoy_ptr config_envoy_ptr, size_t id,
1
    uint64_t value) {
1
  auto* config = static_cast<DynamicModuleAccessLogConfig*>(config_envoy_ptr);
1
  auto gauge = config->getGaugeById(id);
1
  if (!gauge.has_value()) {
    return envoy_dynamic_module_type_metrics_result_MetricNotFound;
  }
1
  gauge->add(value);
1
  return envoy_dynamic_module_type_metrics_result_Success;
1
}
envoy_dynamic_module_type_metrics_result
envoy_dynamic_module_callback_access_logger_decrement_gauge(
    envoy_dynamic_module_type_access_logger_config_envoy_ptr config_envoy_ptr, size_t id,
1
    uint64_t value) {
1
  auto* config = static_cast<DynamicModuleAccessLogConfig*>(config_envoy_ptr);
1
  auto gauge = config->getGaugeById(id);
1
  if (!gauge.has_value()) {
    return envoy_dynamic_module_type_metrics_result_MetricNotFound;
  }
1
  gauge->sub(value);
1
  return envoy_dynamic_module_type_metrics_result_Success;
1
}
envoy_dynamic_module_type_metrics_result
envoy_dynamic_module_callback_access_logger_config_define_histogram(
    envoy_dynamic_module_type_access_logger_config_envoy_ptr config_envoy_ptr,
1
    envoy_dynamic_module_type_module_buffer name, size_t* histogram_id_ptr) {
1
  auto* config = static_cast<DynamicModuleAccessLogConfig*>(config_envoy_ptr);
1
  Stats::StatName main_stat_name =
1
      config->stat_name_pool_.add(absl::string_view(name.ptr, name.length));
1
  Stats::Histogram& h = Stats::Utility::histogramFromStatNames(
1
      *config->stats_scope_, {main_stat_name}, Stats::Histogram::Unit::Unspecified);
1
  *histogram_id_ptr = config->addHistogram({h});
1
  return envoy_dynamic_module_type_metrics_result_Success;
1
}
envoy_dynamic_module_type_metrics_result
envoy_dynamic_module_callback_access_logger_record_histogram_value(
    envoy_dynamic_module_type_access_logger_config_envoy_ptr config_envoy_ptr, size_t id,
2
    uint64_t value) {
2
  auto* config = static_cast<DynamicModuleAccessLogConfig*>(config_envoy_ptr);
2
  auto histogram = config->getHistogramById(id);
2
  if (!histogram.has_value()) {
1
    return envoy_dynamic_module_type_metrics_result_MetricNotFound;
1
  }
1
  histogram->recordValue(value);
1
  return envoy_dynamic_module_type_metrics_result_Success;
2
}
// -----------------------------------------------------------------------------
// Misc Callbacks
// -----------------------------------------------------------------------------
uint32_t envoy_dynamic_module_callback_access_logger_get_worker_index(
9
    envoy_dynamic_module_type_access_logger_envoy_ptr logger_envoy_ptr) {
9
  auto* logger = static_cast<ThreadLocalLogger*>(logger_envoy_ptr);
9
  return logger->worker_index_;
9
}
} // extern "C"
} // namespace DynamicModules
} // namespace AccessLoggers
} // namespace Extensions
} // namespace Envoy