def test_multiple_sensitive_data_fields_get_marked_when_added(self): cased.add_sensitive_field("email") cased.add_sensitive_field("phone") processor = SensitiveDataProcessor(event_with_email_and_phone_field) assert processor.process() == { ".cased": { "pii": { "email": [{ "begin": 0, "end": 19, "label": "email" }], "phone": [{ "begin": 0, "end": 12, "label": "phone" }], } }, "action": "user.create", "actor": "some-actor", "email": "*****@*****.**", "phone": "555-555-5555", }
def test_process_does_everything_needed(self): handler = SensitiveDataHandler("username", username_regex) processor = SensitiveDataProcessor( event_with_multiple_keys_matching.copy(), [handler]) assert processor.process() == { ".cased": { "pii": { "friend_username": [{ "begin": 0, "end": 15, "label": "username" }], "new_username": [ { "begin": 0, "end": 13, "label": "username" }, { "begin": 23, "end": 39, "label": "username" }, ], } }, "action": "user.create", "actor": "some-actor", "friend_username": "******", "new_username": "******", }
def test_process_does_everything_needed_with_redact_configured(self): cased.redact_before_publishing = True handler = SensitiveDataHandler("username", username_regex) processor = SensitiveDataProcessor( event_with_multiple_keys_matching.copy(), [handler]) assert processor.process() == { ".cased": { "pii": { "friend_username": [{ "begin": 0, "end": 15, "label": "username" }], "new_username": [ { "begin": 0, "end": 13, "label": "username" }, { "begin": 23, "end": 39, "label": "username" }, ], } }, "action": "user.create", "actor": "some-actor", "friend_username": "******", "new_username": "******", }
def test_redact_data_with_multiple_key_matches(self): handler = SensitiveDataHandler("username", username_regex) processor = SensitiveDataProcessor( event_with_multiple_keys_matching.copy(), [handler]) ranges = { "friend_username": [{ "begin": 0, "end": 15, "label": "username" }], "new_username": [ { "begin": 0, "end": 13, "label": "username" }, { "begin": 23, "end": 39, "label": "username" }, ], } assert processor.redact_data(ranges) == { "action": "user.create", "actor": "some-actor", "friend_username": "******", "new_username": "******", }
def test_redact_data_with_multiple_handlers(self): cased.redact_before_publishing = True handler1 = SensitiveDataHandler("username", username_regex) handler2 = SensitiveDataHandler("name", name_regex) processor = SensitiveDataProcessor( event_with_multiple_keys_of_different_matches.copy(), [handler1, handler2]) assert processor.process() == { ".cased": { "pii": { "new_username": [{ "begin": 0, "end": 13, "label": "username" }], "name": [{ "begin": 5, "end": 10, "label": "name" }], } }, "name": "Jane XXXXX", "action": "user.create", "actor": "some-actor", "phone": "555-555-5555", "new_username": "******", }
def test_ranges_from_event_works_with_multiple_key_matches(self): handler = SensitiveDataHandler("username", username_regex) processor = SensitiveDataProcessor( event_with_multiple_keys_matching.copy(), [handler]) assert processor.ranges_from_event( event_with_multiple_keys_matching.copy(), handler) == { "friend_username": [{ "begin": 0, "end": 15, "label": "username" }], "new_username": [ { "begin": 0, "end": 13, "label": "username" }, { "begin": 23, "end": 39, "label": "username" }, ], }
def test_add_ranges_to_events(self): handler = SensitiveDataHandler("username", username_regex) processor = SensitiveDataProcessor(event.copy(), [handler]) ranges = { "new_username": [{ "begin": 0, "end": 13, "label": "username" }] } assert processor.add_ranges_to_event(ranges) == { ".cased": { "pii": { "new_username": [{ "begin": 0, "end": 13, "label": "username" }], }, }, "action": "user.create", "actor": "some-actor", "new_username": "******", }
def test_ranges_from_event_works_with_multiple_handlers_and_field_setting( self): handler1 = SensitiveDataHandler("username", username_regex) handler2 = SensitiveDataHandler("name", name_regex) cased.add_sensitive_field("phone") processor = SensitiveDataProcessor( event_with_multiple_keys_of_different_matches.copy(), [handler1, handler2]) assert processor.process()[".cased"]["pii"] == { "new_username": [{ "begin": 0, "end": 13, "label": "username" }], "name": [{ "begin": 5, "end": 10, "label": "name" }], "phone": [{ "begin": 0, "end": 12, "label": "phone" }], } cased.sensitive_fields = set()
def test_ranges_from_event(self): handler = SensitiveDataHandler("username", username_regex) processor = SensitiveDataProcessor(event, [handler]) assert processor.ranges_from_event(event, handler) == { "new_username": [{ "begin": 0, "end": 13, "label": "username" }] }
def test_sensitive_data_processor_has_default_handlers_if_set(self): handler = SensitiveDataHandler("username", username_regex) cased.add_handler(handler) processor = SensitiveDataProcessor(event) assert processor.data_handlers[0].label == handler.label cased.clear_handlers()
def test_sensitive_data_processor_can_be_created_with_mutiple_handlers( self): handler1 = SensitiveDataHandler("username", username_regex) handler2 = SensitiveDataHandler("name", name_regex) processor = SensitiveDataProcessor(event, [handler1, handler2]) assert processor.audit_event == event assert processor.data_handlers == [handler1, handler2]
def test_ranges_from_event_works_with_multiple_matches(self): handler = SensitiveDataHandler("username", username_regex) processor = SensitiveDataProcessor(event_with_two_usernames, [handler]) assert processor.ranges_from_event(event_with_two_usernames, handler) == { "new_username": [ { "begin": 0, "end": 13, "label": "username" }, { "begin": 23, "end": 39, "label": "username" }, ] }
def test_sensitive_data_fields_get_marked_when_added(self): cased.add_sensitive_field("email") processor = SensitiveDataProcessor(event_with_email_field) assert processor.process() == { ".cased": { "pii": { "email": [{ "begin": 0, "end": 19, "label": "email" }] }, }, "action": "user.create", "actor": "some-actor", "email": "*****@*****.**", } assert len(event_with_email_field["email"]) == 19
def test_sensitive_data_fields_get_marked_with_explicit_setting(self): cased.clear_sensitive_fields() cased.sensitive_fields = {"email"} processor = SensitiveDataProcessor(event_with_email_field) assert processor.process() == { ".cased": { "pii": { "email": [{ "begin": 0, "end": 19, "label": "email" }] }, }, "action": "user.create", "actor": "some-actor", "email": "*****@*****.**", } assert (len(event_with_email_field["email"]) == 19 ) # to confirm a match with the "end" parameter in pii
def publish(cls, data, **params): if cased.disable_publishing: return None requestor = Requestor.publish_requestor(**params) publish_data = data.copy() # Using the plugin system, add any data from plugins that have been configured data_plugins = getattr(cased, "data_plugins", []) for plugin in data_plugins: instance = plugin(publish_data) additions = instance.additions() publish_data.update(additions) # Include context data, overriding it with any local publish data current_context = cased.context.current() always_merger.merge(current_context, publish_data) # Update the .cased with any PII ranges processor = SensitiveDataProcessor(current_context) final_publish_data = processor.process() # Add the item to a ReliabilityEngine backend. The backend can be configured # with a "backend" keyword arg passed to publish(), or with the global config. # By default, we try/except just in case the user misconfigured their ReliabilityEngine: # we'd rather still send the audit data then fail here. But we do log a message. # Additionally, if a ReliabilityBackend is not set, we will (optionally) log a warning. try: if "backend" in params: engine = ReliabilityEngine(backend=params["backend"]) engine.add(publish_data) elif cased.reliability_backend: engine = ReliabilityEngine(backend=cased.reliability_backend) engine.add(publish_data) else: if cased.warn_if_no_reliability_backend: log_info("No reliability backend has been set") except ReliabilityEngineError as e: log_info("""Reliability backend is misconfigured. Please check configuration. Client will still send audit data to Cased. Error: {}""".format(e)) try: # Send to Cased response = requestor.request("post", "/", final_publish_data) log_info("Sent to Cased: " + str(final_publish_data)) # Publish the item to any additional publishers additional_publishers = cased.additional_publishers for publisher in additional_publishers: try: publisher.publish(final_publish_data) except AttributeError: raise PublisherException( "Publisher must implement publish()") except Exception as e: log_error(e) if cased.raise_on_publish_errors: raise finally: if cased.clear_context_after_publishing: cased.context.clear() return response
def test_sensitive_data_processor_can_be_created(self): processor = SensitiveDataProcessor(event) assert processor.audit_event == event