Skip to content

Commit

Permalink
feat(py): Add validate_pii_selector (#2687)
Browse files Browse the repository at this point in the history
Expose a function to validate PII selectors directly, so we can use it
to validate safe fields in Sentry.
  • Loading branch information
Dav1dde authored Nov 6, 2023
1 parent 0855e4f commit 5a58efb
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Allow advanced scrubbing expressions for datascrubbing safe fields. ([#2670](https://github.com/getsentry/relay/pull/2670))
- Track when a span was received. ([#2688](https://github.com/getsentry/relay/pull/2688))
- Add context for NEL (Network Error Logging) reports to the event schema. ([#2421](https://github.com/getsentry/relay/pull/2421))
- Add `validate_pii_selector` to CABI for safe fields validation. ([#2687](https://github.com/getsentry/relay/pull/2687))

**Bug Fixes**:

Expand Down
4 changes: 4 additions & 0 deletions py/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

- Add `validate_pii_selector` to validate safe fields. ([#2687](https://github.com/getsentry/relay/pull/2687))

## 0.8.34

- Add context for NEL (Network Error Logging) reports to the event schema. ([#2421](https://github.com/getsentry/relay/pull/2421))
Expand Down
12 changes: 12 additions & 0 deletions py/sentry_relay/processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"is_glob_match",
"is_codeowners_path_match",
"parse_release",
"validate_pii_selector",
"validate_pii_config",
"convert_datascrubbing_config",
"pii_strip_event",
Expand Down Expand Up @@ -166,6 +167,17 @@ def is_codeowners_path_match(value, pattern):
)


def validate_pii_selector(selector):
"""
Validate a PII selector spec. Used to validate datascrubbing safe fields.
"""
assert isinstance(selector, str)
raw_error = rustcall(lib.relay_validate_pii_selector, encode_str(selector))
error = decode_str(raw_error, free=True)
if error:
raise ValueError(error)


def validate_pii_config(config):
"""
Validate a PII config against the schema. Used in project options UI.
Expand Down
18 changes: 18 additions & 0 deletions py/tests/test_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,24 @@ def test_normalize_user_agent(must_normalize):
assert "contexts" not in event


def test_validate_pii_selector():
sentry_relay.validate_pii_selector("test")
sentry_relay.validate_pii_selector("$user.id")
sentry_relay.validate_pii_selector("extra.'sys.argv'.**")

with pytest.raises(ValueError) as e:
sentry_relay.validate_pii_selector("no_spaces allowed")
assert str(e.value) == 'invalid syntax near "no_spaces allowed"'

with pytest.raises(ValueError) as e:
sentry_relay.validate_pii_selector("unterminated.'string")
assert str(e.value) == 'invalid syntax near "unterminated.\'string"'

with pytest.raises(ValueError) as e:
sentry_relay.validate_pii_selector("double.**.wildcard.**")
assert str(e.value) == "deep wildcard used more than once"


def test_validate_pii_config():
sentry_relay.validate_pii_config("{}")
sentry_relay.validate_pii_config('{"applications": {}}')
Expand Down
5 changes: 5 additions & 0 deletions relay-cabi/include/relay.h
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,11 @@ struct RelayStr relay_store_normalizer_normalize_event(struct RelayStoreNormaliz
*/
bool relay_translate_legacy_python_json(struct RelayStr *event);

/**
* Validates a PII selector spec. Used to validate datascrubbing safe fields.
*/
struct RelayStr relay_validate_pii_selector(const struct RelayStr *value);

/**
* Validate a PII config against the schema. Used in project options UI.
*/
Expand Down
56 changes: 40 additions & 16 deletions relay-cabi/src/processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use relay_event_normalization::{
use relay_event_schema::processor::{process_value, split_chunks, ProcessingState};
use relay_event_schema::protocol::{Event, VALID_PLATFORMS};
use relay_pii::{
selector_suggestions_from_value, DataScrubbingConfig, PiiConfig, PiiConfigError, PiiProcessor,
selector_suggestions_from_value, DataScrubbingConfig, InvalidSelectorError, PiiConfig,
PiiConfigError, PiiProcessor, SelectorSpec,
};
use relay_protocol::{Annotated, Remark, RuleCondition};
use relay_sampling::SamplingConfig;
Expand Down Expand Up @@ -150,6 +151,24 @@ pub unsafe extern "C" fn relay_translate_legacy_python_json(event: *mut RelayStr
true
}

/// Validates a PII selector spec. Used to validate datascrubbing safe fields.
#[no_mangle]
#[relay_ffi::catch_unwind]
pub unsafe extern "C" fn relay_validate_pii_selector(value: *const RelayStr) -> RelayStr {
let value = (*value).as_str();
match value.parse::<SelectorSpec>() {
Ok(_) => RelayStr::new(""),
Err(err) => match err {
InvalidSelectorError::ParseError(_) => {
// Change the error to something more concise we can show in an UI.
// Error message follows the same format used for fingerprinting rules.
RelayStr::from_string(format!("invalid syntax near {value:?}"))
}
err => RelayStr::from_string(err.to_string()),
},
}
}

/// Validate a PII config against the schema. Used in project options UI.
#[no_mangle]
#[relay_ffi::catch_unwind]
Expand Down Expand Up @@ -336,9 +355,13 @@ pub unsafe extern "C" fn normalize_global_config(value: *const RelayStr) -> Rela
}
}

#[test]
fn pii_config_validation_invalid_regex() {
let config = r#"
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn pii_config_validation_invalid_regex() {
let config = r#"
{
"rules": {
"strip-fields": {
Expand All @@ -355,15 +378,15 @@ fn pii_config_validation_invalid_regex() {
}
}
"#;
assert_eq!(
unsafe { relay_validate_pii_config(&RelayStr::from(config)).as_str() },
"regex parse error:\n (not valid regex\n ^\nerror: unclosed group"
);
}
assert_eq!(
unsafe { relay_validate_pii_config(&RelayStr::from(config)).as_str() },
"regex parse error:\n (not valid regex\n ^\nerror: unclosed group"
);
}

#[test]
fn pii_config_validation_valid_regex() {
let config = r#"
#[test]
fn pii_config_validation_valid_regex() {
let config = r#"
{
"rules": {
"strip-fields": {
Expand All @@ -380,8 +403,9 @@ fn pii_config_validation_valid_regex() {
}
}
"#;
assert_eq!(
unsafe { relay_validate_pii_config(&RelayStr::from(config)).as_str() },
""
);
assert_eq!(
unsafe { relay_validate_pii_config(&RelayStr::from(config)).as_str() },
""
);
}
}

0 comments on commit 5a58efb

Please sign in to comment.