1use std::{collections::BTreeMap, sync::LazyLock};
2
3use vector_lib::lookup::{OwnedValuePath, owned_value_path};
4use vrl::{
5 btreemap,
6 value::{
7 Kind,
8 kind::{Collection, Field},
9 },
10};
11
12#[derive(Debug, Default, Clone)]
13pub struct DnstapEventSchema;
14
15impl DnstapEventSchema {
16 pub(crate) fn request_message_schema_definition(&self) -> Collection<Field> {
18 let mut result: BTreeMap<Field, Kind> = BTreeMap::new();
19 result.insert(
20 DNSTAP_VALUE_PATHS.time.to_string().into(),
21 Kind::integer().or_undefined(),
22 );
23
24 result.insert(
25 DNSTAP_VALUE_PATHS.time.to_string().into(),
26 Kind::integer().or_undefined(),
27 );
28 result.insert(
29 DNSTAP_VALUE_PATHS.time_precision.to_string().into(),
30 Kind::bytes().or_undefined(),
31 );
32 result.insert(
33 DNSTAP_VALUE_PATHS.time_precision.to_string().into(),
34 Kind::bytes().or_undefined(),
35 );
36 result.insert(
37 DNSTAP_VALUE_PATHS.response_code.to_string().into(),
38 Kind::integer().or_undefined(),
39 );
40 result.insert(
41 DNSTAP_VALUE_PATHS.response_code.to_string().into(),
42 Kind::integer().or_undefined(),
43 );
44 result.insert(
45 DNSTAP_VALUE_PATHS.response.to_string().into(),
46 Kind::bytes().or_undefined(),
47 );
48 result.insert(
49 DNSTAP_VALUE_PATHS.response.to_string().into(),
50 Kind::bytes().or_undefined(),
51 );
52
53 let mut schema = DnsQueryHeaderSchema::schema_definition();
54 schema.merge(DnsUpdateHeaderSchema::schema_definition(), true);
55
56 result.insert(
57 DNSTAP_VALUE_PATHS.header.to_string().into(),
58 Kind::object(schema).or_undefined(),
59 );
60
61 result.insert(
62 DNSTAP_VALUE_PATHS.zone_section.to_string().into(),
63 Kind::object(DnsUpdateZoneInfoSchema::schema_definition()).or_undefined(),
64 );
65
66 result.insert(
67 DNSTAP_VALUE_PATHS.question_section.to_string().into(),
68 Kind::array(Collection::from_unknown(Kind::object(
69 DnsQueryQuestionSchema::schema_definition(),
70 )))
71 .or_undefined(),
72 );
73
74 result.insert(
75 DNSTAP_VALUE_PATHS.answer_section.to_string().into(),
76 Kind::array(Collection::from_unknown(Kind::object(
77 DnsRecordSchema::schema_definition(),
78 )))
79 .or_undefined(),
80 );
81
82 result.insert(
83 DNSTAP_VALUE_PATHS.authority_section.to_string().into(),
84 Kind::array(Collection::from_unknown(Kind::object(
85 DnsRecordSchema::schema_definition(),
86 )))
87 .or_undefined(),
88 );
89
90 result.insert(
91 DNSTAP_VALUE_PATHS.additional_section.to_string().into(),
92 Kind::array(Collection::from_unknown(Kind::object(
93 DnsRecordSchema::schema_definition(),
94 )))
95 .or_undefined(),
96 );
97
98 result.insert(
99 DNSTAP_VALUE_PATHS.opt_pseudo_section.to_string().into(),
100 Kind::object(DnsMessageOptPseudoSectionSchema::schema_definition()).or_undefined(),
101 );
102
103 result.insert(
104 DNSTAP_VALUE_PATHS.raw_data.to_string().into(),
105 Kind::bytes().or_undefined(),
106 );
107
108 result.insert(
109 DNSTAP_VALUE_PATHS.prerequisite_section.to_string().into(),
110 Kind::array(Collection::from_unknown(Kind::object(
111 DnsRecordSchema::schema_definition(),
112 )))
113 .or_undefined(),
114 );
115
116 result.insert(
117 DNSTAP_VALUE_PATHS.update_section.to_string().into(),
118 Kind::array(Collection::from_unknown(Kind::object(
119 DnsRecordSchema::schema_definition(),
120 )))
121 .or_undefined(),
122 );
123
124 result.insert(
125 DNSTAP_VALUE_PATHS.additional_section.to_string().into(),
126 Kind::array(Collection::from_unknown(Kind::object(
127 DnsRecordSchema::schema_definition(),
128 )))
129 .or_undefined(),
130 );
131
132 result.into()
133 }
134
135 fn root_schema_definition(
137 &self,
138 schema: vector_lib::schema::Definition,
139 ) -> vector_lib::schema::Definition {
140 schema
141 .optional_field(&DNSTAP_VALUE_PATHS.server_identity, Kind::bytes(), None)
142 .optional_field(&DNSTAP_VALUE_PATHS.server_version, Kind::bytes(), None)
143 .optional_field(&DNSTAP_VALUE_PATHS.extra, Kind::bytes(), None)
144 .with_event_field(&DNSTAP_VALUE_PATHS.data_type_id, Kind::integer(), None)
145 .optional_field(&DNSTAP_VALUE_PATHS.data_type, Kind::bytes(), None)
146 .optional_field(&DNSTAP_VALUE_PATHS.error, Kind::bytes(), None)
147 .optional_field(&DNSTAP_VALUE_PATHS.raw_data, Kind::bytes(), None)
148 .optional_field(&DNSTAP_VALUE_PATHS.time, Kind::integer(), None)
149 .optional_field(&DNSTAP_VALUE_PATHS.time_precision, Kind::bytes(), None)
150 }
151
152 pub fn message_schema_definition(
154 &self,
155 schema: vector_lib::schema::Definition,
156 ) -> vector_lib::schema::Definition {
157 schema
158 .optional_field(&DNSTAP_VALUE_PATHS.socket_family, Kind::bytes(), None)
159 .optional_field(&DNSTAP_VALUE_PATHS.socket_protocol, Kind::bytes(), None)
160 .optional_field(&DNSTAP_VALUE_PATHS.query_address, Kind::bytes(), None)
161 .optional_field(&DNSTAP_VALUE_PATHS.query_port, Kind::integer(), None)
162 .optional_field(&DNSTAP_VALUE_PATHS.response_address, Kind::bytes(), None)
163 .optional_field(&DNSTAP_VALUE_PATHS.response_port, Kind::integer(), None)
164 .optional_field(&DNSTAP_VALUE_PATHS.query_zone, Kind::bytes(), None)
165 .with_event_field(&DNSTAP_VALUE_PATHS.message_type_id, Kind::integer(), None)
166 .optional_field(&DNSTAP_VALUE_PATHS.message_type, Kind::bytes(), None)
167 .optional_field(
168 &DNSTAP_VALUE_PATHS.request_message,
169 Kind::object(self.request_message_schema_definition()),
170 None,
171 )
172 .optional_field(
173 &DNSTAP_VALUE_PATHS.response_message,
174 Kind::object(self.request_message_schema_definition()),
175 None,
176 )
177 }
178
179 pub fn schema_definition(
181 &self,
182 schema: vector_lib::schema::Definition,
183 ) -> vector_lib::schema::Definition {
184 self.root_schema_definition(self.message_schema_definition(schema))
185 }
186}
187
188#[derive(Debug, Clone)]
190pub struct DnstapPaths {
191 pub server_identity: OwnedValuePath,
193 pub server_version: OwnedValuePath,
194 pub extra: OwnedValuePath,
195 pub data_type: OwnedValuePath,
196 pub data_type_id: OwnedValuePath,
197 pub time: OwnedValuePath,
198 pub time_precision: OwnedValuePath,
199 pub error: OwnedValuePath,
200 pub raw_data: OwnedValuePath,
201
202 pub socket_family: OwnedValuePath,
204 pub socket_protocol: OwnedValuePath,
205 pub query_address: OwnedValuePath,
206 pub query_port: OwnedValuePath,
207 pub response_address: OwnedValuePath,
208 pub response_port: OwnedValuePath,
209 pub query_zone: OwnedValuePath,
210 pub message_type: OwnedValuePath,
211 pub message_type_id: OwnedValuePath,
212 pub request_message: OwnedValuePath,
213 pub response_message: OwnedValuePath,
214
215 pub response_code: OwnedValuePath,
217 pub response: OwnedValuePath,
218 pub header: OwnedValuePath,
219 pub question_section: OwnedValuePath,
220 pub answer_section: OwnedValuePath,
221 pub authority_section: OwnedValuePath,
222 pub additional_section: OwnedValuePath,
223 pub opt_pseudo_section: OwnedValuePath,
224
225 pub zone_section: OwnedValuePath,
227 pub prerequisite_section: OwnedValuePath,
228 pub update_section: OwnedValuePath,
229
230 pub id: OwnedValuePath,
232 pub opcode: OwnedValuePath,
233 pub rcode: OwnedValuePath,
234 pub qr: OwnedValuePath,
235
236 pub aa: OwnedValuePath,
238 pub tc: OwnedValuePath,
239 pub rd: OwnedValuePath,
240 pub ra: OwnedValuePath,
241 pub ad: OwnedValuePath,
242 pub cd: OwnedValuePath,
243 pub question_count: OwnedValuePath,
244 pub answer_count: OwnedValuePath,
245 pub authority_count: OwnedValuePath,
246 pub ar_count: OwnedValuePath,
247
248 pub zone_count: OwnedValuePath,
250 pub prerequisite_count: OwnedValuePath,
251 pub update_count: OwnedValuePath,
252 pub ad_count: OwnedValuePath,
253
254 pub extended_rcode: OwnedValuePath,
256 pub version: OwnedValuePath,
257 pub do_flag: OwnedValuePath,
258 pub udp_max_payload_size: OwnedValuePath,
259 pub ede: OwnedValuePath,
260 pub options: OwnedValuePath,
261
262 pub info_code: OwnedValuePath,
264 pub purpose: OwnedValuePath,
265 pub extra_text: OwnedValuePath,
266
267 pub opt_code: OwnedValuePath,
269 pub opt_name: OwnedValuePath,
270 pub opt_data: OwnedValuePath,
271
272 pub domain_name: OwnedValuePath,
274 pub record_type: OwnedValuePath,
275 pub record_type_id: OwnedValuePath,
276 pub ttl: OwnedValuePath,
277 pub class: OwnedValuePath,
278 pub rdata: OwnedValuePath,
279 pub rdata_bytes: OwnedValuePath,
280
281 pub question_type: OwnedValuePath,
283 pub question_type_id: OwnedValuePath,
284
285 pub zone_name: OwnedValuePath,
287 pub zone_class: OwnedValuePath,
288 pub zone_type: OwnedValuePath,
289 pub zone_type_id: OwnedValuePath,
290}
291
292pub static DNSTAP_VALUE_PATHS: LazyLock<DnstapPaths> = LazyLock::new(|| DnstapPaths {
294 server_identity: owned_value_path!("serverId"),
295 server_version: owned_value_path!("serverVersion"),
296 extra: owned_value_path!("extraInfo"),
297 data_type: owned_value_path!("dataType"),
298 data_type_id: owned_value_path!("dataTypeId"),
299 time: owned_value_path!("time"),
300 time_precision: owned_value_path!("timePrecision"),
301 error: owned_value_path!("error"),
302 raw_data: owned_value_path!("rawData"),
303 socket_family: owned_value_path!("socketFamily"),
304 socket_protocol: owned_value_path!("socketProtocol"),
305 query_address: owned_value_path!("sourceAddress"),
306 query_port: owned_value_path!("sourcePort"),
307 response_address: owned_value_path!("responseAddress"),
308 response_port: owned_value_path!("responsePort"),
309 query_zone: owned_value_path!("queryZone"),
310 message_type: owned_value_path!("messageType"),
311 message_type_id: owned_value_path!("messageTypeId"),
312 request_message: owned_value_path!("requestData"),
313 response_message: owned_value_path!("responseData"),
314 response_code: owned_value_path!("fullRcode"),
315 response: owned_value_path!("rcodeName"),
316 header: owned_value_path!("header"),
317 question_section: owned_value_path!("question"),
318 answer_section: owned_value_path!("answers"),
319 authority_section: owned_value_path!("authority"),
320 additional_section: owned_value_path!("additional"),
321 opt_pseudo_section: owned_value_path!("opt"),
322 zone_section: owned_value_path!("zone"),
323 prerequisite_section: owned_value_path!("prerequisite"),
324 update_section: owned_value_path!("update"),
325 id: owned_value_path!("id"),
326 opcode: owned_value_path!("opcode"),
327 rcode: owned_value_path!("rcode"),
328 qr: owned_value_path!("qr"),
329 aa: owned_value_path!("aa"),
330 tc: owned_value_path!("tc"),
331 rd: owned_value_path!("rd"),
332 ra: owned_value_path!("ra"),
333 ad: owned_value_path!("ad"),
334 cd: owned_value_path!("cd"),
335 question_count: owned_value_path!("qdCount"),
336 answer_count: owned_value_path!("anCount"),
337 authority_count: owned_value_path!("nsCount"),
338 ar_count: owned_value_path!("arCount"),
339 zone_count: owned_value_path!("zoCount"),
340 prerequisite_count: owned_value_path!("prCount"),
341 update_count: owned_value_path!("upCount"),
342 ad_count: owned_value_path!("adCount"),
343 extended_rcode: owned_value_path!("extendedRcode"),
344 version: owned_value_path!("ednsVersion"),
345 do_flag: owned_value_path!("do"),
346 udp_max_payload_size: owned_value_path!("udpPayloadSize"),
347 ede: owned_value_path!("ede"),
348 options: owned_value_path!("options"),
349 info_code: owned_value_path!("infoCode"),
350 purpose: owned_value_path!("purpose"),
351 extra_text: owned_value_path!("extraText"),
352 opt_code: owned_value_path!("optCode"),
353 opt_name: owned_value_path!("optName"),
354 opt_data: owned_value_path!("optValue"),
355 record_type: owned_value_path!("recordType"),
356 record_type_id: owned_value_path!("recordTypeId"),
357 ttl: owned_value_path!("ttl"),
358 class: owned_value_path!("class"),
359 rdata: owned_value_path!("rData"),
360 rdata_bytes: owned_value_path!("rDataBytes"),
361 domain_name: owned_value_path!("domainName"),
362 question_type: owned_value_path!("questionType"),
363 question_type_id: owned_value_path!("questionTypeId"),
364 zone_name: owned_value_path!("zName"),
365 zone_class: owned_value_path!("zClass"),
366 zone_type: owned_value_path!("zType"),
367 zone_type_id: owned_value_path!("zTypeId"),
368});
369
370#[derive(Debug, Default, Clone)]
371pub struct DnsQueryHeaderSchema;
372
373impl DnsQueryHeaderSchema {
374 pub fn schema_definition() -> Collection<Field> {
375 btreemap! {
376 DNSTAP_VALUE_PATHS.id.to_string() => Kind::integer(),
377 DNSTAP_VALUE_PATHS.opcode.to_string() => Kind::integer(),
378 DNSTAP_VALUE_PATHS.rcode.to_string() => Kind::integer(),
379 DNSTAP_VALUE_PATHS.qr.to_string() => Kind::integer(),
380 DNSTAP_VALUE_PATHS.aa.to_string() => Kind::boolean(),
381 DNSTAP_VALUE_PATHS.tc.to_string() => Kind::boolean(),
382 DNSTAP_VALUE_PATHS.rd.to_string() => Kind::boolean(),
383 DNSTAP_VALUE_PATHS.ra.to_string() => Kind::boolean(),
384 DNSTAP_VALUE_PATHS.ad.to_string() => Kind::boolean(),
385 DNSTAP_VALUE_PATHS.cd.to_string() => Kind::boolean(),
386 DNSTAP_VALUE_PATHS.ar_count.to_string() => Kind::integer().or_undefined(),
387 DNSTAP_VALUE_PATHS.question_count.to_string() => Kind::integer().or_undefined(),
388 DNSTAP_VALUE_PATHS.answer_count.to_string() => Kind::integer().or_undefined(),
389 DNSTAP_VALUE_PATHS.authority_count.to_string() => Kind::integer().or_undefined(),
390 }
391 .into()
392 }
393}
394
395#[derive(Debug, Default, Clone)]
396pub struct DnsUpdateHeaderSchema;
397
398impl DnsUpdateHeaderSchema {
399 pub fn schema_definition() -> Collection<Field> {
400 btreemap! {
401 DNSTAP_VALUE_PATHS.id.to_string() => Kind::integer(),
402 DNSTAP_VALUE_PATHS.opcode.to_string() => Kind::integer(),
403 DNSTAP_VALUE_PATHS.rcode.to_string() => Kind::integer(),
404 DNSTAP_VALUE_PATHS.qr.to_string() => Kind::integer(),
405 DNSTAP_VALUE_PATHS.zone_count.to_string() => Kind::integer().or_undefined(),
406 DNSTAP_VALUE_PATHS.prerequisite_count.to_string() => Kind::integer().or_undefined(),
407 DNSTAP_VALUE_PATHS.update_count.to_string() => Kind::integer().or_undefined(),
408 DNSTAP_VALUE_PATHS.ad_count.to_string() => Kind::integer().or_undefined(),
409 }
410 .into()
411 }
412}
413
414#[derive(Debug, Default, Clone)]
415pub struct DnsMessageOptPseudoSectionSchema;
416
417impl DnsMessageOptPseudoSectionSchema {
418 pub fn schema_definition() -> Collection<Field> {
419 btreemap! {
420 DNSTAP_VALUE_PATHS.extended_rcode.to_string() => Kind::integer(),
421 DNSTAP_VALUE_PATHS.version.to_string() => Kind::integer(),
422 DNSTAP_VALUE_PATHS.do_flag.to_string() => Kind::boolean(),
423 DNSTAP_VALUE_PATHS.udp_max_payload_size.to_string() => Kind::integer(),
424 DNSTAP_VALUE_PATHS.options.to_string() => Kind::array(
425 Collection::from_unknown(Kind::object(DnsMessageOptionSchema::schema_definition()))
426 ).or_undefined(),
427 }
428 .into()
429 }
430}
431
432#[derive(Debug, Default, Clone)]
433pub struct DnsMessageEdeOptionSchema;
434
435impl DnsMessageEdeOptionSchema {
436 pub fn schema_definition() -> Collection<Field> {
437 btreemap! {
438 DNSTAP_VALUE_PATHS.info_code.to_string() => Kind::integer(),
439 DNSTAP_VALUE_PATHS.purpose.to_string() => Kind::bytes(),
440 DNSTAP_VALUE_PATHS.extra_text.to_string() => Kind::bytes(),
441 }
442 .into()
443 }
444}
445
446#[derive(Debug, Default, Clone)]
447pub struct DnsMessageOptionSchema;
448
449impl DnsMessageOptionSchema {
450 pub fn schema_definition() -> Collection<Field> {
451 btreemap! {
452 DNSTAP_VALUE_PATHS.opt_code.to_string() => Kind::integer(),
453 DNSTAP_VALUE_PATHS.opt_name.to_string() => Kind::bytes(),
454 DNSTAP_VALUE_PATHS.opt_data.to_string() => Kind::bytes(),
455 }
456 .into()
457 }
458}
459
460#[derive(Debug, Default, Clone)]
461pub struct DnsRecordSchema;
462
463impl DnsRecordSchema {
464 pub fn schema_definition() -> Collection<Field> {
465 btreemap! {
466 DNSTAP_VALUE_PATHS.domain_name.to_string() => Kind::bytes(),
467 DNSTAP_VALUE_PATHS.record_type.to_string() => Kind::bytes().or_undefined(),
468 DNSTAP_VALUE_PATHS.record_type_id.to_string() => Kind::integer(),
469 DNSTAP_VALUE_PATHS.ttl.to_string() => Kind::integer(),
470 DNSTAP_VALUE_PATHS.class.to_string() => Kind::bytes(),
471 DNSTAP_VALUE_PATHS.rdata.to_string() => Kind::bytes(),
472 DNSTAP_VALUE_PATHS.rdata_bytes.to_string() => Kind::bytes().or_undefined(),
473 }
474 .into()
475 }
476}
477
478#[derive(Debug, Default, Clone)]
479pub struct DnsQueryQuestionSchema;
480
481impl DnsQueryQuestionSchema {
482 pub fn schema_definition() -> Collection<Field> {
483 btreemap! {
484 DNSTAP_VALUE_PATHS.class.to_string() => Kind::bytes(),
485 DNSTAP_VALUE_PATHS.domain_name.to_string() => Kind::bytes(),
486 DNSTAP_VALUE_PATHS.question_type.to_string() => Kind::bytes(),
487 DNSTAP_VALUE_PATHS.question_type_id.to_string() => Kind::integer(),
488 }
489 .into()
490 }
491}
492
493#[derive(Debug, Default, Clone)]
494pub struct DnsUpdateZoneInfoSchema;
495
496impl DnsUpdateZoneInfoSchema {
497 pub fn schema_definition() -> Collection<Field> {
498 btreemap! {
499 DNSTAP_VALUE_PATHS.zone_name.to_string() => Kind::bytes(),
500 DNSTAP_VALUE_PATHS.zone_type.to_string() => Kind::bytes().or_undefined(),
501 DNSTAP_VALUE_PATHS.zone_type_id.to_string() => Kind::integer(),
502 DNSTAP_VALUE_PATHS.zone_class.to_string() => Kind::bytes(),
503 }
504 .into()
505 }
506}