def test_given_anonymize_with_encrypt_then_text_returned_with_encrypted_content(): unencrypted_text = "My name is " expected_encrypted_text = "Chloë" text = unencrypted_text + expected_encrypted_text start_index = 11 end_index = 16 key = "WmZq4t7w!z%C&F)J" analyzer_results = [RecognizerResult("PERSON", start_index, end_index, 0.8)] anonymizers_config = {"PERSON": OperatorConfig("encrypt", {"key": key})} actual_anonymize_result = ( AnonymizerEngine().anonymize(text, analyzer_results, anonymizers_config) ) assert len(actual_anonymize_result.items) == 1 anonymized_entities = [ AnonymizerResult.from_operator_result(actual_anonymize_result.items[0]) ] engine = DeanonymizeEngine() decryption = engine.deanonymize( actual_anonymize_result.text, anonymized_entities, {"PERSON": OperatorConfig(Decrypt.NAME, {"key": key})} ) assert decryption.text == "My name is Chloë" assert len(decryption.items) == 1 assert decryption.items[0].text == "Chloë" assert decryption.items[0].end == 16 assert decryption.items[0].start == 11 assert decryption.items[0].entity_type == "PERSON"
def test_given_short_key_then_we_fail(): text = "My name is S184CMt9Drj7QaKQ21JTrpYzghnboTF9pn/neN8JME0=" encryption_results = [ AnonymizerResult( start=11, end=55, entity_type="PERSON" ), ] engine = DeanonymizeEngine() expected_result = "Invalid input, key must be of length 128, 192 or 256 bits" with pytest.raises(InvalidParamException, match=expected_result): engine.deanonymize( text, encryption_results, {"PERSON": OperatorConfig(Decrypt.NAME, {"key": "1234"})} )
def test_given_operator_decrypt_with_valid_params_then_decrypt_text_successfully(): text = "My name is S184CMt9Drj7QaKQ21JTrpYzghnboTF9pn/neN8JME0=" encryption_results = [ AnonymizerResult( start=11, end=55, entity_type="PERSON" ), ] engine = DeanonymizeEngine() decryption = engine.deanonymize( text, encryption_results, {"DEFAULT": OperatorConfig(Decrypt.NAME, {"key": "WmZq4t7w!z%C&F)J"})} ) assert decryption.text == "My name is Chloë" assert len(decryption.items) == 1 assert decryption.items[0].text == "Chloë" assert decryption.items[0].end == 16 assert decryption.items[0].start == 11 assert decryption.items[0].entity_type == "PERSON"
def test_given_request_deanonymizers_return_list(): engine = DeanonymizeEngine() expected_list = ["decrypt"] anon_list = engine.get_deanonymizers() assert anon_list == expected_list
def __init__(self): fileConfig(Path(Path(__file__).parent, LOGGING_CONF_FILE)) self.logger = logging.getLogger("presidio-anonymizer") self.logger.setLevel(os.environ.get("LOG_LEVEL", self.logger.level)) self.app = Flask(__name__) self.logger.info("Starting anonymizer engine") self.anonymizer = AnonymizerEngine() self.deanonymize = DeanonymizeEngine() self.logger.info(WELCOME_MESSAGE) @self.app.route("/health") def health() -> str: """Return basic health probe result.""" return "Presidio Anonymizer service is up" @self.app.route("/anonymize", methods=["POST"]) def anonymize() -> Response: content = request.get_json() if not content: raise BadRequest("Invalid request json") anonymizers_config = AppEntitiesConvertor.operators_config_from_json( content.get("anonymizers")) if AppEntitiesConvertor.check_custom_operator(anonymizers_config): raise BadRequest("Custom type anonymizer is not supported") analyzer_results = AppEntitiesConvertor.analyzer_results_from_json( content.get("analyzer_results")) anoymizer_result = self.anonymizer.anonymize( text=content.get("text"), analyzer_results=analyzer_results, operators=anonymizers_config, ) return Response(anoymizer_result.to_json(), mimetype="application/json") @self.app.route("/deanonymize", methods=["POST"]) def deanonymize() -> Response: content = request.get_json() if not content: raise BadRequest("Invalid request json") text = content.get("text") deanonymize_entities = AppEntitiesConvertor.deanonymize_entities_from_json( content) deanonymize_config = AppEntitiesConvertor.operators_config_from_json( content.get("deanonymizers")) deanonymized_response = self.deanonymize.deanonymize( text=text, entities=deanonymize_entities, operators=deanonymize_config) return Response(deanonymized_response.to_json(), mimetype="application/json") @self.app.route("/anonymizers", methods=["GET"]) def anonymizers(): """Return a list of supported anonymizers.""" return jsonify(self.anonymizer.get_anonymizers()) @self.app.route("/deanonymizers", methods=["GET"]) def deanonymizers(): """Return a list of supported deanonymizers.""" return jsonify(self.deanonymize.get_deanonymizers()) @self.app.errorhandler(InvalidParamException) def invalid_param(err): self.logger.warning( f"Request failed with parameter validation error: {err.err_msg}" ) return jsonify(error=err.err_msg), 422 @self.app.errorhandler(HTTPException) def http_exception(e): return jsonify(error=e.description), e.code @self.app.errorhandler(Exception) def server_error(e): self.logger.error(f"A fatal error occurred during execution: {e}") return jsonify(error="Internal server error"), 500