From f62483ecdaf2e33cc76e5e6afc62a29415900daa Mon Sep 17 00:00:00 2001 From: Alejandro Estringana Ruiz Date: Fri, 8 Nov 2024 11:49:19 +0100 Subject: [PATCH] Add asm event to propagated tags --- appsec/src/extension/ddtrace.c | 28 ++++++++ appsec/src/extension/ddtrace.h | 1 + appsec/src/extension/tags.c | 18 +++-- .../rinit_asm_events_propagate_tags.phpt | 66 +++++++++++++++++++ ddtrace.sym | 1 + .../tracer_tag_propagation.c | 15 +++++ .../tracer_tag_propagation.h | 3 + 7 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 appsec/tests/extension/rinit_asm_events_propagate_tags.phpt diff --git a/appsec/src/extension/ddtrace.c b/appsec/src/extension/ddtrace.c index f26927803b4..96ed5ad389b 100644 --- a/appsec/src/extension/ddtrace.c +++ b/appsec/src/extension/ddtrace.c @@ -28,6 +28,7 @@ static zend_string *_ddtrace_root_span_fname; static zend_string *_meta_propname; static zend_string *_metrics_propname; static zend_string *_meta_struct_propname; +static zend_string *_propagated_tags_propname; static THREAD_LOCAL_ON_ZTS bool _suppress_ddtrace_rshutdown; static uint8_t *_ddtrace_runtime_id = NULL; @@ -40,6 +41,8 @@ static void (*nullable _ddtrace_close_all_spans_and_flush)(void); static void (*nullable _ddtrace_set_priority_sampling_on_span_zobj)( zend_object *nonnull zobj, zend_long priority, enum dd_sampling_mechanism mechanism); +static void (*nullable _ddtrace_add_propagated_tag_on_span_zobj)( + zend_string *nonnull key, zval *nonnull value); static bool (*nullable _ddtrace_user_req_add_listeners)( ddtrace_user_req_listeners *listeners); @@ -88,6 +91,14 @@ static void dd_trace_load_symbols(void) dlerror()); // NOLINT(concurrency-mt-unsafe) } + _ddtrace_add_propagated_tag_on_span_zobj = + dlsym(handle, "ddtrace_add_propagated_tag_on_span_zobj"); + if (_ddtrace_add_propagated_tag_on_span_zobj == NULL) { + mlog(dd_log_error, + "Failed to load ddtrace_add_propagated_tag_on_span_zobj: %s", + dlerror()); // NOLINT(concurrency-mt-unsafe) + } + _ddtrace_user_req_add_listeners = dlsym(handle, "ddtrace_user_req_add_listeners"); if (_ddtrace_user_req_add_listeners == NULL) { @@ -120,6 +131,8 @@ void dd_trace_startup() _metrics_propname = zend_string_init_interned(LSTRARG("metrics"), 1); _meta_struct_propname = zend_string_init_interned(LSTRARG("meta_struct"), 1); + _propagated_tags_propname = + zend_string_init_interned(LSTRARG("propagated_tags"), 1); if (get_global_DD_APPSEC_TESTING()) { _register_testing_objects(); @@ -304,6 +317,11 @@ zval *nullable dd_trace_span_get_meta_struct(zend_object *nonnull zobj) return _get_span_modifiable_array_property(zobj, _meta_struct_propname); } +zval *nullable dd_trace_span_get_propagated_tags(zend_object *nonnull zobj) +{ + return _get_span_modifiable_array_property(zobj, _propagated_tags_propname); +} + // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) zend_string *nullable dd_trace_get_formatted_runtime_id(bool persistent) { @@ -379,6 +397,16 @@ const char *nullable dd_trace_remote_config_get_path() return path; } +void dd_trace_span_add_propagated_tags( + zend_string *nonnull key, zval *nonnull value) +{ + if (UNEXPECTED(_ddtrace_add_propagated_tag_on_span_zobj == NULL)) { + return; + } + + _ddtrace_add_propagated_tag_on_span_zobj(key, value); +} + static PHP_FUNCTION(datadog_appsec_testing_ddtrace_rshutdown) { if (zend_parse_parameters_none() == FAILURE) { diff --git a/appsec/src/extension/ddtrace.h b/appsec/src/extension/ddtrace.h index 7615854df86..f4a24a4f6e7 100644 --- a/appsec/src/extension/ddtrace.h +++ b/appsec/src/extension/ddtrace.h @@ -53,6 +53,7 @@ void dd_trace_close_all_spans_and_flush(void); zval *nullable dd_trace_span_get_meta(zend_object *nonnull); zval *nullable dd_trace_span_get_metrics(zend_object *nonnull); zval *nullable dd_trace_span_get_meta_struct(zend_object *nonnull); +void dd_trace_span_add_propagated_tags(zend_string *nonnull key, zval *nonnull value); zend_string *nullable dd_trace_get_formatted_runtime_id(bool persistent); // Set sampling priority on root span diff --git a/appsec/src/extension/tags.c b/appsec/src/extension/tags.c index 6adebc19f96..a82c144cc2d 100644 --- a/appsec/src/extension/tags.c +++ b/appsec/src/extension/tags.c @@ -109,7 +109,7 @@ static THREAD_LOCAL_ON_ZTS bool _appsec_json_frags_inited; static THREAD_LOCAL_ON_ZTS zend_llist _appsec_json_frags; static THREAD_LOCAL_ON_ZTS zend_string *nullable _event_user_id; static THREAD_LOCAL_ON_ZTS bool _blocked; -static THREAD_LOCAL_ON_ZTS bool _asm_event; +static THREAD_LOCAL_ON_ZTS bool _asm_event_propagated; static THREAD_LOCAL_ON_ZTS bool _force_keep; static void _init_relevant_headers(void); @@ -295,8 +295,8 @@ void dd_tags_rinit() // Just in case... _event_user_id = NULL; _blocked = false; - _asm_event = false; _force_keep = false; + _asm_event_propagated = false; } void dd_tags_add_appsec_json_frag(zend_string *nonnull zstr) @@ -321,6 +321,9 @@ void dd_tags_rshutdown() void dd_appsec_add_asm_event() { + if (_asm_event_propagated) { + return; + } zval *nullable meta = _root_span_get_meta(); if (meta && Z_TYPE_P(meta) == IS_ARRAY) { zend_array *meta_ht = Z_ARRVAL_P(meta); @@ -329,6 +332,11 @@ void dd_appsec_add_asm_event() _add_new_zstr_to_meta( meta_ht, _dd_tag_p_appsec_zstr, _1_zstr, true, false); } + + zval _1_zval; + ZVAL_STR(&_1_zval, _1_zstr); + dd_trace_span_add_propagated_tags(_dd_tag_p_appsec_zstr, &_1_zval); + _asm_event_propagated = true; } void dd_tags_add_tags( @@ -890,13 +898,15 @@ static zval *nullable _root_span_get_meta() { zend_object *nullable span = dd_req_lifecycle_get_cur_span(); if (!span) { - mlog(dd_log_warning, "No root span being tracked by appsec"); +// TODO Uncomment this +// mlog(dd_log_warning, "No root span being tracked by appsec"); return NULL; } zval *nullable meta = dd_trace_span_get_meta(span); if (!meta) { - mlog(dd_log_warning, "Failed to retrieve root span meta"); +// TODO Uncomment this +// mlog(dd_log_warning, "Failed to retrieve root span meta"); } return meta; } diff --git a/appsec/tests/extension/rinit_asm_events_propagate_tags.phpt b/appsec/tests/extension/rinit_asm_events_propagate_tags.phpt new file mode 100644 index 00000000000..636023e0559 --- /dev/null +++ b/appsec/tests/extension/rinit_asm_events_propagate_tags.phpt @@ -0,0 +1,66 @@ +--TEST-- +Asm events are added as meta tags and also as propagated tags +--INI-- +extension=ddtrace.so +datadog.appsec.log_file=/tmp/php_appsec_test.log +datadog.appsec.log_level=debug +datadog.appsec.enabled=1 +--ENV-- +HTTP_X_DATADOG_TRACE_ID=42 +HTTP_X_DATADOG_PARENT_ID=10 +HTTP_X_DATADOG_ORIGIN=datadog +HTTP_X_DATADOG_TAGS=_dd.p.custom_tag=inherited,_dd.p.second_tag=bar +--FILE-- + "rshutdown_value"], ["rshutdown_metric" => 2.1]] + ) + ), +], ['continuous' => true]); + +echo "rinit\n"; +var_dump(rinit()); +$helper->get_commands(); //ignore + +$context = DDTrace\current_context(); +echo "_dd.p.appsec on distributed propagated tags? "; +echo isset($context['distributed_tracing_propagated_tags']['_dd.p.appsec']) && $context['distributed_tracing_propagated_tags']['_dd.p.appsec'] == 1 ? "Yes": "No"; +echo PHP_EOL; + +echo "rshutdown\n"; +var_dump(rshutdown()); +$helper->get_commands(); //ignore + +echo "ddtrace_rshutdown\n"; +var_dump(ddtrace_rshutdown()); +dd_trace_internal_fn('synchronous_flush'); + +$commands = $helper->get_commands(); +$tags = $commands[0]['payload'][0][0]['meta']; + +echo "_dd.p.appsec? "; +echo isset($tags['_dd.p.appsec']) && $tags['_dd.p.appsec'] === "1" ? "Yes": "No"; +echo PHP_EOL; + +$helper->finished_with_commands(); + +?> +--EXPECTF-- +rinit +bool(true) +_dd.p.appsec on distributed propagated tags? Yes +rshutdown +bool(true) +ddtrace_rshutdown +bool(true) +_dd.p.appsec? Yes diff --git a/ddtrace.sym b/ddtrace.sym index d20803d5d3f..2ee54fced30 100644 --- a/ddtrace.sym +++ b/ddtrace.sym @@ -2,6 +2,7 @@ ddtrace_close_all_spans_and_flush ddtrace_get_profiling_context ddtrace_get_root_span ddtrace_set_priority_sampling_on_span_zobj +ddtrace_add_propagated_tag_on_span_zobj ddtrace_runtime_id ddtrace_user_req_add_listeners ddtrace_ip_extraction_find diff --git a/ext/tracer_tag_propagation/tracer_tag_propagation.c b/ext/tracer_tag_propagation/tracer_tag_propagation.c index d872ce55ff8..bb5a0e5c1d8 100644 --- a/ext/tracer_tag_propagation/tracer_tag_propagation.c +++ b/ext/tracer_tag_propagation/tracer_tag_propagation.c @@ -182,3 +182,18 @@ zend_string *ddtrace_format_propagated_tags(zend_array *propagated, zend_array * smart_str_0(&taglist); return taglist.s; } + +DDTRACE_PUBLIC void ddtrace_add_propagated_tag_on_span_zobj(zend_string *key, zval *value) { + ddtrace_root_span_data *root_span = DDTRACE_G(active_stack)->root_span; + zend_array *root_meta = &DDTRACE_G(root_span_tags_preset); + zend_array *propagated_tags = &DDTRACE_G(propagated_root_span_tags); + if (root_span) { + root_meta = ddtrace_property_array(&root_span->property_meta); + propagated_tags = ddtrace_property_array(&root_span->property_propagated_tags); + } + + zval tagstr; + ddtrace_convert_to_string(&tagstr, value); + zend_hash_update(root_meta, key, &tagstr); + zend_hash_add_empty_element(propagated_tags, key); +} diff --git a/ext/tracer_tag_propagation/tracer_tag_propagation.h b/ext/tracer_tag_propagation/tracer_tag_propagation.h index 657b764fe93..a603d4c53cf 100644 --- a/ext/tracer_tag_propagation/tracer_tag_propagation.h +++ b/ext/tracer_tag_propagation/tracer_tag_propagation.h @@ -3,9 +3,12 @@ #include +#include "../ddtrace_export.h" + void ddtrace_clean_tracer_tags(zend_array *root_meta, zend_array *propagated_tags); void ddtrace_add_tracer_tags_from_header(zend_string *headerstr, zend_array *root_meta, zend_array *propagated_tags); void ddtrace_add_tracer_tags_from_array(zend_array *array, zend_array *root_meta, zend_array *propagated_tags); +DDTRACE_PUBLIC void ddtrace_add_propagated_tag_on_span_zobj(zend_string *key, zval *value); void ddtrace_get_propagated_tags(zend_array *tags); zend_string *ddtrace_format_root_propagated_tags(void);