This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch v2-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v2-1-test by this push:
new 73ff5a8 Fix redacting secrets in context exceptions. (#17618)
73ff5a8 is described below
commit 73ff5a89742ec0ebd4097d3e0751c16b0016e14e
Author: Jarek Potiuk <[email protected]>
AuthorDate: Sat Aug 14 22:49:03 2021 +0200
Fix redacting secrets in context exceptions. (#17618)
* Fix redacting secrets in context exceptions.
Secret masking did not work in implicit and
explicit context exceptions (see
https://www.python.org/dev/peps/pep-3134/)
When there was a `try/except/raise` sequence,
or `raise ... from` exception - the original
exceptions were not redacted.
Related: #17604
(cherry picked from commit 6df3ee7997e335eb7d353d4ec0f5c2dd3a0e0d26)
---
airflow/utils/log/secrets_masker.py | 10 ++++-
tests/utils/log/test_secrets_masker.py | 76 ++++++++++++++++++++++++++++++++++
2 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/airflow/utils/log/secrets_masker.py
b/airflow/utils/log/secrets_masker.py
index 0ce0424..f8fbb35 100644
--- a/airflow/utils/log/secrets_masker.py
+++ b/airflow/utils/log/secrets_masker.py
@@ -144,6 +144,13 @@ class SecretsMasker(logging.Filter):
)
return frozenset(record.__dict__).difference({'msg', 'args'})
+ def _redact_exception_with_context(self, exception):
+ exception.args = (self.redact(v) for v in exception.args)
+ if exception.__context__:
+ self._redact_exception_with_context(exception.__context__)
+ if exception.__cause__ and exception.__cause__ is not
exception.__context__:
+ self._redact_exception_with_context(exception.__cause__)
+
def filter(self, record) -> bool:
if self.ALREADY_FILTERED_FLAG in record.__dict__:
# Filters are attached to multiple handlers and logs, keep a
@@ -157,8 +164,7 @@ class SecretsMasker(logging.Filter):
record.__dict__[k] = self.redact(v)
if record.exc_info and record.exc_info[1] is not None:
exc = record.exc_info[1]
- # I'm not sure if this is a good idea!
- exc.args = (self.redact(v) for v in exc.args)
+ self._redact_exception_with_context(exc)
record.__dict__[self.ALREADY_FILTERED_FLAG] = True
return True
diff --git a/tests/utils/log/test_secrets_masker.py
b/tests/utils/log/test_secrets_masker.py
index 78a10b5..e60bdc6 100644
--- a/tests/utils/log/test_secrets_masker.py
+++ b/tests/utils/log/test_secrets_masker.py
@@ -25,6 +25,8 @@ import pytest
from airflow.utils.log.secrets_masker import SecretsMasker,
should_hide_value_for_key
from tests.test_utils.config import conf_vars
+p = "password"
+
@pytest.fixture
def logger(caplog):
@@ -145,6 +147,80 @@ class TestSecretsMasker:
"""
)
+ def test_masking_in_implicit_context_exceptions(self, logger, caplog):
+ """
+ Show that redacting password works in context exceptions.
+ """
+ try:
+ try:
+ try:
+ raise RuntimeError(f"Cannot connect to user:{p}")
+ except RuntimeError as ex1:
+ raise RuntimeError(f'Exception: {ex1}')
+ except RuntimeError as ex2:
+ raise RuntimeError(f'Exception: {ex2}')
+ except RuntimeError:
+ logger.exception("Err")
+
+ line = lineno() - 8
+
+ assert caplog.text == textwrap.dedent(
+ f"""\
+ ERROR Err
+ Traceback (most recent call last):
+ File ".../test_secrets_masker.py", line {line}, in
test_masking_in_implicit_context_exceptions
+ raise RuntimeError(f"Cannot connect to user:{{p}}")
+ RuntimeError: Cannot connect to user:***
+
+ During handling of the above exception, another exception occurred:
+
+ Traceback (most recent call last):
+ File ".../test_secrets_masker.py", line {line+2}, in
test_masking_in_implicit_context_exceptions
+ raise RuntimeError(f'Exception: {{ex1}}')
+ RuntimeError: Exception: Cannot connect to user:***
+
+ During handling of the above exception, another exception occurred:
+
+ Traceback (most recent call last):
+ File ".../test_secrets_masker.py", line {line+4}, in
test_masking_in_implicit_context_exceptions
+ raise RuntimeError(f'Exception: {{ex2}}')
+ RuntimeError: Exception: Exception: Cannot connect to user:***
+ """
+ )
+
+ def test_masking_in_explicit_context_exceptions(self, logger, caplog):
+ """
+ Show that redacting password works in context exceptions.
+ """
+ exception = None
+ try:
+ raise RuntimeError(f"Cannot connect to user:{p}")
+ except RuntimeError as ex:
+ exception = ex
+ try:
+ raise RuntimeError(f'Exception: {exception}') from exception
+ except RuntimeError:
+ logger.exception("Err")
+
+ line = lineno() - 8
+
+ assert caplog.text == textwrap.dedent(
+ f"""\
+ ERROR Err
+ Traceback (most recent call last):
+ File ".../test_secrets_masker.py", line {line}, in
test_masking_in_explicit_context_exceptions
+ raise RuntimeError(f"Cannot connect to user:{{p}}")
+ RuntimeError: Cannot connect to user:***
+
+ The above exception was the direct cause of the following
exception:
+
+ Traceback (most recent call last):
+ File ".../test_secrets_masker.py", line {line+4}, in
test_masking_in_explicit_context_exceptions
+ raise RuntimeError(f'Exception: {{exception}}') from exception
+ RuntimeError: Exception: Cannot connect to user:***
+ """
+ )
+
@pytest.mark.parametrize(
("name", "value", "expected_mask"),
[