-
Notifications
You must be signed in to change notification settings - Fork 104
ref(logs): Change logic for scrubbing attributes #5095
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,8 +5,8 @@ use std::sync::OnceLock; | |
|
|
||
| use regex::Regex; | ||
| use relay_event_schema::processor::{ | ||
| self, Chunk, Pii, ProcessValue, ProcessingAction, ProcessingResult, ProcessingState, Processor, | ||
| ValueType, enum_set, process_value, | ||
| self, Chunk, FieldAttrs, Pii, ProcessValue, ProcessingAction, ProcessingResult, | ||
| ProcessingState, Processor, ValueType, enum_set, process_value, | ||
| }; | ||
| use relay_event_schema::protocol::{ | ||
| AsPair, Event, IpAddr, NativeImagePath, PairList, Replay, ResponseContext, User, | ||
|
|
@@ -19,8 +19,21 @@ use crate::redactions::Redaction; | |
| use crate::regexes::{self, ANYTHING_REGEX, PatternType, ReplaceBehavior}; | ||
| use crate::utils; | ||
|
|
||
| /// Controls how scrubbing rules are applied to attributes. | ||
| #[derive(Debug, Clone, Copy)] | ||
| pub enum AttributeMode { | ||
| /// Treat the attribute as an object and allow referring | ||
| /// to individual fields. | ||
| Object, | ||
| /// Identify the attribute with its value and apply all | ||
| /// rules there directly. | ||
| ValueOnly, | ||
| } | ||
|
|
||
| /// A processor that performs PII stripping. | ||
| pub struct PiiProcessor<'a> { | ||
| /// Controls how rules are applied to attributes. | ||
| attribute_mode: AttributeMode, | ||
| compiled_config: &'a CompiledPiiConfig, | ||
| } | ||
|
|
||
|
|
@@ -29,7 +42,16 @@ impl<'a> PiiProcessor<'a> { | |
| pub fn new(compiled_config: &'a CompiledPiiConfig) -> PiiProcessor<'a> { | ||
| // this constructor needs to be cheap... a new PiiProcessor is created for each event. Move | ||
| // any init logic into CompiledPiiConfig::new. | ||
| PiiProcessor { compiled_config } | ||
| PiiProcessor { | ||
| compiled_config, | ||
| attribute_mode: AttributeMode::Object, | ||
| } | ||
| } | ||
|
|
||
| /// Sets an `AttributeMode` on this processor. | ||
| pub fn attribute_mode(mut self, attribute_mode: AttributeMode) -> Self { | ||
| self.attribute_mode = attribute_mode; | ||
| self | ||
| } | ||
|
|
||
| fn apply_all_rules( | ||
|
|
@@ -45,10 +67,8 @@ impl<'a> PiiProcessor<'a> { | |
|
|
||
| for (selector, rules) in self.compiled_config.applications.iter() { | ||
| if selector.matches_path(&state.path()) { | ||
| #[allow(clippy::needless_option_as_deref)] | ||
| for rule in rules { | ||
| let reborrowed_value = value.as_deref_mut(); | ||
| apply_rule_to_value(meta, rule, state.path().key(), reborrowed_value)?; | ||
| apply_rule_to_value(meta, rule, state.path().key(), value.as_deref_mut())?; | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -199,13 +219,24 @@ impl Processor for PiiProcessor<'_> { | |
| utils::process_pairlist(self, value, state) | ||
| } | ||
|
|
||
| fn process_attributes( | ||
| fn process_attribute( | ||
| &mut self, | ||
| value: &mut relay_event_schema::protocol::Attributes, | ||
| value: &mut relay_event_schema::protocol::Attribute, | ||
| _meta: &mut Meta, | ||
| state: &ProcessingState, | ||
| ) -> ProcessingResult { | ||
| utils::process_attributes(value, self, state) | ||
| match self.attribute_mode { | ||
| AttributeMode::Object => { | ||
| // Treat the attribute as an object and recurse into its children. | ||
| value.process_child_values(self, state) | ||
| } | ||
| AttributeMode::ValueOnly => { | ||
| // Identify the attribute with its value and apply rules there directly. | ||
| let value_state = | ||
| state.enter_nothing(Some(Cow::Owned(FieldAttrs::new().pii(Pii::True)))); | ||
| processor::process_value(&mut value.value.value, self, &value_state) | ||
| } | ||
| } | ||
|
Comment on lines
+228
to
+239
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! |
||
| } | ||
|
|
||
| fn process_user( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,8 @@ | ||
| use relay_event_normalization::{SchemaProcessor, eap}; | ||
| use relay_event_schema::processor::{ProcessingState, ValueType, process_value}; | ||
| use relay_event_schema::processor::{ProcessingState, process_value}; | ||
| use relay_event_schema::protocol::{OurLog, OurLogHeader}; | ||
| use relay_ourlogs::OtelLog; | ||
| use relay_pii::PiiProcessor; | ||
| use relay_pii::{AttributeMode, PiiProcessor}; | ||
| use relay_protocol::Annotated; | ||
| use relay_quotas::DataCategory; | ||
|
|
||
|
|
@@ -139,17 +139,17 @@ fn scrub_log(log: &mut Annotated<OurLog>, ctx: Context<'_>) -> Result<()> { | |
| .map_err(|e| Error::PiiConfig(e.clone()))?; | ||
|
|
||
| if let Some(ref config) = ctx.project_info.config.pii_config { | ||
| let mut processor = PiiProcessor::new(config.compiled()); | ||
| let root_state = ProcessingState::root().enter_static("", None, Some(ValueType::OurLog)); | ||
| process_value(log, &mut processor, &root_state)?; | ||
| let mut processor = PiiProcessor::new(config.compiled()) | ||
| // For advanced rules we want to treat attributes as objects. | ||
| .attribute_mode(AttributeMode::Object); | ||
| process_value(log, &mut processor, ProcessingState::root())?; | ||
| } | ||
|
|
||
| if let Some(config) = pii_config_from_scrubbing { | ||
| let mut processor = PiiProcessor::new(config.compiled()); | ||
| // Use empty root (assumed to be Event) for legacy/default scrubbing rules. | ||
| // process_attributes will collapse Attribute into it's value for the default rules. | ||
| let root_state = ProcessingState::root(); | ||
| process_value(log, &mut processor, root_state)?; | ||
| let mut processor = PiiProcessor::new(config.compiled()) | ||
| // For "legacy" rules we want to identify attributes with their values. | ||
| .attribute_mode(AttributeMode::ValueOnly); | ||
| process_value(log, &mut processor, ProcessingState::root())?; | ||
| } | ||
|
|
||
| Ok(()) | ||
|
|
@@ -309,10 +309,7 @@ mod tests { | |
| scrubbing_config.scrub_data = true; | ||
| scrubbing_config.scrub_defaults = true; | ||
| scrubbing_config.scrub_ip_addresses = true; | ||
| scrubbing_config.sensitive_fields = vec![ | ||
| "value".to_owned(), // Make sure the inner 'value' of the attribute object isn't scrubbed. | ||
| "very_sensitive_data".to_owned(), | ||
| ]; | ||
| scrubbing_config.sensitive_fields = vec!["very_sensitive_data".to_owned()]; | ||
| scrubbing_config.exclude_fields = vec!["public_data".to_owned()]; | ||
|
|
||
| let ctx = make_context(scrubbing_config, None); | ||
|
|
@@ -1098,7 +1095,7 @@ mod tests { | |
| }, | ||
| }, | ||
| "applications": { | ||
| "$log.attributes.remove_this_string_abc123.value": ["remove_abc123"], | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this selector working on master is a bug. As I understand it a path starting with
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Why not? Don't we also have |
||
| "attributes.remove_this_string_abc123.value": ["remove_abc123"], | ||
| } | ||
| })) | ||
| .unwrap(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an incidental change.